From noreply at buildbot.pypy.org Mon Apr 1 09:12:12 2013 From: noreply at buildbot.pypy.org (cfbolz) Date: Mon, 1 Apr 2013 09:12:12 +0200 (CEST) Subject: [pypy-commit] pypy default: kill the _bisect accelerator module. the JIT makes the Python version faster Message-ID: <20130401071212.A0B741C070B@cobra.cs.uni-duesseldorf.de> Author: Carl Friedrich Bolz Branch: Changeset: r62910:b2356b60368c Date: 2013-04-01 09:11 +0200 http://bitbucket.org/pypy/pypy/changeset/b2356b60368c/ Log: kill the _bisect accelerator module. the JIT makes the Python version faster than the RPython version, because it can specialize on the content of the lists diff --git a/pypy/module/_bisect/__init__.py b/pypy/module/_bisect/__init__.py deleted file mode 100644 --- a/pypy/module/_bisect/__init__.py +++ /dev/null @@ -1,27 +0,0 @@ -""" -Mixed-module definition for the _bisect module. -This is an optional module; if not present, bisect.py uses the -pure Python version of these functions. -""" - -from pypy.interpreter.mixedmodule import MixedModule - - -class Module(MixedModule): - """\ -This module provides support for maintaining a list in sorted order without -having to sort the list after each insertion. For long lists of items with -expensive comparison operations, this can be an improvement over the more -common approach.""" - - appleveldefs = { - 'insort': 'app_bisect.insort_right', - 'insort_left': 'app_bisect.insort_left', - 'insort_right': 'app_bisect.insort_right', - } - - interpleveldefs = { - 'bisect': 'interp_bisect.bisect_right', - 'bisect_left': 'interp_bisect.bisect_left', - 'bisect_right': 'interp_bisect.bisect_right', - } diff --git a/pypy/module/_bisect/app_bisect.py b/pypy/module/_bisect/app_bisect.py deleted file mode 100644 --- a/pypy/module/_bisect/app_bisect.py +++ /dev/null @@ -1,23 +0,0 @@ -from _bisect import bisect_left, bisect_right - - -def insort_left(a, x, lo=0, hi=-1): - """Insert item x in list a, and keep it sorted assuming a is sorted. - -If x is already in a, insert it to the left of the leftmost x. - -Optional args lo (default 0) and hi (default len(a)) bound the -slice of a to be searched.""" - n = bisect_left(a, x, lo, hi) - a.insert(n, x) - - -def insort_right(a, x, lo=0, hi=-1): - """Insert item x in list a, and keep it sorted assuming a is sorted. - -If x is already in a, insert it to the right of the rightmost x. - -Optional args lo (default 0) and hi (default len(a)) bound the -slice of a to be searched.""" - n = bisect_right(a, x, lo, hi) - a.insert(n, x) diff --git a/pypy/module/_bisect/interp_bisect.py b/pypy/module/_bisect/interp_bisect.py deleted file mode 100644 --- a/pypy/module/_bisect/interp_bisect.py +++ /dev/null @@ -1,53 +0,0 @@ -from pypy.interpreter.error import OperationError -from pypy.interpreter.gateway import unwrap_spec -from rpython.rlib.rarithmetic import intmask, r_uint - - - at unwrap_spec(lo=int, hi=int) -def bisect_left(space, w_a, w_x, lo=0, hi=-1): - """Return the index where to insert item x in list a, assuming a is sorted. - -The return value i is such that all e in a[:i] have e < x, and all e in -a[i:] have e >= x. So if x already appears in the list, i points just -before the leftmost x already there. - -Optional args lo (default 0) and hi (default len(a)) bound the -slice of a to be searched.""" - if lo < 0: - raise OperationError(space.w_ValueError, - space.wrap("lo must be non-negative")) - if hi == -1: - hi = space.len_w(w_a) - while lo < hi: - mid = intmask((r_uint(lo) + r_uint(hi)) >> 1) - w_litem = space.getitem(w_a, space.wrap(mid)) - if space.is_true(space.lt(w_litem, w_x)): - lo = mid + 1 - else: - hi = mid - return space.wrap(lo) - - - at unwrap_spec(lo=int, hi=int) -def bisect_right(space, w_a, w_x, lo=0, hi=-1): - """Return the index where to insert item x in list a, assuming a is sorted. - -The return value i is such that all e in a[:i] have e <= x, and all e in -a[i:] have e > x. So if x already appears in the list, i points just -beyond the rightmost x already there - -Optional args lo (default 0) and hi (default len(a)) bound the -slice of a to be searched.""" - if lo < 0: - raise OperationError(space.w_ValueError, - space.wrap("lo must be non-negative")) - if hi == -1: - hi = space.len_w(w_a) - while lo < hi: - mid = intmask((r_uint(lo) + r_uint(hi)) >> 1) - w_litem = space.getitem(w_a, space.wrap(mid)) - if space.is_true(space.lt(w_x, w_litem)): - hi = mid - else: - lo = mid + 1 - return space.wrap(lo) diff --git a/pypy/module/_bisect/test/__init__.py b/pypy/module/_bisect/test/__init__.py deleted file mode 100644 diff --git a/pypy/module/_bisect/test/test_bisect.py b/pypy/module/_bisect/test/test_bisect.py deleted file mode 100644 --- a/pypy/module/_bisect/test/test_bisect.py +++ /dev/null @@ -1,100 +0,0 @@ - -class AppTestBisect: - spaceconfig = dict(usemodules=['_bisect']) - - def test_bisect_left(self): - from _bisect import bisect_left - a = [0, 5, 6, 6, 6, 7] - assert bisect_left(a, None) == 0 - assert bisect_left(a, -3) == 0 - assert bisect_left(a, 0) == 0 - assert bisect_left(a, 3) == 1 - assert bisect_left(a, 5) == 1 - assert bisect_left(a, 5.5) == 2 - assert bisect_left(a, 6) == 2 - assert bisect_left(a, 6.0) == 2 - assert bisect_left(a, 6.1) == 5 - assert bisect_left(a, 7) == 5 - assert bisect_left(a, 8) == 6 - a = [] - assert bisect_left(a, 123) == 0 - a = [9] - assert bisect_left(a, -123) == 0 - assert bisect_left(a, 9) == 0 - assert bisect_left(a, 123) == 1 - a = [9, 9] - assert bisect_left(a, -123) == 0 - assert bisect_left(a, 9) == 0 - assert bisect_left(a, 123) == 2 - a = [4, 6, 6, 9] - assert bisect_left(a, 6, 0) == 1 - assert bisect_left(a, 6, 1) == 1 - assert bisect_left(a, 6, 2) == 2 - assert bisect_left(a, 6, 3) == 3 - assert bisect_left(a, 6, 4) == 4 - assert bisect_left(a, 6, 0, 0) == 0 - assert bisect_left(a, 6, 0, 1) == 1 - assert bisect_left(a, 6, 0, 2) == 1 - assert bisect_left(a, 6, 0, 3) == 1 - assert bisect_left(a, 6, 0, 4) == 1 - - raises(ValueError, bisect_left, [1, 2, 3], 5, -1, 3) - - def test_bisect_right(self): - from _bisect import bisect_right - a = [0, 5, 6, 6, 6, 7] - assert bisect_right(a, None) == 0 - assert bisect_right(a, -3) == 0 - assert bisect_right(a, 0) == 1 - assert bisect_right(a, 3) == 1 - assert bisect_right(a, 5) == 2 - assert bisect_right(a, 5.5) == 2 - assert bisect_right(a, 6) == 5 - assert bisect_right(a, 6.0) == 5 - assert bisect_right(a, 6.1) == 5 - assert bisect_right(a, 7) == 6 - assert bisect_right(a, 8) == 6 - a = [] - assert bisect_right(a, 123) == 0 - a = [9] - assert bisect_right(a, -123) == 0 - assert bisect_right(a, 9) == 1 - assert bisect_right(a, 123) == 1 - a = [9, 9] - assert bisect_right(a, -123) == 0 - assert bisect_right(a, 9) == 2 - assert bisect_right(a, 123) == 2 - a = [4, 6, 6, 9] - assert bisect_right(a, 6, 0) == 3 - assert bisect_right(a, 6, 1) == 3 - assert bisect_right(a, 6, 2) == 3 - assert bisect_right(a, 6, 3) == 3 - assert bisect_right(a, 6, 4) == 4 - assert bisect_right(a, 6, 0, 0) == 0 - assert bisect_right(a, 6, 0, 1) == 1 - assert bisect_right(a, 6, 0, 2) == 2 - assert bisect_right(a, 6, 0, 3) == 3 - assert bisect_right(a, 6, 0, 4) == 3 - - def test_insort_left(self): - from _bisect import insort_left - a = [0, 5, 6, 6, 6, 7] - insort_left(a, 6.0) - assert a == [0, 5, 6.0, 6, 6, 6, 7] - assert map(type, a) == [int, int, float, int, int, int, int] - - def test_insort_right(self): - from _bisect import insort_right - a = [0, 5, 6, 6, 6, 7] - insort_right(a, 6.0) - assert a == [0, 5, 6, 6, 6, 6.0, 7] - assert map(type, a) == [int, int, int, int, int, float, int] - - def test_bisect_overflow(self): - from _bisect import bisect_left, bisect_right - import sys - - size = sys.maxsize - data = xrange(size - 1) - assert bisect_left(data, size - 3) == size - 3 - assert bisect_right(data, size - 3) == size - 2 diff --git a/pypy/module/_bisect/test/test_ztranslation.py b/pypy/module/_bisect/test/test_ztranslation.py deleted file mode 100644 --- a/pypy/module/_bisect/test/test_ztranslation.py +++ /dev/null @@ -1,4 +0,0 @@ -from pypy.objspace.fake.checkmodule import checkmodule - -def test_checkmodule(): - checkmodule('_bisect') From noreply at buildbot.pypy.org Mon Apr 1 15:55:22 2013 From: noreply at buildbot.pypy.org (bivab) Date: Mon, 1 Apr 2013 15:55:22 +0200 (CEST) Subject: [pypy-commit] pypy default: xfail test_push_one_reg if we are running on a system using GNU assembler version < 2.23. Message-ID: <20130401135522.0B4E21C070B@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r62911:39ce9a81f240 Date: 2013-04-01 15:53 +0200 http://bitbucket.org/pypy/pypy/changeset/39ce9a81f240/ Log: xfail test_push_one_reg if we are running on a system using GNU assembler version < 2.23. Version 2.22 generates an alternative encoding for pushing only one register than the one we are using diff --git a/rpython/jit/backend/arm/test/support.py b/rpython/jit/backend/arm/test/support.py --- a/rpython/jit/backend/arm/test/support.py +++ b/rpython/jit/backend/arm/test/support.py @@ -39,6 +39,11 @@ i = commands.getoutput("%s -version &1" % AS) check_skip(i) +def get_as_version(): + import commands + i = commands.getoutput("%s -v &1" % AS) + return tuple([int(j) for j in i.split()[-1].split('.')]) + def check_skip(inp, search='arm', msg='only for arm'): skip = True try: diff --git a/rpython/jit/backend/arm/test/test_instr_codebuilder.py b/rpython/jit/backend/arm/test/test_instr_codebuilder.py --- a/rpython/jit/backend/arm/test/test_instr_codebuilder.py +++ b/rpython/jit/backend/arm/test/test_instr_codebuilder.py @@ -2,7 +2,10 @@ from rpython.jit.backend.arm import codebuilder from rpython.jit.backend.arm import conditions from rpython.jit.backend.arm import instructions -from rpython.jit.backend.arm.test.support import (requires_arm_as, define_test, gen_test_function) +from rpython.jit.backend.arm.test.support import requires_arm_as +from rpython.jit.backend.arm.test.support import get_as_version +from rpython.jit.backend.arm.test.support import define_test +from rpython.jit.backend.arm.test.support import gen_test_function from gen import assemble import py @@ -80,6 +83,9 @@ self.assert_equal('ORR r0, r7, r12, lsl #8') def test_push_one_reg(self): + if get_as_version() < (2, 23): + py.test.xfail("GNU as before version 2.23 generates encoding A1 for " + "pushing only one register") self.cb.PUSH([r.r1.value]) self.assert_equal('PUSH {r1}') From noreply at buildbot.pypy.org Mon Apr 1 20:32:01 2013 From: noreply at buildbot.pypy.org (cfbolz) Date: Mon, 1 Apr 2013 20:32:01 +0200 (CEST) Subject: [pypy-commit] pypy default: replace some dicts used as sets in the translator with actual sets Message-ID: <20130401183201.BEB671C0675@cobra.cs.uni-duesseldorf.de> Author: Carl Friedrich Bolz Branch: Changeset: r62912:5454495ac023 Date: 2013-04-01 20:28 +0200 http://bitbucket.org/pypy/pypy/changeset/5454495ac023/ Log: replace some dicts used as sets in the translator with actual sets diff --git a/rpython/memory/gctransform/transform.py b/rpython/memory/gctransform/transform.py --- a/rpython/memory/gctransform/transform.py +++ b/rpython/memory/gctransform/transform.py @@ -86,9 +86,9 @@ def __init__(self, translator, inline=False): self.translator = translator - self.seen_graphs = {} + self.seen_graphs = set() self.prepared = False - self.minimal_transform = {} + self.minimal_transform = set() if translator: self.mixlevelannotator = MixLevelHelperAnnotator(translator.rtyper) else: @@ -109,8 +109,8 @@ return exceptiondata.lltype_of_exception_value def need_minimal_transform(self, graph): - self.seen_graphs[graph] = True - self.minimal_transform[graph] = True + self.seen_graphs.add(graph) + self.minimal_transform.add(graph) def prepare_inline_helpers(self, graphs): from rpython.translator.backendopt.inline import iter_callsites @@ -210,11 +210,11 @@ if graph in self.minimal_transform: if self.minimalgctransformer: self.minimalgctransformer.transform_graph(graph) - del self.minimal_transform[graph] + self.minimal_transform.remove(graph) return if graph in self.seen_graphs: return - self.seen_graphs[graph] = True + self.seen_graphs.add(graph) self.links_to_split = {} # link -> vars to pop_alive across the link diff --git a/rpython/translator/backendopt/support.py b/rpython/translator/backendopt/support.py --- a/rpython/translator/backendopt/support.py +++ b/rpython/translator/backendopt/support.py @@ -59,18 +59,18 @@ if block is None: block = graph.startblock if seen is None: - seen = {block: None} + seen = set([block]) if seeing is None: - seeing = {} - seeing[block] = True + seeing = set() + seeing.add(block) for link in block.exits: if link.target in seen: if link.target in seeing: backedges.append(link) else: - seen[link.target] = None + seen.add(link.target) backedges.extend(find_backedges(graph, link.target, seen, seeing)) - del seeing[block] + seeing.remove(block) return backedges def compute_reachability(graph): diff --git a/rpython/translator/c/database.py b/rpython/translator/c/database.py --- a/rpython/translator/c/database.py +++ b/rpython/translator/c/database.py @@ -115,7 +115,7 @@ elif isinstance(T, (Struct, Array, _WeakRefType)): node = self.gettypedefnode(T, varlength=varlength) if who_asks is not None: - who_asks.dependencies[node] = True + who_asks.dependencies.add(node) return node.gettype() elif isinstance(T, FuncType): resulttype = self.gettype(T.RESULT) @@ -136,7 +136,7 @@ elif T.hints.get("render_structure", False): node = self.gettypedefnode(T, varlength=varlength) if who_asks is not None: - who_asks.dependencies[node] = True + who_asks.dependencies.add(node) return 'struct %s @' % node.name elif T.hints.get('external', None) == 'C': return '%s @' % T.hints['c_name'] @@ -364,15 +364,15 @@ def getstructdeflist(self): # return the StructDefNodes sorted according to dependencies result = [] - seen = {} + seen = set() def produce(node): if node not in seen: - deps = node.dependencies.keys() + deps = list(node.dependencies) deps.sort(key=lambda x: x.name) for othernode in deps: produce(othernode) result.append(node) - seen[node] = True + seen.add(node) nodes = self.structdefnodes.values() nodes.sort(key=lambda x: x.name) for node in nodes: diff --git a/rpython/translator/c/funcgen.py b/rpython/translator/c/funcgen.py --- a/rpython/translator/c/funcgen.py +++ b/rpython/translator/c/funcgen.py @@ -184,15 +184,15 @@ def cfunction_declarations(self): # declare the local variables, excluding the function arguments - seen = {} + seen = set() for a in self.graph.getargs(): - seen[a.name] = True + seen.add(a.name) result_by_name = [] for v in self.allvariables(): name = v.name if name not in seen: - seen[name] = True + seen.add(name) result = cdecl(self.lltypename(v), LOCALVAR % name) + ';' if self.lltypemap(v) is Void: continue #result = '/*%s*/' % result diff --git a/rpython/translator/c/gcc/trackgcroot.py b/rpython/translator/c/gcc/trackgcroot.py --- a/rpython/translator/c/gcc/trackgcroot.py +++ b/rpython/translator/c/gcc/trackgcroot.py @@ -342,12 +342,12 @@ def walk_instructions_backwards(self, walker, initial_insn, initial_state): pending = [] - seen = {} + seen = set() def schedule(insn, state): for previnsn in insn.previous_insns: key = previnsn, state if key not in seen: - seen[key] = True + seen.add(key) pending.append(key) schedule(initial_insn, initial_state) while pending: diff --git a/rpython/translator/c/node.py b/rpython/translator/c/node.py --- a/rpython/translator/c/node.py +++ b/rpython/translator/c/node.py @@ -32,13 +32,23 @@ else: return self.fget(obj) +class Node(object): + __slots__ = ("db", ) + def __init__(self, db): + self.db = db -class StructDefNode: +class NodeWithDependencies(Node): + __slots__ = ("dependencies", ) + def __init__(self, db): + Node.__init__(self, db) + self.dependencies = set() + +class StructDefNode(NodeWithDependencies): typetag = 'struct' extra_union_for_varlength = True def __init__(self, db, STRUCT, varlength=1): - self.db = db + NodeWithDependencies.__init__(self, db) self.STRUCT = STRUCT self.LLTYPE = STRUCT self.varlength = varlength @@ -66,7 +76,6 @@ with_number=with_number, bare=True) self.prefix = somelettersfrom(STRUCT._name) + '_' - self.dependencies = {} # self.fieldnames = STRUCT._names if STRUCT._hints.get('typeptr', False): @@ -188,12 +197,12 @@ self.name, cname) -class ArrayDefNode: +class ArrayDefNode(NodeWithDependencies): typetag = 'struct' extra_union_for_varlength = True def __init__(self, db, ARRAY, varlength=1): - self.db = db + NodeWithDependencies.__init__(self, db) self.ARRAY = ARRAY self.LLTYPE = ARRAY self.gcfields = [] @@ -208,7 +217,6 @@ (self.barename, self.name) = db.namespace.uniquename(basename, with_number=with_number, bare=True) - self.dependencies = {} self.fulltypename = '%s %s @' % (self.typetag, self.name) self.fullptrtypename = '%s %s *@' % (self.typetag, self.name) @@ -315,7 +323,7 @@ yield '-1' -class BareBoneArrayDefNode: +class BareBoneArrayDefNode(NodeWithDependencies): """For 'simple' array types which don't need a length nor GC headers. Implemented directly as a C array instead of a struct with an items field. rffi kind of expects such arrays to be 'bare' C arrays. @@ -326,11 +334,10 @@ extra_union_for_varlength = False def __init__(self, db, ARRAY, varlength=1): - self.db = db + NodeWithDependencies.__init__(self, db) self.ARRAY = ARRAY self.LLTYPE = ARRAY self.varlength = varlength - self.dependencies = {} contained_type = ARRAY.OF # There is no such thing as an array of voids: # we use a an array of chars instead; only the pointer can be void*. @@ -379,17 +386,16 @@ yield 'sizeof(%s)' % (cdecl(self.itemtypename, ''),) -class FixedSizeArrayDefNode: +class FixedSizeArrayDefNode(NodeWithDependencies): gcinfo = None name = None typetag = 'struct' extra_union_for_varlength = False def __init__(self, db, FIXEDARRAY): - self.db = db + NodeWithDependencies.__init__(self, db) self.FIXEDARRAY = FIXEDARRAY self.LLTYPE = FIXEDARRAY - self.dependencies = {} self.itemtypename = db.gettype(FIXEDARRAY.OF, who_asks=self) self.fulltypename = self.itemtypename.replace('@', '(@)[%d]' % FIXEDARRAY.length) @@ -456,14 +462,13 @@ return [] -class ExtTypeOpaqueDefNode: +class ExtTypeOpaqueDefNode(NodeWithDependencies): """For OpaqueTypes created with the hint render_structure.""" typetag = 'struct' def __init__(self, db, T): - self.db = db + NodeWithDependencies.__init__(self, db) self.T = T - self.dependencies = {} self.name = 'RPyOpaque_%s' % (T.tag,) def setup(self): @@ -475,7 +480,7 @@ # ____________________________________________________________ -class ContainerNode(object): +class ContainerNode(Node): if USESLOTS: # keep the number of slots down! __slots__ = """db obj typename implementationtypename @@ -485,9 +490,8 @@ eci_name = '_compilation_info' def __init__(self, db, T, obj): - self.db = db + Node.__init__(self, db) self.obj = obj - #self.dependencies = {} self.typename = db.gettype(T) #, who_asks=self) self.implementationtypename = db.gettype(T, varlength=self.getlength()) parent, parentindex = parentlink(obj) @@ -813,8 +817,8 @@ # be necessary def __init__(self, db, T, obj, forcename=None): + Node.__init__(self, db) self.globalcontainer = True - self.db = db self.T = T self.obj = obj callable = getattr(obj, '_callable', None) @@ -827,7 +831,6 @@ self.name = (forcename or db.namespace.uniquename('g_' + self.basename())) self.make_funcgens() - #self.dependencies = {} self.typename = db.gettype(T) #, who_asks=self) def getptrname(self): diff --git a/rpython/translator/exceptiontransform.py b/rpython/translator/exceptiontransform.py --- a/rpython/translator/exceptiontransform.py +++ b/rpython/translator/exceptiontransform.py @@ -284,13 +284,13 @@ return need_exc_matching, n_gen_exc_checks def comes_from_last_exception(self, entrymap, link): - seen = {} + seen = set() pending = [(link, link.args[1])] while pending: link, v = pending.pop() if (link, v) in seen: continue - seen[link, v] = True + seen.add((link, v)) if link.last_exc_value is not None and v is link.last_exc_value: return True block = link.prevblock diff --git a/rpython/translator/gensupp.py b/rpython/translator/gensupp.py --- a/rpython/translator/gensupp.py +++ b/rpython/translator/gensupp.py @@ -3,14 +3,14 @@ Another name could be genEric, but well... """ -def uniquemodulename(name, SEEN={}): +def uniquemodulename(name, SEEN=set()): # never reuse the same module name within a Python session! i = 0 while True: i += 1 result = '%s_%d' % (name, i) if result not in SEEN: - SEEN[result] = True + SEEN.add(result) return result # a translation table suitable for str.translate() to remove diff --git a/rpython/translator/transform.py b/rpython/translator/transform.py --- a/rpython/translator/transform.py +++ b/rpython/translator/transform.py @@ -12,12 +12,12 @@ from rpython.rtyper.lltypesystem import lltype def checkgraphs(self, blocks): - seen = {} + seen = set() for block in blocks: graph = self.annotated[block] if graph not in seen: checkgraph(graph) - seen[graph] = True + seen.add(graph) def fully_annotated_blocks(self): """Ignore blocked blocks.""" From noreply at buildbot.pypy.org Mon Apr 1 22:19:08 2013 From: noreply at buildbot.pypy.org (cfbolz) Date: Mon, 1 Apr 2013 22:19:08 +0200 (CEST) Subject: [pypy-commit] pypy default: don't store arity twice, move bool results as flag on class Message-ID: <20130401201908.806141C0188@cobra.cs.uni-duesseldorf.de> Author: Carl Friedrich Bolz Branch: Changeset: r62913:2619f89c28cc Date: 2013-04-01 22:09 +0200 http://bitbucket.org/pypy/pypy/changeset/2619f89c28cc/ Log: don't store arity twice, move bool results as flag on class diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py --- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py @@ -7,7 +7,7 @@ from rpython.jit.metainterp.history import AbstractDescr, ConstInt, BoxInt from rpython.jit.metainterp.history import TreeLoop from rpython.jit.metainterp import compile, resume -from rpython.jit.metainterp.resoperation import rop, opname, opargnum +from rpython.jit.metainterp.resoperation import rop, opname, oparity from rpython.jit.metainterp.optimizeopt.test.test_optimizebasic import FakeMetaInterpStaticData def test_build_opt_chain(): @@ -188,7 +188,7 @@ if 'FLOAT' in op: continue args = [] - for _ in range(opargnum[opnum]): + for _ in range(oparity[opnum]): args.append(random.randrange(1, 20)) ops = """ [] diff --git a/rpython/jit/metainterp/resoperation.py b/rpython/jit/metainterp/resoperation.py --- a/rpython/jit/metainterp/resoperation.py +++ b/rpython/jit/metainterp/resoperation.py @@ -21,6 +21,7 @@ name = "" pc = 0 opnum = 0 + _cls_has_bool_result = False _attrs_ = ('result',) @@ -172,12 +173,7 @@ return rop._FINAL_FIRST <= self.getopnum() <= rop._FINAL_LAST def returns_bool_result(self): - opnum = self.getopnum() - if we_are_translated(): - assert opnum >= 0 - elif opnum < 0: - return False # for tests - return opboolresult[opnum] + return self._cls_has_bool_result # =================== @@ -550,11 +546,9 @@ pass opclasses = [] # mapping numbers to the concrete ResOp class -opargnum = [] # mapping numbers to number or args (or -1) opname = {} # mapping numbers to the original names, for debugging oparity = [] # mapping numbers to the arity of the operation or -1 opwithdescr = [] # mapping numbers to a flag "takes a descr" -opboolresult= [] # mapping numbers to a flag "returns a boolean" def setup(debug_print=False): @@ -576,14 +570,13 @@ if not name.startswith('_'): opname[i] = name cls = create_class_for_op(name, i, arity, withdescr) + cls._cls_has_bool_result = boolresult else: cls = None opclasses.append(cls) - opargnum.append(arity) oparity.append(arity) opwithdescr.append(withdescr) - opboolresult.append(boolresult) - assert len(opclasses)==len(oparity)==len(opwithdescr)==len(opboolresult)==len(_oplist) + assert len(opclasses)==len(oparity)==len(opwithdescr)==len(_oplist) def get_base_class(mixin, base): try: From noreply at buildbot.pypy.org Mon Apr 1 22:22:08 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Mon, 1 Apr 2013 22:22:08 +0200 (CEST) Subject: [pypy-commit] pypy py3k: merge default Message-ID: <20130401202209.006A01C01A0@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r62914:eef0f65d771e Date: 2013-04-01 13:21 -0700 http://bitbucket.org/pypy/pypy/changeset/eef0f65d771e/ Log: merge default diff too long, truncating to 2000 out of 4479 lines diff --git a/.tddium.requirements.txt b/.tddium.requirements.txt new file mode 100644 --- /dev/null +++ b/.tddium.requirements.txt @@ -0,0 +1,1 @@ +pytest diff --git a/pypy/config/test/test_pypyoption.py b/pypy/config/test/test_pypyoption.py --- a/pypy/config/test/test_pypyoption.py +++ b/pypy/config/test/test_pypyoption.py @@ -11,11 +11,11 @@ assert conf.objspace.usemodules.gc - conf.objspace.std.withsmallint = True - assert not conf.objspace.std.withprebuiltint + conf.objspace.std.withmapdict = True + assert conf.objspace.std.withmethodcache conf = get_pypy_config() - conf.objspace.std.withprebuiltint = True - py.test.raises(ConfigError, "conf.objspace.std.withsmallint = True") + conf.objspace.std.withmethodcache = False + py.test.raises(ConfigError, "conf.objspace.std.withmapdict = True") def test_conflicting_gcrootfinder(): conf = get_pypy_config() diff --git a/pypy/doc/arm.rst b/pypy/doc/arm.rst --- a/pypy/doc/arm.rst +++ b/pypy/doc/arm.rst @@ -145,7 +145,7 @@ :: - pypy ~/path_to_pypy_checkout/rpython/translator/goal/translate.py -O1 --platform=arm target.py + pypy ~/path_to_pypy_checkout/rpython/bin/rpython -O1 --platform=arm target.py If everything worked correctly this should yield an ARM binary. Running this binary in the ARM chroot or on an ARM device should produce the output ``"Hello World"``. @@ -153,7 +153,7 @@ :: - pypy /rpython/translator/goal/translate.py -Ojit --platform=arm --gcrootfinder=shadowstack --jit-backend=arm targetpypystandalone.py + pypy /rpython/bin/rpython -Ojit --platform=arm --gcrootfinder=shadowstack --jit-backend=armv7 targetpypystandalone.py The gcrootfinder option is needed to work around `issue 1377`_ and the jit-backend works around `issue 1376`_ diff --git a/pypy/doc/config/objspace.std.withsmallint.txt b/pypy/doc/config/objspace.std.withsmallint.txt deleted file mode 100644 --- a/pypy/doc/config/objspace.std.withsmallint.txt +++ /dev/null @@ -1,6 +0,0 @@ -Use "tagged pointers" to represent small enough integer values: Integers that -fit into 31 bits (respective 63 bits on 64 bit machines) are not represented by -boxing them in an instance of ``W_IntObject``. Instead they are represented as a -pointer having the lowest bit set and the rest of the bits used to store the -value of the integer. This gives a small speedup for integer operations as well -as better memory behaviour. diff --git a/pypy/doc/config/translation.taggedpointers.txt b/pypy/doc/config/translation.taggedpointers.txt --- a/pypy/doc/config/translation.taggedpointers.txt +++ b/pypy/doc/config/translation.taggedpointers.txt @@ -1,3 +1,3 @@ Enable tagged pointers. This option is mostly useful for the Smalltalk and Prolog interpreters. For the Python interpreter the option -:config:`objspace.std.withsmallint` should be used. +:config:`objspace.std.withsmalllong` should be used. diff --git a/pypy/doc/interpreter-optimizations.rst b/pypy/doc/interpreter-optimizations.rst --- a/pypy/doc/interpreter-optimizations.rst +++ b/pypy/doc/interpreter-optimizations.rst @@ -55,7 +55,7 @@ them from normal pointers. This completely avoids the boxing step, saving time and memory. -You can enable this feature with the :config:`objspace.std.withsmallint` option. +You can enable this feature with the :config:`objspace.std.withsmalllong` option. Dictionary Optimizations ------------------------ diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -42,6 +42,10 @@ .. branch: rpython-bytearray Rudimentary support for bytearray in RPython +.. branch: refactor-call_release_gil +Fix a bug which casused cffi to return the wrong result when calling a C +function which calls a Python callback which forces the frames + .. branches we don't care about .. branch: autoreds .. branch: reflex-support diff --git a/pypy/interpreter/function.py b/pypy/interpreter/function.py --- a/pypy/interpreter/function.py +++ b/pypy/interpreter/function.py @@ -22,7 +22,6 @@ assert not func.can_change_code return func.code - class Function(W_Root): """A function is a code object captured with some environment: an object space, a dictionary of globals, default arguments, diff --git a/pypy/interpreter/gateway.py b/pypy/interpreter/gateway.py --- a/pypy/interpreter/gateway.py +++ b/pypy/interpreter/gateway.py @@ -830,6 +830,8 @@ d = {} exec func_code.compile() in d f = d['f'] + f.__module__ = func.__module__ + # necessary for unique identifiers for pickling f.func_name = func.func_name if unwrap_spec is None: unwrap_spec = {} @@ -896,9 +898,9 @@ for i, (name, defaultval) in enumerate(self._staticdefs): if name.startswith('w_'): assert defaultval is None, ( - "%s: default value for '%s' can only be None; " + "%s: default value for '%s' can only be None, got %r; " "use unwrap_spec(...=WrappedDefault(default))" % ( - self._code.identifier, name)) + self._code.identifier, name, defaultval)) defs_w.append(None) else: spec = unwrap_spec[i] diff --git a/pypy/module/__builtin__/functional.py b/pypy/module/__builtin__/functional.py --- a/pypy/module/__builtin__/functional.py +++ b/pypy/module/__builtin__/functional.py @@ -293,6 +293,7 @@ __next__ = interp2app(W_ReversedIterator.descr_next), __reduce__ = interp2app(W_ReversedIterator.descr___reduce__), ) +W_ReversedIterator.typedef.acceptable_as_base_class = False # exported through _pickle_support def _make_reversed(space, w_seq, w_remaining): @@ -460,6 +461,7 @@ count = interp2app(W_Range.descr_count), index = interp2app(W_Range.descr_index), ) +W_Range.typedef.acceptable_as_base_class = False class W_RangeIterator(W_Root): def __init__(self, space, w_start, w_step, w_len, w_index=None): @@ -503,6 +505,7 @@ __next__ = interp2app(W_RangeIterator.descr_next), __reduce__ = interp2app(W_RangeIterator.descr_reduce), ) +W_RangeIterator.typedef.acceptable_as_base_class = False class W_Map(W_Root): diff --git a/pypy/module/_bisect/__init__.py b/pypy/module/_bisect/__init__.py deleted file mode 100644 --- a/pypy/module/_bisect/__init__.py +++ /dev/null @@ -1,27 +0,0 @@ -""" -Mixed-module definition for the _bisect module. -This is an optional module; if not present, bisect.py uses the -pure Python version of these functions. -""" - -from pypy.interpreter.mixedmodule import MixedModule - - -class Module(MixedModule): - """\ -This module provides support for maintaining a list in sorted order without -having to sort the list after each insertion. For long lists of items with -expensive comparison operations, this can be an improvement over the more -common approach.""" - - appleveldefs = { - 'insort': 'app_bisect.insort_right', - 'insort_left': 'app_bisect.insort_left', - 'insort_right': 'app_bisect.insort_right', - } - - interpleveldefs = { - 'bisect': 'interp_bisect.bisect_right', - 'bisect_left': 'interp_bisect.bisect_left', - 'bisect_right': 'interp_bisect.bisect_right', - } diff --git a/pypy/module/_bisect/app_bisect.py b/pypy/module/_bisect/app_bisect.py deleted file mode 100644 --- a/pypy/module/_bisect/app_bisect.py +++ /dev/null @@ -1,23 +0,0 @@ -from _bisect import bisect_left, bisect_right - - -def insort_left(a, x, lo=0, hi=-1): - """Insert item x in list a, and keep it sorted assuming a is sorted. - -If x is already in a, insert it to the left of the leftmost x. - -Optional args lo (default 0) and hi (default len(a)) bound the -slice of a to be searched.""" - n = bisect_left(a, x, lo, hi) - a.insert(n, x) - - -def insort_right(a, x, lo=0, hi=-1): - """Insert item x in list a, and keep it sorted assuming a is sorted. - -If x is already in a, insert it to the right of the rightmost x. - -Optional args lo (default 0) and hi (default len(a)) bound the -slice of a to be searched.""" - n = bisect_right(a, x, lo, hi) - a.insert(n, x) diff --git a/pypy/module/_bisect/interp_bisect.py b/pypy/module/_bisect/interp_bisect.py deleted file mode 100644 --- a/pypy/module/_bisect/interp_bisect.py +++ /dev/null @@ -1,53 +0,0 @@ -from pypy.interpreter.error import OperationError -from pypy.interpreter.gateway import unwrap_spec -from rpython.rlib.rarithmetic import intmask, r_uint - - - at unwrap_spec(lo=int, hi=int) -def bisect_left(space, w_a, w_x, lo=0, hi=-1): - """Return the index where to insert item x in list a, assuming a is sorted. - -The return value i is such that all e in a[:i] have e < x, and all e in -a[i:] have e >= x. So if x already appears in the list, i points just -before the leftmost x already there. - -Optional args lo (default 0) and hi (default len(a)) bound the -slice of a to be searched.""" - if lo < 0: - raise OperationError(space.w_ValueError, - space.wrap("lo must be non-negative")) - if hi == -1: - hi = space.len_w(w_a) - while lo < hi: - mid = intmask((r_uint(lo) + r_uint(hi)) >> 1) - w_litem = space.getitem(w_a, space.wrap(mid)) - if space.is_true(space.lt(w_litem, w_x)): - lo = mid + 1 - else: - hi = mid - return space.wrap(lo) - - - at unwrap_spec(lo=int, hi=int) -def bisect_right(space, w_a, w_x, lo=0, hi=-1): - """Return the index where to insert item x in list a, assuming a is sorted. - -The return value i is such that all e in a[:i] have e <= x, and all e in -a[i:] have e > x. So if x already appears in the list, i points just -beyond the rightmost x already there - -Optional args lo (default 0) and hi (default len(a)) bound the -slice of a to be searched.""" - if lo < 0: - raise OperationError(space.w_ValueError, - space.wrap("lo must be non-negative")) - if hi == -1: - hi = space.len_w(w_a) - while lo < hi: - mid = intmask((r_uint(lo) + r_uint(hi)) >> 1) - w_litem = space.getitem(w_a, space.wrap(mid)) - if space.is_true(space.lt(w_x, w_litem)): - hi = mid - else: - lo = mid + 1 - return space.wrap(lo) diff --git a/pypy/module/_bisect/test/__init__.py b/pypy/module/_bisect/test/__init__.py deleted file mode 100644 diff --git a/pypy/module/_bisect/test/test_bisect.py b/pypy/module/_bisect/test/test_bisect.py deleted file mode 100644 --- a/pypy/module/_bisect/test/test_bisect.py +++ /dev/null @@ -1,98 +0,0 @@ - -class AppTestBisect: - spaceconfig = dict(usemodules=['_bisect']) - - def test_bisect_left(self): - from _bisect import bisect_left - a = [0, 5, 6, 6, 6, 7] - assert bisect_left(a, -3) == 0 - assert bisect_left(a, 0) == 0 - assert bisect_left(a, 3) == 1 - assert bisect_left(a, 5) == 1 - assert bisect_left(a, 5.5) == 2 - assert bisect_left(a, 6) == 2 - assert bisect_left(a, 6.0) == 2 - assert bisect_left(a, 6.1) == 5 - assert bisect_left(a, 7) == 5 - assert bisect_left(a, 8) == 6 - a = [] - assert bisect_left(a, 123) == 0 - a = [9] - assert bisect_left(a, -123) == 0 - assert bisect_left(a, 9) == 0 - assert bisect_left(a, 123) == 1 - a = [9, 9] - assert bisect_left(a, -123) == 0 - assert bisect_left(a, 9) == 0 - assert bisect_left(a, 123) == 2 - a = [4, 6, 6, 9] - assert bisect_left(a, 6, 0) == 1 - assert bisect_left(a, 6, 1) == 1 - assert bisect_left(a, 6, 2) == 2 - assert bisect_left(a, 6, 3) == 3 - assert bisect_left(a, 6, 4) == 4 - assert bisect_left(a, 6, 0, 0) == 0 - assert bisect_left(a, 6, 0, 1) == 1 - assert bisect_left(a, 6, 0, 2) == 1 - assert bisect_left(a, 6, 0, 3) == 1 - assert bisect_left(a, 6, 0, 4) == 1 - - raises(ValueError, bisect_left, [1, 2, 3], 5, -1, 3) - - def test_bisect_right(self): - from _bisect import bisect_right - a = [0, 5, 6, 6, 6, 7] - assert bisect_right(a, -3) == 0 - assert bisect_right(a, 0) == 1 - assert bisect_right(a, 3) == 1 - assert bisect_right(a, 5) == 2 - assert bisect_right(a, 5.5) == 2 - assert bisect_right(a, 6) == 5 - assert bisect_right(a, 6.0) == 5 - assert bisect_right(a, 6.1) == 5 - assert bisect_right(a, 7) == 6 - assert bisect_right(a, 8) == 6 - a = [] - assert bisect_right(a, 123) == 0 - a = [9] - assert bisect_right(a, -123) == 0 - assert bisect_right(a, 9) == 1 - assert bisect_right(a, 123) == 1 - a = [9, 9] - assert bisect_right(a, -123) == 0 - assert bisect_right(a, 9) == 2 - assert bisect_right(a, 123) == 2 - a = [4, 6, 6, 9] - assert bisect_right(a, 6, 0) == 3 - assert bisect_right(a, 6, 1) == 3 - assert bisect_right(a, 6, 2) == 3 - assert bisect_right(a, 6, 3) == 3 - assert bisect_right(a, 6, 4) == 4 - assert bisect_right(a, 6, 0, 0) == 0 - assert bisect_right(a, 6, 0, 1) == 1 - assert bisect_right(a, 6, 0, 2) == 2 - assert bisect_right(a, 6, 0, 3) == 3 - assert bisect_right(a, 6, 0, 4) == 3 - - def test_insort_left(self): - from _bisect import insort_left - a = [0, 5, 6, 6, 6, 7] - insort_left(a, 6.0) - assert a == [0, 5, 6.0, 6, 6, 6, 7] - assert list(map(type, a)) == [int, int, float, int, int, int, int] - - def test_insort_right(self): - from _bisect import insort_right - a = [0, 5, 6, 6, 6, 7] - insort_right(a, 6.0) - assert a == [0, 5, 6, 6, 6, 6.0, 7] - assert list(map(type, a)) == [int, int, int, int, int, float, int] - - def test_bisect_overflow(self): - from _bisect import bisect_left, bisect_right - import sys - - size = sys.maxsize - data = range(size - 1) - assert bisect_left(data, size - 3) == size - 3 - assert bisect_right(data, size - 3) == size - 2 diff --git a/pypy/module/_bisect/test/test_ztranslation.py b/pypy/module/_bisect/test/test_ztranslation.py deleted file mode 100644 --- a/pypy/module/_bisect/test/test_ztranslation.py +++ /dev/null @@ -1,4 +0,0 @@ -from pypy.objspace.fake.checkmodule import checkmodule - -def test_checkmodule(): - checkmodule('_bisect') diff --git a/pypy/module/_cffi_backend/cdataobj.py b/pypy/module/_cffi_backend/cdataobj.py --- a/pypy/module/_cffi_backend/cdataobj.py +++ b/pypy/module/_cffi_backend/cdataobj.py @@ -91,20 +91,15 @@ space = self.space cdata1 = self._cdata if isinstance(w_other, W_CData): - if requires_ordering: - if (isinstance(self.ctype, W_CTypePrimitive) or - isinstance(w_other.ctype, W_CTypePrimitive)): - raise OperationError(space.w_TypeError, - space.wrap("cannot do comparison on a " - "primitive cdata")) cdata2 = w_other._cdata - elif (misc.is_zero(space, w_other) and - not isinstance(self.ctype, W_CTypePrimitive)): - cdata2 = lltype.nullptr(rffi.CCHARP.TO) else: return space.w_NotImplemented if requires_ordering: + if (isinstance(self.ctype, W_CTypePrimitive) or + isinstance(w_other.ctype, W_CTypePrimitive)): + raise OperationError(space.w_TypeError, + space.wrap("cannot do comparison on a primitive cdata")) cdata1 = rffi.cast(lltype.Unsigned, cdata1) cdata2 = rffi.cast(lltype.Unsigned, cdata2) return space.newbool(op(cdata1, cdata2)) diff --git a/pypy/module/_cffi_backend/ctypeptr.py b/pypy/module/_cffi_backend/ctypeptr.py --- a/pypy/module/_cffi_backend/ctypeptr.py +++ b/pypy/module/_cffi_backend/ctypeptr.py @@ -154,10 +154,6 @@ def convert_from_object(self, cdata, w_ob): space = self.space if not isinstance(w_ob, cdataobj.W_CData): - if misc.is_zero(space, w_ob): - NULL = lltype.nullptr(rffi.CCHARP.TO) - rffi.cast(rffi.CCHARPP, cdata)[0] = NULL - return raise self._convert_error("cdata pointer", w_ob) other = w_ob.ctype if not isinstance(other, W_CTypePtrBase): @@ -259,15 +255,7 @@ def _prepare_pointer_call_argument(self, w_init, cdata): space = self.space - if misc.is_zero(space, w_init): - # Convert 0 to NULL. Note that passing 0 is not ambigous, - # despite the potential confusion: as a 'T*' argument, 0 means - # NULL, but as a 'T[]' argument it would mean "array of size 0" - # --- except that we specifically refuse to interpret numbers - # as the array size when passing arguments. - rffi.cast(rffi.CCHARPP, cdata)[0] = lltype.nullptr(rffi.CCHARP.TO) - return 3 - elif (space.isinstance_w(w_init, space.w_list) or + if (space.isinstance_w(w_init, space.w_list) or space.isinstance_w(w_init, space.w_tuple)): length = space.int_w(space.len(w_init)) elif (space.isinstance_w(w_init, space.w_unicode) or diff --git a/pypy/module/_cffi_backend/misc.py b/pypy/module/_cffi_backend/misc.py --- a/pypy/module/_cffi_backend/misc.py +++ b/pypy/module/_cffi_backend/misc.py @@ -208,9 +208,6 @@ neg_msg = "can't convert negative number to unsigned" ovf_msg = "long too big to convert" -def is_zero(space, w_ob): - return space.isinstance_w(w_ob, space.w_int) and not space.is_true(w_ob) - # ____________________________________________________________ class _NotStandardObject(Exception): diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py --- a/pypy/module/_cffi_backend/test/_backend_test_c.py +++ b/pypy/module/_cffi_backend/test/_backend_test_c.py @@ -387,19 +387,8 @@ assert (x != None) is True assert (x == ["hello"]) is False assert (x != ["hello"]) is True - -def test_cmp_pointer_with_0(): - p = new_pointer_type(new_primitive_type("int")) - x = cast(p, 0) - assert (x == 0) is True - assert (x != 0) is False - assert (0 == x) is True - assert (0 != x) is False - y = cast(p, 42) - assert (y == 0) is False - assert (y != 0) is True - assert (0 == y) is False - assert (0 != y) is True + y = cast(p, 0) + assert (y == None) is False def test_invalid_indexing(): p = new_primitive_type("int") @@ -779,7 +768,7 @@ assert s.a2 == 456 assert s.a3 == 0 assert s.p4 == cast(BVoidP, 0) - assert s.p4 == 0 + assert s.p4 != 0 # s = newp(BStructPtr, {'a2': 41122, 'a3': -123}) assert s.a1 == 0 @@ -792,14 +781,11 @@ p = newp(BIntPtr, 14141) s = newp(BStructPtr, [12, 34, 56, p]) assert s.p4 == p - s.p4 = 0 - assert s.p4 == 0 + assert s.p4 # s = newp(BStructPtr, [12, 34, 56, cast(BVoidP, 0)]) - assert s.p4 == 0 - # - s = newp(BStructPtr, [12, 34, 56, 0]) assert s.p4 == cast(BVoidP, 0) + assert not s.p4 # py.test.raises(TypeError, newp, BStructPtr, [12, 34, 56, None]) @@ -1017,11 +1003,10 @@ f = cast(BFunc23, _testfunc(23)) res = f(b"foo") assert res == 1000 * ord(b'f') - res = f(0) # NULL - assert res == -42 - res = f(long(0)) # NULL + res = f(cast(BVoidP, 0)) # NULL assert res == -42 py.test.raises(TypeError, f, None) + py.test.raises(TypeError, f, 0) py.test.raises(TypeError, f, 0.0) def test_call_function_23_bis(): @@ -2277,6 +2262,7 @@ def test_longdouble(): py_py = 'PY_DOT_PY' in globals() + BInt = new_primitive_type("int") BLongDouble = new_primitive_type("long double") BLongDoublePtr = new_pointer_type(BLongDouble) BLongDoubleArray = new_array_type(BLongDoublePtr, None) @@ -2294,21 +2280,23 @@ assert float(x) == 1.23 assert int(x) == 1 # - BFunc19 = new_function_type((BLongDouble,), BLongDouble) + BFunc19 = new_function_type((BLongDouble, BInt), BLongDouble) f = cast(BFunc19, _testfunc(19)) - start = 8 + start = lstart = 1.5 for i in range(107): - start = f(start) - if sizeof(BLongDouble) > sizeof(new_primitive_type("double")): - if not py_py: - assert repr(start).startswith("") - # - c = newp(BLongDoubleArray, [start]) - x = c[0] - if not py_py: - assert repr(x).endswith("E+902>") - assert float(x) == float("inf") + start = 4 * start - start * start + lstart = f(lstart, 1) + lother = f(1.5, 107) + if not py_py: + assert float(lstart) == float(lother) + assert repr(lstart) == repr(lother) + if sizeof(BLongDouble) > sizeof(new_primitive_type("double")): + assert float(lstart) != start + assert repr(lstart).startswith("a1 + (int)ptr->a2; } -static long double _testfunc19(long double x) +static long double _testfunc19(long double x, int count) { int i; - for (i=0; i<28; i++) - x += x; + for (i=0; i 0: diff --git a/pypy/module/pypyjit/test_pypy_c/test_call.py b/pypy/module/pypyjit/test_pypy_c/test_call.py --- a/pypy/module/pypyjit/test_pypy_c/test_call.py +++ b/pypy/module/pypyjit/test_pypy_c/test_call.py @@ -339,6 +339,7 @@ loop, = log.loops_by_filename(self.filepath) # the int strategy is used here assert loop.match_by_id('append', """ + guard_not_invalidated(descr=...) i13 = getfield_gc(p8, descr=) i15 = int_add(i13, 1) # Will be killed by the backend @@ -581,7 +582,7 @@ d = {'a': 2, 'b': 3, 'd':4} f(*a, **d) # ID: call i += 1 - return 13 + return 13 """, [1000]) loop, = log.loops_by_id('call') assert loop.match_by_id('call', ''' @@ -602,7 +603,7 @@ while i < stop: f(*a, **d) # ID: call i += 1 - return 13 + return 13 """, [1000]) def test_complex_case_loopconst(self): @@ -617,5 +618,5 @@ while i < stop: f(*a, **d) # ID: call i += 1 - return 13 + return 13 """, [1000]) diff --git a/pypy/module/pypyjit/test_pypy_c/test_jitlogparser.py b/pypy/module/pypyjit/test_pypy_c/test_jitlogparser.py new file mode 100644 --- /dev/null +++ b/pypy/module/pypyjit/test_pypy_c/test_jitlogparser.py @@ -0,0 +1,76 @@ +import re + +from rpython.tool.logparser import extract_category + +from pypy.tool.jitlogparser.parser import (import_log, parse_log_counts, + mangle_descr) +from pypy.module.pypyjit.test_pypy_c.test_00_model import BaseTestPyPyC + + +class TestLogParser(BaseTestPyPyC): + log_string = 'jit-log-opt,jit-backend' + + def test(self): + def fn_with_bridges(N): + def is_prime(x): + for y in xrange(2, x): + if x % y == 0: + return False + return True + result = 0 + for x in xrange(N): + if x % 3 == 0: + result += 5 + elif x % 5 == 0: + result += 3 + elif is_prime(x): + result += x + elif x == 99: + result *= 2 + return result + # + N = 10000 + _log = self.run(fn_with_bridges, [N]) + log, loops = import_log(_log.logfile) + parse_log_counts(extract_category(log, 'jit-backend-count'), loops) + + is_prime_loops = [] + fn_with_bridges_loops = [] + bridges = {} + + lib_re = re.compile("file '.*lib-python.*'") + for loop in loops: + if hasattr(loop, 'force_asm'): + loop.force_asm() + if lib_re.search(loop.comment) or \ + lib_re.search(loop.operations[0].repr()): + # do not care for _optimize_charset or _mk_bitmap + continue + assert loop.count > 0 + if ' is_prime, ' in loop.comment: + is_prime_loops.append(loop) + elif ' fn_with_bridges, ' in loop.comment: + fn_with_bridges_loops.append(loop) + else: + assert ' bridge ' in loop.comment + key = mangle_descr(loop.descr) + assert key not in bridges + bridges[key] = loop + + by_count = lambda l: -l.count + is_prime_loops.sort(key=by_count) + fn_with_bridges_loops.sort(key=by_count) + + # check that we can find bridges corresponding to " % 3" and " % 5" + mod_bridges = [] + for op in fn_with_bridges_loops[0].operations: + if op.descr is not None: + bridge = bridges.get(mangle_descr(op.descr)) + if bridge is not None: + mod_bridges.append(bridge) + assert len(mod_bridges) == 2 + + # check that counts are reasonable (precise # may change in the future) + assert N - 2000 < sum(l.count for l in fn_with_bridges_loops) < N + + diff --git a/pypy/module/zipimport/test/test_zipimport.py b/pypy/module/zipimport/test/test_zipimport.py --- a/pypy/module/zipimport/test/test_zipimport.py +++ b/pypy/module/zipimport/test/test_zipimport.py @@ -52,7 +52,7 @@ w_co = space.call_method(space.builtin, 'compile', w(source), w('uuu.py'), w('exec')) - tmpdir = udir.ensure('zipimport_%s' % cls.__name__, dir=1) + tmpdir = udir.ensure('zipimport_%s_%s' % (__name__, cls.__name__), dir=1) now = time.time() cls.w_now = w(now) test_pyc = cls.make_pyc(space, w_co, now) diff --git a/pypy/module/zipimport/test/test_zipimport_deflated.py b/pypy/module/zipimport/test/test_zipimport_deflated.py new file mode 100644 --- /dev/null +++ b/pypy/module/zipimport/test/test_zipimport_deflated.py @@ -0,0 +1,18 @@ +import py + +from zipfile import ZIP_DEFLATED + +from pypy.module.zipimport.test.test_zipimport import AppTestZipimport as Base + +class AppTestZipimportDeflated(Base): + compression = ZIP_DEFLATED + spaceconfig = { + "usemodules": ['zipimport', 'zlib', 'rctime', 'struct', 'itertools', 'binascii'], + } + + def setup_class(cls): + try: + import rpython.rlib.rzlib + except ImportError: + py.test.skip("zlib not available, cannot test compressed zipfiles") + cls.make_class() diff --git a/pypy/objspace/std/dictmultiobject.py b/pypy/objspace/std/dictmultiobject.py --- a/pypy/objspace/std/dictmultiobject.py +++ b/pypy/objspace/std/dictmultiobject.py @@ -12,6 +12,8 @@ from rpython.rlib import rerased, jit +UNROLL_CUTOFF = 5 + def _is_str(space, w_key): return space.is_w(space.type(w_key), space.w_str) @@ -35,7 +37,7 @@ an actual dict """ return jit.isvirtual(w_dct) or (jit.isconstant(w_dct) and - w_dct.length() <= jit.UNROLL_CUTOFF) + w_dct.length() <= UNROLL_CUTOFF) class W_DictMultiObject(W_Object): diff --git a/pypy/objspace/std/floatobject.py b/pypy/objspace/std/floatobject.py --- a/pypy/objspace/std/floatobject.py +++ b/pypy/objspace/std/floatobject.py @@ -1,7 +1,7 @@ import operator -from pypy.interpreter import gateway from pypy.interpreter.error import OperationError from pypy.objspace.std import model, newformat +from pypy.objspace.std.floattype import float_typedef, W_AbstractFloatObject from pypy.objspace.std.multimethod import FailedToImplementArgs from pypy.objspace.std.model import registerimplementation, W_Object from pypy.objspace.std.register_all import register_all @@ -22,36 +22,13 @@ HASH_INF = 314159 HASH_NAN = 0 -class W_AbstractFloatObject(W_Object): - __slots__ = () - - def is_w(self, space, w_other): - from rpython.rlib.longlong2float import float2longlong - if not isinstance(w_other, W_AbstractFloatObject): - return False - if self.user_overridden_class or w_other.user_overridden_class: - return self is w_other - one = float2longlong(space.float_w(self)) - two = float2longlong(space.float_w(w_other)) - return one == two - - def immutable_unique_id(self, space): - if self.user_overridden_class: - return None - from rpython.rlib.longlong2float import float2longlong - from pypy.objspace.std.model import IDTAG_FLOAT as tag - val = float2longlong(space.float_w(self)) - b = rbigint.fromrarith_int(val) - b = b.lshift(3).or_(rbigint.fromint(tag)) - return space.newlong_from_rbigint(b) - - class W_FloatObject(W_AbstractFloatObject): """This is a implementation of the app-level 'float' type. The constructor takes an RPython float as an argument.""" - from pypy.objspace.std.floattype import float_typedef as typedef _immutable_fields_ = ['floatval'] + typedef = float_typedef + def __init__(w_self, floatval): w_self.floatval = floatval @@ -62,6 +39,9 @@ return self.floatval def int(self, space): + if (type(self) is not W_FloatObject and + space.is_overloaded(self, space.w_float, '__int__')): + return W_Object.int(self, space) try: value = ovfcheck_float_to_int(self.floatval) except OverflowError: diff --git a/pypy/objspace/std/floattype.py b/pypy/objspace/std/floattype.py --- a/pypy/objspace/std/floattype.py +++ b/pypy/objspace/std/floattype.py @@ -3,13 +3,15 @@ from rpython.rlib.unroll import unrolling_iterable from rpython.rlib import rfloat, rarithmetic from pypy.interpreter import typedef -from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault -from pypy.interpreter.baseobjspace import ObjSpace, W_Root +from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault,\ + interpindirect2app from pypy.interpreter.error import OperationError from pypy.objspace.std.register_all import register_all from pypy.objspace.std.stdtypedef import StdTypeDef, SMM from pypy.objspace.std.strutil import ParseStringError from pypy.objspace.std.strutil import string_to_float +from pypy.objspace.std.model import W_Object +from rpython.rlib.rbigint import rbigint float_as_integer_ratio = SMM("as_integer_ratio", 1) @@ -312,6 +314,32 @@ # ____________________________________________________________ +class W_AbstractFloatObject(W_Object): + __slots__ = () + + def is_w(self, space, w_other): + from rpython.rlib.longlong2float import float2longlong + if not isinstance(w_other, W_AbstractFloatObject): + return False + if self.user_overridden_class or w_other.user_overridden_class: + return self is w_other + one = float2longlong(space.float_w(self)) + two = float2longlong(space.float_w(w_other)) + return one == two + + def immutable_unique_id(self, space): + if self.user_overridden_class: + return None + from rpython.rlib.longlong2float import float2longlong + from pypy.objspace.std.model import IDTAG_FLOAT as tag + val = float2longlong(space.float_w(self)) + b = rbigint.fromrarith_int(val) + b = b.lshift(3).or_(rbigint.fromint(tag)) + return space.newlong_from_rbigint(b) + + def int(self, space): + raise NotImplementedError + float_typedef = StdTypeDef("float", __doc__ = '''float(x) -> floating point number @@ -323,5 +351,6 @@ conjugate = interp2app(descr_conjugate), real = typedef.GetSetProperty(descr_get_real), imag = typedef.GetSetProperty(descr_get_imag), + __int__ = interpindirect2app(W_AbstractFloatObject.int), ) float_typedef.registermethods(globals()) diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py --- a/pypy/objspace/std/listobject.py +++ b/pypy/objspace/std/listobject.py @@ -18,6 +18,7 @@ from pypy.objspace.std.stdtypedef import StdTypeDef, SMM from sys import maxint +UNROLL_CUTOFF = 5 class W_AbstractListObject(W_Object): __slots__ = () @@ -42,7 +43,7 @@ return W_ListObject.from_storage_and_strategy(space, storage, strategy) @jit.look_inside_iff(lambda space, list_w, sizehint: - jit.loop_unrolling_heuristic(list_w, len(list_w))) + jit.loop_unrolling_heuristic(list_w, len(list_w), UNROLL_CUTOFF)) def get_strategy_from_list_objects(space, list_w, sizehint): if not list_w: if sizehint != -1: @@ -961,7 +962,7 @@ raise NotImplementedError("abstract base class") @jit.look_inside_iff(lambda space, w_list, list_w: - jit.loop_unrolling_heuristic(list_w, len(list_w))) + jit.loop_unrolling_heuristic(list_w, len(list_w), UNROLL_CUTOFF)) def init_from_list_w(self, w_list, list_w): l = [self.unwrap(w_item) for w_item in list_w] w_list.lstorage = self.erase(l) @@ -1010,7 +1011,7 @@ return self.wrap(r) @jit.look_inside_iff(lambda self, w_list: - jit.loop_unrolling_heuristic(w_list, w_list.length())) + jit.loop_unrolling_heuristic(w_list, w_list.length(), UNROLL_CUTOFF)) def getitems_copy(self, w_list): return [self.wrap(item) for item in self.unerase(w_list.lstorage)] @@ -1019,7 +1020,7 @@ return [self.wrap(item) for item in self.unerase(w_list.lstorage)] @jit.look_inside_iff(lambda self, w_list: - jit.loop_unrolling_heuristic(w_list, w_list.length())) + jit.loop_unrolling_heuristic(w_list, w_list.length(), UNROLL_CUTOFF)) def getitems_fixedsize(self, w_list): return self.getitems_unroll(w_list) @@ -1455,8 +1456,8 @@ return w_list def list_unroll_condition(space, w_list1, w_list2): - return jit.loop_unrolling_heuristic(w_list1, w_list1.length()) or \ - jit.loop_unrolling_heuristic(w_list2, w_list2.length()) + return jit.loop_unrolling_heuristic(w_list1, w_list1.length(), UNROLL_CUTOFF) or \ + jit.loop_unrolling_heuristic(w_list2, w_list2.length(), UNROLL_CUTOFF) @jit.look_inside_iff(list_unroll_condition) def eq__List_List(space, w_list1, w_list2): diff --git a/pypy/objspace/std/longobject.py b/pypy/objspace/std/longobject.py --- a/pypy/objspace/std/longobject.py +++ b/pypy/objspace/std/longobject.py @@ -6,14 +6,16 @@ from pypy.objspace.std.multimethod import FailedToImplementArgs from pypy.objspace.std.intobject import W_IntObject, W_AbstractIntObject from pypy.objspace.std.noneobject import W_NoneObject -from rpython.rlib.rbigint import rbigint, SHIFT +from rpython.rlib.rbigint import rbigint +from pypy.objspace.std.longtype import long_typedef class W_LongObject(W_AbstractIntObject): """This is a wrapper of rbigint.""" - from pypy.objspace.std.longtype import long_typedef as typedef _immutable_fields_ = ['num'] + typedef = long_typedef + def __init__(w_self, l): w_self.num = l # instance of rbigint diff --git a/pypy/objspace/std/longtype.py b/pypy/objspace/std/longtype.py --- a/pypy/objspace/std/longtype.py +++ b/pypy/objspace/std/longtype.py @@ -1,8 +1,8 @@ from pypy.interpreter.error import OperationError from pypy.interpreter import typedef -from pypy.interpreter.gateway import (applevel, interp2app, unwrap_spec, - WrappedDefault) -from pypy.objspace.std.register_all import register_all +from pypy.interpreter.gateway import ( + WrappedDefault, applevel, interp2app, interpindirect2app, unwrap_spec) +from pypy.objspace.std.model import W_Object from pypy.objspace.std.stdtypedef import StdTypeDef, SMM from pypy.objspace.std.strutil import string_to_bigint, ParseStringError from rpython.rlib.rbigint import rbigint, InvalidEndiannessError, InvalidSignednessError @@ -62,7 +62,7 @@ try: strval = space.bufferstr_w(w_value) s = strval.decode('latin-1') - except OperationError, e: + except OperationError: raise OperationError(space.w_TypeError, space.wrap("long() can't convert non-string " "with explicit base")) @@ -201,6 +201,30 @@ # ____________________________________________________________ +class W_AbstractLongObject(W_Object): + __slots__ = () + + def is_w(self, space, w_other): + if not isinstance(w_other, W_AbstractLongObject): + return False + if self.user_overridden_class or w_other.user_overridden_class: + return self is w_other + return space.bigint_w(self).eq(space.bigint_w(w_other)) + + def immutable_unique_id(self, space): + if self.user_overridden_class: + return None + from pypy.objspace.std.model import IDTAG_LONG as tag + b = space.bigint_w(self) + b = b.lshift(3).or_(rbigint.fromint(tag)) + return space.newlong_from_rbigint(b) + + def unwrap(w_self, space): #YYYYYY + return w_self.longval() + + def int(self, space): + raise NotImplementedError + long_typedef = StdTypeDef("int", __doc__ = '''int(x[, base]) -> integer @@ -218,6 +242,7 @@ imag = typedef.GetSetProperty(descr_get_imag), bit_length = interp2app(bit_length), from_bytes = interp2app(descr_from_bytes, as_classmethod=True), - to_bytes = interp2app(descr_to_bytes) + to_bytes = interp2app(descr_to_bytes), + __int__ = interpindirect2app(W_AbstractLongObject.int), ) long_typedef.registermethods(globals()) diff --git a/pypy/objspace/std/setobject.py b/pypy/objspace/std/setobject.py --- a/pypy/objspace/std/setobject.py +++ b/pypy/objspace/std/setobject.py @@ -15,6 +15,8 @@ from rpython.rlib.rarithmetic import intmask, r_uint from rpython.rlib import rerased, jit +UNROLL_CUTOFF = 5 + class W_BaseSetObject(W_Object): typedef = None @@ -381,7 +383,7 @@ raise NotImplementedError @jit.look_inside_iff(lambda self, list_w: - jit.loop_unrolling_heuristic(list_w, len(list_w))) + jit.loop_unrolling_heuristic(list_w, len(list_w), UNROLL_CUTOFF)) def get_storage_from_list(self, list_w): setdata = self.get_empty_dict() for w_item in list_w: @@ -389,7 +391,7 @@ return self.erase(setdata) @jit.look_inside_iff(lambda self, items: - jit.loop_unrolling_heuristic(items, len(items))) + jit.loop_unrolling_heuristic(items, len(items), UNROLL_CUTOFF)) def get_storage_from_unwrapped_list(self, items): setdata = self.get_empty_dict() for item in items: @@ -1023,7 +1025,7 @@ _pick_correct_strategy(space, w_set, iterable_w) @jit.look_inside_iff(lambda space, w_set, iterable_w: - jit.loop_unrolling_heuristic(iterable_w, len(iterable_w))) + jit.loop_unrolling_heuristic(iterable_w, len(iterable_w), UNROLL_CUTOFF)) def _pick_correct_strategy(space, w_set, iterable_w): # check for integers for w_item in iterable_w: diff --git a/pypy/objspace/std/test/test_longobject.py b/pypy/objspace/std/test/test_longobject.py --- a/pypy/objspace/std/test/test_longobject.py +++ b/pypy/objspace/std/test/test_longobject.py @@ -232,13 +232,13 @@ def test_math_log(self): import math - raises(ValueError, math.log, 0) - raises(ValueError, math.log, -1) - raises(ValueError, math.log, -2) + raises(ValueError, math.log, 0) + raises(ValueError, math.log, -1) + raises(ValueError, math.log, -2) raises(ValueError, math.log, -(1 << 10000)) - #raises(ValueError, math.log, 0) - raises(ValueError, math.log, -1) - raises(ValueError, math.log, -2) + #raises(ValueError, math.log, 0) + raises(ValueError, math.log, -1) + raises(ValueError, math.log, -2) def test_long(self): import sys @@ -347,6 +347,19 @@ def test_base_overflow(self): raises(ValueError, int, '42', 2**63) + def test_long_real(self): + class A(int): pass + b = A(5).real + assert type(b) is int + + def test__int__(self): + class A(int): + def __int__(self): + return 42 + + assert int(int(3)) == int(3) + assert int(A(13)) == 42 + def test_large_identity(self): import sys a = sys.maxsize + 1 diff --git a/pypy/objspace/std/tupleobject.py b/pypy/objspace/std/tupleobject.py --- a/pypy/objspace/std/tupleobject.py +++ b/pypy/objspace/std/tupleobject.py @@ -10,6 +10,7 @@ from rpython.rlib import jit from rpython.tool.sourcetools import func_with_new_name +UNROLL_CUTOFF = 10 class W_AbstractTupleObject(W_Object): __slots__ = () @@ -79,7 +80,7 @@ return space.newtuple(subitems) @jit.look_inside_iff(lambda space, w_tuple, w_obj: - jit.loop_unrolling_heuristic(w_tuple, len(w_tuple.wrappeditems))) + jit.loop_unrolling_heuristic(w_tuple, len(w_tuple.wrappeditems), UNROLL_CUTOFF)) def contains__Tuple_ANY(space, w_tuple, w_obj): for w_item in w_tuple.wrappeditems: if space.eq_w(w_item, w_obj): @@ -114,8 +115,8 @@ return mul_tuple_times(space, w_tuple, w_times) def tuple_unroll_condition(space, w_tuple1, w_tuple2): - return jit.loop_unrolling_heuristic(w_tuple1, len(w_tuple1.wrappeditems)) or \ - jit.loop_unrolling_heuristic(w_tuple2, len(w_tuple2.wrappeditems)) + return jit.loop_unrolling_heuristic(w_tuple1, len(w_tuple1.wrappeditems), UNROLL_CUTOFF) or \ + jit.loop_unrolling_heuristic(w_tuple2, len(w_tuple2.wrappeditems), UNROLL_CUTOFF) @jit.look_inside_iff(tuple_unroll_condition) def eq__Tuple_Tuple(space, w_tuple1, w_tuple2): @@ -169,7 +170,7 @@ return space.wrap(hash_tuple(space, w_tuple.wrappeditems)) @jit.look_inside_iff(lambda space, wrappeditems: - jit.loop_unrolling_heuristic(wrappeditems, len(wrappeditems))) + jit.loop_unrolling_heuristic(wrappeditems, len(wrappeditems), UNROLL_CUTOFF)) def hash_tuple(space, wrappeditems): # this is the CPython 2.4 algorithm (changed from 2.3) mult = 1000003 diff --git a/pypy/tool/jitlogparser/parser.py b/pypy/tool/jitlogparser/parser.py --- a/pypy/tool/jitlogparser/parser.py +++ b/pypy/tool/jitlogparser/parser.py @@ -447,6 +447,17 @@ num, count = line.split(':', 2) mapping[num].count = int(count) + +def mangle_descr(descr): + if descr.startswith('TargetToken('): + return descr[len('TargetToken('):-1] + if descr.startswith('> 16 - self.MOVW_ri(r, bottom, cond) - if top: - self.MOVT_ri(r, top, cond) + bottom = value & 0xFFFF + top = value >> 16 + self.MOVW_ri(r, bottom, cond) + if top: + self.MOVT_ri(r, top, cond) - max_size_of_gen_load_int = 2 * WORD + +class AbstractARMv6Builder(AbstractARMv7Builder): + + def __init__(self): + AbstractARMv7Builder.__init__(self) + + def gen_load_int(self, r, value, cond=cond.AL): + from rpython.jit.backend.arm.conditions import AL + if cond != AL or 0 <= value <= 0xFFFF: + self._load_by_shifting(r, value, cond) + else: + self.LDR_ri(r, reg.pc.value) + self.MOV_rr(reg.pc.value, reg.pc.value) + self.write32(value) + + max_size_of_gen_load_int = 4 ofs_shift = zip(range(8, 25, 8), range(12, 0, -4)) def _load_by_shifting(self, r, value, c=cond.AL): # to be sure it is only called for the correct cases @@ -276,10 +288,15 @@ t = b | (shift << 8) self.ORR_ri(r, r, imm=t, cond=c) +if autodetect().startswith('armv7'): + AbstractBuilder = AbstractARMv7Builder +else: + AbstractBuilder = AbstractARMv6Builder -class OverwritingBuilder(AbstractARMv7Builder): + +class OverwritingBuilder(AbstractBuilder): def __init__(self, cb, start, size): - AbstractARMv7Builder.__init__(self) + AbstractBuilder.__init__(self) self.cb = cb self.index = start self.end = start + size @@ -293,9 +310,9 @@ self.index += 1 -class ARMv7Builder(BlockBuilderMixin, AbstractARMv7Builder): +class InstrBuilder(BlockBuilderMixin, AbstractBuilder): def __init__(self): - AbstractARMv7Builder.__init__(self) + AbstractBuilder.__init__(self) self.init_block_builder() # # ResOperation --> offset in the assembly. @@ -349,4 +366,4 @@ return self.get_relative_pos() -define_instructions(AbstractARMv7Builder) +define_instructions(AbstractBuilder) diff --git a/rpython/jit/backend/arm/helper/assembler.py b/rpython/jit/backend/arm/helper/assembler.py --- a/rpython/jit/backend/arm/helper/assembler.py +++ b/rpython/jit/backend/arm/helper/assembler.py @@ -1,7 +1,7 @@ from __future__ import with_statement from rpython.jit.backend.arm import conditions as c from rpython.jit.backend.arm import registers as r -from rpython.jit.backend.arm.codebuilder import AbstractARMv7Builder +from rpython.jit.backend.arm.codebuilder import InstrBuilder from rpython.jit.metainterp.history import ConstInt, BoxInt, FLOAT from rpython.rlib.rarithmetic import r_uint, r_longlong, intmask from rpython.jit.metainterp.resoperation import rop @@ -34,8 +34,8 @@ return f def gen_emit_op_ri(name, opname): - ri_op = getattr(AbstractARMv7Builder, '%s_ri' % opname) - rr_op = getattr(AbstractARMv7Builder, '%s_rr' % opname) + ri_op = getattr(InstrBuilder, '%s_ri' % opname) + rr_op = getattr(InstrBuilder, '%s_rr' % opname) def f(self, op, arglocs, regalloc, fcond): assert fcond is not None l0, l1, res = arglocs @@ -48,7 +48,7 @@ return f def gen_emit_op_by_helper_call(name, opname): - helper = getattr(AbstractARMv7Builder, opname) + helper = getattr(InstrBuilder, opname) def f(self, op, arglocs, regalloc, fcond): assert fcond is not None if op.result: @@ -97,7 +97,7 @@ return f def gen_emit_float_op(name, opname): - op_rr = getattr(AbstractARMv7Builder, opname) + op_rr = getattr(InstrBuilder, opname) def f(self, op, arglocs, regalloc, fcond): arg1, arg2, result = arglocs op_rr(self.mc, result.value, arg1.value, arg2.value) @@ -105,7 +105,7 @@ f.__name__ = 'emit_op_%s' % name return f def gen_emit_unary_float_op(name, opname): - op_rr = getattr(AbstractARMv7Builder, opname) + op_rr = getattr(InstrBuilder, opname) def f(self, op, arglocs, regalloc, fcond): arg1, result = arglocs op_rr(self.mc, result.value, arg1.value) diff --git a/rpython/jit/backend/arm/helper/regalloc.py b/rpython/jit/backend/arm/helper/regalloc.py --- a/rpython/jit/backend/arm/helper/regalloc.py +++ b/rpython/jit/backend/arm/helper/regalloc.py @@ -1,6 +1,5 @@ from rpython.jit.backend.arm import conditions as c from rpython.jit.backend.arm import registers as r -from rpython.jit.backend.arm.codebuilder import AbstractARMv7Builder from rpython.jit.metainterp.history import ConstInt, BoxInt, Box, FLOAT from rpython.jit.metainterp.history import ConstInt from rpython.rlib.objectmodel import we_are_translated diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -17,7 +17,7 @@ saved_registers, count_reg_args) from rpython.jit.backend.arm.helper.regalloc import check_imm_arg -from rpython.jit.backend.arm.codebuilder import ARMv7Builder, OverwritingBuilder +from rpython.jit.backend.arm.codebuilder import InstrBuilder, OverwritingBuilder from rpython.jit.backend.arm.jump import remap_frame_layout from rpython.jit.backend.arm.regalloc import TempInt, TempPtr from rpython.jit.backend.arm.locations import imm @@ -299,19 +299,10 @@ is_guard_not_invalidated=True) def emit_op_jump(self, op, arglocs, regalloc, fcond): - # The backend's logic assumes that the target code is in a piece of - # assembler that was also called with the same number of arguments, - # so that the locations [ebp+8..] of the input arguments are valid - # stack locations both before and after the jump. - # target_token = op.getdescr() + assert isinstance(target_token, TargetToken) target = target_token._ll_loop_code - assert isinstance(target_token, TargetToken) assert fcond == c.AL - my_nbargs = self.current_clt._debug_nbargs - target_nbargs = target_token._arm_clt._debug_nbargs - assert my_nbargs == target_nbargs - if target_token in self.target_tokens_currently_compiling: self.mc.B_offs(target, fcond) else: @@ -576,10 +567,12 @@ def emit_op_cond_call_gc_wb(self, op, arglocs, regalloc, fcond): self._write_barrier_fastpath(self.mc, op.getdescr(), arglocs, fcond) + return fcond def emit_op_cond_call_gc_wb_array(self, op, arglocs, regalloc, fcond): self._write_barrier_fastpath(self.mc, op.getdescr(), arglocs, fcond, array=True) + return fcond def _write_barrier_fastpath(self, mc, descr, arglocs, fcond=c.AL, array=False, is_frame=False): @@ -1219,7 +1212,7 @@ baseofs = self.cpu.get_baseofs_of_frame_field() newlooptoken.compiled_loop_token.update_frame_info( oldlooptoken.compiled_loop_token, baseofs) - mc = ARMv7Builder() + mc = InstrBuilder() mc.B(target) mc.copy_to_raw_memory(oldadr) diff --git a/rpython/jit/backend/arm/regalloc.py b/rpython/jit/backend/arm/regalloc.py --- a/rpython/jit/backend/arm/regalloc.py +++ b/rpython/jit/backend/arm/regalloc.py @@ -752,6 +752,7 @@ # self.frame_manager.hint_frame_locations[box] = loc def prepare_op_jump(self, op, fcond): + assert self.jump_target_descr is None descr = op.getdescr() assert isinstance(descr, TargetToken) self.jump_target_descr = descr diff --git a/rpython/jit/backend/arm/runner.py b/rpython/jit/backend/arm/runner.py --- a/rpython/jit/backend/arm/runner.py +++ b/rpython/jit/backend/arm/runner.py @@ -86,10 +86,10 @@ possible then to re-call invalidate_loop() on the same looptoken, which must invalidate all newer GUARD_NOT_INVALIDATED, but not the old one that already has a bridge attached to it.""" - from rpython.jit.backend.arm.codebuilder import ARMv7Builder + from rpython.jit.backend.arm.codebuilder import InstrBuilder for jmp, tgt in looptoken.compiled_loop_token.invalidate_positions: - mc = ARMv7Builder() + mc = InstrBuilder() mc.B_offs(tgt) mc.copy_to_raw_memory(jmp) # positions invalidated @@ -106,27 +106,26 @@ return l def build_regalloc(self): - ''' for tests''' - from rpython.jit.backend.arm.regalloc import Regalloc - assert self.assembler is not None - return Regalloc(self.assembler) + ''' for tests''' + from rpython.jit.backend.arm.regalloc import Regalloc + assert self.assembler is not None + return Regalloc(self.assembler) class CPU_ARM(AbstractARMCPU): """ARM v7 uses softfp ABI, requires vfp""" - backend_name = "arm" + backend_name = "armv7" ArmCPU = CPU_ARM class CPU_ARMHF(AbstractARMCPU): """ARM v7 uses hardfp ABI, requires vfp""" use_hf_abi = True - backend_name = "armhf" + backend_name = "armv7hf" supports_floats = False supports_singlefloats = False class CPU_ARMv6(AbstractARMCPU): """ ARM v6, uses hardfp ABI, requires vfp""" use_hf_abi = True - backend_name = "armv6" + backend_name = "armv6hf" supports_floats = False supports_singlefloats = False - diff --git a/rpython/jit/backend/arm/test/conftest.py b/rpython/jit/backend/arm/test/conftest.py --- a/rpython/jit/backend/arm/test/conftest.py +++ b/rpython/jit/backend/arm/test/conftest.py @@ -17,5 +17,5 @@ help="run tests that translate code") def pytest_runtest_setup(item): - if cpu not in ('arm', 'armhf'): + if not cpu.startswith('arm'): py.test.skip("ARM(v7) tests skipped: cpu is %r" % (cpu,)) diff --git a/rpython/jit/backend/arm/test/support.py b/rpython/jit/backend/arm/test/support.py --- a/rpython/jit/backend/arm/test/support.py +++ b/rpython/jit/backend/arm/test/support.py @@ -39,6 +39,11 @@ i = commands.getoutput("%s -version &1" % AS) check_skip(i) +def get_as_version(): + import commands + i = commands.getoutput("%s -v &1" % AS) + return tuple([int(j) for j in i.split()[-1].split('.')]) + def check_skip(inp, search='arm', msg='only for arm'): skip = True try: diff --git a/rpython/jit/backend/arm/test/test_assembler.py b/rpython/jit/backend/arm/test/test_assembler.py --- a/rpython/jit/backend/arm/test/test_assembler.py +++ b/rpython/jit/backend/arm/test/test_assembler.py @@ -240,9 +240,11 @@ x = 0x60002224 self.a.gen_func_prolog() self.a.mc.gen_load_int(r.r1.value, x) + self.a.mc.SUB_ri(r.sp.value, r.sp.value, 8) self.a.mc.MOV_ri(r.r3.value, 8) - self.a.mc.STR_rr(r.r1.value, r.fp.value, r.r3.value) - self.a.mc.LDR_ri(r.r0.value, r.fp.value, 8) + self.a.mc.STR_rr(r.r1.value, r.sp.value, r.r3.value) + self.a.mc.LDR_ri(r.r0.value, r.sp.value, 8) + self.a.mc.ADD_ri(r.sp.value, r.sp.value, 8) self.a.gen_func_epilog() assert run_asm(self.a) == x diff --git a/rpython/jit/backend/arm/test/test_calling_convention.py b/rpython/jit/backend/arm/test/test_calling_convention.py --- a/rpython/jit/backend/arm/test/test_calling_convention.py +++ b/rpython/jit/backend/arm/test/test_calling_convention.py @@ -1,10 +1,12 @@ +import py + from rpython.rtyper.annlowlevel import llhelper from rpython.jit.metainterp.history import JitCellToken from rpython.jit.backend.test.calling_convention_test import CallingConvTests, parse from rpython.rtyper.lltypesystem import lltype from rpython.jit.codewriter.effectinfo import EffectInfo -from rpython.jit.backend.arm.codebuilder import ARMv7Builder +from rpython.jit.backend.arm.codebuilder import InstrBuilder from rpython.jit.backend.arm import registers as r from rpython.jit.backend.arm.test.support import skip_unless_run_slow_tests from rpython.jit.backend.arm.test.test_runner import boxfloat, constfloat @@ -25,9 +27,9 @@ # ../../test/calling_convention_test.py def make_function_returning_stack_pointer(self): - mc = ARMv7Builder() - mc.MOV_rr(r.r0.value, r.sp.value) - mc.MOV_rr(r.pc.value, r.lr.value) + mc = InstrBuilder() + mc.MOV_rr(r.r0.value, r.sp.value) + mc.MOV_rr(r.pc.value, r.lr.value) return mc.materialize(self.cpu.asmmemmgr, []) def get_alignment_requirements(self): diff --git a/rpython/jit/backend/arm/test/test_instr_codebuilder.py b/rpython/jit/backend/arm/test/test_instr_codebuilder.py --- a/rpython/jit/backend/arm/test/test_instr_codebuilder.py +++ b/rpython/jit/backend/arm/test/test_instr_codebuilder.py @@ -2,13 +2,16 @@ from rpython.jit.backend.arm import codebuilder from rpython.jit.backend.arm import conditions from rpython.jit.backend.arm import instructions -from rpython.jit.backend.arm.test.support import (requires_arm_as, define_test, gen_test_function) +from rpython.jit.backend.arm.test.support import requires_arm_as +from rpython.jit.backend.arm.test.support import get_as_version +from rpython.jit.backend.arm.test.support import define_test +from rpython.jit.backend.arm.test.support import gen_test_function from gen import assemble import py requires_arm_as() -class CodeBuilder(codebuilder.ARMv7Builder): +class CodeBuilder(codebuilder.InstrBuilder): def __init__(self): self.buffer = [] @@ -80,6 +83,9 @@ self.assert_equal('ORR r0, r7, r12, lsl #8') def test_push_one_reg(self): + if get_as_version() < (2, 23): + py.test.xfail("GNU as before version 2.23 generates encoding A1 for " + "pushing only one register") self.cb.PUSH([r.r1.value]) self.assert_equal('PUSH {r1}') diff --git a/rpython/jit/backend/arm/test/test_runner.py b/rpython/jit/backend/arm/test/test_runner.py --- a/rpython/jit/backend/arm/test/test_runner.py +++ b/rpython/jit/backend/arm/test/test_runner.py @@ -27,6 +27,19 @@ bridge_loop_instructions = ['ldr', 'mov', 'nop', 'cmp', 'bge', 'push', 'mov', 'mov', 'push', 'mov', 'mov', 'blx', 'mov', 'mov', 'bx'] + if CPU.backend_name.startswith('armv7'): + bridge_loop_instructions = ['ldr', 'mov', 'nop', 'cmp', 'bge', + 'push', 'mov', 'mov', 'push', 'mov', 'mov', + 'blx', 'mov', 'mov', 'bx'] + else: + bridge_loop_instructions = ['ldr', 'mov', 'nop', 'nop', 'nop', 'cmp', 'bge', + 'push', 'ldr', 'mov', + '', # inline constant + 'push', 'ldr', 'mov', + 'ldrsblt', #inline constant (decodes as instruction) + 'blx', 'ldr', 'mov', + '', # inline constant + 'bx'] def get_cpu(self): cpu = CPU(rtyper=None, stats=FakeStats()) diff --git a/rpython/jit/backend/llsupport/regalloc.py b/rpython/jit/backend/llsupport/regalloc.py --- a/rpython/jit/backend/llsupport/regalloc.py +++ b/rpython/jit/backend/llsupport/regalloc.py @@ -278,11 +278,11 @@ no_lower_byte_regs = [] save_around_call_regs = [] frame_reg = None - temp_boxes = [] def __init__(self, longevity, frame_manager=None, assembler=None): self.free_regs = self.all_regs[:] self.longevity = longevity + self.temp_boxes = [] if not we_are_translated(): self.reg_bindings = OrderedDict() else: diff --git a/rpython/jit/backend/llsupport/test/test_regalloc_integration.py b/rpython/jit/backend/llsupport/test/test_regalloc_integration.py --- a/rpython/jit/backend/llsupport/test/test_regalloc_integration.py +++ b/rpython/jit/backend/llsupport/test/test_regalloc_integration.py @@ -515,6 +515,10 @@ # FIXME: Verify that i19 - i23 are removed class TestRegallocFloats(BaseTestRegalloc): + def setup_class(cls): + if not cls.cpu.supports_floats: + py.test.skip("needs float support") + def test_float_add(self): ops = ''' [f0, f1] diff --git a/rpython/jit/backend/test/test_zll_stress_0.py b/rpython/jit/backend/test/test_zll_stress_0.py new file mode 100644 --- /dev/null +++ b/rpython/jit/backend/test/test_zll_stress_0.py @@ -0,0 +1,4 @@ +from rpython.jit.backend.test import zll_stress + +def test_stress_0(): + zll_stress.do_test_stress(0) diff --git a/rpython/jit/backend/test/test_zll_stress_1.py b/rpython/jit/backend/test/test_zll_stress_1.py new file mode 100644 --- /dev/null +++ b/rpython/jit/backend/test/test_zll_stress_1.py @@ -0,0 +1,4 @@ +from rpython.jit.backend.test import zll_stress + +def test_stress_1(): + zll_stress.do_test_stress(1) diff --git a/rpython/jit/backend/test/test_zll_stress_2.py b/rpython/jit/backend/test/test_zll_stress_2.py new file mode 100644 --- /dev/null +++ b/rpython/jit/backend/test/test_zll_stress_2.py @@ -0,0 +1,4 @@ +from rpython.jit.backend.test import zll_stress + +def test_stress_2(): + zll_stress.do_test_stress(2) diff --git a/rpython/jit/backend/test/test_zll_stress_3.py b/rpython/jit/backend/test/test_zll_stress_3.py new file mode 100644 --- /dev/null +++ b/rpython/jit/backend/test/test_zll_stress_3.py @@ -0,0 +1,4 @@ +from rpython.jit.backend.test import zll_stress + +def test_stress_3(): + zll_stress.do_test_stress(3) diff --git a/rpython/jit/backend/test/test_zll_stress.py b/rpython/jit/backend/test/zll_stress.py rename from rpython/jit/backend/test/test_zll_stress.py rename to rpython/jit/backend/test/zll_stress.py --- a/rpython/jit/backend/test/test_zll_stress.py +++ b/rpython/jit/backend/test/zll_stress.py @@ -5,14 +5,18 @@ CPU = getcpuclass() -iterations = 1000 +total_iterations = 1000 if platform.machine().startswith('arm'): - iterations = 100 + total_iterations = 100 +pieces = 4 +per_piece = total_iterations / pieces -def test_stress(): + +def do_test_stress(piece): cpu = CPU(None, None) cpu.setup_once() r = Random() - for i in range(iterations): - check_random_function(cpu, LLtypeOperationBuilder, r, i, iterations) + r.jumpahead(piece*per_piece) + for i in range(piece*per_piece, (piece+1)*per_piece): + check_random_function(cpu, LLtypeOperationBuilder, r, i, total_iterations) diff --git a/rpython/jit/backend/tool/viewcode.py b/rpython/jit/backend/tool/viewcode.py --- a/rpython/jit/backend/tool/viewcode.py +++ b/rpython/jit/backend/tool/viewcode.py @@ -53,8 +53,8 @@ 'x86_32': 'i386', 'x86_64': 'x86-64', 'i386': 'i386', - 'arm': 'arm', - 'arm_32': 'arm', + 'armv6_32': 'arm', + 'armv7_32': 'arm', } cmd = find_objdump() objdump = ('%(command)s -M %(backend)s -b binary -m %(machine)s ' diff --git a/rpython/memory/gc/env.py b/rpython/memory/gc/env.py --- a/rpython/memory/gc/env.py +++ b/rpython/memory/gc/env.py @@ -270,7 +270,8 @@ def best_nursery_size_for_L2cache(L2cache): # Heuristically, the best nursery size to choose is about half # of the L2 cache. - if L2cache > 0: + if L2cache > 1024 * 1024: # we don't want to have nursery estimated + # on L2 when L3 is present return L2cache // 2 else: return NURSERY_SIZE_UNKNOWN_CACHE diff --git a/rpython/memory/gc/minimark.py b/rpython/memory/gc/minimark.py --- a/rpython/memory/gc/minimark.py +++ b/rpython/memory/gc/minimark.py @@ -348,7 +348,8 @@ # size (needed to handle mallocs just below 'large_objects') but # hacking at the current nursery position in collect_and_reserve(). if newsize <= 0: - newsize = 4*1024*1024 # fixed to 4MB by default + newsize = env.estimate_best_nursery_size() + # 4*1024*1024 # fixed to 4MB by default # (it was env.estimate_best_nursery_size()) if newsize <= 0: newsize = defaultsize @@ -624,7 +625,7 @@ """To call when nursery_free overflows nursery_top. First check if the nursery_top is the real top, otherwise we can just move the top of one cleanup and continue - + Do a minor collection, and possibly also a major collection, and finally reserve 'totalsize' bytes at the start of the now-empty nursery. diff --git a/rpython/memory/gctransform/framework.py b/rpython/memory/gctransform/framework.py --- a/rpython/memory/gctransform/framework.py +++ b/rpython/memory/gctransform/framework.py @@ -468,6 +468,7 @@ # thread support if translator.config.translation.continuation: + root_walker.stacklet_support = True root_walker.need_stacklet_support(self, getfn) if translator.config.translation.thread: root_walker.need_thread_support(self, getfn) @@ -1275,6 +1276,7 @@ def __init__(self, gctransformer): self.gcdata = gctransformer.gcdata self.gc = self.gcdata.gc + self.stacklet_support = False def _freeze_(self): return True diff --git a/rpython/memory/gctransform/shadowstack.py b/rpython/memory/gctransform/shadowstack.py --- a/rpython/memory/gctransform/shadowstack.py +++ b/rpython/memory/gctransform/shadowstack.py @@ -113,7 +113,7 @@ # gc_thread_run and gc_thread_die. See docstrings below. shadow_stack_pool = self.shadow_stack_pool - SHADOWSTACKREF = get_shadowstackref(gctransformer) + SHADOWSTACKREF = get_shadowstackref(self, gctransformer) # this is a dict {tid: SHADOWSTACKREF}, where the tid for the # current thread may be missing so far @@ -217,7 +217,7 @@ def need_stacklet_support(self, gctransformer, getfn): shadow_stack_pool = self.shadow_stack_pool - SHADOWSTACKREF = get_shadowstackref(gctransformer) + SHADOWSTACKREF = get_shadowstackref(self, gctransformer) def gc_shadowstackref_new(): ssref = shadow_stack_pool.allocate(SHADOWSTACKREF) @@ -366,7 +366,7 @@ return result -def get_shadowstackref(gctransformer): +def get_shadowstackref(root_walker, gctransformer): if hasattr(gctransformer, '_SHADOWSTACKREF'): return gctransformer._SHADOWSTACKREF @@ -394,12 +394,20 @@ customtraceptr = llhelper(lltype.Ptr(CUSTOMTRACEFUNC), customtrace) def shadowstack_destructor(shadowstackref): - from rpython.rlib import _rffi_stacklet as _c - h = shadowstackref.context - h = llmemory.cast_adr_to_ptr(h, _c.handle) - llmemory.raw_free(shadowstackref.base) - if h: - _c.destroy(h) + if root_walker.stacklet_support: + from rpython.rlib import _rffi_stacklet as _c + h = shadowstackref.context + h = llmemory.cast_adr_to_ptr(h, _c.handle) + shadowstackref.context = llmemory.NULL + # + base = shadowstackref.base + shadowstackref.base = llmemory.NULL + shadowstackref.top = llmemory.NULL + llmemory.raw_free(base) + # + if root_walker.stacklet_support: + if h: + _c.destroy(h) destrptr = gctransformer.annotate_helper(shadowstack_destructor, [SHADOWSTACKREFPTR], lltype.Void) diff --git a/rpython/memory/gctransform/transform.py b/rpython/memory/gctransform/transform.py --- a/rpython/memory/gctransform/transform.py +++ b/rpython/memory/gctransform/transform.py @@ -86,9 +86,9 @@ def __init__(self, translator, inline=False): self.translator = translator - self.seen_graphs = {} + self.seen_graphs = set() self.prepared = False - self.minimal_transform = {} + self.minimal_transform = set() if translator: self.mixlevelannotator = MixLevelHelperAnnotator(translator.rtyper) else: @@ -109,8 +109,8 @@ return exceptiondata.lltype_of_exception_value def need_minimal_transform(self, graph): From noreply at buildbot.pypy.org Mon Apr 1 22:30:49 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Mon, 1 Apr 2013 22:30:49 +0200 (CEST) Subject: [pypy-commit] pypy default: kill more _bisect remnants Message-ID: <20130401203049.CDEAF1C01A0@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: Changeset: r62915:f972f33923d5 Date: 2013-04-01 13:30 -0700 http://bitbucket.org/pypy/pypy/changeset/f972f33923d5/ Log: kill more _bisect remnants diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py --- a/pypy/config/pypyoption.py +++ b/pypy/config/pypyoption.py @@ -33,7 +33,7 @@ "crypt", "signal", "_rawffi", "termios", "zlib", "bz2", "struct", "_hashlib", "_md5", "_sha", "_minimal_curses", "cStringIO", "thread", "itertools", "pyexpat", "_ssl", "cpyext", "array", - "_bisect", "binascii", "_multiprocessing", '_warnings', + "binascii", "_multiprocessing", '_warnings', "_collections", "_multibytecodec", "micronumpy", "_ffi", "_continuation", "_cffi_backend", "_csv"] )) diff --git a/pypy/doc/config/objspace.usemodules._bisect.txt b/pypy/doc/config/objspace.usemodules._bisect.txt deleted file mode 100644 --- a/pypy/doc/config/objspace.usemodules._bisect.txt +++ /dev/null @@ -1,4 +0,0 @@ -Use the '_bisect' module. -Used, optionally, by the 'bisect' standard lib module. This module is expected to be working and is included by default. - - diff --git a/pypy/doc/cpython_differences.rst b/pypy/doc/cpython_differences.rst --- a/pypy/doc/cpython_differences.rst +++ b/pypy/doc/cpython_differences.rst @@ -21,7 +21,6 @@ __builtin__ `__pypy__`_ _ast - _bisect _codecs _collections `_continuation`_ From noreply at buildbot.pypy.org Mon Apr 1 23:41:30 2013 From: noreply at buildbot.pypy.org (wlav) Date: Mon, 1 Apr 2013 23:41:30 +0200 (CEST) Subject: [pypy-commit] pypy reflex-support: initial scaffolding to allow a loadable reflection library to provide the capi Message-ID: <20130401214130.74F441C0675@cobra.cs.uni-duesseldorf.de> Author: Wim Lavrijsen Branch: reflex-support Changeset: r62916:faf90f3638ca Date: 2013-04-01 14:35 -0700 http://bitbucket.org/pypy/pypy/changeset/faf90f3638ca/ Log: initial scaffolding to allow a loadable reflection library to provide the capi (this includes a cleanup of cppyy startup) diff --git a/pypy/module/cppyy/__init__.py b/pypy/module/cppyy/__init__.py --- a/pypy/module/cppyy/__init__.py +++ b/pypy/module/cppyy/__init__.py @@ -20,7 +20,7 @@ } appleveldefs = { - 'gbl' : 'pythonify.gbl', + '_init_pythonify' : 'pythonify._init_pythonify', 'load_reflection_info' : 'pythonify.load_reflection_info', 'add_pythonization' : 'pythonify.add_pythonization', } @@ -33,3 +33,9 @@ # code generation is not, so give it a chance to run now from pypy.module.cppyy import capi capi.register_pythonizations(space) + + def startup(self, space): + from pypy.module.cppyy import capi + capi.verify_backend(space) # may raise ImportError + + space.call_method(space.wrap(self), '_init_pythonify') diff --git a/pypy/module/cppyy/capi/__init__.py b/pypy/module/cppyy/capi/builtin_capi.py rename from pypy/module/cppyy/capi/__init__.py rename to pypy/module/cppyy/capi/builtin_capi.py --- a/pypy/module/cppyy/capi/__init__.py +++ b/pypy/module/cppyy/capi/builtin_capi.py @@ -34,6 +34,9 @@ C_METHPTRGETTER = lltype.FuncType([C_OBJECT], rffi.VOIDP) C_METHPTRGETTER_PTR = lltype.Ptr(C_METHPTRGETTER) +def verify_backend(space): + return True # by definition + def direct_ptradd(ptr, offset): offset = rffi.cast(rffi.SIZE_T, offset) jit.promote(offset) @@ -52,7 +55,7 @@ [C_SCOPE], rffi.INT, threadsafe=ts_reflect, compilation_info=backend.eci) -def c_num_scopes(cppscope): +def c_num_scopes(space, cppscope): return _c_num_scopes(cppscope.handle) _c_scope_name = rffi.llexternal( "cppyy_scope_name", @@ -68,11 +71,13 @@ compilation_info=backend.eci) def c_resolve_name(name): return charp2str_free(_c_resolve_name(name)) -c_get_scope_opaque = rffi.llexternal( +_c_get_scope_opaque = rffi.llexternal( "cppyy_get_scope", [rffi.CCHARP], C_SCOPE, threadsafe=ts_reflect, compilation_info=backend.eci) +def c_get_scope_opaque(space, name): + return _c_get_scope_opaque(name) c_get_template = rffi.llexternal( "cppyy_get_template", [rffi.CCHARP], C_TYPE, @@ -83,7 +88,7 @@ [C_TYPE, C_OBJECT], C_TYPE, threadsafe=ts_reflect, compilation_info=backend.eci) -def c_actual_class(cppclass, cppobj): +def c_actual_class(space, cppclass, cppobj): return _c_actual_class(cppclass.handle, cppobj) # memory management ---------------------------------------------------------- @@ -282,6 +287,8 @@ if derived == base: return 0 return _c_base_offset(derived.handle, base.handle, address, direction) +def c_base_offset1(derived_h, base, address, direction): + return _c_base_offset(derived_h, base.handle, address, direction) # method/function reflection information ------------------------------------- _c_num_methods = rffi.llexternal( diff --git a/pypy/module/cppyy/capi/loadable_capi.py b/pypy/module/cppyy/capi/loadable_capi.py new file mode 100644 --- /dev/null +++ b/pypy/module/cppyy/capi/loadable_capi.py @@ -0,0 +1,590 @@ +import atexit + +from rpython.rtyper.lltypesystem import rffi, lltype +from rpython.rlib import jit, rdynload, objectmodel +from rpython.tool import leakfinder + +from pypy.interpreter.error import OperationError + +from pypy.module._cffi_backend.libraryobj import W_Library +from pypy.module._cffi_backend.ctypefunc import W_CTypeFunc +from pypy.module._cffi_backend.newtype import new_primitive_type, new_pointer_type +from pypy.module._cffi_backend.cdataobj import W_CData + + +import reflex_capi as backend +#import cint_capi as backend + +def identify(): + return 'loadable_capi' +pythonize = backend.pythonize +register_pythonizations = backend.register_pythonizations +std_string_name = backend.std_string_name + +ts_reflect = backend.ts_reflect +ts_call = backend.ts_call +ts_memory = backend.ts_memory +ts_helper = backend.ts_helper + +_C_OPAQUE_PTR = rffi.LONG +_C_OPAQUE_NULL = lltype.nullptr(rffi.LONGP.TO)# ALT: _C_OPAQUE_PTR.TO + +C_SCOPE = _C_OPAQUE_PTR +C_NULL_SCOPE = rffi.cast(C_SCOPE, _C_OPAQUE_NULL) + +C_TYPE = C_SCOPE +C_NULL_TYPE = C_NULL_SCOPE + +C_OBJECT = _C_OPAQUE_PTR +C_NULL_OBJECT = rffi.cast(C_OBJECT, _C_OPAQUE_NULL) + +C_METHOD = _C_OPAQUE_PTR +C_INDEX = rffi.LONG +C_INDEX_ARRAY = rffi.LONGP +WLAVC_INDEX = rffi.LONG + +C_METHPTRGETTER = lltype.FuncType([C_OBJECT], rffi.VOIDP) +C_METHPTRGETTER_PTR = lltype.Ptr(C_METHPTRGETTER) + +def direct_ptradd(ptr, offset): + offset = rffi.cast(rffi.SIZE_T, offset) + jit.promote(offset) + assert lltype.typeOf(ptr) == C_OBJECT + address = rffi.cast(rffi.CCHARP, ptr) + return rffi.cast(C_OBJECT, lltype.direct_ptradd(address, offset)) + +def exchange_address(ptr, cif_descr, index): + return rffi.ptradd(ptr, cif_descr.exchange_args[index]) + +c_load_dictionary = backend.c_load_dictionary + +class State(object): + def __init__(self, space): + self.library = None + self.capi_calls = {} + + c_scope_s = 'long' + c_type_s = 'long' + + self.capi_call_ifaces = { + 'num_scopes' : ([new_primitive_type(space, c_scope_s)], + new_primitive_type(space, 'int')), + 'scope_name' : ([new_primitive_type(space, c_scope_s), new_primitive_type(space, 'int')], + new_pointer_type(space, new_primitive_type(space, 'char'))), + + 'get_scope' : ([new_pointer_type(space, new_primitive_type(space, 'char'))], + new_primitive_type(space, c_scope_s)), + + 'actual_class' : ([new_primitive_type(space, c_type_s), new_primitive_type(space, c_scope_s)], + new_primitive_type(space, c_type_s)), + } + +def verify_backend(space): + state = space.fromcache(State) + try: + if state.library is None: + state.library = W_Library(space, 'rflxlib.so', rdynload.RTLD_LOCAL | rdynload.RTLD_LAZY) + except Exception: + if objectmodel.we_are_translated(): + raise OperationError(space.w_ImportError, + space.wrap("missing reflection module rflxlib.so!")) + return False + return True + +def get_capi_call(space, name): + state = space.fromcache(State) + try: + return state.capi_calls[name] + except KeyError: + pass + try: + if state.library is None: + state.library = W_Library(space, 'rflxlib.so', rdynload.RTLD_LOCAL | rdynload.RTLD_LAZY) + iface = state.capi_call_ifaces[name] + cfunc = W_CTypeFunc(space, iface[0], iface[1], False) + capi_call = state.library.load_function(cfunc, 'cppyy_'+name) + # TODO: there must be a better way to trick the leakfinder ... + if not objectmodel.we_are_translated(): + leakfinder.remember_free(capi_call.ctype.cif_descr._obj0) + state.capi_calls[name] = capi_call + return capi_call + except Exception: + pass + return None + + +# name to opaque C++ scope representation ------------------------------------ +def c_num_scopes(space, cppscope): + num_scopes = get_capi_call(space, 'num_scopes') + if num_scopes: + return space.int_w(num_scopes.call([space.wrap(cppscope.handle)])) + return 0 +_c_scope_name = rffi.llexternal( + "cppyy_scope_name", + [C_SCOPE, rffi.INT], rffi.CCHARP, + compilation_info = backend.eci) +def c_scope_name(cppscope, iscope): + return charp2str_free(_c_scope_name(cppscope.handle, iscope)) + +_c_resolve_name = rffi.llexternal( + "cppyy_resolve_name", + [rffi.CCHARP], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_resolve_name(name): + return charp2str_free(_c_resolve_name(name)) +def c_get_scope_opaque(space, name): + get_scope = get_capi_call(space, 'get_scope') + if get_scope: + return rffi.cast(C_SCOPE, space.int_w(get_scope.call([space.wrap(name)]))) + return rffi.cast(C_SCOPE, 0) + +c_get_template = rffi.llexternal( + "cppyy_get_template", + [rffi.CCHARP], C_TYPE, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_actual_class(space, cppclass, cppobj): + actual_class = get_capi_call(space, 'actual_class') + if actual_class: + return rffi.cast(C_TYPE, space.int_w( + actual_class.call([space.wrap(cppclass.handle), space.wrap(cppobj)]))) + return rffi.cast(C_TYPE, 0) + +# memory management ---------------------------------------------------------- +_c_allocate = rffi.llexternal( + "cppyy_allocate", + [C_TYPE], C_OBJECT, + threadsafe=ts_memory, + compilation_info=backend.eci) +def c_allocate(cppclass): + return _c_allocate(cppclass.handle) +_c_deallocate = rffi.llexternal( + "cppyy_deallocate", + [C_TYPE, C_OBJECT], lltype.Void, + threadsafe=ts_memory, + compilation_info=backend.eci) +def c_deallocate(cppclass, cppobject): + _c_deallocate(cppclass.handle, cppobject) +_c_destruct = rffi.llexternal( + "cppyy_destruct", + [C_TYPE, C_OBJECT], lltype.Void, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_destruct(cppclass, cppobject): + _c_destruct(cppclass.handle, cppobject) + +# method/function dispatching ------------------------------------------------ +c_call_v = rffi.llexternal( + "cppyy_call_v", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], lltype.Void, + threadsafe=ts_call, + compilation_info=backend.eci) +c_call_b = rffi.llexternal( + "cppyy_call_b", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.UCHAR, + threadsafe=ts_call, + compilation_info=backend.eci) +c_call_c = rffi.llexternal( + "cppyy_call_c", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.CHAR, + threadsafe=ts_call, + compilation_info=backend.eci) +c_call_h = rffi.llexternal( + "cppyy_call_h", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.SHORT, + threadsafe=ts_call, + compilation_info=backend.eci) +c_call_i = rffi.llexternal( + "cppyy_call_i", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.INT, + threadsafe=ts_call, + compilation_info=backend.eci) +c_call_l = rffi.llexternal( + "cppyy_call_l", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.LONG, + threadsafe=ts_call, + compilation_info=backend.eci) +c_call_ll = rffi.llexternal( + "cppyy_call_ll", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.LONGLONG, + threadsafe=ts_call, + compilation_info=backend.eci) +c_call_f = rffi.llexternal( + "cppyy_call_f", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.FLOAT, + threadsafe=ts_call, + compilation_info=backend.eci) +c_call_d = rffi.llexternal( + "cppyy_call_d", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.DOUBLE, + threadsafe=ts_call, + compilation_info=backend.eci) + +c_call_r = rffi.llexternal( + "cppyy_call_r", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.VOIDP, + threadsafe=ts_call, + compilation_info=backend.eci) +c_call_s = rffi.llexternal( + "cppyy_call_s", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.CCHARP, + threadsafe=ts_call, + compilation_info=backend.eci) + +c_constructor = rffi.llexternal( + "cppyy_constructor", + [C_METHOD, C_TYPE, rffi.INT, rffi.VOIDP], C_OBJECT, + threadsafe=ts_call, + compilation_info=backend.eci) +_c_call_o = rffi.llexternal( + "cppyy_call_o", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP, C_TYPE], rffi.LONG, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_o(method, cppobj, nargs, args, cppclass): + return _c_call_o(method, cppobj, nargs, args, cppclass.handle) + +_c_get_methptr_getter = rffi.llexternal( + "cppyy_get_methptr_getter", + [C_SCOPE, C_INDEX], C_METHPTRGETTER_PTR, + threadsafe=ts_reflect, + compilation_info=backend.eci, + elidable_function=True) +def c_get_methptr_getter(cppscope, index): + return _c_get_methptr_getter(cppscope.handle, index) + +# handling of function argument buffer --------------------------------------- +c_allocate_function_args = rffi.llexternal( + "cppyy_allocate_function_args", + [rffi.SIZE_T], rffi.VOIDP, + threadsafe=ts_memory, + compilation_info=backend.eci) +c_deallocate_function_args = rffi.llexternal( + "cppyy_deallocate_function_args", + [rffi.VOIDP], lltype.Void, + threadsafe=ts_memory, + compilation_info=backend.eci) +c_function_arg_sizeof = rffi.llexternal( + "cppyy_function_arg_sizeof", + [], rffi.SIZE_T, + threadsafe=ts_memory, + compilation_info=backend.eci, + elidable_function=True) +c_function_arg_typeoffset = rffi.llexternal( + "cppyy_function_arg_typeoffset", + [], rffi.SIZE_T, + threadsafe=ts_memory, + compilation_info=backend.eci, + elidable_function=True) + +# scope reflection information ----------------------------------------------- +c_is_namespace = rffi.llexternal( + "cppyy_is_namespace", + [C_SCOPE], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +c_is_enum = rffi.llexternal( + "cppyy_is_enum", + [rffi.CCHARP], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) + +# type/class reflection information ------------------------------------------ +_c_final_name = rffi.llexternal( + "cppyy_final_name", + [C_TYPE], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_final_name(cpptype): + return charp2str_free(_c_final_name(cpptype)) +_c_scoped_final_name = rffi.llexternal( + "cppyy_scoped_final_name", + [C_TYPE], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_scoped_final_name(cpptype): + return charp2str_free(_c_scoped_final_name(cpptype)) +c_has_complex_hierarchy = rffi.llexternal( + "cppyy_has_complex_hierarchy", + [C_TYPE], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +_c_num_bases = rffi.llexternal( + "cppyy_num_bases", + [C_TYPE], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_num_bases(cppclass): + return _c_num_bases(cppclass.handle) +_c_base_name = rffi.llexternal( + "cppyy_base_name", + [C_TYPE, rffi.INT], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_base_name(cppclass, base_index): + return charp2str_free(_c_base_name(cppclass.handle, base_index)) +_c_is_subtype = rffi.llexternal( + "cppyy_is_subtype", + [C_TYPE, C_TYPE], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci, + elidable_function=True) + at jit.elidable_promote() +def c_is_subtype(derived, base): + if derived == base: + return 1 + return _c_is_subtype(derived.handle, base.handle) + +_c_base_offset = rffi.llexternal( + "cppyy_base_offset", + [C_TYPE, C_TYPE, C_OBJECT, rffi.INT], rffi.SIZE_T, + threadsafe=ts_reflect, + compilation_info=backend.eci, + elidable_function=True) + at jit.elidable_promote() +def c_base_offset(derived, base, address, direction): + if derived == base: + return 0 + return _c_base_offset(derived.handle, base.handle, address, direction) +def c_base_offset1(derived_h, base, address, direction): + return _c_base_offset(derived_h, base.handle, address, direction) + +# method/function reflection information ------------------------------------- +_c_num_methods = rffi.llexternal( + "cppyy_num_methods", + [C_SCOPE], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_num_methods(cppscope): + return _c_num_methods(cppscope.handle) +_c_method_index_at = rffi.llexternal( + "cppyy_method_index_at", + [C_SCOPE, rffi.INT], C_INDEX, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_index_at(cppscope, imethod): + return _c_method_index_at(cppscope.handle, imethod) +_c_method_indices_from_name = rffi.llexternal( + "cppyy_method_indices_from_name", + [C_SCOPE, rffi.CCHARP], C_INDEX_ARRAY, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_indices_from_name(cppscope, name): + indices = _c_method_indices_from_name(cppscope.handle, name) + if not indices: + return [] + py_indices = [] + i = 0 + index = indices[i] + while index != -1: + i += 1 + py_indices.append(index) + index = indices[i] + c_free(rffi.cast(rffi.VOIDP, indices)) # c_free defined below + return py_indices + +_c_method_name = rffi.llexternal( + "cppyy_method_name", + [C_SCOPE, C_INDEX], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_name(cppscope, index): + return charp2str_free(_c_method_name(cppscope.handle, index)) +_c_method_result_type = rffi.llexternal( + "cppyy_method_result_type", + [C_SCOPE, C_INDEX], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_result_type(cppscope, index): + return charp2str_free(_c_method_result_type(cppscope.handle, index)) +_c_method_num_args = rffi.llexternal( + "cppyy_method_num_args", + [C_SCOPE, C_INDEX], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_num_args(cppscope, index): + return _c_method_num_args(cppscope.handle, index) +_c_method_req_args = rffi.llexternal( + "cppyy_method_req_args", + [C_SCOPE, C_INDEX], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_req_args(cppscope, index): + return _c_method_req_args(cppscope.handle, index) +_c_method_arg_type = rffi.llexternal( + "cppyy_method_arg_type", + [C_SCOPE, C_INDEX, rffi.INT], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_arg_type(cppscope, index, arg_index): + return charp2str_free(_c_method_arg_type(cppscope.handle, index, arg_index)) +_c_method_arg_default = rffi.llexternal( + "cppyy_method_arg_default", + [C_SCOPE, C_INDEX, rffi.INT], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_arg_default(cppscope, index, arg_index): + return charp2str_free(_c_method_arg_default(cppscope.handle, index, arg_index)) +_c_method_signature = rffi.llexternal( + "cppyy_method_signature", + [C_SCOPE, C_INDEX], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_signature(cppscope, index): + return charp2str_free(_c_method_signature(cppscope.handle, index)) + +_c_method_is_template = rffi.llexternal( + "cppyy_method_is_template", + [C_SCOPE, C_INDEX], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_is_template(cppscope, index): + return _c_method_is_template(cppscope.handle, index) +_c_method_num_template_args = rffi.llexternal( + "cppyy_method_num_template_args", + [C_SCOPE, C_INDEX], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +_c_method_template_arg_name = rffi.llexternal( + "cppyy_method_template_arg_name", + [C_SCOPE, C_INDEX, C_INDEX], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_template_args(cppscope, index): + nargs = _c_method_num_template_args(cppscope.handle, index) + args = [c_resolve_name( + charp2str_free(_c_method_template_arg_name(cppscope.handle, index, iarg))) + for iarg in range(nargs)] + return args + +_c_get_method = rffi.llexternal( + "cppyy_get_method", + [C_SCOPE, C_INDEX], C_METHOD, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_get_method(cppscope, index): + return _c_get_method(cppscope.handle, index) +_c_get_global_operator = rffi.llexternal( + "cppyy_get_global_operator", + [C_SCOPE, C_SCOPE, C_SCOPE, rffi.CCHARP], WLAVC_INDEX, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_get_global_operator(nss, lc, rc, op): + if nss is not None: + return _c_get_global_operator(nss.handle, lc.handle, rc.handle, op) + return rffi.cast(WLAVC_INDEX, -1) + +# method properties ---------------------------------------------------------- +_c_is_constructor = rffi.llexternal( + "cppyy_is_constructor", + [C_TYPE, C_INDEX], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_is_constructor(cppclass, index): + return _c_is_constructor(cppclass.handle, index) +_c_is_staticmethod = rffi.llexternal( + "cppyy_is_staticmethod", + [C_TYPE, C_INDEX], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_is_staticmethod(cppclass, index): + return _c_is_staticmethod(cppclass.handle, index) + +# data member reflection information ----------------------------------------- +_c_num_datamembers = rffi.llexternal( + "cppyy_num_datamembers", + [C_SCOPE], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_num_datamembers(cppscope): + return _c_num_datamembers(cppscope.handle) +_c_datamember_name = rffi.llexternal( + "cppyy_datamember_name", + [C_SCOPE, rffi.INT], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_datamember_name(cppscope, datamember_index): + return charp2str_free(_c_datamember_name(cppscope.handle, datamember_index)) +_c_datamember_type = rffi.llexternal( + "cppyy_datamember_type", + [C_SCOPE, rffi.INT], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_datamember_type(cppscope, datamember_index): + return charp2str_free(_c_datamember_type(cppscope.handle, datamember_index)) +_c_datamember_offset = rffi.llexternal( + "cppyy_datamember_offset", + [C_SCOPE, rffi.INT], rffi.SIZE_T, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_datamember_offset(cppscope, datamember_index): + return _c_datamember_offset(cppscope.handle, datamember_index) + +_c_datamember_index = rffi.llexternal( + "cppyy_datamember_index", + [C_SCOPE, rffi.CCHARP], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_datamember_index(cppscope, name): + return _c_datamember_index(cppscope.handle, name) + +# data member properties ----------------------------------------------------- +_c_is_publicdata = rffi.llexternal( + "cppyy_is_publicdata", + [C_SCOPE, rffi.INT], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_is_publicdata(cppscope, datamember_index): + return _c_is_publicdata(cppscope.handle, datamember_index) +_c_is_staticdata = rffi.llexternal( + "cppyy_is_staticdata", + [C_SCOPE, rffi.INT], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_is_staticdata(cppscope, datamember_index): + return _c_is_staticdata(cppscope.handle, datamember_index) + +# misc helpers --------------------------------------------------------------- +c_strtoll = rffi.llexternal( + "cppyy_strtoll", + [rffi.CCHARP], rffi.LONGLONG, + threadsafe=ts_helper, + compilation_info=backend.eci) +c_strtoull = rffi.llexternal( + "cppyy_strtoull", + [rffi.CCHARP], rffi.ULONGLONG, + threadsafe=ts_helper, + compilation_info=backend.eci) +c_free = rffi.llexternal( + "cppyy_free", + [rffi.VOIDP], lltype.Void, + threadsafe=ts_memory, + compilation_info=backend.eci) + +def charp2str_free(charp): + string = rffi.charp2str(charp) + voidp = rffi.cast(rffi.VOIDP, charp) + c_free(voidp) + return string + +c_charp2stdstring = rffi.llexternal( + "cppyy_charp2stdstring", + [rffi.CCHARP], C_OBJECT, + threadsafe=ts_helper, + compilation_info=backend.eci) +c_stdstring2stdstring = rffi.llexternal( + "cppyy_stdstring2stdstring", + [C_OBJECT], C_OBJECT, + threadsafe=ts_helper, + compilation_info=backend.eci) +c_assign2stdstring = rffi.llexternal( + "cppyy_assign2stdstring", + [C_OBJECT, rffi.CCHARP], lltype.Void, + threadsafe=ts_helper, + compilation_info=backend.eci) +c_free_stdstring = rffi.llexternal( + "cppyy_free_stdstring", + [C_OBJECT], lltype.Void, + threadsafe=ts_helper, + compilation_info=backend.eci) diff --git a/pypy/module/cppyy/interp_cppyy.py b/pypy/module/cppyy/interp_cppyy.py --- a/pypy/module/cppyy/interp_cppyy.py +++ b/pypy/module/cppyy/interp_cppyy.py @@ -58,7 +58,7 @@ except KeyError: pass - opaque_handle = capi.c_get_scope_opaque(true_name) + opaque_handle = capi.c_get_scope_opaque(space, true_name) assert lltype.typeOf(opaque_handle) == capi.C_SCOPE if opaque_handle: final_name = capi.c_final_name(opaque_handle) @@ -496,7 +496,7 @@ # The following code tries out each of the functions in order. If # argument conversion fails (or simply if the number of arguments do - # not match, that will lead to an exception, The JIT will snip out + # not match), that will lead to an exception, The JIT will snip out # those (always) failing paths, but only if they have no side-effects. # A second loop gathers all exceptions in the case all methods fail # (the exception gathering would otherwise be a side-effect as far as @@ -795,7 +795,7 @@ # The backend can filter by returning empty strings. Special care is # taken for functions, which need not be unique (overloading). alldir = [] - for i in range(capi.c_num_scopes(self)): + for i in range(capi.c_num_scopes(self.space, self)): sname = capi.c_scope_name(self, i) if sname: alldir.append(self.space.wrap(sname)) allmeth = {} @@ -1139,11 +1139,11 @@ # cast to actual cast if requested and possible w_pycppclass = space.w_None if do_cast and rawobject: - actual = capi.c_actual_class(cppclass, rawobject) + actual = capi.c_actual_class(space, cppclass, rawobject) if actual != cppclass.handle: try: w_pycppclass = get_pythonized_cppclass(space, actual) - offset = capi._c_base_offset(actual, cppclass.handle, rawobject, -1) + offset = capi.c_base_offset1(actual, cppclass, rawobject, -1) rawobject = capi.direct_ptradd(rawobject, offset) w_cppclass = space.findattr(w_pycppclass, space.wrap("_cpp_proxy")) cppclass = space.interp_w(W_CPPClass, w_cppclass, can_be_None=False) diff --git a/pypy/module/cppyy/pythonify.py b/pypy/module/cppyy/pythonify.py --- a/pypy/module/cppyy/pythonify.py +++ b/pypy/module/cppyy/pythonify.py @@ -1,5 +1,5 @@ # NOT_RPYTHON -import cppyy +# do not load cppyy here, see _init_pythonify() import types, sys @@ -22,12 +22,7 @@ class CppyyClassMeta(CppyyScopeMeta): pass -class CppyyClass(cppyy.CPPInstance): - __metaclass__ = CppyyClassMeta - - def __init__(self, *args, **kwds): - pass # ignored, for the C++ backend, ctor == __new__ + __init__ - +# class CppyyClass defined in _init_pythonify() class CppyyTemplateType(object): def __init__(self, scope, name): @@ -36,6 +31,7 @@ def _arg_to_str(self, arg): if arg == str: + import cppyy arg = cppyy._std_string_name() elif type(arg) != str: arg = arg.__name__ @@ -53,7 +49,7 @@ def clgen_callback(name): return get_pycppclass(name) -cppyy._set_class_generator(clgen_callback) + def make_static_function(func_name, cppol): def function(*args): @@ -81,6 +77,7 @@ else: d = dict() def cpp_proxy_loader(cls): + import cppyy cpp_proxy = cppyy._scope_byname(cls.__name__ != '::' and cls.__name__ or '') del cls.__class__._cpp_proxy cls._cpp_proxy = cpp_proxy @@ -179,11 +176,13 @@ # its base class, resulting in the __set__() of its base class being called # by setattr(); so, store directly on the dictionary pycppclass.__dict__[dm_name] = cppdm - if cppyy._is_static(cppdm): + import cppyy + if cppyy._is_static(cppdm): # TODO: make this a method of cppdm metacpp.__dict__[dm_name] = cppdm # the call to register will add back-end specific pythonizations and thus # needs to run first, so that the generic pythonizations can use them + import cppyy cppyy._register_class(pycppclass) _pythonize(pycppclass) return pycppclass @@ -193,6 +192,8 @@ def get_pycppitem(scope, name): + import cppyy + # resolve typedefs/aliases full_name = (scope == gbl) and name or (scope.__name__+'::'+name) true_name = cppyy._resolve_name(full_name) @@ -232,7 +233,7 @@ try: cppdm = scope._cpp_proxy.get_datamember(name) setattr(scope, name, cppdm) - if cppyy._is_static(cppdm): + if cppyy._is_static(cppdm): # TODO: make this a method of cppdm setattr(scope.__class__, name, cppdm) pycppitem = getattr(scope, name) # gets actual property value except AttributeError: @@ -301,6 +302,8 @@ # general note: use 'in pyclass.__dict__' rather than 'hasattr' to prevent # adding pythonizations multiple times in derived classes + import cppyy + # map __eq__/__ne__ through a comparison to None if '__eq__' in pyclass.__dict__: def __eq__(self, other): @@ -384,21 +387,44 @@ try: return _loaded_dictionaries[name] except KeyError: + import cppyy lib = cppyy._load_dictionary(name) _loaded_dictionaries[name] = lib return lib +def _init_pythonify(): + # cppyy should not be loaded at the module level, as that will trigger a + # call to space.getbuiltinmodule(), which will cause cppyy to be loaded + # at pypy-c startup, rather than on the "import cppyy" statement + import cppyy -# user interface objects (note the two-step of not calling scope_byname here: -# creation of global functions may cause the creation of classes in the global -# namespace, so gbl must exist at that point to cache them) -gbl = make_cppnamespace(None, "::", None, False) # global C++ namespace -gbl.__doc__ = "Global C++ namespace." -sys.modules['cppyy.gbl'] = gbl + # top-level classes + global CppyyClass + class CppyyClass(cppyy.CPPInstance): + __metaclass__ = CppyyClassMeta -# mostly for the benefit of the CINT backend, which treats std as special -gbl.std = make_cppnamespace(None, "std", None, False) -sys.modules['cppyy.gbl.std'] = gbl.std + def __init__(self, *args, **kwds): + pass # ignored, for the C++ backend, ctor == __new__ + __init__ + + # class generator callback + cppyy._set_class_generator(clgen_callback) + + # user interface objects (note the two-step of not calling scope_byname here: + # creation of global functions may cause the creation of classes in the global + # namespace, so gbl must exist at that point to cache them) + global gbl + gbl = make_cppnamespace(None, "::", None, False) # global C++ namespace + gbl.__doc__ = "Global C++ namespace." + + # mostly for the benefit of the CINT backend, which treats std as special + gbl.std = make_cppnamespace(None, "std", None, False) + + # install for user access + cppyy.gbl = gbl + + # install as modules to allow importing from + sys.modules['cppyy.gbl'] = gbl + sys.modules['cppyy.gbl.std'] = gbl.std # user-defined pythonizations interface _pythonizations = {} diff --git a/pypy/module/cppyy/test/test_advancedcpp.py b/pypy/module/cppyy/test/test_advancedcpp.py --- a/pypy/module/cppyy/test/test_advancedcpp.py +++ b/pypy/module/cppyy/test/test_advancedcpp.py @@ -523,8 +523,9 @@ # wrong (clear from the generated code). Keep this test as it should # be all better in the cling/llvm world ... - if self.capi_identity == 'Reflex': # don't test anything - return + # TODO: get the capi-identify test selection right ... + if self.capi_identity != 'CINT': # don't test anything for Reflex + return import cppyy diff --git a/pypy/module/cppyy/test/test_zjit.py b/pypy/module/cppyy/test/test_zjit.py --- a/pypy/module/cppyy/test/test_zjit.py +++ b/pypy/module/cppyy/test/test_zjit.py @@ -9,6 +9,8 @@ # These tests are for the backend that support the fast path only. if capi.identify() == 'CINT': py.test.skip("CINT does not support fast path") +elif capi.identify() == 'loadable_capi': + py.test.skip("can not currently use FakeSpace with _cffi_backend") # load cpyext early, or its global vars are counted as leaks in the test # (note that the module is not otherwise used in the test itself) From noreply at buildbot.pypy.org Tue Apr 2 01:39:55 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Tue, 2 Apr 2013 01:39:55 +0200 (CEST) Subject: [pypy-commit] pypy py3k: workaround fake.checkmodule-only translation failures with a stupid hack -- Message-ID: <20130401233955.3FD921C0188@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r62917:67096a23ed90 Date: 2013-04-01 16:38 -0700 http://bitbucket.org/pypy/pypy/changeset/67096a23ed90/ Log: workaround fake.checkmodule-only translation failures with a stupid hack -- April Fools!, not diff --git a/pypy/interpreter/error.py b/pypy/interpreter/error.py --- a/pypy/interpreter/error.py +++ b/pypy/interpreter/error.py @@ -39,7 +39,12 @@ from pypy.objspace.std.typeobject import W_TypeObject self.w_type = w_type self._w_value = w_value - if isinstance(w_type, W_TypeObject): + # HACK: isinstance(w_type, W_TypeObject) won't translate under + # the fake objspace, but w_type.__class__ is W_TypeObject does + # and short circuits to a False constant there, causing the + # isinstance to be ignored =[ + if (w_type is not None and w_type.__class__ is W_TypeObject and + isinstance(w_type, W_TypeObject)): self.setup_context(w_type.space) if not we_are_translated(): self.debug_excs = [] From noreply at buildbot.pypy.org Tue Apr 2 01:39:56 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Tue, 2 Apr 2013 01:39:56 +0200 (CEST) Subject: [pypy-commit] pypy py3k: allow the full r_uint range for kevent fds Message-ID: <20130401233956.A00041C0188@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r62918:65a892b674c1 Date: 2013-04-01 16:39 -0700 http://bitbucket.org/pypy/pypy/changeset/65a892b674c1/ Log: allow the full r_uint range for kevent fds diff --git a/pypy/module/select/interp_kqueue.py b/pypy/module/select/interp_kqueue.py --- a/pypy/module/select/interp_kqueue.py +++ b/pypy/module/select/interp_kqueue.py @@ -242,7 +242,10 @@ @unwrap_spec(filter=int, flags='c_uint', fflags='c_uint', data=int, udata=r_uint) def descr__init__(self, space, w_ident, filter=KQ_FILTER_READ, flags=KQ_EV_ADD, fflags=0, data=0, udata=r_uint(0)): - ident = r_uint(space.c_filedescriptor_w(w_ident)) + if space.isinstance_w(w_ident, space.w_int): + ident = space.uint_w(w_ident) + else: + ident = r_uint(space.c_filedescriptor_w(w_ident)) self.event = lltype.malloc(kevent, flavor="raw") rffi.setintfield(self.event, "c_ident", ident) diff --git a/pypy/module/select/test/test_kqueue.py b/pypy/module/select/test/test_kqueue.py --- a/pypy/module/select/test/test_kqueue.py +++ b/pypy/module/select/test/test_kqueue.py @@ -74,13 +74,12 @@ assert ev == ev assert ev != other - bignum = (sys.maxsize * 2 + 1) & 0xffffffff - fd = sys.maxsize - ev = select.kevent(fd, 1, 2, bignum, sys.maxsize, bignum) - assert ev.ident == fd + bignum = sys.maxsize * 2 + 1 + ev = select.kevent(bignum, 1, 2, 3, sys.maxsize, bignum) + assert ev.ident == bignum assert ev.filter == 1 assert ev.flags == 2 - assert ev.fflags == bignum + assert ev.fflags == 3 assert ev.data == sys.maxsize assert ev.udata == bignum assert ev == ev From noreply at buildbot.pypy.org Tue Apr 2 02:10:08 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Tue, 2 Apr 2013 02:10:08 +0200 (CEST) Subject: [pypy-commit] pypy py3k: merge default Message-ID: <20130402001008.E14A11C0675@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r62919:0aa3b8f0a520 Date: 2013-04-01 17:09 -0700 http://bitbucket.org/pypy/pypy/changeset/0aa3b8f0a520/ Log: merge default diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py --- a/pypy/config/pypyoption.py +++ b/pypy/config/pypyoption.py @@ -33,7 +33,7 @@ "crypt", "signal", "_rawffi", "termios", "zlib", "bz2", "struct", "_hashlib", "_md5", "_minimal_curses", "thread", "itertools", "pyexpat", "_ssl", "cpyext", "array", - "_bisect", "binascii", "_multiprocessing", '_warnings', + "binascii", "_multiprocessing", '_warnings', "_collections", "_multibytecodec", "_ffi", "_continuation", "_csv", "_cffi_backend", # "micronumpy", "_posixsubprocess", diff --git a/pypy/doc/config/objspace.usemodules._bisect.txt b/pypy/doc/config/objspace.usemodules._bisect.txt deleted file mode 100644 --- a/pypy/doc/config/objspace.usemodules._bisect.txt +++ /dev/null @@ -1,4 +0,0 @@ -Use the '_bisect' module. -Used, optionally, by the 'bisect' standard lib module. This module is expected to be working and is included by default. - - diff --git a/pypy/doc/cpython_differences.rst b/pypy/doc/cpython_differences.rst --- a/pypy/doc/cpython_differences.rst +++ b/pypy/doc/cpython_differences.rst @@ -21,7 +21,6 @@ __builtin__ `__pypy__`_ _ast - _bisect _codecs _collections `_continuation`_ diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py --- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py @@ -7,7 +7,7 @@ from rpython.jit.metainterp.history import AbstractDescr, ConstInt, BoxInt from rpython.jit.metainterp.history import TreeLoop from rpython.jit.metainterp import compile, resume -from rpython.jit.metainterp.resoperation import rop, opname, opargnum +from rpython.jit.metainterp.resoperation import rop, opname, oparity from rpython.jit.metainterp.optimizeopt.test.test_optimizebasic import FakeMetaInterpStaticData def test_build_opt_chain(): @@ -188,7 +188,7 @@ if 'FLOAT' in op: continue args = [] - for _ in range(opargnum[opnum]): + for _ in range(oparity[opnum]): args.append(random.randrange(1, 20)) ops = """ [] diff --git a/rpython/jit/metainterp/resoperation.py b/rpython/jit/metainterp/resoperation.py --- a/rpython/jit/metainterp/resoperation.py +++ b/rpython/jit/metainterp/resoperation.py @@ -21,6 +21,7 @@ name = "" pc = 0 opnum = 0 + _cls_has_bool_result = False _attrs_ = ('result',) @@ -172,12 +173,7 @@ return rop._FINAL_FIRST <= self.getopnum() <= rop._FINAL_LAST def returns_bool_result(self): - opnum = self.getopnum() - if we_are_translated(): - assert opnum >= 0 - elif opnum < 0: - return False # for tests - return opboolresult[opnum] + return self._cls_has_bool_result # =================== @@ -550,11 +546,9 @@ pass opclasses = [] # mapping numbers to the concrete ResOp class -opargnum = [] # mapping numbers to number or args (or -1) opname = {} # mapping numbers to the original names, for debugging oparity = [] # mapping numbers to the arity of the operation or -1 opwithdescr = [] # mapping numbers to a flag "takes a descr" -opboolresult= [] # mapping numbers to a flag "returns a boolean" def setup(debug_print=False): @@ -576,14 +570,13 @@ if not name.startswith('_'): opname[i] = name cls = create_class_for_op(name, i, arity, withdescr) + cls._cls_has_bool_result = boolresult else: cls = None opclasses.append(cls) - opargnum.append(arity) oparity.append(arity) opwithdescr.append(withdescr) - opboolresult.append(boolresult) - assert len(opclasses)==len(oparity)==len(opwithdescr)==len(opboolresult)==len(_oplist) + assert len(opclasses)==len(oparity)==len(opwithdescr)==len(_oplist) def get_base_class(mixin, base): try: From noreply at buildbot.pypy.org Tue Apr 2 03:22:30 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Tue, 2 Apr 2013 03:22:30 +0200 (CEST) Subject: [pypy-commit] pypy default: minor cleanup Message-ID: <20130402012230.5BDEE1C01A0@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: Changeset: r62920:ba5a6f84c3f2 Date: 2013-04-01 18:21 -0700 http://bitbucket.org/pypy/pypy/changeset/ba5a6f84c3f2/ Log: minor cleanup diff --git a/pypy/module/pypyjit/test/test_jit_hook.py b/pypy/module/pypyjit/test/test_jit_hook.py --- a/pypy/module/pypyjit/test/test_jit_hook.py +++ b/pypy/module/pypyjit/test/test_jit_hook.py @@ -132,8 +132,9 @@ assert int_add.name == 'int_add' assert int_add.num == self.int_add_num self.on_compile_bridge() - code_repr = "(, 0, False)" - assert repr(all[0]) == '>' % code_repr + expected = ('>' % repr(self.f.func_code)) + assert repr(all[0]) == expected assert len(all) == 2 pypyjit.set_compile_hook(None) self.on_compile() From noreply at buildbot.pypy.org Tue Apr 2 03:22:31 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Tue, 2 Apr 2013 03:22:31 +0200 (CEST) Subject: [pypy-commit] pypy py3k: merge default Message-ID: <20130402012231.8D4A11C01A0@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r62921:604a99e857e8 Date: 2013-04-01 18:22 -0700 http://bitbucket.org/pypy/pypy/changeset/604a99e857e8/ Log: merge default diff --git a/pypy/module/pypyjit/test/test_jit_hook.py b/pypy/module/pypyjit/test/test_jit_hook.py --- a/pypy/module/pypyjit/test/test_jit_hook.py +++ b/pypy/module/pypyjit/test/test_jit_hook.py @@ -132,8 +132,9 @@ assert int_add.name == 'int_add' assert int_add.num == self.int_add_num self.on_compile_bridge() - code_repr = "(, 0, False)" - assert repr(all[0]) == '>' % code_repr + expected = ('>' % repr(self.f.__code__)) + assert repr(all[0]) == expected assert len(all) == 2 pypyjit.set_compile_hook(None) self.on_compile() From noreply at buildbot.pypy.org Tue Apr 2 03:52:42 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Tue, 2 Apr 2013 03:52:42 +0200 (CEST) Subject: [pypy-commit] pypy py3k: maintain the old unused_data Message-ID: <20130402015242.BB3EC1C070B@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r62922:41bea643d6b4 Date: 2013-04-01 18:51 -0700 http://bitbucket.org/pypy/pypy/changeset/41bea643d6b4/ Log: maintain the old unused_data diff --git a/pypy/module/zlib/interp_zlib.py b/pypy/module/zlib/interp_zlib.py --- a/pypy/module/zlib/interp_zlib.py +++ b/pypy/module/zlib/interp_zlib.py @@ -281,7 +281,7 @@ tail = data[unused_start:] if finished: self.unconsumed_tail = b'' - self.unused_data = tail + self.unused_data += tail else: self.unconsumed_tail = tail return self.space.wrapbytes(string) diff --git a/pypy/module/zlib/test/test_zlib.py b/pypy/module/zlib/test/test_zlib.py --- a/pypy/module/zlib/test/test_zlib.py +++ b/pypy/module/zlib/test/test_zlib.py @@ -176,7 +176,7 @@ assert d.unused_data == b'spam' * 100 assert s1 + s2 + s3 == self.expanded s4 = d.decompress(b'egg' * 50) - assert d.unused_data == (b'spam' * 100) + (b'egg' * 50), d.unused_data + assert d.unused_data == (b'spam' * 100) + (b'egg' * 50) assert s4 == b'' From noreply at buildbot.pypy.org Tue Apr 2 04:22:46 2013 From: noreply at buildbot.pypy.org (wlav) Date: Tue, 2 Apr 2013 04:22:46 +0200 (CEST) Subject: [pypy-commit] pypy reflex-support: new __init__.py after moving the old one to builtin_capi.py Message-ID: <20130402022246.BB1BB1C01A0@cobra.cs.uni-duesseldorf.de> Author: Wim Lavrijsen Branch: reflex-support Changeset: r62923:5a5e6dc078be Date: 2013-04-01 19:22 -0700 http://bitbucket.org/pypy/pypy/changeset/5a5e6dc078be/ Log: new __init__.py after moving the old one to builtin_capi.py diff --git a/pypy/module/cppyy/capi/__init__.py b/pypy/module/cppyy/capi/__init__.py new file mode 100644 --- /dev/null +++ b/pypy/module/cppyy/capi/__init__.py @@ -0,0 +1,44 @@ +from rpython.rtyper.lltypesystem import rffi, lltype + +# There are two possible ways of accessing the backend through the reflection +# C-API: built it into pypy-c, or load it dynamically. The latter is preferred +# (and is the default) for use with Reflex. B/c of some builtin pythonizations, +# the former is recommended (for now) with CINT. + +# Note: if builtin_capi is chosen, then inside builtin_capi.py, there is still +# the selection of the desired backend (default is Reflex). + +# choose C-API access method: +from loadable_capi import * +#from builtin_capi import * + +# shared definitions +_C_OPAQUE_PTR = rffi.LONG +_C_OPAQUE_NULL = lltype.nullptr(rffi.LONGP.TO)# ALT: _C_OPAQUE_PTR.TO + +C_SCOPE = _C_OPAQUE_PTR +C_NULL_SCOPE = rffi.cast(C_SCOPE, _C_OPAQUE_NULL) + +C_TYPE = C_SCOPE +C_NULL_TYPE = C_NULL_SCOPE + +C_OBJECT = _C_OPAQUE_PTR +C_NULL_OBJECT = rffi.cast(C_OBJECT, _C_OPAQUE_NULL) + +C_METHOD = _C_OPAQUE_PTR +C_INDEX = rffi.LONG +C_INDEX_ARRAY = rffi.LONGP +WLAVC_INDEX = rffi.LONG + +C_METHPTRGETTER = lltype.FuncType([C_OBJECT], rffi.VOIDP) +C_METHPTRGETTER_PTR = lltype.Ptr(C_METHPTRGETTER) + +def direct_ptradd(ptr, offset): + offset = rffi.cast(rffi.SIZE_T, offset) + jit.promote(offset) + assert lltype.typeOf(ptr) == C_OBJECT + address = rffi.cast(rffi.CCHARP, ptr) + return rffi.cast(C_OBJECT, lltype.direct_ptradd(address, offset)) + +def exchange_address(ptr, cif_descr, index): + return rffi.ptradd(ptr, cif_descr.exchange_args[index]) From noreply at buildbot.pypy.org Tue Apr 2 05:30:55 2013 From: noreply at buildbot.pypy.org (alex_gaynor) Date: Tue, 2 Apr 2013 05:30:55 +0200 (CEST) Subject: [pypy-commit] pypy default: unroll isinstance checks with old style classes Message-ID: <20130402033055.7BA071C01A0@cobra.cs.uni-duesseldorf.de> Author: Alex Gaynor Branch: Changeset: r62924:73524812269e Date: 2013-04-01 20:30 -0700 http://bitbucket.org/pypy/pypy/changeset/73524812269e/ Log: unroll isinstance checks with old style classes diff --git a/pypy/module/__builtin__/abstractinst.py b/pypy/module/__builtin__/abstractinst.py --- a/pypy/module/__builtin__/abstractinst.py +++ b/pypy/module/__builtin__/abstractinst.py @@ -94,9 +94,8 @@ return w_obj.w_class.is_subclass_of(w_klass_or_tuple) return _abstract_isinstance_w_helper(space, w_obj, w_klass_or_tuple) - at jit.dont_look_inside + def _abstract_isinstance_w_helper(space, w_obj, w_klass_or_tuple): - # -- case (anything, abstract-class) check_class(space, w_klass_or_tuple, "isinstance() arg 2 must be a class, type," @@ -111,7 +110,7 @@ return _issubclass_recurse(space, w_abstractclass, w_klass_or_tuple) - at jit.dont_look_inside + at jit.unroll_safe def _issubclass_recurse(space, w_derived, w_top): """Internal helper for abstract cases. Here, w_top cannot be a tuple.""" if space.is_w(w_derived, w_top): From noreply at buildbot.pypy.org Tue Apr 2 10:07:28 2013 From: noreply at buildbot.pypy.org (fijal) Date: Tue, 2 Apr 2013 10:07:28 +0200 (CEST) Subject: [pypy-commit] pypy.org extradoc: update the progrss bar Message-ID: <20130402080728.B3A121C0A4A@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: extradoc Changeset: r384:7fa4ff8b4fbf Date: 2013-04-02 10:07 +0200 http://bitbucket.org/pypy/pypy.org/changeset/7fa4ff8b4fbf/ Log: update the progrss bar diff --git a/don1.html b/don1.html --- a/don1.html +++ b/don1.html @@ -9,13 +9,13 @@ - $44419 of $105000 (42.3%) + $46527 of $105000 (44.3%)
diff --git a/don3.html b/don3.html --- a/don3.html +++ b/don3.html @@ -9,13 +9,13 @@ - $45211 of $60000 (75.4%) + $45872 of $60000 (76.5%)
diff --git a/don4.html b/don4.html --- a/don4.html +++ b/don4.html @@ -9,13 +9,13 @@ - $22540 of $50400 (44.7%) + $26247 of $50400 (52.0%)
From noreply at buildbot.pypy.org Tue Apr 2 19:02:28 2013 From: noreply at buildbot.pypy.org (fijal) Date: Tue, 2 Apr 2013 19:02:28 +0200 (CEST) Subject: [pypy-commit] cffi default: mention Mike Pall in AUTHORS Message-ID: <20130402170228.C62571C0188@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r1219:61e9d06579eb Date: 2013-04-02 19:02 +0200 http://bitbucket.org/cffi/cffi/changeset/61e9d06579eb/ Log: mention Mike Pall in AUTHORS diff --git a/AUTHORS b/AUTHORS --- a/AUTHORS +++ b/AUTHORS @@ -1,2 +1,3 @@ This package has been mostly done by Armin Rigo with help from -Maciej Fijałkowski. \ No newline at end of file +Maciej Fijałkowski. The idea is heavily based (although not directly +copied) from LuaJIT ffi by Mike Pall. From noreply at buildbot.pypy.org Tue Apr 2 19:21:17 2013 From: noreply at buildbot.pypy.org (arigo) Date: Tue, 2 Apr 2013 19:21:17 +0200 (CEST) Subject: [pypy-commit] cffi default: Python 3 compat Message-ID: <20130402172117.A078A1C0334@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r1220:8bd74325f873 Date: 2013-04-01 17:54 +0200 http://bitbucket.org/cffi/cffi/changeset/8bd74325f873/ Log: Python 3 compat diff --git a/testing/test_verify.py b/testing/test_verify.py --- a/testing/test_verify.py +++ b/testing/test_verify.py @@ -1590,7 +1590,9 @@ py.test.raises(TypeError, lib.seeme2, 0.0) py.test.raises(TypeError, lib.seeme1, 0) py.test.raises(TypeError, lib.seeme2, 0) - py.test.raises(TypeError, lib.seeme2, 0L) + zeroL = 99999999999999999999 + zeroL -= 99999999999999999999 + py.test.raises(TypeError, lib.seeme2, zeroL) def test_typeof_function(): ffi = FFI() From noreply at buildbot.pypy.org Tue Apr 2 19:21:18 2013 From: noreply at buildbot.pypy.org (arigo) Date: Tue, 2 Apr 2013 19:21:18 +0200 (CEST) Subject: [pypy-commit] cffi default: merge heads Message-ID: <20130402172118.C854F1C0334@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r1221:e43094a16966 Date: 2013-04-02 19:21 +0200 http://bitbucket.org/cffi/cffi/changeset/e43094a16966/ Log: merge heads diff --git a/AUTHORS b/AUTHORS --- a/AUTHORS +++ b/AUTHORS @@ -1,2 +1,3 @@ This package has been mostly done by Armin Rigo with help from -Maciej Fijałkowski. \ No newline at end of file +Maciej Fijałkowski. The idea is heavily based (although not directly +copied) from LuaJIT ffi by Mike Pall. From noreply at buildbot.pypy.org Tue Apr 2 19:32:19 2013 From: noreply at buildbot.pypy.org (bivab) Date: Tue, 2 Apr 2013 19:32:19 +0200 (CEST) Subject: [pypy-commit] pypy default: Store architecture version on cpu and use the value at runtime to choose which Message-ID: <20130402173219.B9F841C0334@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r62925:2b5f633c5e12 Date: 2013-04-02 19:27 +0200 http://bitbucket.org/pypy/pypy/changeset/2b5f633c5e12/ Log: Store architecture version on cpu and use the value at runtime to choose which instructions to emit (so far only in gen_load_int). diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -59,7 +59,7 @@ if we_are_translated(): self.debug = False self.current_clt = looptoken.compiled_loop_token - self.mc = InstrBuilder() + self.mc = InstrBuilder(self.cpu.arch_version) self.pending_guards = [] assert self.datablockwrapper is None allblocks = self.get_asmmemmgr_blocks(looptoken) @@ -156,7 +156,7 @@ if not self.cpu.propagate_exception_descr: return # not supported (for tests, or non-translated) # - mc = InstrBuilder() + mc = InstrBuilder(self.cpu.arch_version) self._store_and_reset_exception(mc, r.r0) ofs = self.cpu.get_ofs_of_frame_field('jf_guard_exc') # make sure ofs fits into a register @@ -241,7 +241,7 @@ # | my own retaddr | <-- sp # +-----------------------+ # - mc = InstrBuilder() + mc = InstrBuilder(self.cpu.arch_version) # save argument registers and return address mc.PUSH([reg.value for reg in r.argument_regs] + [r.ip.value, r.lr.value]) # stack is aligned here @@ -282,7 +282,7 @@ # write barriers. It must save all registers, and optionally # all vfp registers. It takes a single argument which is in r0. # It must keep stack alignment accordingly. - mc = InstrBuilder() + mc = InstrBuilder(self.cpu.arch_version) # exc0 = exc1 = None mc.PUSH([r.ip.value, r.lr.value]) # push two words to keep alignment @@ -326,7 +326,7 @@ self.wb_slowpath[withcards + 2 * withfloats] = rawstart def _build_malloc_slowpath(self): - mc = InstrBuilder() + mc = InstrBuilder(self.cpu.arch_version) self._push_all_regs_to_jitframe(mc, [r.r0, r.r1], self.cpu.supports_floats) ofs = self.cpu.get_ofs_of_frame_field('jf_gcmap') # store the gc pattern @@ -438,7 +438,7 @@ self.load_reg(mc, vfpr, r.fp, ofs) def _build_failure_recovery(self, exc, withfloats=False): - mc = InstrBuilder() + mc = InstrBuilder(self.cpu.arch_version) self._push_all_regs_to_jitframe(mc, [], withfloats) if exc: @@ -732,7 +732,7 @@ mc.LDR_ri(r.ip.value, r.fp.value, imm=ofs) stack_check_cmp_ofs = mc.currpos() if expected_size == -1: - for _ in range(mc.max_size_of_gen_load_int): + for _ in range(mc.get_max_size_of_gen_load_int()): mc.NOP() else: mc.gen_load_int(r.lr.value, expected_size) @@ -765,7 +765,7 @@ # f) store the address of the new jitframe in the shadowstack # c) set the gcmap field to 0 in the new jitframe # g) restore registers and return - mc = InstrBuilder() + mc = InstrBuilder(self.cpu.arch_version) self._push_all_regs_to_jitframe(mc, [], self.cpu.supports_floats) # this is the gcmap stored by push_gcmap(mov=True) in _check_stack_frame # and the expected_size pushed in _check_stack_frame @@ -825,7 +825,7 @@ self.target_tokens_currently_compiling = None def _patch_stackadjust(self, adr, allocated_depth): - mc = InstrBuilder() + mc = InstrBuilder(self.cpu.arch_version) mc.gen_load_int(r.lr.value, allocated_depth) mc.copy_to_raw_memory(adr) @@ -861,7 +861,7 @@ # patch the guard jumpt to the stub # overwrite the generate NOP with a B_offs to the pos of the # stub - mc = InstrBuilder() + mc = InstrBuilder(self.cpu.arch_version) mc.B_offs(relative_offset, c.get_opposite_of(tok.fcond)) mc.copy_to_raw_memory(guard_pos) else: @@ -940,7 +940,7 @@ self.mc.ASR_ri(resloc.value, resloc.value, 16) def patch_trace(self, faildescr, looptoken, bridge_addr, regalloc): - b = InstrBuilder() + b = InstrBuilder(self.cpu.arch_version) patch_addr = faildescr._arm_failure_recovery_block assert patch_addr != 0 b.B(bridge_addr) diff --git a/rpython/jit/backend/arm/codebuilder.py b/rpython/jit/backend/arm/codebuilder.py --- a/rpython/jit/backend/arm/codebuilder.py +++ b/rpython/jit/backend/arm/codebuilder.py @@ -28,10 +28,10 @@ return f -class AbstractARMv7Builder(object): +class AbstractARMBuilder(object): - def __init__(self): - pass + def __init__(self, arch_version=7): + self.arch_version = arch_version def align(self): while(self.currpos() % FUNC_ALIGN != 0): @@ -250,8 +250,13 @@ def currpos(self): raise NotImplementedError - max_size_of_gen_load_int = 2 def gen_load_int(self, r, value, cond=cond.AL): + if self.arch_version < 7: + self.gen_load_int_v6(r, value, cond) + else: + self.gen_load_int_v7(r, value, cond) + + def gen_load_int_v7(self, r, value, cond=cond.AL): """r is the register number, value is the value to be loaded to the register""" bottom = value & 0xFFFF @@ -260,23 +265,20 @@ if top: self.MOVT_ri(r, top, cond) + def gen_load_int_v6(self, r, value, cond=cond.AL): + from rpython.jit.backend.arm.conditions import AL + if cond != AL or 0 <= value <= 0xFFFF: + self._load_by_shifting(r, value, cond) + else: + self.LDR_ri(r, reg.pc.value) + self.MOV_rr(reg.pc.value, reg.pc.value) + self.write32(value) -class AbstractARMv6Builder(AbstractARMv7Builder): + def get_max_size_of_gen_load_int(self): + return 4 if self.arch_version < 7 else 2 - def __init__(self): - AbstractARMv7Builder.__init__(self) + ofs_shift = zip(range(8, 25, 8), range(12, 0, -4)) - def gen_load_int(self, r, value, cond=cond.AL): - from rpython.jit.backend.arm.conditions import AL - if cond != AL or 0 <= value <= 0xFFFF: - self._load_by_shifting(r, value, cond) - else: - self.LDR_ri(r, reg.pc.value) - self.MOV_rr(reg.pc.value, reg.pc.value) - self.write32(value) - - max_size_of_gen_load_int = 4 - ofs_shift = zip(range(8, 25, 8), range(12, 0, -4)) def _load_by_shifting(self, r, value, c=cond.AL): # to be sure it is only called for the correct cases assert c != cond.AL or 0 <= value <= 0xFFFF @@ -288,15 +290,10 @@ t = b | (shift << 8) self.ORR_ri(r, r, imm=t, cond=c) -if autodetect().startswith('armv7'): - AbstractBuilder = AbstractARMv7Builder -else: - AbstractBuilder = AbstractARMv6Builder - -class OverwritingBuilder(AbstractBuilder): +class OverwritingBuilder(AbstractARMBuilder): def __init__(self, cb, start, size): - AbstractBuilder.__init__(self) + AbstractARMBuilder.__init__(self, cb.arch_version) self.cb = cb self.index = start self.end = start + size @@ -310,9 +307,10 @@ self.index += 1 -class InstrBuilder(BlockBuilderMixin, AbstractBuilder): - def __init__(self): - AbstractBuilder.__init__(self) +class InstrBuilder(BlockBuilderMixin, AbstractARMBuilder): + + def __init__(self, arch_version=7): + AbstractARMBuilder.__init__(self, arch_version) self.init_block_builder() # # ResOperation --> offset in the assembly. @@ -366,4 +364,4 @@ return self.get_relative_pos() -define_instructions(AbstractBuilder) +define_instructions(AbstractARMBuilder) diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -1212,7 +1212,7 @@ baseofs = self.cpu.get_baseofs_of_frame_field() newlooptoken.compiled_loop_token.update_frame_info( oldlooptoken.compiled_loop_token, baseofs) - mc = InstrBuilder() + mc = InstrBuilder(self.cpu.arch_version) mc.B(target) mc.copy_to_raw_memory(oldadr) diff --git a/rpython/jit/backend/arm/runner.py b/rpython/jit/backend/arm/runner.py --- a/rpython/jit/backend/arm/runner.py +++ b/rpython/jit/backend/arm/runner.py @@ -26,6 +26,7 @@ frame_reg = fp use_hf_abi = False # use hard float abi flag + arch_version = 7 def __init__(self, rtyper, stats, opts=None, translate_support_code=False, gcdescr=None): @@ -88,8 +89,8 @@ old one that already has a bridge attached to it.""" from rpython.jit.backend.arm.codebuilder import InstrBuilder - for jmp, tgt in looptoken.compiled_loop_token.invalidate_positions: - mc = InstrBuilder() + for jmp, tgt in looptoken.compiled_loop_token.invalidate_positions: + mc = InstrBuilder(self.arch_version) mc.B_offs(tgt) mc.copy_to_raw_memory(jmp) # positions invalidated @@ -126,6 +127,7 @@ class CPU_ARMv6(AbstractARMCPU): """ ARM v6, uses hardfp ABI, requires vfp""" use_hf_abi = True + arch_version = 6 backend_name = "armv6hf" supports_floats = False supports_singlefloats = False diff --git a/rpython/jit/backend/arm/test/test_instr_codebuilder.py b/rpython/jit/backend/arm/test/test_instr_codebuilder.py --- a/rpython/jit/backend/arm/test/test_instr_codebuilder.py +++ b/rpython/jit/backend/arm/test/test_instr_codebuilder.py @@ -12,7 +12,8 @@ requires_arm_as() class CodeBuilder(codebuilder.InstrBuilder): - def __init__(self): + def __init__(self, arch_version=7): + self.arch_version = arch_version self.buffer = [] def writechar(self, char): @@ -170,6 +171,13 @@ self.cb.MOVT_ri(r.r3.value, 0xFFFF, conditions.NE) self.assert_equal("MOVTNE r3, #65535") + +def test_size_of_gen_load_int(): + for v, n in [(5, 4), (6, 4), (7, 2)]: + c = CodeBuilder(v) + assert c.get_max_size_of_gen_load_int() == n + + class TestInstrCodeBuilderForGeneratedInstr(ASMTest): def setup_method(self, ffuu_method): self.cb = CodeBuilder() From noreply at buildbot.pypy.org Tue Apr 2 19:32:21 2013 From: noreply at buildbot.pypy.org (bivab) Date: Tue, 2 Apr 2013 19:32:21 +0200 (CEST) Subject: [pypy-commit] pypy default: some code and naming cleanups Message-ID: <20130402173221.04BCF1C0334@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r62926:2a95e0487acb Date: 2013-04-02 19:31 +0200 http://bitbucket.org/pypy/pypy/changeset/2a95e0487acb/ Log: some code and naming cleanups diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -342,7 +342,7 @@ def _emit_call(self, adr, arglocs, fcond=c.AL, resloc=None, result_info=(-1, -1), can_collect=1): - if self.cpu.use_hf_abi: + if self.cpu.hf_abi: stack_args, adr = self._setup_call_hf(adr, arglocs, fcond, resloc, result_info) else: @@ -368,7 +368,7 @@ # ensure the result is wellformed and stored in the correct location if resloc is not None: - if resloc.is_vfp_reg() and not self.cpu.use_hf_abi: + if resloc.is_vfp_reg() and not self.cpu.hf_abi: # move result to the allocated register self.mov_to_vfp_loc(r.r0, r.r1, resloc) elif resloc.is_reg() and result_info != (-1, -1): diff --git a/rpython/jit/backend/arm/runner.py b/rpython/jit/backend/arm/runner.py --- a/rpython/jit/backend/arm/runner.py +++ b/rpython/jit/backend/arm/runner.py @@ -1,7 +1,6 @@ from rpython.jit.backend.arm.arch import JITFRAME_FIXED_SIZE from rpython.jit.backend.arm.assembler import AssemblerARM -from rpython.jit.backend.arm.regalloc import CoreRegisterManager,\ - VFPRegisterManager +from rpython.jit.backend.arm.regalloc import VFPRegisterManager from rpython.jit.backend.arm.registers import fp, all_regs from rpython.jit.backend.llsupport import jitframe from rpython.jit.backend.llsupport.llmodel import AbstractLLCPU @@ -25,7 +24,7 @@ float_regs = VFPRegisterManager.all_regs frame_reg = fp - use_hf_abi = False # use hard float abi flag + hf_abi = False # use hard float abi flag arch_version = 7 def __init__(self, rtyper, stats, opts=None, translate_support_code=False, @@ -33,7 +32,6 @@ AbstractLLCPU.__init__(self, rtyper, stats, opts, translate_support_code, gcdescr) - def set_debug(self, flag): return self.assembler.set_debug(flag) @@ -72,7 +70,7 @@ def cast_ptr_to_int(x): adr = llmemory.cast_ptr_to_adr(x) - return ArmCPU.cast_adr_to_int(adr) + return CPU_ARM.cast_adr_to_int(adr) cast_ptr_to_int._annspecialcase_ = 'specialize:arglltype(0)' cast_ptr_to_int = staticmethod(cast_ptr_to_int) @@ -112,21 +110,23 @@ assert self.assembler is not None return Regalloc(self.assembler) + class CPU_ARM(AbstractARMCPU): """ARM v7 uses softfp ABI, requires vfp""" backend_name = "armv7" -ArmCPU = CPU_ARM + class CPU_ARMHF(AbstractARMCPU): """ARM v7 uses hardfp ABI, requires vfp""" - use_hf_abi = True + hf_abi = True backend_name = "armv7hf" supports_floats = False supports_singlefloats = False -class CPU_ARMv6(AbstractARMCPU): + +class CPU_ARMv6HF(AbstractARMCPU): """ ARM v6, uses hardfp ABI, requires vfp""" - use_hf_abi = True + hf_abi = True arch_version = 6 backend_name = "armv6hf" supports_floats = False diff --git a/rpython/jit/backend/detect_cpu.py b/rpython/jit/backend/detect_cpu.py --- a/rpython/jit/backend/detect_cpu.py +++ b/rpython/jit/backend/detect_cpu.py @@ -78,7 +78,7 @@ elif backend_name == 'cli': return "rpython.jit.backend.cli.runner", "CliCPU" elif backend_name == 'armv6hf': - return "rpython.jit.backend.arm.runner", "CPU_ARMv6" + return "rpython.jit.backend.arm.runner", "CPU_ARMv6HF" elif backend_name == 'armv7': return "rpython.jit.backend.arm.runner", "CPU_ARM" elif backend_name == 'armv7hf': From noreply at buildbot.pypy.org Tue Apr 2 20:46:07 2013 From: noreply at buildbot.pypy.org (fijal) Date: Tue, 2 Apr 2013 20:46:07 +0200 (CEST) Subject: [pypy-commit] pypy default: fix docs Message-ID: <20130402184607.66A831C0228@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r62927:65d6c0f528f2 Date: 2013-04-02 20:36 +0200 http://bitbucket.org/pypy/pypy/changeset/65d6c0f528f2/ Log: fix docs diff --git a/pypy/doc/gc_info.rst b/pypy/doc/gc_info.rst --- a/pypy/doc/gc_info.rst +++ b/pypy/doc/gc_info.rst @@ -11,7 +11,7 @@ ``PYPY_GC_NURSERY`` The nursery size. - Defaults to ``4MB``. + Defaults to 1/2 of your cache or ``4M``. Small values (like 1 or 1KB) are useful for debugging. ``PYPY_GC_MAJOR_COLLECT`` diff --git a/rpython/memory/gc/minimark.py b/rpython/memory/gc/minimark.py --- a/rpython/memory/gc/minimark.py +++ b/rpython/memory/gc/minimark.py @@ -2,7 +2,8 @@ Environment variables can be used to fine-tune the following parameters: - PYPY_GC_NURSERY The nursery size. Defaults to '4MB'. Small values + PYPY_GC_NURSERY The nursery size. Defaults to 1/2 of your cache or + '4M'. Small values (like 1 or 1KB) are useful for debugging. PYPY_GC_NURSERY_CLEANUP The interval at which nursery is cleaned up. Must From noreply at buildbot.pypy.org Tue Apr 2 20:46:08 2013 From: noreply at buildbot.pypy.org (fijal) Date: Tue, 2 Apr 2013 20:46:08 +0200 (CEST) Subject: [pypy-commit] pypy default: merge Message-ID: <20130402184608.B79D81C0334@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r62928:3513f7b46640 Date: 2013-04-02 20:45 +0200 http://bitbucket.org/pypy/pypy/changeset/3513f7b46640/ Log: merge diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -59,7 +59,7 @@ if we_are_translated(): self.debug = False self.current_clt = looptoken.compiled_loop_token - self.mc = InstrBuilder() + self.mc = InstrBuilder(self.cpu.arch_version) self.pending_guards = [] assert self.datablockwrapper is None allblocks = self.get_asmmemmgr_blocks(looptoken) @@ -156,7 +156,7 @@ if not self.cpu.propagate_exception_descr: return # not supported (for tests, or non-translated) # - mc = InstrBuilder() + mc = InstrBuilder(self.cpu.arch_version) self._store_and_reset_exception(mc, r.r0) ofs = self.cpu.get_ofs_of_frame_field('jf_guard_exc') # make sure ofs fits into a register @@ -241,7 +241,7 @@ # | my own retaddr | <-- sp # +-----------------------+ # - mc = InstrBuilder() + mc = InstrBuilder(self.cpu.arch_version) # save argument registers and return address mc.PUSH([reg.value for reg in r.argument_regs] + [r.ip.value, r.lr.value]) # stack is aligned here @@ -282,7 +282,7 @@ # write barriers. It must save all registers, and optionally # all vfp registers. It takes a single argument which is in r0. # It must keep stack alignment accordingly. - mc = InstrBuilder() + mc = InstrBuilder(self.cpu.arch_version) # exc0 = exc1 = None mc.PUSH([r.ip.value, r.lr.value]) # push two words to keep alignment @@ -326,7 +326,7 @@ self.wb_slowpath[withcards + 2 * withfloats] = rawstart def _build_malloc_slowpath(self): - mc = InstrBuilder() + mc = InstrBuilder(self.cpu.arch_version) self._push_all_regs_to_jitframe(mc, [r.r0, r.r1], self.cpu.supports_floats) ofs = self.cpu.get_ofs_of_frame_field('jf_gcmap') # store the gc pattern @@ -438,7 +438,7 @@ self.load_reg(mc, vfpr, r.fp, ofs) def _build_failure_recovery(self, exc, withfloats=False): - mc = InstrBuilder() + mc = InstrBuilder(self.cpu.arch_version) self._push_all_regs_to_jitframe(mc, [], withfloats) if exc: @@ -732,7 +732,7 @@ mc.LDR_ri(r.ip.value, r.fp.value, imm=ofs) stack_check_cmp_ofs = mc.currpos() if expected_size == -1: - for _ in range(mc.max_size_of_gen_load_int): + for _ in range(mc.get_max_size_of_gen_load_int()): mc.NOP() else: mc.gen_load_int(r.lr.value, expected_size) @@ -765,7 +765,7 @@ # f) store the address of the new jitframe in the shadowstack # c) set the gcmap field to 0 in the new jitframe # g) restore registers and return - mc = InstrBuilder() + mc = InstrBuilder(self.cpu.arch_version) self._push_all_regs_to_jitframe(mc, [], self.cpu.supports_floats) # this is the gcmap stored by push_gcmap(mov=True) in _check_stack_frame # and the expected_size pushed in _check_stack_frame @@ -825,7 +825,7 @@ self.target_tokens_currently_compiling = None def _patch_stackadjust(self, adr, allocated_depth): - mc = InstrBuilder() + mc = InstrBuilder(self.cpu.arch_version) mc.gen_load_int(r.lr.value, allocated_depth) mc.copy_to_raw_memory(adr) @@ -861,7 +861,7 @@ # patch the guard jumpt to the stub # overwrite the generate NOP with a B_offs to the pos of the # stub - mc = InstrBuilder() + mc = InstrBuilder(self.cpu.arch_version) mc.B_offs(relative_offset, c.get_opposite_of(tok.fcond)) mc.copy_to_raw_memory(guard_pos) else: @@ -940,7 +940,7 @@ self.mc.ASR_ri(resloc.value, resloc.value, 16) def patch_trace(self, faildescr, looptoken, bridge_addr, regalloc): - b = InstrBuilder() + b = InstrBuilder(self.cpu.arch_version) patch_addr = faildescr._arm_failure_recovery_block assert patch_addr != 0 b.B(bridge_addr) diff --git a/rpython/jit/backend/arm/codebuilder.py b/rpython/jit/backend/arm/codebuilder.py --- a/rpython/jit/backend/arm/codebuilder.py +++ b/rpython/jit/backend/arm/codebuilder.py @@ -28,10 +28,10 @@ return f -class AbstractARMv7Builder(object): +class AbstractARMBuilder(object): - def __init__(self): - pass + def __init__(self, arch_version=7): + self.arch_version = arch_version def align(self): while(self.currpos() % FUNC_ALIGN != 0): @@ -250,8 +250,13 @@ def currpos(self): raise NotImplementedError - max_size_of_gen_load_int = 2 def gen_load_int(self, r, value, cond=cond.AL): + if self.arch_version < 7: + self.gen_load_int_v6(r, value, cond) + else: + self.gen_load_int_v7(r, value, cond) + + def gen_load_int_v7(self, r, value, cond=cond.AL): """r is the register number, value is the value to be loaded to the register""" bottom = value & 0xFFFF @@ -260,23 +265,20 @@ if top: self.MOVT_ri(r, top, cond) + def gen_load_int_v6(self, r, value, cond=cond.AL): + from rpython.jit.backend.arm.conditions import AL + if cond != AL or 0 <= value <= 0xFFFF: + self._load_by_shifting(r, value, cond) + else: + self.LDR_ri(r, reg.pc.value) + self.MOV_rr(reg.pc.value, reg.pc.value) + self.write32(value) -class AbstractARMv6Builder(AbstractARMv7Builder): + def get_max_size_of_gen_load_int(self): + return 4 if self.arch_version < 7 else 2 - def __init__(self): - AbstractARMv7Builder.__init__(self) + ofs_shift = zip(range(8, 25, 8), range(12, 0, -4)) - def gen_load_int(self, r, value, cond=cond.AL): - from rpython.jit.backend.arm.conditions import AL - if cond != AL or 0 <= value <= 0xFFFF: - self._load_by_shifting(r, value, cond) - else: - self.LDR_ri(r, reg.pc.value) - self.MOV_rr(reg.pc.value, reg.pc.value) - self.write32(value) - - max_size_of_gen_load_int = 4 - ofs_shift = zip(range(8, 25, 8), range(12, 0, -4)) def _load_by_shifting(self, r, value, c=cond.AL): # to be sure it is only called for the correct cases assert c != cond.AL or 0 <= value <= 0xFFFF @@ -288,15 +290,10 @@ t = b | (shift << 8) self.ORR_ri(r, r, imm=t, cond=c) -if autodetect().startswith('armv7'): - AbstractBuilder = AbstractARMv7Builder -else: - AbstractBuilder = AbstractARMv6Builder - -class OverwritingBuilder(AbstractBuilder): +class OverwritingBuilder(AbstractARMBuilder): def __init__(self, cb, start, size): - AbstractBuilder.__init__(self) + AbstractARMBuilder.__init__(self, cb.arch_version) self.cb = cb self.index = start self.end = start + size @@ -310,9 +307,10 @@ self.index += 1 -class InstrBuilder(BlockBuilderMixin, AbstractBuilder): - def __init__(self): - AbstractBuilder.__init__(self) +class InstrBuilder(BlockBuilderMixin, AbstractARMBuilder): + + def __init__(self, arch_version=7): + AbstractARMBuilder.__init__(self, arch_version) self.init_block_builder() # # ResOperation --> offset in the assembly. @@ -366,4 +364,4 @@ return self.get_relative_pos() -define_instructions(AbstractBuilder) +define_instructions(AbstractARMBuilder) diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -342,7 +342,7 @@ def _emit_call(self, adr, arglocs, fcond=c.AL, resloc=None, result_info=(-1, -1), can_collect=1): - if self.cpu.use_hf_abi: + if self.cpu.hf_abi: stack_args, adr = self._setup_call_hf(adr, arglocs, fcond, resloc, result_info) else: @@ -368,7 +368,7 @@ # ensure the result is wellformed and stored in the correct location if resloc is not None: - if resloc.is_vfp_reg() and not self.cpu.use_hf_abi: + if resloc.is_vfp_reg() and not self.cpu.hf_abi: # move result to the allocated register self.mov_to_vfp_loc(r.r0, r.r1, resloc) elif resloc.is_reg() and result_info != (-1, -1): @@ -1212,7 +1212,7 @@ baseofs = self.cpu.get_baseofs_of_frame_field() newlooptoken.compiled_loop_token.update_frame_info( oldlooptoken.compiled_loop_token, baseofs) - mc = InstrBuilder() + mc = InstrBuilder(self.cpu.arch_version) mc.B(target) mc.copy_to_raw_memory(oldadr) diff --git a/rpython/jit/backend/arm/runner.py b/rpython/jit/backend/arm/runner.py --- a/rpython/jit/backend/arm/runner.py +++ b/rpython/jit/backend/arm/runner.py @@ -1,7 +1,6 @@ from rpython.jit.backend.arm.arch import JITFRAME_FIXED_SIZE from rpython.jit.backend.arm.assembler import AssemblerARM -from rpython.jit.backend.arm.regalloc import CoreRegisterManager,\ - VFPRegisterManager +from rpython.jit.backend.arm.regalloc import VFPRegisterManager from rpython.jit.backend.arm.registers import fp, all_regs from rpython.jit.backend.llsupport import jitframe from rpython.jit.backend.llsupport.llmodel import AbstractLLCPU @@ -25,14 +24,14 @@ float_regs = VFPRegisterManager.all_regs frame_reg = fp - use_hf_abi = False # use hard float abi flag + hf_abi = False # use hard float abi flag + arch_version = 7 def __init__(self, rtyper, stats, opts=None, translate_support_code=False, gcdescr=None): AbstractLLCPU.__init__(self, rtyper, stats, opts, translate_support_code, gcdescr) - def set_debug(self, flag): return self.assembler.set_debug(flag) @@ -71,7 +70,7 @@ def cast_ptr_to_int(x): adr = llmemory.cast_ptr_to_adr(x) - return ArmCPU.cast_adr_to_int(adr) + return CPU_ARM.cast_adr_to_int(adr) cast_ptr_to_int._annspecialcase_ = 'specialize:arglltype(0)' cast_ptr_to_int = staticmethod(cast_ptr_to_int) @@ -88,8 +87,8 @@ old one that already has a bridge attached to it.""" from rpython.jit.backend.arm.codebuilder import InstrBuilder - for jmp, tgt in looptoken.compiled_loop_token.invalidate_positions: - mc = InstrBuilder() + for jmp, tgt in looptoken.compiled_loop_token.invalidate_positions: + mc = InstrBuilder(self.arch_version) mc.B_offs(tgt) mc.copy_to_raw_memory(jmp) # positions invalidated @@ -111,21 +110,24 @@ assert self.assembler is not None return Regalloc(self.assembler) + class CPU_ARM(AbstractARMCPU): """ARM v7 uses softfp ABI, requires vfp""" backend_name = "armv7" -ArmCPU = CPU_ARM + class CPU_ARMHF(AbstractARMCPU): """ARM v7 uses hardfp ABI, requires vfp""" - use_hf_abi = True + hf_abi = True backend_name = "armv7hf" supports_floats = False supports_singlefloats = False -class CPU_ARMv6(AbstractARMCPU): + +class CPU_ARMv6HF(AbstractARMCPU): """ ARM v6, uses hardfp ABI, requires vfp""" - use_hf_abi = True + hf_abi = True + arch_version = 6 backend_name = "armv6hf" supports_floats = False supports_singlefloats = False diff --git a/rpython/jit/backend/arm/test/test_instr_codebuilder.py b/rpython/jit/backend/arm/test/test_instr_codebuilder.py --- a/rpython/jit/backend/arm/test/test_instr_codebuilder.py +++ b/rpython/jit/backend/arm/test/test_instr_codebuilder.py @@ -12,7 +12,8 @@ requires_arm_as() class CodeBuilder(codebuilder.InstrBuilder): - def __init__(self): + def __init__(self, arch_version=7): + self.arch_version = arch_version self.buffer = [] def writechar(self, char): @@ -170,6 +171,13 @@ self.cb.MOVT_ri(r.r3.value, 0xFFFF, conditions.NE) self.assert_equal("MOVTNE r3, #65535") + +def test_size_of_gen_load_int(): + for v, n in [(5, 4), (6, 4), (7, 2)]: + c = CodeBuilder(v) + assert c.get_max_size_of_gen_load_int() == n + + class TestInstrCodeBuilderForGeneratedInstr(ASMTest): def setup_method(self, ffuu_method): self.cb = CodeBuilder() diff --git a/rpython/jit/backend/detect_cpu.py b/rpython/jit/backend/detect_cpu.py --- a/rpython/jit/backend/detect_cpu.py +++ b/rpython/jit/backend/detect_cpu.py @@ -78,7 +78,7 @@ elif backend_name == 'cli': return "rpython.jit.backend.cli.runner", "CliCPU" elif backend_name == 'armv6hf': - return "rpython.jit.backend.arm.runner", "CPU_ARMv6" + return "rpython.jit.backend.arm.runner", "CPU_ARMv6HF" elif backend_name == 'armv7': return "rpython.jit.backend.arm.runner", "CPU_ARM" elif backend_name == 'armv7hf': From noreply at buildbot.pypy.org Tue Apr 2 21:17:52 2013 From: noreply at buildbot.pypy.org (fijal) Date: Tue, 2 Apr 2013 21:17:52 +0200 (CEST) Subject: [pypy-commit] cffi default: fixes Message-ID: <20130402191752.ADC0B1C0228@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r1222:b8eb8ed2ede6 Date: 2013-04-02 21:17 +0200 http://bitbucket.org/cffi/cffi/changeset/b8eb8ed2ede6/ Log: fixes diff --git a/README.md b/README.md --- a/README.md +++ b/README.md @@ -14,3 +14,7 @@ ------- [Mailing list](https://groups.google.com/forum/#!forum/python-cffi) + +To run tests under CPython, run: + +python setup.py build_ext -i diff --git a/cffi/cparser.py b/cffi/cparser.py --- a/cffi/cparser.py +++ b/cffi/cparser.py @@ -1,7 +1,11 @@ from . import api, model from .commontypes import COMMON_TYPES, resolve_common_type -import pycparser.c_parser, weakref, re, sys +try: + from cffi import _pycparser as pycparser +except ImportError: + import pycparser +import weakref, re, sys try: if sys.version_info < (3,): @@ -513,7 +517,7 @@ nextenumvalue = self._parse_constant(enum.value) enumvalues.append(nextenumvalue) nextenumvalue += 1 - enumvalues = tuple(enumvalues) + enumvalues = tuple(enumvalues) tp = model.EnumType(explicit_name, enumerators, enumvalues) tp.partial = partial else: # opaque enum diff --git a/testing/test_zintegration.py b/testing/test_zintegration.py --- a/testing/test_zintegration.py +++ b/testing/test_zintegration.py @@ -18,7 +18,7 @@ site_packages = dirpath break if site_packages: - for module in ('cffi', '_cffi_backend', 'pycparser', 'ply'): + for module in ('cffi', '_cffi_backend', 'pycparser'): target = imp.find_module(module)[1] os.symlink(target, os.path.join(site_packages, os.path.basename(target))) From noreply at buildbot.pypy.org Tue Apr 2 21:34:50 2013 From: noreply at buildbot.pypy.org (fijal) Date: Tue, 2 Apr 2013 21:34:50 +0200 (CEST) Subject: [pypy-commit] cffi default: skip this if we're on PyPy Message-ID: <20130402193450.76E741C0228@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r1223:89f4e47b3e98 Date: 2013-04-02 21:34 +0200 http://bitbucket.org/cffi/cffi/changeset/89f4e47b3e98/ Log: skip this if we're on PyPy diff --git a/testing/test_version.py b/testing/test_version.py --- a/testing/test_version.py +++ b/testing/test_version.py @@ -1,6 +1,10 @@ -import py, os +import py, os, sys import cffi, _cffi_backend +def setup_module(mod): + if '_cffi_backend' in sys.builtin_module_names: + py.test.skip("this is embedded version") + BACKEND_VERSIONS = { '0.4.2': '0.4', # did not change } From noreply at buildbot.pypy.org Tue Apr 2 21:38:19 2013 From: noreply at buildbot.pypy.org (fijal) Date: Tue, 2 Apr 2013 21:38:19 +0200 (CEST) Subject: [pypy-commit] cffi default: some more fixes Message-ID: <20130402193819.8EAAE1C0228@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r1224:7195ec9d79bc Date: 2013-04-02 21:38 +0200 http://bitbucket.org/cffi/cffi/changeset/7195ec9d79bc/ Log: some more fixes diff --git a/testing/test_zintegration.py b/testing/test_zintegration.py --- a/testing/test_zintegration.py +++ b/testing/test_zintegration.py @@ -18,7 +18,12 @@ site_packages = dirpath break if site_packages: - for module in ('cffi', '_cffi_backend', 'pycparser'): + try: + from cffi import _pycparser + modules = ('cffi', '_cffi_backend') + except ImportError: + modules = ('cffi', '_cffi_backend', 'pycparser') + for module in modules: target = imp.find_module(module)[1] os.symlink(target, os.path.join(site_packages, os.path.basename(target))) From noreply at buildbot.pypy.org Tue Apr 2 21:40:46 2013 From: noreply at buildbot.pypy.org (fijal) Date: Tue, 2 Apr 2013 21:40:46 +0200 (CEST) Subject: [pypy-commit] pypy default: import cffi into pypy, wuhu. also a script to do that. Message-ID: <20130402194046.0734C1C0675@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r62929:575ee104f5f0 Date: 2013-04-02 21:40 +0200 http://bitbucket.org/pypy/pypy/changeset/575ee104f5f0/ Log: import cffi into pypy, wuhu. also a script to do that. diff too long, truncating to 2000 out of 22065 lines diff --git a/.hgignore b/.hgignore --- a/.hgignore +++ b/.hgignore @@ -31,6 +31,7 @@ ^pypy/module/cppyy/test/.+\.rootmap$ ^pypy/module/cppyy/test/.+\.exe$ ^pypy/module/cppyy/test/.+_cint.h$ +^pypy/module/test_lib_pypy/cffi_tests/__pycache__.+$ ^pypy/doc/.+\.html$ ^pypy/doc/config/.+\.rst$ ^pypy/doc/basicblock\.asc$ diff --git a/lib_pypy/cffi/__init__.py b/lib_pypy/cffi/__init__.py new file mode 100644 --- /dev/null +++ b/lib_pypy/cffi/__init__.py @@ -0,0 +1,8 @@ +__all__ = ['FFI', 'VerificationError', 'VerificationMissing', 'CDefError', + 'FFIError'] + +from .api import FFI, CDefError, FFIError +from .ffiplatform import VerificationError, VerificationMissing + +__version__ = "0.6" +__version_info__ = (0, 6) diff --git a/lib_pypy/cffi/_pycparser/__init__.py b/lib_pypy/cffi/_pycparser/__init__.py new file mode 100644 --- /dev/null +++ b/lib_pypy/cffi/_pycparser/__init__.py @@ -0,0 +1,94 @@ +#----------------------------------------------------------------- +# pycparser: __init__.py +# +# This package file exports some convenience functions for +# interacting with pycparser +# +# Copyright (C) 2008-2012, Eli Bendersky +# License: BSD +#----------------------------------------------------------------- +__all__ = ['c_lexer', 'c_parser', 'c_ast'] +__version__ = '2.09.1' + +from subprocess import Popen, PIPE +from .c_parser import CParser + + +def preprocess_file(filename, cpp_path='cpp', cpp_args=''): + """ Preprocess a file using cpp. + + filename: + Name of the file you want to preprocess. + + cpp_path: + cpp_args: + Refer to the documentation of parse_file for the meaning of these + arguments. + + When successful, returns the preprocessed file's contents. + Errors from cpp will be printed out. + """ + path_list = [cpp_path] + if isinstance(cpp_args, list): + path_list += cpp_args + elif cpp_args != '': + path_list += [cpp_args] + path_list += [filename] + + try: + # Note the use of universal_newlines to treat all newlines + # as \n for Python's purpose + # + pipe = Popen( path_list, + stdout=PIPE, + universal_newlines=True) + text = pipe.communicate()[0] + except OSError as e: + raise RuntimeError("Unable to invoke 'cpp'. " + + 'Make sure its path was passed correctly\n' + + ('Original error: %s' % e)) + + return text + + +def parse_file(filename, use_cpp=False, cpp_path='cpp', cpp_args='', + parser=None): + """ Parse a C file using pycparser. + + filename: + Name of the file you want to parse. + + use_cpp: + Set to True if you want to execute the C pre-processor + on the file prior to parsing it. + + cpp_path: + If use_cpp is True, this is the path to 'cpp' on your + system. If no path is provided, it attempts to just + execute 'cpp', so it must be in your PATH. + + cpp_args: + If use_cpp is True, set this to the command line arguments strings + to cpp. Be careful with quotes - it's best to pass a raw string + (r'') here. For example: + r'-I../utils/fake_libc_include' + If several arguments are required, pass a list of strings. + + parser: + Optional parser object to be used instead of the default CParser + + When successful, an AST is returned. ParseError can be + thrown if the file doesn't parse successfully. + + Errors from cpp will be printed out. + """ + if use_cpp: + text = preprocess_file(filename, cpp_path, cpp_args) + else: + with open(filename, 'rU') as f: + text = f.read() + + if parser is None: + parser = CParser() + return parser.parse(text, filename) + diff --git a/lib_pypy/cffi/_pycparser/_ast_gen.py b/lib_pypy/cffi/_pycparser/_ast_gen.py new file mode 100644 --- /dev/null +++ b/lib_pypy/cffi/_pycparser/_ast_gen.py @@ -0,0 +1,273 @@ +#----------------------------------------------------------------- +# _ast_gen.py +# +# Generates the AST Node classes from a specification given in +# a .yaml file +# +# The design of this module was inspired by astgen.py from the +# Python 2.5 code-base. +# +# Copyright (C) 2008-2012, Eli Bendersky +# License: BSD +#----------------------------------------------------------------- +import pprint +from string import Template + + +class ASTCodeGenerator(object): + def __init__(self, cfg_filename='_c_ast.cfg'): + """ Initialize the code generator from a configuration + file. + """ + self.cfg_filename = cfg_filename + self.node_cfg = [NodeCfg(name, contents) + for (name, contents) in self.parse_cfgfile(cfg_filename)] + + def generate(self, file=None): + """ Generates the code into file, an open file buffer. + """ + src = Template(_PROLOGUE_COMMENT).substitute( + cfg_filename=self.cfg_filename) + + src += _PROLOGUE_CODE + for node_cfg in self.node_cfg: + src += node_cfg.generate_source() + '\n\n' + + file.write(src) + + def parse_cfgfile(self, filename): + """ Parse the configuration file and yield pairs of + (name, contents) for each node. + """ + with open(filename, "r") as f: + for line in f: + line = line.strip() + if not line or line.startswith('#'): + continue + colon_i = line.find(':') + lbracket_i = line.find('[') + rbracket_i = line.find(']') + if colon_i < 1 or lbracket_i <= colon_i or rbracket_i <= lbracket_i: + raise RuntimeError("Invalid line in %s:\n%s\n" % (filename, line)) + + name = line[:colon_i] + val = line[lbracket_i + 1:rbracket_i] + vallist = [v.strip() for v in val.split(',')] if val else [] + yield name, vallist + + +class NodeCfg(object): + """ Node configuration. + + name: node name + contents: a list of contents - attributes and child nodes + See comment at the top of the configuration file for details. + """ + def __init__(self, name, contents): + self.name = name + self.all_entries = [] + self.attr = [] + self.child = [] + self.seq_child = [] + + for entry in contents: + clean_entry = entry.rstrip('*') + self.all_entries.append(clean_entry) + + if entry.endswith('**'): + self.seq_child.append(clean_entry) + elif entry.endswith('*'): + self.child.append(clean_entry) + else: + self.attr.append(entry) + + def generate_source(self): + src = self._gen_init() + src += '\n' + self._gen_children() + src += '\n' + self._gen_attr_names() + return src + + def _gen_init(self): + src = "class %s(Node):\n" % self.name + + if self.all_entries: + args = ', '.join(self.all_entries) + arglist = '(self, %s, coord=None)' % args + else: + arglist = '(self, coord=None)' + + src += " def __init__%s:\n" % arglist + + for name in self.all_entries + ['coord']: + src += " self.%s = %s\n" % (name, name) + + return src + + def _gen_children(self): + src = ' def children(self):\n' + + if self.all_entries: + src += ' nodelist = []\n' + + for child in self.child: + src += ( + ' if self.%(child)s is not None:' + + ' nodelist.append(("%(child)s", self.%(child)s))\n') % ( + dict(child=child)) + + for seq_child in self.seq_child: + src += ( + ' for i, child in enumerate(self.%(child)s or []):\n' + ' nodelist.append(("%(child)s[%%d]" %% i, child))\n') % ( + dict(child=seq_child)) + + src += ' return tuple(nodelist)\n' + else: + src += ' return ()\n' + + return src + + def _gen_attr_names(self): + src = " attr_names = (" + ''.join("%r," % nm for nm in self.attr) + ')' + return src + + +_PROLOGUE_COMMENT = \ +r'''#----------------------------------------------------------------- +# ** ATTENTION ** +# This code was automatically generated from the file: +# $cfg_filename +# +# Do not modify it directly. Modify the configuration file and +# run the generator again. +# ** ** *** ** ** +# +# pycparser: c_ast.py +# +# AST Node classes. +# +# Copyright (C) 2008-2012, Eli Bendersky +# License: BSD +#----------------------------------------------------------------- + +''' + +_PROLOGUE_CODE = r''' +import sys + + +class Node(object): + """ Abstract base class for AST nodes. + """ + def children(self): + """ A sequence of all children that are Nodes + """ + pass + + def show(self, buf=sys.stdout, offset=0, attrnames=False, nodenames=False, showcoord=False, _my_node_name=None): + """ Pretty print the Node and all its attributes and + children (recursively) to a buffer. + + buf: + Open IO buffer into which the Node is printed. + + offset: + Initial offset (amount of leading spaces) + + attrnames: + True if you want to see the attribute names in + name=value pairs. False to only see the values. + + nodenames: + True if you want to see the actual node names + within their parents. + + showcoord: + Do you want the coordinates of each Node to be + displayed. + """ + lead = ' ' * offset + if nodenames and _my_node_name is not None: + buf.write(lead + self.__class__.__name__+ ' <' + _my_node_name + '>: ') + else: + buf.write(lead + self.__class__.__name__+ ': ') + + if self.attr_names: + if attrnames: + nvlist = [(n, getattr(self,n)) for n in self.attr_names] + attrstr = ', '.join('%s=%s' % nv for nv in nvlist) + else: + vlist = [getattr(self, n) for n in self.attr_names] + attrstr = ', '.join('%s' % v for v in vlist) + buf.write(attrstr) + + if showcoord: + buf.write(' (at %s)' % self.coord) + buf.write('\n') + + for (child_name, child) in self.children(): + child.show( + buf, + offset=offset + 2, + attrnames=attrnames, + nodenames=nodenames, + showcoord=showcoord, + _my_node_name=child_name) + + +class NodeVisitor(object): + """ A base NodeVisitor class for visiting c_ast nodes. + Subclass it and define your own visit_XXX methods, where + XXX is the class name you want to visit with these + methods. + + For example: + + class ConstantVisitor(NodeVisitor): + def __init__(self): + self.values = [] + + def visit_Constant(self, node): + self.values.append(node.value) + + Creates a list of values of all the constant nodes + encountered below the given node. To use it: + + cv = ConstantVisitor() + cv.visit(node) + + Notes: + + * generic_visit() will be called for AST nodes for which + no visit_XXX method was defined. + * The children of nodes for which a visit_XXX was + defined will not be visited - if you need this, call + generic_visit() on the node. + You can use: + NodeVisitor.generic_visit(self, node) + * Modeled after Python's own AST visiting facilities + (the ast module of Python 3.0) + """ + def visit(self, node): + """ Visit a node. + """ + method = 'visit_' + node.__class__.__name__ + visitor = getattr(self, method, self.generic_visit) + return visitor(node) + + def generic_visit(self, node): + """ Called if no explicit visitor function exists for a + node. Implements preorder visiting of the node. + """ + for c_name, c in node.children(): + self.visit(c) + + +''' + + +if __name__ == "__main__": + import sys + ast_gen = ASTCodeGenerator('_c_ast.cfg') + ast_gen.generate(open('c_ast.py', 'w')) + diff --git a/lib_pypy/cffi/_pycparser/_build_tables.py b/lib_pypy/cffi/_pycparser/_build_tables.py new file mode 100644 --- /dev/null +++ b/lib_pypy/cffi/_pycparser/_build_tables.py @@ -0,0 +1,34 @@ +#----------------------------------------------------------------- +# pycparser: _build_tables.py +# +# A dummy for generating the lexing/parsing tables and and +# compiling them into .pyc for faster execution in optimized mode. +# Also generates AST code from the configuration file. +# Should be called from the pycparser directory. +# +# Copyright (C) 2008-2012, Eli Bendersky +# License: BSD +#----------------------------------------------------------------- + +# Generate c_ast.py +# +from _ast_gen import ASTCodeGenerator +ast_gen = ASTCodeGenerator('_c_ast.cfg') +ast_gen.generate(open('c_ast.py', 'w')) + +import sys +sys.path.extend(['.', '..']) +from pycparser import c_parser + +# Generates the tables +# +c_parser.CParser( + lex_optimize=True, + yacc_debug=False, + yacc_optimize=True) + +# Load to compile into .pyc +# +import lextab +import yacctab +import c_ast diff --git a/lib_pypy/cffi/_pycparser/_c_ast.cfg b/lib_pypy/cffi/_pycparser/_c_ast.cfg new file mode 100644 --- /dev/null +++ b/lib_pypy/cffi/_pycparser/_c_ast.cfg @@ -0,0 +1,188 @@ +#----------------------------------------------------------------- +# pycparser: _c_ast_gen.cfg +# +# Defines the AST Node classes used in pycparser. +# +# Each entry is a Node sub-class name, listing the attributes +# and child nodes of the class: +# * - a child node +# ** - a sequence of child nodes +# - an attribute +# +# Copyright (C) 2008-2012, Eli Bendersky +# License: BSD +#----------------------------------------------------------------- + +ArrayDecl: [type*, dim*] + +ArrayRef: [name*, subscript*] + +# op: =, +=, /= etc. +# +Assignment: [op, lvalue*, rvalue*] + +BinaryOp: [op, left*, right*] + +Break: [] + +Case: [expr*, stmts**] + +Cast: [to_type*, expr*] + +# Compound statement in C99 is a list of block items (declarations or +# statements). +# +Compound: [block_items**] + +# Compound literal (anonymous aggregate) for C99. +# (type-name) {initializer_list} +# type: the typename +# init: InitExprList for the initializer list +# +CompoundLiteral: [type*, init*] + +# type: int, char, float, etc. see CLexer for constant token types +# +Constant: [type, value] + +Continue: [] + +# name: the variable being declared +# quals: list of qualifiers (const, volatile) +# funcspec: list function specifiers (i.e. inline in C99) +# storage: list of storage specifiers (extern, register, etc.) +# type: declaration type (probably nested with all the modifiers) +# init: initialization value, or None +# bitsize: bit field size, or None +# +Decl: [name, quals, storage, funcspec, type*, init*, bitsize*] + +DeclList: [decls**] + +Default: [stmts**] + +DoWhile: [cond*, stmt*] + +# Represents the ellipsis (...) parameter in a function +# declaration +# +EllipsisParam: [] + +# An empty statement (a semicolon ';' on its own) +# +EmptyStatement: [] + +# Enumeration type specifier +# name: an optional ID +# values: an EnumeratorList +# +Enum: [name, values*] + +# A name/value pair for enumeration values +# +Enumerator: [name, value*] + +# A list of enumerators +# +EnumeratorList: [enumerators**] + +# A list of expressions separated by the comma operator. +# +ExprList: [exprs**] + +# This is the top of the AST, representing a single C file (a +# translation unit in K&R jargon). It contains a list of +# "external-declaration"s, which is either declarations (Decl), +# Typedef or function definitions (FuncDef). +# +FileAST: [ext**] + +# for (init; cond; next) stmt +# +For: [init*, cond*, next*, stmt*] + +# name: Id +# args: ExprList +# +FuncCall: [name*, args*] + +# type (args) +# +FuncDecl: [args*, type*] + +# Function definition: a declarator for the function name and +# a body, which is a compound statement. +# There's an optional list of parameter declarations for old +# K&R-style definitions +# +FuncDef: [decl*, param_decls**, body*] + +Goto: [name] + +ID: [name] + +# Holder for types that are a simple identifier (e.g. the built +# ins void, char etc. and typedef-defined types) +# +IdentifierType: [names] + +If: [cond*, iftrue*, iffalse*] + +# An initialization list used for compound literals. +# +InitList: [exprs**] + +Label: [name, stmt*] + +# A named initializer for C99. +# The name of a NamedInitializer is a sequence of Nodes, because +# names can be hierarchical and contain constant expressions. +# +NamedInitializer: [name**, expr*] + +# a list of comma separated function parameter declarations +# +ParamList: [params**] + +PtrDecl: [quals, type*] + +Return: [expr*] + +# name: struct tag name +# decls: declaration of members +# +Struct: [name, decls**] + +# type: . or -> +# name.field or name->field +# +StructRef: [name*, type, field*] + +Switch: [cond*, stmt*] + +# cond ? iftrue : iffalse +# +TernaryOp: [cond*, iftrue*, iffalse*] + +# A base type declaration +# +TypeDecl: [declname, quals, type*] + +# A typedef declaration. +# Very similar to Decl, but without some attributes +# +Typedef: [name, quals, storage, type*] + +Typename: [quals, type*] + +UnaryOp: [op, expr*] + +# name: union tag name +# decls: declaration of members +# +Union: [name, decls**] + +While: [cond*, stmt*] + + + diff --git a/lib_pypy/cffi/_pycparser/ast_transforms.py b/lib_pypy/cffi/_pycparser/ast_transforms.py new file mode 100644 --- /dev/null +++ b/lib_pypy/cffi/_pycparser/ast_transforms.py @@ -0,0 +1,105 @@ +#------------------------------------------------------------------------------ +# pycparser: ast_transforms.py +# +# Some utilities used by the parser to create a friendlier AST. +# +# Copyright (C) 2008-2012, Eli Bendersky +# License: BSD +#------------------------------------------------------------------------------ + +from . import c_ast + + +def fix_switch_cases(switch_node): + """ The 'case' statements in a 'switch' come out of parsing with one + child node, so subsequent statements are just tucked to the parent + Compound. Additionally, consecutive (fall-through) case statements + come out messy. This is a peculiarity of the C grammar. The following: + + switch (myvar) { + case 10: + k = 10; + p = k + 1; + return 10; + case 20: + case 30: + return 20; + default: + break; + } + + Creates this tree (pseudo-dump): + + Switch + ID: myvar + Compound: + Case 10: + k = 10 + p = k + 1 + return 10 + Case 20: + Case 30: + return 20 + Default: + break + + The goal of this transform it to fix this mess, turning it into the + following: + + Switch + ID: myvar + Compound: + Case 10: + k = 10 + p = k + 1 + return 10 + Case 20: + Case 30: + return 20 + Default: + break + + A fixed AST node is returned. The argument may be modified. + """ + assert isinstance(switch_node, c_ast.Switch) + if not isinstance(switch_node.stmt, c_ast.Compound): + return switch_node + + # The new Compound child for the Switch, which will collect children in the + # correct order + new_compound = c_ast.Compound([], switch_node.stmt.coord) + + # The last Case/Default node + last_case = None + + # Goes over the children of the Compound below the Switch, adding them + # either directly below new_compound or below the last Case as appropriate + for child in switch_node.stmt.block_items: + if isinstance(child, (c_ast.Case, c_ast.Default)): + # If it's a Case/Default: + # 1. Add it to the Compound and mark as "last case" + # 2. If its immediate child is also a Case or Default, promote it + # to a sibling. + new_compound.block_items.append(child) + _extract_nested_case(child, new_compound.block_items) + last_case = new_compound.block_items[-1] + else: + # Other statements are added as childrent to the last case, if it + # exists. + if last_case is None: + new_compound.block_items.append(child) + else: + last_case.stmts.append(child) + + switch_node.stmt = new_compound + return switch_node + + +def _extract_nested_case(case_node, stmts_list): + """ Recursively extract consecutive Case statements that are made nested + by the parser and add them to the stmts_list. + """ + if isinstance(case_node.stmts[0], (c_ast.Case, c_ast.Default)): + stmts_list.append(case_node.stmts.pop()) + _extract_nested_case(stmts_list[-1], stmts_list) + diff --git a/lib_pypy/cffi/_pycparser/c_ast.py b/lib_pypy/cffi/_pycparser/c_ast.py new file mode 100644 --- /dev/null +++ b/lib_pypy/cffi/_pycparser/c_ast.py @@ -0,0 +1,748 @@ +#----------------------------------------------------------------- +# ** ATTENTION ** +# This code was automatically generated from the file: +# _c_ast.cfg +# +# Do not modify it directly. Modify the configuration file and +# run the generator again. +# ** ** *** ** ** +# +# pycparser: c_ast.py +# +# AST Node classes. +# +# Copyright (C) 2008-2012, Eli Bendersky +# License: BSD +#----------------------------------------------------------------- + + +import sys + + +class Node(object): + """ Abstract base class for AST nodes. + """ + def children(self): + """ A sequence of all children that are Nodes + """ + pass + + def show(self, buf=sys.stdout, offset=0, attrnames=False, nodenames=False, showcoord=False, _my_node_name=None): + """ Pretty print the Node and all its attributes and + children (recursively) to a buffer. + + buf: + Open IO buffer into which the Node is printed. + + offset: + Initial offset (amount of leading spaces) + + attrnames: + True if you want to see the attribute names in + name=value pairs. False to only see the values. + + nodenames: + True if you want to see the actual node names + within their parents. + + showcoord: + Do you want the coordinates of each Node to be + displayed. + """ + lead = ' ' * offset + if nodenames and _my_node_name is not None: + buf.write(lead + self.__class__.__name__+ ' <' + _my_node_name + '>: ') + else: + buf.write(lead + self.__class__.__name__+ ': ') + + if self.attr_names: + if attrnames: + nvlist = [(n, getattr(self,n)) for n in self.attr_names] + attrstr = ', '.join('%s=%s' % nv for nv in nvlist) + else: + vlist = [getattr(self, n) for n in self.attr_names] + attrstr = ', '.join('%s' % v for v in vlist) + buf.write(attrstr) + + if showcoord: + buf.write(' (at %s)' % self.coord) + buf.write('\n') + + for (child_name, child) in self.children(): + child.show( + buf, + offset=offset + 2, + attrnames=attrnames, + nodenames=nodenames, + showcoord=showcoord, + _my_node_name=child_name) + + +class NodeVisitor(object): + """ A base NodeVisitor class for visiting c_ast nodes. + Subclass it and define your own visit_XXX methods, where + XXX is the class name you want to visit with these + methods. + + For example: + + class ConstantVisitor(NodeVisitor): + def __init__(self): + self.values = [] + + def visit_Constant(self, node): + self.values.append(node.value) + + Creates a list of values of all the constant nodes + encountered below the given node. To use it: + + cv = ConstantVisitor() + cv.visit(node) + + Notes: + + * generic_visit() will be called for AST nodes for which + no visit_XXX method was defined. + * The children of nodes for which a visit_XXX was + defined will not be visited - if you need this, call + generic_visit() on the node. + You can use: + NodeVisitor.generic_visit(self, node) + * Modeled after Python's own AST visiting facilities + (the ast module of Python 3.0) + """ + def visit(self, node): + """ Visit a node. + """ + method = 'visit_' + node.__class__.__name__ + visitor = getattr(self, method, self.generic_visit) + return visitor(node) + + def generic_visit(self, node): + """ Called if no explicit visitor function exists for a + node. Implements preorder visiting of the node. + """ + for c_name, c in node.children(): + self.visit(c) + + +class ArrayDecl(Node): + def __init__(self, type, dim, coord=None): + self.type = type + self.dim = dim + self.coord = coord + + def children(self): + nodelist = [] + if self.type is not None: nodelist.append(("type", self.type)) + if self.dim is not None: nodelist.append(("dim", self.dim)) + return tuple(nodelist) + + attr_names = () + +class ArrayRef(Node): + def __init__(self, name, subscript, coord=None): + self.name = name + self.subscript = subscript + self.coord = coord + + def children(self): + nodelist = [] + if self.name is not None: nodelist.append(("name", self.name)) + if self.subscript is not None: nodelist.append(("subscript", self.subscript)) + return tuple(nodelist) + + attr_names = () + +class Assignment(Node): + def __init__(self, op, lvalue, rvalue, coord=None): + self.op = op + self.lvalue = lvalue + self.rvalue = rvalue + self.coord = coord + + def children(self): + nodelist = [] + if self.lvalue is not None: nodelist.append(("lvalue", self.lvalue)) + if self.rvalue is not None: nodelist.append(("rvalue", self.rvalue)) + return tuple(nodelist) + + attr_names = ('op',) + +class BinaryOp(Node): + def __init__(self, op, left, right, coord=None): + self.op = op + self.left = left + self.right = right + self.coord = coord + + def children(self): + nodelist = [] + if self.left is not None: nodelist.append(("left", self.left)) + if self.right is not None: nodelist.append(("right", self.right)) + return tuple(nodelist) + + attr_names = ('op',) + +class Break(Node): + def __init__(self, coord=None): + self.coord = coord + + def children(self): + return () + + attr_names = () + +class Case(Node): + def __init__(self, expr, stmts, coord=None): + self.expr = expr + self.stmts = stmts + self.coord = coord + + def children(self): + nodelist = [] + if self.expr is not None: nodelist.append(("expr", self.expr)) + for i, child in enumerate(self.stmts or []): + nodelist.append(("stmts[%d]" % i, child)) + return tuple(nodelist) + + attr_names = () + +class Cast(Node): + def __init__(self, to_type, expr, coord=None): + self.to_type = to_type + self.expr = expr + self.coord = coord + + def children(self): + nodelist = [] + if self.to_type is not None: nodelist.append(("to_type", self.to_type)) + if self.expr is not None: nodelist.append(("expr", self.expr)) + return tuple(nodelist) + + attr_names = () + +class Compound(Node): + def __init__(self, block_items, coord=None): + self.block_items = block_items + self.coord = coord + + def children(self): + nodelist = [] + for i, child in enumerate(self.block_items or []): + nodelist.append(("block_items[%d]" % i, child)) + return tuple(nodelist) + + attr_names = () + +class CompoundLiteral(Node): + def __init__(self, type, init, coord=None): + self.type = type + self.init = init + self.coord = coord + + def children(self): + nodelist = [] + if self.type is not None: nodelist.append(("type", self.type)) + if self.init is not None: nodelist.append(("init", self.init)) + return tuple(nodelist) + + attr_names = () + +class Constant(Node): + def __init__(self, type, value, coord=None): + self.type = type + self.value = value + self.coord = coord + + def children(self): + nodelist = [] + return tuple(nodelist) + + attr_names = ('type','value',) + +class Continue(Node): + def __init__(self, coord=None): + self.coord = coord + + def children(self): + return () + + attr_names = () + +class Decl(Node): + def __init__(self, name, quals, storage, funcspec, type, init, bitsize, coord=None): + self.name = name + self.quals = quals + self.storage = storage + self.funcspec = funcspec + self.type = type + self.init = init + self.bitsize = bitsize + self.coord = coord + + def children(self): + nodelist = [] + if self.type is not None: nodelist.append(("type", self.type)) + if self.init is not None: nodelist.append(("init", self.init)) + if self.bitsize is not None: nodelist.append(("bitsize", self.bitsize)) + return tuple(nodelist) + + attr_names = ('name','quals','storage','funcspec',) + +class DeclList(Node): + def __init__(self, decls, coord=None): + self.decls = decls + self.coord = coord + + def children(self): + nodelist = [] + for i, child in enumerate(self.decls or []): + nodelist.append(("decls[%d]" % i, child)) + return tuple(nodelist) + + attr_names = () + +class Default(Node): + def __init__(self, stmts, coord=None): + self.stmts = stmts + self.coord = coord + + def children(self): + nodelist = [] + for i, child in enumerate(self.stmts or []): + nodelist.append(("stmts[%d]" % i, child)) + return tuple(nodelist) + + attr_names = () + +class DoWhile(Node): + def __init__(self, cond, stmt, coord=None): + self.cond = cond + self.stmt = stmt + self.coord = coord + + def children(self): + nodelist = [] + if self.cond is not None: nodelist.append(("cond", self.cond)) + if self.stmt is not None: nodelist.append(("stmt", self.stmt)) + return tuple(nodelist) + + attr_names = () + +class EllipsisParam(Node): + def __init__(self, coord=None): + self.coord = coord + + def children(self): + return () + + attr_names = () + +class EmptyStatement(Node): + def __init__(self, coord=None): + self.coord = coord + + def children(self): + return () + + attr_names = () + +class Enum(Node): + def __init__(self, name, values, coord=None): + self.name = name + self.values = values + self.coord = coord + + def children(self): + nodelist = [] + if self.values is not None: nodelist.append(("values", self.values)) + return tuple(nodelist) + + attr_names = ('name',) + +class Enumerator(Node): + def __init__(self, name, value, coord=None): + self.name = name + self.value = value + self.coord = coord + + def children(self): + nodelist = [] + if self.value is not None: nodelist.append(("value", self.value)) + return tuple(nodelist) + + attr_names = ('name',) + +class EnumeratorList(Node): + def __init__(self, enumerators, coord=None): + self.enumerators = enumerators + self.coord = coord + + def children(self): + nodelist = [] + for i, child in enumerate(self.enumerators or []): + nodelist.append(("enumerators[%d]" % i, child)) + return tuple(nodelist) + + attr_names = () + +class ExprList(Node): + def __init__(self, exprs, coord=None): + self.exprs = exprs + self.coord = coord + + def children(self): + nodelist = [] + for i, child in enumerate(self.exprs or []): + nodelist.append(("exprs[%d]" % i, child)) + return tuple(nodelist) + + attr_names = () + +class FileAST(Node): + def __init__(self, ext, coord=None): + self.ext = ext + self.coord = coord + + def children(self): + nodelist = [] + for i, child in enumerate(self.ext or []): + nodelist.append(("ext[%d]" % i, child)) + return tuple(nodelist) + + attr_names = () + +class For(Node): + def __init__(self, init, cond, next, stmt, coord=None): + self.init = init + self.cond = cond + self.next = next + self.stmt = stmt + self.coord = coord + + def children(self): + nodelist = [] + if self.init is not None: nodelist.append(("init", self.init)) + if self.cond is not None: nodelist.append(("cond", self.cond)) + if self.next is not None: nodelist.append(("next", self.next)) + if self.stmt is not None: nodelist.append(("stmt", self.stmt)) + return tuple(nodelist) + + attr_names = () + +class FuncCall(Node): + def __init__(self, name, args, coord=None): + self.name = name + self.args = args + self.coord = coord + + def children(self): + nodelist = [] + if self.name is not None: nodelist.append(("name", self.name)) + if self.args is not None: nodelist.append(("args", self.args)) + return tuple(nodelist) + + attr_names = () + +class FuncDecl(Node): + def __init__(self, args, type, coord=None): + self.args = args + self.type = type + self.coord = coord + + def children(self): + nodelist = [] + if self.args is not None: nodelist.append(("args", self.args)) + if self.type is not None: nodelist.append(("type", self.type)) + return tuple(nodelist) + + attr_names = () + +class FuncDef(Node): + def __init__(self, decl, param_decls, body, coord=None): + self.decl = decl + self.param_decls = param_decls + self.body = body + self.coord = coord + + def children(self): + nodelist = [] + if self.decl is not None: nodelist.append(("decl", self.decl)) + if self.body is not None: nodelist.append(("body", self.body)) + for i, child in enumerate(self.param_decls or []): + nodelist.append(("param_decls[%d]" % i, child)) + return tuple(nodelist) + + attr_names = () + +class Goto(Node): + def __init__(self, name, coord=None): + self.name = name + self.coord = coord + + def children(self): + nodelist = [] + return tuple(nodelist) + + attr_names = ('name',) + +class ID(Node): + def __init__(self, name, coord=None): + self.name = name + self.coord = coord + + def children(self): + nodelist = [] + return tuple(nodelist) + + attr_names = ('name',) + +class IdentifierType(Node): + def __init__(self, names, coord=None): + self.names = names + self.coord = coord + + def children(self): + nodelist = [] + return tuple(nodelist) + + attr_names = ('names',) + +class If(Node): + def __init__(self, cond, iftrue, iffalse, coord=None): + self.cond = cond + self.iftrue = iftrue + self.iffalse = iffalse + self.coord = coord + + def children(self): + nodelist = [] + if self.cond is not None: nodelist.append(("cond", self.cond)) + if self.iftrue is not None: nodelist.append(("iftrue", self.iftrue)) + if self.iffalse is not None: nodelist.append(("iffalse", self.iffalse)) + return tuple(nodelist) + + attr_names = () + +class InitList(Node): + def __init__(self, exprs, coord=None): + self.exprs = exprs + self.coord = coord + + def children(self): + nodelist = [] + for i, child in enumerate(self.exprs or []): + nodelist.append(("exprs[%d]" % i, child)) + return tuple(nodelist) + + attr_names = () + +class Label(Node): + def __init__(self, name, stmt, coord=None): + self.name = name + self.stmt = stmt + self.coord = coord + + def children(self): + nodelist = [] + if self.stmt is not None: nodelist.append(("stmt", self.stmt)) + return tuple(nodelist) + + attr_names = ('name',) + +class NamedInitializer(Node): + def __init__(self, name, expr, coord=None): + self.name = name + self.expr = expr + self.coord = coord + + def children(self): + nodelist = [] + if self.expr is not None: nodelist.append(("expr", self.expr)) + for i, child in enumerate(self.name or []): + nodelist.append(("name[%d]" % i, child)) + return tuple(nodelist) + + attr_names = () + +class ParamList(Node): + def __init__(self, params, coord=None): + self.params = params + self.coord = coord + + def children(self): + nodelist = [] + for i, child in enumerate(self.params or []): + nodelist.append(("params[%d]" % i, child)) + return tuple(nodelist) + + attr_names = () + +class PtrDecl(Node): + def __init__(self, quals, type, coord=None): + self.quals = quals + self.type = type + self.coord = coord + + def children(self): + nodelist = [] + if self.type is not None: nodelist.append(("type", self.type)) + return tuple(nodelist) + + attr_names = ('quals',) + +class Return(Node): + def __init__(self, expr, coord=None): + self.expr = expr + self.coord = coord + + def children(self): + nodelist = [] + if self.expr is not None: nodelist.append(("expr", self.expr)) + return tuple(nodelist) + + attr_names = () + +class Struct(Node): + def __init__(self, name, decls, coord=None): + self.name = name + self.decls = decls + self.coord = coord + + def children(self): + nodelist = [] + for i, child in enumerate(self.decls or []): + nodelist.append(("decls[%d]" % i, child)) + return tuple(nodelist) + + attr_names = ('name',) + +class StructRef(Node): + def __init__(self, name, type, field, coord=None): + self.name = name + self.type = type + self.field = field + self.coord = coord + + def children(self): + nodelist = [] + if self.name is not None: nodelist.append(("name", self.name)) + if self.field is not None: nodelist.append(("field", self.field)) + return tuple(nodelist) + + attr_names = ('type',) + +class Switch(Node): + def __init__(self, cond, stmt, coord=None): + self.cond = cond + self.stmt = stmt + self.coord = coord + + def children(self): + nodelist = [] + if self.cond is not None: nodelist.append(("cond", self.cond)) + if self.stmt is not None: nodelist.append(("stmt", self.stmt)) + return tuple(nodelist) + + attr_names = () + +class TernaryOp(Node): + def __init__(self, cond, iftrue, iffalse, coord=None): + self.cond = cond + self.iftrue = iftrue + self.iffalse = iffalse + self.coord = coord + + def children(self): + nodelist = [] + if self.cond is not None: nodelist.append(("cond", self.cond)) + if self.iftrue is not None: nodelist.append(("iftrue", self.iftrue)) + if self.iffalse is not None: nodelist.append(("iffalse", self.iffalse)) + return tuple(nodelist) + + attr_names = () + +class TypeDecl(Node): + def __init__(self, declname, quals, type, coord=None): + self.declname = declname + self.quals = quals + self.type = type + self.coord = coord + + def children(self): + nodelist = [] + if self.type is not None: nodelist.append(("type", self.type)) + return tuple(nodelist) + + attr_names = ('declname','quals',) + +class Typedef(Node): + def __init__(self, name, quals, storage, type, coord=None): + self.name = name + self.quals = quals + self.storage = storage + self.type = type + self.coord = coord + + def children(self): + nodelist = [] + if self.type is not None: nodelist.append(("type", self.type)) + return tuple(nodelist) + + attr_names = ('name','quals','storage',) + +class Typename(Node): + def __init__(self, quals, type, coord=None): + self.quals = quals + self.type = type + self.coord = coord + + def children(self): + nodelist = [] + if self.type is not None: nodelist.append(("type", self.type)) + return tuple(nodelist) + + attr_names = ('quals',) + +class UnaryOp(Node): + def __init__(self, op, expr, coord=None): + self.op = op + self.expr = expr + self.coord = coord + + def children(self): + nodelist = [] + if self.expr is not None: nodelist.append(("expr", self.expr)) + return tuple(nodelist) + + attr_names = ('op',) + +class Union(Node): + def __init__(self, name, decls, coord=None): + self.name = name + self.decls = decls + self.coord = coord + + def children(self): + nodelist = [] + for i, child in enumerate(self.decls or []): + nodelist.append(("decls[%d]" % i, child)) + return tuple(nodelist) + + attr_names = ('name',) + +class While(Node): + def __init__(self, cond, stmt, coord=None): + self.cond = cond + self.stmt = stmt + self.coord = coord + + def children(self): + nodelist = [] + if self.cond is not None: nodelist.append(("cond", self.cond)) + if self.stmt is not None: nodelist.append(("stmt", self.stmt)) + return tuple(nodelist) + + attr_names = () + diff --git a/lib_pypy/cffi/_pycparser/c_generator.py b/lib_pypy/cffi/_pycparser/c_generator.py new file mode 100644 --- /dev/null +++ b/lib_pypy/cffi/_pycparser/c_generator.py @@ -0,0 +1,402 @@ +#------------------------------------------------------------------------------ +# pycparser: c_generator.py +# +# C code generator from pycparser AST nodes. +# +# Copyright (C) 2008-2012, Eli Bendersky +# License: BSD +#------------------------------------------------------------------------------ +from . import c_ast + + +class CGenerator(object): + """ Uses the same visitor pattern as c_ast.NodeVisitor, but modified to + return a value from each visit method, using string accumulation in + generic_visit. + """ + def __init__(self): + self.output = '' + + # Statements start with indentation of self.indent_level spaces, using + # the _make_indent method + # + self.indent_level = 0 + + def _make_indent(self): + return ' ' * self.indent_level + + def visit(self, node): + method = 'visit_' + node.__class__.__name__ + return getattr(self, method, self.generic_visit)(node) + + def generic_visit(self, node): + #~ print('generic:', type(node)) + if node is None: + return '' + else: + return ''.join(self.visit(c) for c in node.children()) + + def visit_Constant(self, n): + return n.value + + def visit_ID(self, n): + return n.name + + def visit_ArrayRef(self, n): + arrref = self._parenthesize_unless_simple(n.name) + return arrref + '[' + self.visit(n.subscript) + ']' + + def visit_StructRef(self, n): + sref = self._parenthesize_unless_simple(n.name) + return sref + n.type + self.visit(n.field) + + def visit_FuncCall(self, n): + fref = self._parenthesize_unless_simple(n.name) + return fref + '(' + self.visit(n.args) + ')' + + def visit_UnaryOp(self, n): + operand = self._parenthesize_unless_simple(n.expr) + if n.op == 'p++': + return '%s++' % operand + elif n.op == 'p--': + return '%s--' % operand + elif n.op == 'sizeof': + # Always parenthesize the argument of sizeof since it can be + # a name. + return 'sizeof(%s)' % self.visit(n.expr) + else: + return '%s%s' % (n.op, operand) + + def visit_BinaryOp(self, n): + lval_str = self._parenthesize_if(n.left, + lambda d: not self._is_simple_node(d)) + rval_str = self._parenthesize_if(n.right, + lambda d: not self._is_simple_node(d)) + return '%s %s %s' % (lval_str, n.op, rval_str) + + def visit_Assignment(self, n): + rval_str = self._parenthesize_if( + n.rvalue, + lambda n: isinstance(n, c_ast.Assignment)) + return '%s %s %s' % (self.visit(n.lvalue), n.op, rval_str) + + def visit_IdentifierType(self, n): + return ' '.join(n.names) + + def visit_Decl(self, n, no_type=False): + # no_type is used when a Decl is part of a DeclList, where the type is + # explicitly only for the first delaration in a list. + # + s = n.name if no_type else self._generate_decl(n) + if n.bitsize: s += ' : ' + self.visit(n.bitsize) + if n.init: + if isinstance(n.init, c_ast.InitList): + s += ' = {' + self.visit(n.init) + '}' + elif isinstance(n.init, c_ast.ExprList): + s += ' = (' + self.visit(n.init) + ')' + else: + s += ' = ' + self.visit(n.init) + return s + + def visit_DeclList(self, n): + s = self.visit(n.decls[0]) + if len(n.decls) > 1: + s += ', ' + ', '.join(self.visit_Decl(decl, no_type=True) + for decl in n.decls[1:]) + return s + + def visit_Typedef(self, n): + s = '' + if n.storage: s += ' '.join(n.storage) + ' ' + s += self._generate_type(n.type) + return s + + def visit_Cast(self, n): + s = '(' + self._generate_type(n.to_type) + ')' + return s + ' ' + self._parenthesize_unless_simple(n.expr) + + def visit_ExprList(self, n): + visited_subexprs = [] + for expr in n.exprs: + if isinstance(expr, c_ast.ExprList): + visited_subexprs.append('{' + self.visit(expr) + '}') + else: + visited_subexprs.append(self.visit(expr)) + return ', '.join(visited_subexprs) + + def visit_InitList(self, n): + visited_subexprs = [] + for expr in n.exprs: + if isinstance(expr, c_ast.InitList): + visited_subexprs.append('(' + self.visit(expr) + ')') + else: + visited_subexprs.append(self.visit(expr)) + return ', '.join(visited_subexprs) + + def visit_Enum(self, n): + s = 'enum' + if n.name: s += ' ' + n.name + if n.values: + s += ' {' + for i, enumerator in enumerate(n.values.enumerators): + s += enumerator.name + if enumerator.value: + s += ' = ' + self.visit(enumerator.value) + if i != len(n.values.enumerators) - 1: + s += ', ' + s += '}' + return s + + def visit_FuncDef(self, n): + decl = self.visit(n.decl) + self.indent_level = 0 + body = self.visit(n.body) + if n.param_decls: + knrdecls = ';\n'.join(self.visit(p) for p in n.param_decls) + return decl + '\n' + knrdecls + ';\n' + body + '\n' + else: + return decl + '\n' + body + '\n' + + def visit_FileAST(self, n): + s = '' + for ext in n.ext: + if isinstance(ext, c_ast.FuncDef): + s += self.visit(ext) + else: + s += self.visit(ext) + ';\n' + return s + + def visit_Compound(self, n): + s = self._make_indent() + '{\n' + self.indent_level += 2 + if n.block_items: + s += ''.join(self._generate_stmt(stmt) for stmt in n.block_items) + self.indent_level -= 2 + s += self._make_indent() + '}\n' + return s + + def visit_EmptyStatement(self, n): + return ';' + + def visit_ParamList(self, n): + return ', '.join(self.visit(param) for param in n.params) + + def visit_Return(self, n): + s = 'return' + if n.expr: s += ' ' + self.visit(n.expr) + return s + ';' + + def visit_Break(self, n): + return 'break;' + + def visit_Continue(self, n): + return 'continue;' + + def visit_TernaryOp(self, n): + s = self.visit(n.cond) + ' ? ' + s += self.visit(n.iftrue) + ' : ' + s += self.visit(n.iffalse) + return s + + def visit_If(self, n): + s = 'if (' + if n.cond: s += self.visit(n.cond) + s += ')\n' + s += self._generate_stmt(n.iftrue, add_indent=True) + if n.iffalse: + s += self._make_indent() + 'else\n' + s += self._generate_stmt(n.iffalse, add_indent=True) + return s + + def visit_For(self, n): + s = 'for (' + if n.init: s += self.visit(n.init) + s += ';' + if n.cond: s += ' ' + self.visit(n.cond) + s += ';' + if n.next: s += ' ' + self.visit(n.next) + s += ')\n' + s += self._generate_stmt(n.stmt, add_indent=True) + return s + + def visit_While(self, n): + s = 'while (' + if n.cond: s += self.visit(n.cond) + s += ')\n' + s += self._generate_stmt(n.stmt, add_indent=True) + return s + + def visit_DoWhile(self, n): + s = 'do\n' + s += self._generate_stmt(n.stmt, add_indent=True) + s += self._make_indent() + 'while (' + if n.cond: s += self.visit(n.cond) + s += ');' + return s + + def visit_Switch(self, n): + s = 'switch (' + self.visit(n.cond) + ')\n' + s += self._generate_stmt(n.stmt, add_indent=True) + return s + + def visit_Case(self, n): + s = 'case ' + self.visit(n.expr) + ':\n' + for stmt in n.stmts: + s += self._generate_stmt(stmt, add_indent=True) + return s + + def visit_Default(self, n): + s = 'default:\n' + for stmt in n.stmts: + s += self._generate_stmt(stmt, add_indent=True) + return s + + def visit_Label(self, n): + return n.name + ':\n' + self._generate_stmt(n.stmt) + + def visit_Goto(self, n): + return 'goto ' + n.name + ';' + + def visit_EllipsisParam(self, n): + return '...' + + def visit_Struct(self, n): + return self._generate_struct_union(n, 'struct') + + def visit_Typename(self, n): + return self._generate_type(n.type) + + def visit_Union(self, n): + return self._generate_struct_union(n, 'union') + + def visit_NamedInitializer(self, n): + s = '' + for name in n.name: + if isinstance(name, c_ast.ID): + s += '.' + name.name + elif isinstance(name, c_ast.Constant): + s += '[' + name.value + ']' + s += ' = ' + self.visit(n.expr) + return s + + def _generate_struct_union(self, n, name): + """ Generates code for structs and unions. name should be either + 'struct' or union. + """ + s = name + ' ' + (n.name or '') + if n.decls: + s += '\n' + s += self._make_indent() + self.indent_level += 2 + s += '{\n' + for decl in n.decls: + s += self._generate_stmt(decl) + self.indent_level -= 2 + s += self._make_indent() + '}' + return s + + def _generate_stmt(self, n, add_indent=False): + """ Generation from a statement node. This method exists as a wrapper + for individual visit_* methods to handle different treatment of + some statements in this context. + """ + typ = type(n) + if add_indent: self.indent_level += 2 + indent = self._make_indent() + if add_indent: self.indent_level -= 2 + + if typ in ( + c_ast.Decl, c_ast.Assignment, c_ast.Cast, c_ast.UnaryOp, + c_ast.BinaryOp, c_ast.TernaryOp, c_ast.FuncCall, c_ast.ArrayRef, + c_ast.StructRef, c_ast.Constant, c_ast.ID, c_ast.Typedef): + # These can also appear in an expression context so no semicolon + # is added to them automatically + # + return indent + self.visit(n) + ';\n' + elif typ in (c_ast.Compound,): + # No extra indentation required before the opening brace of a + # compound - because it consists of multiple lines it has to + # compute its own indentation. + # + return self.visit(n) + else: + return indent + self.visit(n) + '\n' + + def _generate_decl(self, n): + """ Generation from a Decl node. + """ + s = '' + if n.funcspec: s = ' '.join(n.funcspec) + ' ' + if n.storage: s += ' '.join(n.storage) + ' ' + s += self._generate_type(n.type) + return s + + def _generate_type(self, n, modifiers=[]): + """ Recursive generation from a type node. n is the type node. + modifiers collects the PtrDecl, ArrayDecl and FuncDecl modifiers + encountered on the way down to a TypeDecl, to allow proper + generation from it. + """ + typ = type(n) + #~ print(n, modifiers) + + if typ == c_ast.TypeDecl: + s = '' + if n.quals: s += ' '.join(n.quals) + ' ' + s += self.visit(n.type) + + nstr = n.declname if n.declname else '' + # Resolve modifiers. + # Wrap in parens to distinguish pointer to array and pointer to + # function syntax. + # + for i, modifier in enumerate(modifiers): + if isinstance(modifier, c_ast.ArrayDecl): + if (i != 0 and isinstance(modifiers[i - 1], c_ast.PtrDecl)): + nstr = '(' + nstr + ')' + nstr += '[' + self.visit(modifier.dim) + ']' + elif isinstance(modifier, c_ast.FuncDecl): + if (i != 0 and isinstance(modifiers[i - 1], c_ast.PtrDecl)): + nstr = '(' + nstr + ')' + nstr += '(' + self.visit(modifier.args) + ')' + elif isinstance(modifier, c_ast.PtrDecl): + if modifier.quals: + nstr = '* %s %s' % (' '.join(modifier.quals), nstr) + else: + nstr = '*' + nstr + if nstr: s += ' ' + nstr + return s + elif typ == c_ast.Decl: + return self._generate_decl(n.type) + elif typ == c_ast.Typename: + return self._generate_type(n.type) + elif typ == c_ast.IdentifierType: + return ' '.join(n.names) + ' ' + elif typ in (c_ast.ArrayDecl, c_ast.PtrDecl, c_ast.FuncDecl): + return self._generate_type(n.type, modifiers + [n]) + else: + return self.visit(n) + + def _parenthesize_if(self, n, condition): + """ Visits 'n' and returns its string representation, parenthesized + if the condition function applied to the node returns True. + """ + s = self.visit(n) + if condition(n): + return '(' + s + ')' + else: + return s + + def _parenthesize_unless_simple(self, n): + """ Common use case for _parenthesize_if + """ + return self._parenthesize_if(n, lambda d: not self._is_simple_node(d)) + + def _is_simple_node(self, n): + """ Returns True for nodes that are "simple" - i.e. nodes that always + have higher precedence than operators. + """ + return isinstance(n,( c_ast.Constant, c_ast.ID, c_ast.ArrayRef, + c_ast.StructRef, c_ast.FuncCall)) + + diff --git a/lib_pypy/cffi/_pycparser/c_lexer.py b/lib_pypy/cffi/_pycparser/c_lexer.py new file mode 100644 --- /dev/null +++ b/lib_pypy/cffi/_pycparser/c_lexer.py @@ -0,0 +1,481 @@ +# pycparser: c_lexer.py +# +# CLexer class: lexer for the C language +# +# Copyright (C) 2008-2011, Eli Bendersky +# License: BSD +#----------------------------------------------------------------- + +import re +import sys + +from .ply import lex +from .ply.lex import TOKEN + + +class CLexer(object): + """ A lexer for the C language. After building it, set the + input text with input(), and call token() to get new + tokens. + + The public attribute filename can be set to an initial + filaneme, but the lexer will update it upon #line + directives. + """ + def __init__(self, error_func, type_lookup_func): + """ Create a new Lexer. + + error_func: + An error function. Will be called with an error + message, line and column as arguments, in case of + an error during lexing. + + type_lookup_func: + A type lookup function. Given a string, it must + return True IFF this string is a name of a type + that was defined with a typedef earlier. + """ + self.error_func = error_func + self.type_lookup_func = type_lookup_func + self.filename = '' + + # Allow either "# line" or "# " to support GCC's + # cpp output + # + self.line_pattern = re.compile('([ \t]*line\W)|([ \t]*\d+)') + + self.pragma_pattern = re.compile('[ \t]*pragma\W') + + def build(self, **kwargs): + """ Builds the lexer from the specification. Must be + called after the lexer object is created. + + This method exists separately, because the PLY + manual warns against calling lex.lex inside + __init__ + """ + self.lexer = lex.lex(object=self, **kwargs) + + def reset_lineno(self): + """ Resets the internal line number counter of the lexer. + """ + self.lexer.lineno = 1 + + def input(self, text): + self.lexer.input(text) + + def token(self): + g = self.lexer.token() + return g + + def find_tok_column(self, token): + """ Find the column of the token in its line. + """ + last_cr = self.lexer.lexdata.rfind('\n', 0, token.lexpos) + return token.lexpos - last_cr + + ######################-- PRIVATE --###################### + + ## + ## Internal auxiliary methods + ## + def _error(self, msg, token): + location = self._make_tok_location(token) + self.error_func(msg, location[0], location[1]) + self.lexer.skip(1) + + def _make_tok_location(self, token): + return (token.lineno, self.find_tok_column(token)) + + ## + ## Reserved keywords + ## From noreply at buildbot.pypy.org Tue Apr 2 21:43:58 2013 From: noreply at buildbot.pypy.org (fijal) Date: Tue, 2 Apr 2013 21:43:58 +0200 (CEST) Subject: [pypy-commit] pypy default: try to add egg info for cffi Message-ID: <20130402194358.737CD1C0675@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r62930:b2e3aff13ba5 Date: 2013-04-02 21:43 +0200 http://bitbucket.org/pypy/pypy/changeset/b2e3aff13ba5/ Log: try to add egg info for cffi diff --git a/lib-python/2/cffi.egg-info b/lib-python/2/cffi.egg-info new file mode 100644 --- /dev/null +++ b/lib-python/2/cffi.egg-info @@ -0,0 +1,10 @@ +Metadata-Version: 1.0 +Name: cffi +Version: 0.6 +Summary: Foreign Function Interface for Python calling C code. +Home-page: http://cffi.readthedocs.org +Author: Armin Rigo, Maciej Fijalkowski +Author-email: python-cffi at googlegroups.com +License: MIT +Description: UNKNOWN +Platform: UNKNOWN From noreply at buildbot.pypy.org Tue Apr 2 23:22:22 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Tue, 2 Apr 2013 23:22:22 +0200 (CEST) Subject: [pypy-commit] pypy default: fix pexpect handling Message-ID: <20130402212222.6CEA81C0228@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: Changeset: r62931:f9a1fdbded60 Date: 2013-04-02 14:21 -0700 http://bitbucket.org/pypy/pypy/changeset/f9a1fdbded60/ Log: fix pexpect handling diff --git a/rpython/rtyper/module/test/test_ll_termios.py b/rpython/rtyper/module/test/test_ll_termios.py --- a/rpython/rtyper/module/test/test_ll_termios.py +++ b/rpython/rtyper/module/test/test_ll_termios.py @@ -19,10 +19,8 @@ print str(termios.tcgetattr(2)[:-1]) ''') child = pexpect.spawn('python', [str(fname)]) - child.logfile = sys.stderr - x = child.wait() - assert x == 0 - mod.TCGETATTR = child.readlines()[0][:-2] + child.expect(pexpect.EOF) + mod.TCGETATTR = child.before[:-2] class TestLLTermios(object): From noreply at buildbot.pypy.org Wed Apr 3 00:00:44 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Wed, 3 Apr 2013 00:00:44 +0200 (CEST) Subject: [pypy-commit] pypy default: cleanup f9a1fdbded60 Message-ID: <20130402220044.7846D1C0675@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r62932:d710f80233d0 Date: 2013-04-02 18:00 -0400 http://bitbucket.org/pypy/pypy/changeset/d710f80233d0/ Log: cleanup f9a1fdbded60 diff --git a/rpython/rtyper/module/test/test_ll_termios.py b/rpython/rtyper/module/test/test_ll_termios.py --- a/rpython/rtyper/module/test/test_ll_termios.py +++ b/rpython/rtyper/module/test/test_ll_termios.py @@ -18,9 +18,11 @@ import termios print str(termios.tcgetattr(2)[:-1]) ''') - child = pexpect.spawn('python', [str(fname)]) + child = pexpect.spawn('python', [str(fname)], logfile=sys.stderr) child.expect(pexpect.EOF) mod.TCGETATTR = child.before[:-2] + child.close() + assert child.exitstatus == 0 class TestLLTermios(object): @@ -29,7 +31,7 @@ child = pexpect.spawn(str(arg.builder.executable_name)) child.expect(re.escape(expected)) assert child.status is None - + def test_tcgetattr(self): from rpython.translator.c.test.test_genc import compile from rpython.rlib import rtermios @@ -44,7 +46,7 @@ from rpython.translator.c.test.test_genc import compile from rpython.rlib import rtermios import os, errno - def runs_tcgetattr(): + def runs_tcgetattr(): fd = os.open('.', 0, 0777) try: rtermios.tcgetattr(fd) @@ -54,7 +56,7 @@ fn = compile(runs_tcgetattr, [], backendopt=False) self.run(fn, "ok") - + def test_tcsetattr(self): # a test, which doesn't even check anything. # I've got no idea how to test it to be honest :-( @@ -100,4 +102,3 @@ attr[3] |= termios.ICANON rtermios.tcsetattr(2, termios.TCSANOW, attr) self.run_test(f) - From noreply at buildbot.pypy.org Wed Apr 3 02:22:12 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Wed, 3 Apr 2013 02:22:12 +0200 (CEST) Subject: [pypy-commit] pypy py3k: fix translation Message-ID: <20130403002212.666F51C0675@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r62933:9aa2731f9946 Date: 2013-04-02 17:21 -0700 http://bitbucket.org/pypy/pypy/changeset/9aa2731f9946/ Log: fix translation diff --git a/pypy/objspace/std/model.py b/pypy/objspace/std/model.py --- a/pypy/objspace/std/model.py +++ b/pypy/objspace/std/model.py @@ -22,7 +22,7 @@ } IDTAG_INT = 1 -#IDTAG_LONG = 3 +IDTAG_LONG = 3 IDTAG_FLOAT = 5 IDTAG_COMPLEX = 7 From noreply at buildbot.pypy.org Wed Apr 3 08:17:36 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 3 Apr 2013 08:17:36 +0200 (CEST) Subject: [pypy-commit] pypy default: Only run those tests with -A Message-ID: <20130403061736.ECD3C1C01E1@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r62934:9775f9f216ea Date: 2013-04-03 08:16 +0200 http://bitbucket.org/pypy/pypy/changeset/9775f9f216ea/ Log: Only run those tests with -A diff --git a/pypy/module/test_lib_pypy/cffi_tests/conftest.py b/pypy/module/test_lib_pypy/cffi_tests/conftest.py new file mode 100644 --- /dev/null +++ b/pypy/module/test_lib_pypy/cffi_tests/conftest.py @@ -0,0 +1,6 @@ + +def pytest_ignore_collect(path, config): + if config.option.runappdirect: + return False + # only run if -A is specified + return True From noreply at buildbot.pypy.org Wed Apr 3 08:17:38 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 3 Apr 2013 08:17:38 +0200 (CEST) Subject: [pypy-commit] pypy default: merge Message-ID: <20130403061738.5524C1C030B@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r62935:81f66d14e6f8 Date: 2013-04-03 08:17 +0200 http://bitbucket.org/pypy/pypy/changeset/81f66d14e6f8/ Log: merge diff --git a/rpython/rtyper/module/test/test_ll_termios.py b/rpython/rtyper/module/test/test_ll_termios.py --- a/rpython/rtyper/module/test/test_ll_termios.py +++ b/rpython/rtyper/module/test/test_ll_termios.py @@ -18,11 +18,11 @@ import termios print str(termios.tcgetattr(2)[:-1]) ''') - child = pexpect.spawn('python', [str(fname)]) - child.logfile = sys.stderr - x = child.wait() - assert x == 0 - mod.TCGETATTR = child.readlines()[0][:-2] + child = pexpect.spawn('python', [str(fname)], logfile=sys.stderr) + child.expect(pexpect.EOF) + mod.TCGETATTR = child.before[:-2] + child.close() + assert child.exitstatus == 0 class TestLLTermios(object): @@ -31,7 +31,7 @@ child = pexpect.spawn(str(arg.builder.executable_name)) child.expect(re.escape(expected)) assert child.status is None - + def test_tcgetattr(self): from rpython.translator.c.test.test_genc import compile from rpython.rlib import rtermios @@ -46,7 +46,7 @@ from rpython.translator.c.test.test_genc import compile from rpython.rlib import rtermios import os, errno - def runs_tcgetattr(): + def runs_tcgetattr(): fd = os.open('.', 0, 0777) try: rtermios.tcgetattr(fd) @@ -56,7 +56,7 @@ fn = compile(runs_tcgetattr, [], backendopt=False) self.run(fn, "ok") - + def test_tcsetattr(self): # a test, which doesn't even check anything. # I've got no idea how to test it to be honest :-( @@ -102,4 +102,3 @@ attr[3] |= termios.ICANON rtermios.tcsetattr(2, termios.TCSANOW, attr) self.run_test(f) - From noreply at buildbot.pypy.org Wed Apr 3 08:22:50 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 3 Apr 2013 08:22:50 +0200 (CEST) Subject: [pypy-commit] cffi default: use abspath in tests Message-ID: <20130403062250.386861C030B@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r1225:ba77a83bc4db Date: 2013-04-03 08:22 +0200 http://bitbucket.org/cffi/cffi/changeset/ba77a83bc4db/ Log: use abspath in tests diff --git a/testing/test_zintegration.py b/testing/test_zintegration.py --- a/testing/test_zintegration.py +++ b/testing/test_zintegration.py @@ -7,7 +7,7 @@ tmpdir = udir.join(name) try: subprocess.check_call(['virtualenv', '--distribute', - '-p', sys.executable, + '-p', os.path.abspath(sys.executable), str(tmpdir)]) except OSError as e: py.test.skip("Cannot execute virtualenv: %s" % (e,)) From noreply at buildbot.pypy.org Wed Apr 3 08:22:55 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 3 Apr 2013 08:22:55 +0200 (CEST) Subject: [pypy-commit] pypy default: reimport cffi Message-ID: <20130403062255.AD61F1C030B@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r62936:713dc024b11b Date: 2013-04-03 08:21 +0200 http://bitbucket.org/pypy/pypy/changeset/713dc024b11b/ Log: reimport cffi diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_zintegration.py b/pypy/module/test_lib_pypy/cffi_tests/test_zintegration.py --- a/pypy/module/test_lib_pypy/cffi_tests/test_zintegration.py +++ b/pypy/module/test_lib_pypy/cffi_tests/test_zintegration.py @@ -7,7 +7,7 @@ tmpdir = udir.join(name) try: subprocess.check_call(['virtualenv', '--distribute', - '-p', sys.executable, + '-p', os.path.abspath(sys.executable), str(tmpdir)]) except OSError as e: py.test.skip("Cannot execute virtualenv: %s" % (e,)) From noreply at buildbot.pypy.org Wed Apr 3 08:27:52 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 3 Apr 2013 08:27:52 +0200 (CEST) Subject: [pypy-commit] pypy default: fix whatsnew Message-ID: <20130403062752.52B621C01E1@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r62937:63d97a479555 Date: 2013-04-03 08:24 +0200 http://bitbucket.org/pypy/pypy/changeset/63d97a479555/ Log: fix whatsnew diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -114,3 +114,4 @@ .. branch: extregistry-refactor .. branch: remove-list-smm +.. branch: bridge-logging From noreply at buildbot.pypy.org Wed Apr 3 08:37:40 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 3 Apr 2013 08:37:40 +0200 (CEST) Subject: [pypy-commit] pypy default: fix Message-ID: <20130403063740.25AB81C01E1@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r62938:62d1937a83d2 Date: 2013-04-03 08:37 +0200 http://bitbucket.org/pypy/pypy/changeset/62d1937a83d2/ Log: fix diff --git a/pypy/tool/jitlogparser/parser.py b/pypy/tool/jitlogparser/parser.py --- a/pypy/tool/jitlogparser/parser.py +++ b/pypy/tool/jitlogparser/parser.py @@ -34,7 +34,7 @@ self.descr = descr self._is_guard = name.startswith('guard_') if self._is_guard: - self.guard_no = int(self.descr[len(' Author: Maciej Fijalkowski Branch: Changeset: r62939:09c60a05dd39 Date: 2013-04-03 08:37 +0200 http://bitbucket.org/pypy/pypy/changeset/09c60a05dd39/ Log: more fixes for negatives diff --git a/pypy/tool/jitlogparser/storage.py b/pypy/tool/jitlogparser/storage.py --- a/pypy/tool/jitlogparser/storage.py +++ b/pypy/tool/jitlogparser/storage.py @@ -63,7 +63,7 @@ for loop_no, loop in enumerate(loops): for op in loop.operations: if op.name.startswith('guard_'): - guard_dict[int(op.descr[len(' Author: Maciej Fijalkowski Branch: Changeset: r62940:88fd66eefa33 Date: 2013-04-03 08:39 +0200 http://bitbucket.org/pypy/pypy/changeset/88fd66eefa33/ Log: there can be a - too diff --git a/pypy/tool/jitlogparser/parser.py b/pypy/tool/jitlogparser/parser.py --- a/pypy/tool/jitlogparser/parser.py +++ b/pypy/tool/jitlogparser/parser.py @@ -364,7 +364,7 @@ def import_log(logname, ParserCls=SimpleParser): log = parse_log_file(logname) - hex_re = '0x([\da-f]+)' + hex_re = '0x(-?[\da-f]+)' addrs = {} for entry in extract_category(log, 'jit-backend-addr'): m = re.search('bootstrap ' + hex_re, entry) @@ -416,7 +416,7 @@ labels = [0] if trace.comment and 'Guard' in trace.comment: descrs = ['bridge %d' % int( - re.search('Guard 0x([\da-f]+)', trace.comment).group(1), 16)] + re.search('Guard 0x(-?[\da-f]+)', trace.comment).group(1), 16)] else: descrs = ['entry ' + re.search('Loop (\d+)', trace.comment).group(1)] for i, op in enumerate(trace.operations): From noreply at buildbot.pypy.org Wed Apr 3 08:39:43 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 3 Apr 2013 08:39:43 +0200 (CEST) Subject: [pypy-commit] pypy default: and here Message-ID: <20130403063943.943E41C01E1@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r62941:fa72a9f2325c Date: 2013-04-03 08:39 +0200 http://bitbucket.org/pypy/pypy/changeset/fa72a9f2325c/ Log: and here diff --git a/pypy/tool/jitlogparser/parser.py b/pypy/tool/jitlogparser/parser.py --- a/pypy/tool/jitlogparser/parser.py +++ b/pypy/tool/jitlogparser/parser.py @@ -396,7 +396,7 @@ comm = loop.comment comm = comm.lower() if comm.startswith('# bridge'): - m = re.search('guard ([\da-f]+)', comm) + m = re.search('guard (-?[\da-f]+)', comm) name = 'guard ' + m.group(1) elif "(" in comm: name = comm[2:comm.find('(')-1] From noreply at buildbot.pypy.org Wed Apr 3 08:46:37 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 3 Apr 2013 08:46:37 +0200 (CEST) Subject: [pypy-commit] pypy default: if we're a bit unlucky, the bridge is the main path, so we end up Message-ID: <20130403064637.5F5FF1C01E1@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r62942:82d673cea68a Date: 2013-04-03 08:46 +0200 http://bitbucket.org/pypy/pypy/changeset/82d673cea68a/ Log: if we're a bit unlucky, the bridge is the main path, so we end up with a bridge-on-bridge instead. just relax this check diff --git a/pypy/module/pypyjit/test_pypy_c/test_jitlogparser.py b/pypy/module/pypyjit/test_pypy_c/test_jitlogparser.py --- a/pypy/module/pypyjit/test_pypy_c/test_jitlogparser.py +++ b/pypy/module/pypyjit/test_pypy_c/test_jitlogparser.py @@ -68,7 +68,7 @@ bridge = bridges.get(mangle_descr(op.descr)) if bridge is not None: mod_bridges.append(bridge) - assert len(mod_bridges) == 2 + assert len(mod_bridges) in (1, 2) # check that counts are reasonable (precise # may change in the future) assert N - 2000 < sum(l.count for l in fn_with_bridges_loops) < N From noreply at buildbot.pypy.org Wed Apr 3 09:16:48 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 3 Apr 2013 09:16:48 +0200 (CEST) Subject: [pypy-commit] pypy default: I think it's fine if codecs are not preimported, honestly Message-ID: <20130403071648.B4A141C0228@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r62943:17dbaa121d5d Date: 2013-04-03 09:16 +0200 http://bitbucket.org/pypy/pypy/changeset/17dbaa121d5d/ Log: I think it's fine if codecs are not preimported, honestly diff --git a/pypy/module/test_lib_pypy/test_site_extra.py b/pypy/module/test_lib_pypy/test_site_extra.py --- a/pypy/module/test_lib_pypy/test_site_extra.py +++ b/pypy/module/test_lib_pypy/test_site_extra.py @@ -2,7 +2,7 @@ def test_preimported_modules(): - lst = ['__builtin__', '_codecs', '_warnings', 'codecs', 'encodings', + lst = ['__builtin__', '_warnings', 'exceptions', 'signal', 'sys', 'zipimport'] g = os.popen("'%s' -c 'import sys; print sorted(sys.modules)'" % (sys.executable,)) From noreply at buildbot.pypy.org Wed Apr 3 09:45:27 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 3 Apr 2013 09:45:27 +0200 (CEST) Subject: [pypy-commit] cffi default: an attempt to not run it on older virtualenvs Message-ID: <20130403074527.DA9371C030B@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r1226:982940f8c484 Date: 2013-04-03 09:45 +0200 http://bitbucket.org/cffi/cffi/changeset/982940f8c484/ Log: an attempt to not run it on older virtualenvs diff --git a/testing/test_zintegration.py b/testing/test_zintegration.py --- a/testing/test_zintegration.py +++ b/testing/test_zintegration.py @@ -3,6 +3,18 @@ import subprocess from testing.udir import udir +def setup_module(mod): + if '__pypy__' in sys.builtin_module_names: + try: + ver = subprocess.check_output(['virtualenv', '--version']) + except OSError as e: + py.test.skip("Cannot execute virtualenv: %s" % (e,)) + # this check is absolutely broken, but I can't think about a better + # idea + if ((ver.startswith('1.9') and ver <= "1.9.1") or + ver[2] != '1'): + py.test.skip("pypy requires virtualenv >= 1.9.2") + def create_venv(name): tmpdir = udir.join(name) try: From noreply at buildbot.pypy.org Wed Apr 3 09:47:23 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 3 Apr 2013 09:47:23 +0200 (CEST) Subject: [pypy-commit] pypy default: reimport cffi Message-ID: <20130403074723.8E43D1C01E1@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r62944:3a51f6849889 Date: 2013-04-03 09:47 +0200 http://bitbucket.org/pypy/pypy/changeset/3a51f6849889/ Log: reimport cffi diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_zintegration.py b/pypy/module/test_lib_pypy/cffi_tests/test_zintegration.py --- a/pypy/module/test_lib_pypy/cffi_tests/test_zintegration.py +++ b/pypy/module/test_lib_pypy/cffi_tests/test_zintegration.py @@ -3,6 +3,18 @@ import subprocess from pypy.module.test_lib_pypy.cffi_tests.udir import udir +def setup_module(mod): + if '__pypy__' in sys.builtin_module_names: + try: + ver = subprocess.check_output(['virtualenv', '--version']) + except OSError as e: + py.test.skip("Cannot execute virtualenv: %s" % (e,)) + # this check is absolutely broken, but I can't think about a better + # idea + if ((ver.startswith('1.9') and ver <= "1.9.1") or + ver[2] != '1'): + py.test.skip("pypy requires virtualenv >= 1.9.2") + def create_venv(name): tmpdir = udir.join(name) try: From noreply at buildbot.pypy.org Wed Apr 3 09:52:33 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 3 Apr 2013 09:52:33 +0200 (CEST) Subject: [pypy-commit] pypy default: this test hangs on OS X, seems pyrepl is completely broken there, but I don't want to care Message-ID: <20130403075233.231771C030B@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r62945:8c742965eb99 Date: 2013-04-03 09:52 +0200 http://bitbucket.org/pypy/pypy/changeset/8c742965eb99/ Log: this test hangs on OS X, seems pyrepl is completely broken there, but I don't want to care diff --git a/pypy/module/test_lib_pypy/pyrepl/test_bugs.py b/pypy/module/test_lib_pypy/pyrepl/test_bugs.py --- a/pypy/module/test_lib_pypy/pyrepl/test_bugs.py +++ b/pypy/module/test_lib_pypy/pyrepl/test_bugs.py @@ -46,7 +46,7 @@ read_spec(spec, HistoricalTestReader) - at pytest.mark.skipif("os.name != 'posix'") + at pytest.mark.skipif("os.name != 'posix' or sys.platform='darwin'") def test_signal_failure(monkeypatch): import os import pty From noreply at buildbot.pypy.org Wed Apr 3 09:53:30 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 3 Apr 2013 09:53:30 +0200 (CEST) Subject: [pypy-commit] pypy default: oops Message-ID: <20130403075330.B4BBC1C030B@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r62946:994a2bcc7018 Date: 2013-04-03 09:53 +0200 http://bitbucket.org/pypy/pypy/changeset/994a2bcc7018/ Log: oops diff --git a/pypy/module/test_lib_pypy/pyrepl/test_bugs.py b/pypy/module/test_lib_pypy/pyrepl/test_bugs.py --- a/pypy/module/test_lib_pypy/pyrepl/test_bugs.py +++ b/pypy/module/test_lib_pypy/pyrepl/test_bugs.py @@ -46,7 +46,7 @@ read_spec(spec, HistoricalTestReader) - at pytest.mark.skipif("os.name != 'posix' or sys.platform='darwin'") + at pytest.mark.skipif("os.name != 'posix' or sys.platform == 'darwin'") def test_signal_failure(monkeypatch): import os import pty From noreply at buildbot.pypy.org Wed Apr 3 09:55:15 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 3 Apr 2013 09:55:15 +0200 (CEST) Subject: [pypy-commit] pypy default: revert those changes, we should either skip the entire dir or just forget it Message-ID: <20130403075515.5CC351C030B@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r62947:40f2d95fa9b4 Date: 2013-04-03 09:55 +0200 http://bitbucket.org/pypy/pypy/changeset/40f2d95fa9b4/ Log: revert those changes, we should either skip the entire dir or just forget it diff --git a/pypy/module/test_lib_pypy/pyrepl/test_bugs.py b/pypy/module/test_lib_pypy/pyrepl/test_bugs.py --- a/pypy/module/test_lib_pypy/pyrepl/test_bugs.py +++ b/pypy/module/test_lib_pypy/pyrepl/test_bugs.py @@ -46,7 +46,7 @@ read_spec(spec, HistoricalTestReader) - at pytest.mark.skipif("os.name != 'posix' or sys.platform == 'darwin'") + at pytest.mark.skipif("os.name != 'posix'") def test_signal_failure(monkeypatch): import os import pty From noreply at buildbot.pypy.org Wed Apr 3 10:03:41 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Wed, 3 Apr 2013 10:03:41 +0200 (CEST) Subject: [pypy-commit] pypy default: make sure encodings is always preimported to match cpython Message-ID: <20130403080341.854791C030B@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r62948:f160281ab661 Date: 2013-04-03 01:02 -0700 http://bitbucket.org/pypy/pypy/changeset/f160281ab661/ Log: make sure encodings is always preimported to match cpython diff --git a/lib-python/2/site.py b/lib-python/2/site.py --- a/lib-python/2/site.py +++ b/lib-python/2/site.py @@ -554,6 +554,8 @@ def import_builtin_stuff(): """PyPy specific: pre-import a few built-in modules, because some programs actually rely on them to be in sys.modules :-(""" + # encodings is imported sometimes but not always by app_main + import encodings import exceptions if 'zipimport' in sys.builtin_module_names: import zipimport From noreply at buildbot.pypy.org Wed Apr 3 10:03:42 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Wed, 3 Apr 2013 10:03:42 +0200 (CEST) Subject: [pypy-commit] pypy default: backout 17dbaa121d5d Message-ID: <20130403080342.D3D2B1C030B@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r62949:d3233835e793 Date: 2013-04-03 01:03 -0700 http://bitbucket.org/pypy/pypy/changeset/d3233835e793/ Log: backout 17dbaa121d5d diff --git a/pypy/module/test_lib_pypy/test_site_extra.py b/pypy/module/test_lib_pypy/test_site_extra.py --- a/pypy/module/test_lib_pypy/test_site_extra.py +++ b/pypy/module/test_lib_pypy/test_site_extra.py @@ -2,7 +2,7 @@ def test_preimported_modules(): - lst = ['__builtin__', '_warnings', + lst = ['__builtin__', '_codecs', '_warnings', 'codecs', 'encodings', 'exceptions', 'signal', 'sys', 'zipimport'] g = os.popen("'%s' -c 'import sys; print sorted(sys.modules)'" % (sys.executable,)) From noreply at buildbot.pypy.org Wed Apr 3 10:06:01 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 3 Apr 2013 10:06:01 +0200 (CEST) Subject: [pypy-commit] pypy curses_cffi: close to be merged branch Message-ID: <20130403080601.652F01C030B@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: curses_cffi Changeset: r62950:b11934bd68f0 Date: 2013-04-03 10:01 +0200 http://bitbucket.org/pypy/pypy/changeset/b11934bd68f0/ Log: close to be merged branch From noreply at buildbot.pypy.org Wed Apr 3 10:06:02 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 3 Apr 2013 10:06:02 +0200 (CEST) Subject: [pypy-commit] pypy default: merge curses_cffi Message-ID: <20130403080602.9C9901C030B@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r62951:f0b6bedc5a31 Date: 2013-04-03 10:01 +0200 http://bitbucket.org/pypy/pypy/changeset/f0b6bedc5a31/ Log: merge curses_cffi diff --git a/lib_pypy/_curses.py b/lib_pypy/_curses.py new file mode 100644 --- /dev/null +++ b/lib_pypy/_curses.py @@ -0,0 +1,1368 @@ +"""Reimplementation of the standard extension module '_curses' using cffi.""" + +import sys +from functools import wraps + +from cffi import FFI + +ffi = FFI() + +ffi.cdef(""" +typedef ... WINDOW; +typedef ... SCREEN; +typedef unsigned long mmask_t; +typedef unsigned char bool; +typedef unsigned long chtype; +typedef chtype attr_t; + +typedef struct +{ + short id; /* ID to distinguish multiple devices */ + int x, y, z; /* event coordinates (character-cell) */ + mmask_t bstate; /* button state bits */ +} +MEVENT; + +static const int ERR, OK; +static const int TRUE, FALSE; +static const int KEY_MIN, KEY_MAX; + +static const int COLOR_BLACK; +static const int COLOR_RED; +static const int COLOR_GREEN; +static const int COLOR_YELLOW; +static const int COLOR_BLUE; +static const int COLOR_MAGENTA; +static const int COLOR_CYAN; +static const int COLOR_WHITE; + +static const chtype A_ATTRIBUTES; +static const chtype A_NORMAL; +static const chtype A_STANDOUT; +static const chtype A_UNDERLINE; +static const chtype A_REVERSE; +static const chtype A_BLINK; +static const chtype A_DIM; +static const chtype A_BOLD; +static const chtype A_ALTCHARSET; +static const chtype A_INVIS; +static const chtype A_PROTECT; +static const chtype A_CHARTEXT; +static const chtype A_COLOR; + +static const int BUTTON1_RELEASED; +static const int BUTTON1_PRESSED; +static const int BUTTON1_CLICKED; +static const int BUTTON1_DOUBLE_CLICKED; +static const int BUTTON1_TRIPLE_CLICKED; +static const int BUTTON2_RELEASED; +static const int BUTTON2_PRESSED; +static const int BUTTON2_CLICKED; +static const int BUTTON2_DOUBLE_CLICKED; +static const int BUTTON2_TRIPLE_CLICKED; +static const int BUTTON3_RELEASED; +static const int BUTTON3_PRESSED; +static const int BUTTON3_CLICKED; +static const int BUTTON3_DOUBLE_CLICKED; +static const int BUTTON3_TRIPLE_CLICKED; +static const int BUTTON4_RELEASED; +static const int BUTTON4_PRESSED; +static const int BUTTON4_CLICKED; +static const int BUTTON4_DOUBLE_CLICKED; +static const int BUTTON4_TRIPLE_CLICKED; +static const int BUTTON_SHIFT; +static const int BUTTON_CTRL; +static const int BUTTON_ALT; +static const int ALL_MOUSE_EVENTS; +static const int REPORT_MOUSE_POSITION; + +int setupterm(char *, int, int *); + +WINDOW *stdscr; +int COLORS; +int COLOR_PAIRS; +int COLS; +int LINES; + +int baudrate(void); +int beep(void); +int box(WINDOW *, chtype, chtype); +bool can_change_color(void); +int cbreak(void); +int clearok(WINDOW *, bool); +int color_content(short, short*, short*, short*); +int copywin(const WINDOW*, WINDOW*, int, int, int, int, int, int, int); +int curs_set(int); +int def_prog_mode(void); +int def_shell_mode(void); +int delay_output(int); +int delwin(WINDOW *); +WINDOW * derwin(WINDOW *, int, int, int, int); +int doupdate(void); +int echo(void); +int endwin(void); +char erasechar(void); +void filter(void); +int flash(void); +int flushinp(void); +chtype getbkgd(WINDOW *); +WINDOW * getwin(FILE *); +int halfdelay(int); +bool has_colors(void); +bool has_ic(void); +bool has_il(void); +void idcok(WINDOW *, bool); +int idlok(WINDOW *, bool); +void immedok(WINDOW *, bool); +WINDOW * initscr(void); +int init_color(short, short, short, short); +int init_pair(short, short, short); +int intrflush(WINDOW *, bool); +bool isendwin(void); +bool is_linetouched(WINDOW *, int); +bool is_wintouched(WINDOW *); +const char * keyname(int); +int keypad(WINDOW *, bool); +char killchar(void); +int leaveok(WINDOW *, bool); +char * longname(void); +int meta(WINDOW *, bool); +int mvderwin(WINDOW *, int, int); +int mvwaddch(WINDOW *, int, int, const chtype); +int mvwaddnstr(WINDOW *, int, int, const char *, int); +int mvwaddstr(WINDOW *, int, int, const char *); +int mvwchgat(WINDOW *, int, int, int, attr_t, short, const void *); +int mvwdelch(WINDOW *, int, int); +int mvwgetch(WINDOW *, int, int); +int mvwgetnstr(WINDOW *, int, int, char *, int); +int mvwin(WINDOW *, int, int); +chtype mvwinch(WINDOW *, int, int); +int mvwinnstr(WINDOW *, int, int, char *, int); +int mvwinsch(WINDOW *, int, int, chtype); +int mvwinsnstr(WINDOW *, int, int, const char *, int); +int mvwinsstr(WINDOW *, int, int, const char *); +int napms(int); +WINDOW * newpad(int, int); +WINDOW * newwin(int, int, int, int); +int nl(void); +int nocbreak(void); +int nodelay(WINDOW *, bool); +int noecho(void); +int nonl(void); +void noqiflush(void); +int noraw(void); +int notimeout(WINDOW *, bool); +int overlay(const WINDOW*, WINDOW *); +int overwrite(const WINDOW*, WINDOW *); +int pair_content(short, short*, short*); +int pechochar(WINDOW *, const chtype); +int pnoutrefresh(WINDOW*, int, int, int, int, int, int); +int prefresh(WINDOW *, int, int, int, int, int, int); +int putwin(WINDOW *, FILE *); +void qiflush(void); +int raw(void); +int redrawwin(WINDOW *); +int resetty(void); +int reset_prog_mode(void); +int reset_shell_mode(void); +int savetty(void); +int scroll(WINDOW *); +int scrollok(WINDOW *, bool); +int start_color(void); +WINDOW * subpad(WINDOW *, int, int, int, int); +WINDOW * subwin(WINDOW *, int, int, int, int); +int syncok(WINDOW *, bool); +chtype termattrs(void); +char * termname(void); +int touchline(WINDOW *, int, int); +int touchwin(WINDOW *); +int typeahead(int); +int ungetch(int); +int untouchwin(WINDOW *); +void use_env(bool); +int waddch(WINDOW *, const chtype); +int waddnstr(WINDOW *, const char *, int); +int waddstr(WINDOW *, const char *); +int wattron(WINDOW *, int); +int wattroff(WINDOW *, int); +int wattrset(WINDOW *, int); +int wbkgd(WINDOW *, chtype); +void wbkgdset(WINDOW *, chtype); +int wborder(WINDOW *, chtype, chtype, chtype, chtype, + chtype, chtype, chtype, chtype); +int wchgat(WINDOW *, int, attr_t, short, const void *); +int wclear(WINDOW *); +int wclrtobot(WINDOW *); +int wclrtoeol(WINDOW *); +void wcursyncup(WINDOW *); +int wdelch(WINDOW *); +int wdeleteln(WINDOW *); +int wechochar(WINDOW *, const chtype); +int werase(WINDOW *); +int wgetch(WINDOW *); +int wgetnstr(WINDOW *, char *, int); +int whline(WINDOW *, chtype, int); +chtype winch(WINDOW *); +int winnstr(WINDOW *, char *, int); +int winsch(WINDOW *, chtype); +int winsdelln(WINDOW *, int); +int winsertln(WINDOW *); +int winsnstr(WINDOW *, const char *, int); +int winsstr(WINDOW *, const char *); +int wmove(WINDOW *, int, int); +int wresize(WINDOW *, int, int); +int wnoutrefresh(WINDOW *); +int wredrawln(WINDOW *, int, int); +int wrefresh(WINDOW *); +int wscrl(WINDOW *, int); +int wsetscrreg(WINDOW *, int, int); +int wstandout(WINDOW *); +int wstandend(WINDOW *); +void wsyncdown(WINDOW *); +void wsyncup(WINDOW *); +void wtimeout(WINDOW *, int); +int wtouchln(WINDOW *, int, int, int); +int wvline(WINDOW *, chtype, int); +int tigetflag(char *); +int tigetnum(char *); +char * tigetstr(char *); +int putp(const char *); +char * tparm(const char *, ...); +int getattrs(const WINDOW *); +int getcurx(const WINDOW *); +int getcury(const WINDOW *); +int getbegx(const WINDOW *); +int getbegy(const WINDOW *); +int getmaxx(const WINDOW *); +int getmaxy(const WINDOW *); +int getparx(const WINDOW *); +int getpary(const WINDOW *); + +int getmouse(MEVENT *); +int ungetmouse(MEVENT *); +mmask_t mousemask(mmask_t, mmask_t *); +bool wenclose(const WINDOW *, int, int); +int mouseinterval(int); + +void setsyx(int y, int x); +const char *unctrl(chtype); +int use_default_colors(void); + +int has_key(int); +bool is_term_resized(int, int); + +#define _m_STRICT_SYSV_CURSES ... +#define _m_NCURSES_MOUSE_VERSION ... +#define _m_NetBSD ... +int _m_ispad(WINDOW *); + +chtype acs_map[]; + +// For _curses_panel: + +typedef ... PANEL; + +WINDOW *panel_window(const PANEL *); +void update_panels(void); +int hide_panel(PANEL *); +int show_panel(PANEL *); +int del_panel(PANEL *); +int top_panel(PANEL *); +int bottom_panel(PANEL *); +PANEL *new_panel(WINDOW *); +PANEL *panel_above(const PANEL *); +PANEL *panel_below(const PANEL *); +int set_panel_userptr(PANEL *, void *); +const void *panel_userptr(const PANEL *); +int move_panel(PANEL *, int, int); +int replace_panel(PANEL *,WINDOW *); +int panel_hidden(const PANEL *); + +void _m_getsyx(int *yx); +""") + + +lib = ffi.verify(""" +#include +#include +#include + +#if defined STRICT_SYSV_CURSES +#define _m_STRICT_SYSV_CURSES TRUE +#else +#define _m_STRICT_SYSV_CURSES FALSE +#endif + +#if defined NCURSES_MOUSE_VERSION +#define _m_NCURSES_MOUSE_VERSION TRUE +#else +#define _m_NCURSES_MOUSE_VERSION FALSE +#endif + +#if defined __NetBSD__ +#define _m_NetBSD TRUE +#else +#define _m_NetBSD FALSE +#endif + +int _m_ispad(WINDOW *win) { +#if defined WINDOW_HAS_FLAGS + return (win->_flags & _ISPAD); +#else + return 0; +#endif +} + +void _m_getsyx(int *yx) { + getsyx(yx[0], yx[1]); +} +""", libraries=['ncurses', 'panel']) + + +def _copy_to_globals(name): + globals()[name] = getattr(lib, name) + + +def _setup(): + for name in ['ERR', 'OK', 'KEY_MIN', 'KEY_MAX', + 'A_ATTRIBUTES', 'A_NORMAL', 'A_STANDOUT', 'A_UNDERLINE', + 'A_REVERSE', 'A_BLINK', 'A_DIM', 'A_BOLD', 'A_ALTCHARSET', + 'A_PROTECT', 'A_CHARTEXT', 'A_COLOR', + 'COLOR_BLACK', 'COLOR_RED', 'COLOR_GREEN', 'COLOR_YELLOW', + 'COLOR_BLUE', 'COLOR_MAGENTA', 'COLOR_CYAN', 'COLOR_WHITE', + ]: + _copy_to_globals(name) + + if not lib._m_NetBSD: + _copy_to_globals('A_INVIS') + + for name in ['A_HORIZONTAL', 'A_LEFT', 'A_LOW', 'A_RIGHT', 'A_TOP', + 'A_VERTICAL', + ]: + if hasattr(lib, name): + _copy_to_globals(name) + + if lib._m_NCURSES_MOUSE_VERSION: + for name in ["BUTTON1_PRESSED", "BUTTON1_RELEASED", "BUTTON1_CLICKED", + "BUTTON1_DOUBLE_CLICKED", "BUTTON1_TRIPLE_CLICKED", + "BUTTON2_PRESSED", "BUTTON2_RELEASED", "BUTTON2_CLICKED", + "BUTTON2_DOUBLE_CLICKED", "BUTTON2_TRIPLE_CLICKED", + "BUTTON3_PRESSED", "BUTTON3_RELEASED", "BUTTON3_CLICKED", + "BUTTON3_DOUBLE_CLICKED", "BUTTON3_TRIPLE_CLICKED", + "BUTTON4_PRESSED", "BUTTON4_RELEASED", "BUTTON4_CLICKED", + "BUTTON4_DOUBLE_CLICKED", "BUTTON4_TRIPLE_CLICKED", + "BUTTON_SHIFT", "BUTTON_CTRL", "BUTTON_ALT", + "ALL_MOUSE_EVENTS", "REPORT_MOUSE_POSITION", + ]: + _copy_to_globals(name) + + if not lib._m_NetBSD: + for key in range(lib.KEY_MIN, lib.KEY_MAX): + key_n = lib.keyname(key) + if key_n == ffi.NULL or ffi.string(key_n) == "UNKNOWN KEY": + continue + key_n = ffi.string(key_n).replace('(', '').replace(')', '') + globals()[key_n] = key + +_setup() + +# Do we want this? +# version = "2.2" +# __version__ = "2.2" + + +# ____________________________________________________________ + + +_initialised_setupterm = False +_initialised = False +_initialised_color = False + + +def _ensure_initialised_setupterm(): + if not _initialised_setupterm: + raise error("must call (at least) setupterm() first") + + +def _ensure_initialised(): + if not _initialised: + raise error("must call initscr() first") + + +def _ensure_initialised_color(): + if not _initialised and _initialised_color: + raise error("must call start_color() first") + + +def _check_ERR(code, fname): + if code != lib.ERR: + return None + elif fname is None: + raise error("curses function returned ERR") + else: + raise error("%s() returned ERR" % (fname,)) + + +def _check_NULL(rval): + if rval == ffi.NULL: + raise error("curses function returned NULL") + return rval + + +def _call_lib(method_name, *args): + return getattr(lib, method_name)(*args) + + +def _call_lib_check_ERR(method_name, *args): + return _check_ERR(_call_lib(method_name, *args), method_name) + + +def _mk_no_return(method_name): + def _execute(): + _ensure_initialised() + return _call_lib_check_ERR(method_name) + _execute.__name__ = method_name + return _execute + + +def _mk_flag_func(method_name): + # This is in the CPython implementation, but not documented anywhere. + # We have to support it, though, even if it make me sad. + def _execute(flag=True): + _ensure_initialised() + if flag: + return _call_lib_check_ERR(method_name) + else: + return _call_lib_check_ERR('no' + method_name) + _execute.__name__ = method_name + return _execute + + +def _mk_return_val(method_name): + def _execute(): + return _call_lib(method_name) + _execute.__name__ = method_name + return _execute + + +def _mk_w_getyx(method_name): + def _execute(self): + y = _call_lib(method_name + 'y', self._win) + x = _call_lib(method_name + 'x', self._win) + return (y, x) + _execute.__name__ = method_name + return _execute + + +def _mk_w_no_return(method_name): + def _execute(self, *args): + return _call_lib_check_ERR(method_name, self._win, *args) + _execute.__name__ = method_name + return _execute + + +def _mk_w_return_val(method_name): + def _execute(self, *args): + return _call_lib(method_name, self._win, *args) + _execute.__name__ = method_name + return _execute + + +def _chtype(ch): + return int(ffi.cast("chtype", ch)) + + +def _extract_yx(args): + if len(args) >= 2: + return (args[0], args[1], args[2:]) + return (None, None, args) + + +def _process_args(funcname, args, count, optcount, frontopt=0): + outargs = [] + if frontopt: + if len(args) > count + optcount: + # We have the front optional args here. + outargs.extend(args[:frontopt]) + args = args[frontopt:] + else: + # No front optional args, so make them None. + outargs.extend([None] * frontopt) + if (len(args) < count) or (len(args) > count + optcount): + raise error("%s requires %s to %s arguments" % ( + funcname, count, count + optcount + frontopt)) + outargs.extend(args) + return outargs + + +def _argspec(count, optcount=0, frontopt=0): + def _argspec_deco(func): + @wraps(func) + def _wrapped(self, *args): + outargs = _process_args( + func.__name__, args, count, optcount, frontopt) + return func(self, *outargs) + return _wrapped + return _argspec_deco + + +# ____________________________________________________________ + + +class error(Exception): + pass + + +class Window(object): + def __init__(self, window): + self._win = window + + def __del__(self): + if self._win != lib.stdscr: + lib.delwin(self._win) + + untouchwin = _mk_w_no_return("untouchwin") + touchwin = _mk_w_no_return("touchwin") + redrawwin = _mk_w_no_return("redrawwin") + insertln = _mk_w_no_return("winsertln") + erase = _mk_w_no_return("werase") + deleteln = _mk_w_no_return("wdeleteln") + + is_wintouched = _mk_w_return_val("is_wintouched") + + syncdown = _mk_w_return_val("wsyncdown") + syncup = _mk_w_return_val("wsyncup") + standend = _mk_w_return_val("wstandend") + standout = _mk_w_return_val("wstandout") + cursyncup = _mk_w_return_val("wcursyncup") + clrtoeol = _mk_w_return_val("wclrtoeol") + clrtobot = _mk_w_return_val("wclrtobot") + clear = _mk_w_return_val("wclear") + + idcok = _mk_w_no_return("idcok") + immedok = _mk_w_no_return("immedok") + timeout = _mk_w_no_return("wtimeout") + + getyx = _mk_w_getyx("getcur") + getbegyx = _mk_w_getyx("getbeg") + getmaxyx = _mk_w_getyx("getmax") + getparyx = _mk_w_getyx("getpar") + + clearok = _mk_w_no_return("clearok") + idlok = _mk_w_no_return("idlok") + leaveok = _mk_w_no_return("leaveok") + notimeout = _mk_w_no_return("notimeout") + scrollok = _mk_w_no_return("scrollok") + insdelln = _mk_w_no_return("winsdelln") + syncok = _mk_w_no_return("syncok") + + mvwin = _mk_w_no_return("mvwin") + mvderwin = _mk_w_no_return("mvderwin") + move = _mk_w_no_return("wmove") + + if not lib._m_STRICT_SYSV_CURSES: + resize = _mk_w_no_return("wresize") + + if lib._m_NetBSD: + keypad = _mk_w_return_val("keypad") + nodelay = _mk_w_return_val("nodelay") + else: + keypad = _mk_w_no_return("keypad") + nodelay = _mk_w_no_return("nodelay") + + @_argspec(1, 1, 2) + def addch(self, y, x, ch, attr=None): + if attr is None: + attr = lib.A_NORMAL + ch = _chtype(ch) + + if y is not None: + code = lib.mvwaddch(self._win, y, x, ch | attr) + else: + code = lib.waddch(self._win, ch | attr) + return _check_ERR(code, "addch") + + @_argspec(1, 1, 2) + def addstr(self, y, x, text, attr=None): + if attr is not None: + attr_old = lib.getattrs(self._win) + lib.wattrset(self._win, attr) + if y is not None: + code = lib.mvwaddstr(self._win, y, x, text) + else: + code = lib.waddstr(self._win, text) + if attr is not None: + lib.wattrset(self._win, attr_old) + return _check_ERR(code, "addstr") + + @_argspec(2, 1, 2) + def addnstr(self, y, x, text, n, attr=None): + if attr is not None: + attr_old = lib.getattrs(self._win) + lib.wattrset(self._win, attr) + if y is not None: + code = lib.mvwaddnstr(self._win, y, x, text, n) + else: + code = lib.waddnstr(self._win, text, n) + if attr is not None: + lib.wattrset(self._win, attr_old) + return _check_ERR(code, "addnstr") + + def bkgd(self, ch, attr=None): + if attr is None: + attr = lib.A_NORMAL + return _check_ERR(lib.wbkgd(self._win, _chtype(ch) | attr), "bkgd") + + attroff = _mk_w_no_return("wattroff") + attron = _mk_w_no_return("wattron") + attrset = _mk_w_no_return("wattrset") + + def bkgdset(self, ch, attr=None): + if attr is None: + attr = lib.A_NORMAL + lib.wbkgdset(self._win, _chtype(ch) | attr) + return None + + def border(self, ls=0, rs=0, ts=0, bs=0, tl=0, tr=0, bl=0, br=0): + lib.wborder(self._win, + _chtype(ls), _chtype(rs), _chtype(ts), _chtype(bs), + _chtype(tl), _chtype(tr), _chtype(bl), _chtype(br)) + return None + + def box(self, vertint=0, horint=0): + lib.box(self._win, vertint, horint) + return None + + @_argspec(1, 1, 2) + def chgat(self, y, x, num, attr=None): + # These optional args are in a weird order. + if attr is None: + attr = num + num = -1 + + color = ((attr >> 8) & 0xff) + attr = attr - (color << 8) + + if y is not None: + code = lib.mvwchgat(self._win, y, x, num, attr, color, ffi.NULL) + lib.touchline(self._win, y, 1) + else: + yy, _ = self.getyx() + code = lib.wchgat(self._win, num, attr, color, ffi.NULL) + lib.touchline(self._win, yy, 1) + return _check_ERR(code, "chgat") + + def delch(self, *args): + if len(args) == 0: + code = lib.wdelch(self._win) + elif len(args) == 2: + code = lib.mvwdelch(self._win, *args) + else: + raise error("delch requires 0 or 2 arguments") + return _check_ERR(code, "[mv]wdelch") + + def derwin(self, *args): + nlines = 0 + ncols = 0 + if len(args) == 2: + begin_y, begin_x = args + elif len(args) == 4: + nlines, ncols, begin_y, begin_x = args + else: + raise error("derwin requires 2 or 4 arguments") + + win = lib.derwin(self._win, nlines, ncols, begin_y, begin_x) + return Window(_check_NULL(win)) + + def echochar(self, ch, attr=None): + if attr is None: + attr = lib.A_NORMAL + ch = _chtype(ch) + + if lib._m_ispad(self._win): + code = lib.pechochar(self._win, ch | attr) + else: + code = lib.wechochar(self._win, ch | attr) + return _check_ERR(code, "echochar") + + if lib._m_NCURSES_MOUSE_VERSION: + enclose = _mk_w_return_val("wenclose") + + getbkgd = _mk_w_return_val("getbkgd") + + def getch(self, *args): + if len(args) == 0: + val = lib.wgetch(self._win) + elif len(args) == 2: + val = lib.mvwgetch(self._win, *args) + else: + raise error("getch requires 0 or 2 arguments") + return val + + def getkey(self, *args): + if len(args) == 0: + val = lib.wgetch(self._win) + elif len(args) == 2: + val = lib.mvwgetch(self._win, *args) + else: + raise error("getkey requires 0 or 2 arguments") + + if val == lib.ERR: + raise error("no input") + elif val <= 255: + return chr(val) + else: + # XXX: The following line is different if `__NetBSD__` is defined. + val = lib.keyname(val) + if val == ffi.NULL: + return "" + return ffi.string(val) + + @_argspec(0, 1, 2) + def getstr(self, y, x, n=1023): + n = min(n, 1023) + buf = ffi.new("char[1024]") # /* This should be big enough.. I hope */ + + if y is None: + val = lib.wgetnstr(self._win, buf, n) + else: + val = lib.mvwgetnstr(self._win, y, x, buf, n) + + if val == lib.ERR: + return "" + return ffi.string(buf) + + @_argspec(2, 1, 2) + def hline(self, y, x, ch, n, attr=None): + ch = _chtype(ch) + if attr is None: + attr = lib.A_NORMAL + if y is not None: + _check_ERR(lib.wmove(self._win, y, x), "wmove") + return _check_ERR(lib.whline(self._win, ch | attr, n), "hline") + + @_argspec(1, 1, 2) + def insch(self, y, x, ch, attr=None): + ch = _chtype(ch) + if attr is None: + attr = lib.A_NORMAL + if y is not None: + code = lib.mvwinsch(self._win, y, x, ch | attr) + else: + code = lib.winsch(self._win, ch | attr) + return _check_ERR(code, "insch") + + def inch(self, *args): + if len(args) == 0: + return lib.winch(self._win) + elif len(args) == 2: + return lib.mvwinch(self._win, *args) + else: + raise error("inch requires 0 or 2 arguments") + + @_argspec(0, 1, 2) + def instr(self, y, x, n=1023): + n = min(n, 1023) + buf = ffi.new("char[1024]") # /* This should be big enough.. I hope */ + if y is None: + code = lib.winnstr(self._win, buf, n) + else: + code = lib.mvwinnstr(self._win, y, x, buf, n) + + if code == lib.ERR: + return "" + return ffi.string(buf) + + @_argspec(1, 1, 2) + def insstr(self, y, x, text, attr=None): + if attr is not None: + attr_old = lib.getattrs(self._win) + lib.wattrset(self._win, attr) + if y is not None: + code = lib.mvwinsstr(self._win, y, x, text) + else: + code = lib.winsstr(self._win, text) + if attr is not None: + lib.wattrset(self._win, attr_old) + return _check_ERR(code, "insstr") + + @_argspec(2, 1, 2) + def insnstr(self, y, x, text, n, attr=None): + if attr is not None: + attr_old = lib.getattrs(self._win) + lib.wattrset(self._win, attr) + if y is not None: + code = lib.mvwinsnstr(self._win, y, x, text, n) + else: + code = lib.winsnstr(self._win, text, n) + if attr is not None: + lib.wattrset(self._win, attr_old) + return _check_ERR(code, "insnstr") + + def is_linetouched(self, line): + code = lib.is_linetouched(self._win, line) + if code == lib.ERR: + raise error("is_linetouched: line number outside of boundaries") + if code == lib.FALSE: + return False + return True + + def noutrefresh(self, *args): + if lib._m_ispad(self._win): + if len(args) != 6: + raise error( + "noutrefresh() called for a pad requires 6 arguments") + return _check_ERR(lib.pnoutrefresh(self._win, *args), + "pnoutrefresh") + else: + # XXX: Better args check here? We need zero args. + return _check_ERR(lib.wnoutrefresh(self._win, *args), + "wnoutrefresh") + + nooutrefresh = noutrefresh # "to be removed in 2.3", but in 2.7, 3.x. + + def _copywin(self, dstwin, overlay, + sminr, sminc, dminr, dminc, dmaxr, dmaxc): + return _check_ERR(lib.copywin(self._win, dstwin._win, + sminr, sminc, dminr, dminc, dmaxr, dmaxc, + overlay), "copywin") + + def overlay(self, dstwin, *args): + if len(args) == 6: + return self._copywin(dstwin, True, *args) + elif len(args) == 0: + return _check_ERR(lib.overlay(self._win, dstwin._win), "overlay") + else: + raise error("overlay requires one or seven arguments") + + def overwrite(self, dstwin, *args): + if len(args) == 6: + return self._copywin(dstwin, False, *args) + elif len(args) == 0: + return _check_ERR(lib.overwrite(self._win, dstwin._win), + "overwrite") + else: + raise error("overwrite requires one or seven arguments") + + def putwin(self, filep): + # filestar = ffi.new("FILE *", filep) + return _check_ERR(lib.putwin(self._win, filep), "putwin") + + def redrawln(self, beg, num): + return _check_ERR(lib.wredrawln(self._win, beg, num), "redrawln") + + def refresh(self, *args): + if lib._m_ispad(self._win): + if len(args) != 6: + raise error( + "noutrefresh() called for a pad requires 6 arguments") + return _check_ERR(lib.prefresh(self._win, *args), "prefresh") + else: + # XXX: Better args check here? We need zero args. + return _check_ERR(lib.wrefresh(self._win, *args), "wrefresh") + + def setscrreg(self, y, x): + return _check_ERR(lib.wsetscrreg(self._win, y, x), "wsetscrreg") + + def subwin(self, *args): + nlines = 0 + ncols = 0 + if len(args) == 2: + begin_y, begin_x = args + elif len(args) == 4: + nlines, ncols, begin_y, begin_x = args + else: + raise error("subwin requires 2 or 4 arguments") + + if lib._m_ispad(self._win): + win = lib.subpad(self._win, nlines, ncols, begin_y, begin_x) + else: + win = lib.subwin(self._win, nlines, ncols, begin_y, begin_x) + return Window(_check_NULL(win)) + + def scroll(self, nlines=None): + if nlines is None: + return _check_ERR(lib.scroll(self._win), "scroll") + else: + return _check_ERR(lib.wscrl(self._win, nlines), "scroll") + + def touchline(self, st, cnt, val=None): + if val is None: + return _check_ERR(lib.touchline(self._win, st, cnt), "touchline") + else: + return _check_ERR(lib.wtouchln(self._win, st, cnt, val), + "touchline") + + @_argspec(2, 1, 2) + def vline(self, y, x, ch, n, attr=None): + ch = _chtype(ch) + if attr is None: + attr = lib.A_NORMAL + if y is not None: + _check_ERR(lib.wmove(self._win, y, x), "wmove") + return _check_ERR(lib.wvline(self._win, ch | attr, n), "vline") + + +beep = _mk_no_return("beep") +def_prog_mode = _mk_no_return("def_prog_mode") +def_shell_mode = _mk_no_return("def_shell_mode") +doupdate = _mk_no_return("doupdate") +endwin = _mk_no_return("endwin") +flash = _mk_no_return("flash") +nocbreak = _mk_no_return("nocbreak") +noecho = _mk_no_return("noecho") +nonl = _mk_no_return("nonl") +noraw = _mk_no_return("noraw") +reset_prog_mode = _mk_no_return("reset_prog_mode") +reset_shell_mode = _mk_no_return("reset_shell_mode") +resetty = _mk_no_return("resetty") +savetty = _mk_no_return("savetty") + +cbreak = _mk_flag_func("cbreak") +echo = _mk_flag_func("echo") +nl = _mk_flag_func("nl") +raw = _mk_flag_func("raw") + +baudrate = _mk_return_val("baudrate") +termattrs = _mk_return_val("termattrs") + +termname = _mk_return_val("termname") +longname = _mk_return_val("longname") + +can_change_color = _mk_return_val("can_change_color") +has_colors = _mk_return_val("has_colors") +has_ic = _mk_return_val("has_ic") +has_il = _mk_return_val("has_il") +isendwin = _mk_return_val("isendwin") +flushinp = _mk_return_val("flushinp") +noqiflush = _mk_return_val("noqiflush") + + +def filter(): + lib.filter() + return None + + +def color_content(color): + _ensure_initialised_color() + r, g, b = ffi.new("short *"), ffi.new("short *"), ffi.new("short *") + if lib.color_content(color, r, g, b) == lib.ERR: + raise error("Argument 1 was out of range. Check value of COLORS.") + return (r, g, b) + + +def color_pair(n): + _ensure_initialised_color() + return (n << 8) + + +def curs_set(vis): + _ensure_initialised() + val = lib.curs_set(vis) + _check_ERR(val, "curs_set") + return val + + +def delay_output(ms): + _ensure_initialised() + return _check_ERR(lib.delay_output(ms), "delay_output") + + +def erasechar(): + _ensure_initialised() + return lib.erasechar() + + +def getsyx(): + _ensure_initialised() + yx = ffi.new("int[2]") + lib._m_getsyx(yx) + return (yx[0], yx[1]) + + +if lib._m_NCURSES_MOUSE_VERSION: + + def getmouse(): + _ensure_initialised() + mevent = ffi.new("MEVENT *") + _check_ERR(lib.getmouse(mevent), "getmouse") + return (mevent.id, mevent.x, mevent.y, mevent.z, mevent.bstate) + + def ungetmouse(id, x, y, z, bstate): + _ensure_initialised() + mevent = ffi.new("MEVENT *") + mevent.id, mevent.x, mevent.y, mevent.z, mevent.bstate = ( + id, x, y, z, bstate) + return _check_ERR(lib.ungetmouse(mevent), "ungetmouse") + + +def getwin(filep): + return Window(_check_NULL(lib.getwin(filep))) + + +def halfdelay(tenths): + _ensure_initialised() + return _check_ERR(lib.halfdelay(tenths), "halfdelay") + + +if not lib._m_STRICT_SYSV_CURSES: + def has_key(ch): + _ensure_initialised() + return lib.has_key(ch) + + +def init_color(color, r, g, b): + _ensure_initialised_color() + return _check_ERR(lib.init_color(color, r, g, b), "init_color") + + +def init_pair(pair, f, b): + _ensure_initialised_color() + return _check_ERR(lib.init_pair(pair, f, b), "init_pair") + + +def _mk_acs(name, ichar): + if len(ichar) == 1: + globals()[name] = lib.acs_map[ord(ichar)] + else: + globals()[name] = globals()[ichar] + + +def _map_acs(): + _mk_acs("ACS_ULCORNER", 'l') + _mk_acs("ACS_LLCORNER", 'm') + _mk_acs("ACS_URCORNER", 'k') + _mk_acs("ACS_LRCORNER", 'j') + _mk_acs("ACS_LTEE", 't') + _mk_acs("ACS_RTEE", 'u') + _mk_acs("ACS_BTEE", 'v') + _mk_acs("ACS_TTEE", 'w') + _mk_acs("ACS_HLINE", 'q') + _mk_acs("ACS_VLINE", 'x') + _mk_acs("ACS_PLUS", 'n') + _mk_acs("ACS_S1", 'o') + _mk_acs("ACS_S9", 's') + _mk_acs("ACS_DIAMOND", '`') + _mk_acs("ACS_CKBOARD", 'a') + _mk_acs("ACS_DEGREE", 'f') + _mk_acs("ACS_PLMINUS", 'g') + _mk_acs("ACS_BULLET", '~') + _mk_acs("ACS_LARROW", ',') + _mk_acs("ACS_RARROW", '+') + _mk_acs("ACS_DARROW", '.') + _mk_acs("ACS_UARROW", '-') + _mk_acs("ACS_BOARD", 'h') + _mk_acs("ACS_LANTERN", 'i') + _mk_acs("ACS_BLOCK", '0') + _mk_acs("ACS_S3", 'p') + _mk_acs("ACS_S7", 'r') + _mk_acs("ACS_LEQUAL", 'y') + _mk_acs("ACS_GEQUAL", 'z') + _mk_acs("ACS_PI", '{') + _mk_acs("ACS_NEQUAL", '|') + _mk_acs("ACS_STERLING", '}') + _mk_acs("ACS_BSSB", "ACS_ULCORNER") + _mk_acs("ACS_SSBB", "ACS_LLCORNER") + _mk_acs("ACS_BBSS", "ACS_URCORNER") + _mk_acs("ACS_SBBS", "ACS_LRCORNER") + _mk_acs("ACS_SBSS", "ACS_RTEE") + _mk_acs("ACS_SSSB", "ACS_LTEE") + _mk_acs("ACS_SSBS", "ACS_BTEE") + _mk_acs("ACS_BSSS", "ACS_TTEE") + _mk_acs("ACS_BSBS", "ACS_HLINE") + _mk_acs("ACS_SBSB", "ACS_VLINE") + _mk_acs("ACS_SSSS", "ACS_PLUS") + + +def initscr(): + if _initialised: + lib.wrefresh(lib.stdscr) + return Window(lib.stdscr) + + win = _check_NULL(lib.initscr()) + globals()['_initialised_setupterm'] = True + globals()['_initialised'] = True + + _map_acs() + + globals()["LINES"] = lib.LINES + globals()["COLS"] = lib.COLS + + return Window(win) + + +def setupterm(term=None, fd=-1): + if fd == -1: + # XXX: Check for missing stdout here? + fd = sys.stdout.fileno() + + if _initialised_setupterm: + return None + + if term is None: + term = ffi.NULL + err = ffi.new("int *") + if lib.setupterm(term, fd, err) == lib.ERR: + if err == 0: + raise error("setupterm: could not find terminal") + elif err == -1: + raise error("setupterm: could not find terminfo database") + else: + raise error("setupterm: unknown error") + + globals()["_initialised_setupterm"] = True + return None + + +def intrflush(ch): + _ensure_initialised() + return _check_ERR(lib.intrflush(ffi.NULL, ch), "intrflush") + + +# XXX: #ifdef HAVE_CURSES_IS_TERM_RESIZED +def is_term_resized(lines, columns): + _ensure_initialised() + return lib.is_term_resized(lines, columns) + + +if not lib._m_NetBSD: + def keyname(ch): + _ensure_initialised() + if ch < 0: + raise error("invalid key number") + knp = lib.keyname(ch) + if knp == ffi.NULL: + return "" + return ffi.string(knp) + + +def killchar(): + return lib.killchar() + + +def meta(ch): + return _check_ERR(lib.meta(lib.stdscr, ch), "meta") + + +if lib._m_NCURSES_MOUSE_VERSION: + + def mouseinterval(interval): + _ensure_initialised() + return _check_ERR(lib.mouseinterval(interval), "mouseinterval") + + def mousemask(newmask): + _ensure_initialised() + oldmask = ffi.new("mmask_t *") + availmask = lib.mousemask(newmask, oldmask) + return (availmask, oldmask) + + +def napms(ms): + _ensure_initialised() + return lib.napms(ms) + + +def newpad(nlines, ncols): + _ensure_initialised() + return Window(_check_NULL(lib.newpad(nlines, ncols))) + + +def newwin(nlines, ncols, begin_y=None, begin_x=None): + _ensure_initialised() + if begin_x is None: + if begin_y is not None: + raise error("newwin requires 2 or 4 arguments") + begin_y = begin_x = 0 + + return Window(_check_NULL(lib.newwin(nlines, ncols, begin_y, begin_x))) + + +def pair_content(pair): + _ensure_initialised_color() + f = ffi.new("short *") + b = ffi.new("short *") + if lib.pair_content(pair, f, b) == lib.ERR: + raise error("Argument 1 was out of range. (1..COLOR_PAIRS-1)") + return (f, b) + + +def pair_number(pairvalue): + _ensure_initialised_color() + return (pairvalue & lib.A_COLOR) >> 8 + + +def putp(text): + return _check_ERR(lib.putp(text), "putp") + + +def qiflush(flag=True): + _ensure_initialised() + if flag: + lib.qiflush() + else: + lib.noqiflush() + return None + + +# XXX: Do something about the following? +# /* Internal helper used for updating curses.LINES, curses.COLS, _curses.LINES +# * and _curses.COLS */ +# #if defined(HAVE_CURSES_RESIZETERM) || defined(HAVE_CURSES_RESIZE_TERM) +# static int +# update_lines_cols(void) +# { +# PyObject *o; +# PyObject *m = PyImport_ImportModuleNoBlock("curses"); + +# if (!m) +# return 0; + +# o = PyInt_FromLong(LINES); +# if (!o) { +# Py_DECREF(m); +# return 0; +# } +# if (PyObject_SetAttrString(m, "LINES", o)) { +# Py_DECREF(m); +# Py_DECREF(o); +# return 0; +# } +# if (PyDict_SetItemString(ModDict, "LINES", o)) { +# Py_DECREF(m); +# Py_DECREF(o); +# return 0; +# } +# Py_DECREF(o); +# o = PyInt_FromLong(COLS); +# if (!o) { +# Py_DECREF(m); +# return 0; +# } +# if (PyObject_SetAttrString(m, "COLS", o)) { +# Py_DECREF(m); +# Py_DECREF(o); +# return 0; +# } +# if (PyDict_SetItemString(ModDict, "COLS", o)) { +# Py_DECREF(m); +# Py_DECREF(o); +# return 0; +# } +# Py_DECREF(o); +# Py_DECREF(m); +# return 1; +# } +# #endif + +# #ifdef HAVE_CURSES_RESIZETERM +# static PyObject * +# PyCurses_ResizeTerm(PyObject *self, PyObject *args) +# { +# int lines; +# int columns; +# PyObject *result; + +# PyCursesInitialised; + +# if (!PyArg_ParseTuple(args,"ii:resizeterm", &lines, &columns)) +# return NULL; + +# result = PyCursesCheckERR(resizeterm(lines, columns), "resizeterm"); +# if (!result) +# return NULL; +# if (!update_lines_cols()) +# return NULL; +# return result; +# } + +# #endif + +# #ifdef HAVE_CURSES_RESIZE_TERM +# static PyObject * +# PyCurses_Resize_Term(PyObject *self, PyObject *args) +# { +# int lines; +# int columns; + +# PyObject *result; + +# PyCursesInitialised; + +# if (!PyArg_ParseTuple(args,"ii:resize_term", &lines, &columns)) +# return NULL; + +# result = PyCursesCheckERR(resize_term(lines, columns), "resize_term"); +# if (!result) +# return NULL; +# if (!update_lines_cols()) +# return NULL; +# return result; +# } +# #endif /* HAVE_CURSES_RESIZE_TERM */ + + +def setsyx(y, x): + _ensure_initialised() + lib.setsyx(y, x) + return None + + +def start_color(): + _check_ERR(lib.start_color(), "start_color") + globals()["COLORS"] = lib.COLORS + globals()["COLOR_PAIRS"] = lib.COLOR_PAIRS + globals()["_initialised_color"] = True + return None + + +def tigetflag(capname): + _ensure_initialised_setupterm() + return lib.tigetflag(capname) + + +def tigetnum(capname): + _ensure_initialised_setupterm() + return lib.tigetnum(capname) + + +def tigetstr(capname): + _ensure_initialised_setupterm() + val = lib.tigetstr(capname) + if val in (0, -1, ffi.NULL): + return None + return ffi.string(val) + + +def tparm(fmt, i1=0, i2=0, i3=0, i4=0, i5=0, i6=0, i7=0, i8=0, i9=0): + args = [ffi.cast("int", i) for i in (i1, i2, i3, i4, i5, i6, i7, i8, i9)] + result = lib.tparm(fmt, *args) + if result == ffi.NULL: + raise error("tparm() returned NULL") + return ffi.string(result) + + +def typeahead(fd): + _ensure_initialised() + return _check_ERR(lib.typeahead(fd), "typeahead") + + +def unctrl(ch): + _ensure_initialised() + return lib.unctrl(_chtype(ch)) + + +def ungetch(ch): + _ensure_initialised() + return _check_ERR(lib.ungetch(_chtype(ch)), "ungetch") + + +def use_env(flag): + lib.use_env(flag) + return None + + +if not lib._m_STRICT_SYSV_CURSES: + + def use_default_colors(): + _ensure_initialised_color() + return _check_ERR(lib.use_default_colors(), "use_default_colors") diff --git a/lib_pypy/_curses_panel.py b/lib_pypy/_curses_panel.py new file mode 100644 --- /dev/null +++ b/lib_pypy/_curses_panel.py @@ -0,0 +1,132 @@ +"Reimplementation of the standard extension module '_curses_panel' using cffi." + +from _curses import _ensure_initialised, _check_ERR, error, ffi, lib + + +def _call_lib(method_name, *args): + return getattr(lib, method_name)(*args) + + +def _call_lib_check_ERR(method_name, *args): + return _check_ERR(_call_lib(method_name, *args), method_name) + + +def _mk_no_arg_no_return(method_name): + def _execute(): + _ensure_initialised() + return _call_lib_check_ERR(method_name) + _execute.__name__ = method_name + return _execute + + +def _mk_no_arg_return_val(method_name): + def _execute(): + return _call_lib(method_name) + _execute.__name__ = method_name + return _execute + + +def _mk_args_no_return(method_name): + def _execute(*args): + return _call_lib_check_ERR(method_name, *args) + _execute.__name__ = method_name + return _execute + + +# ____________________________________________________________ + + +bottom_panel = _mk_no_arg_no_return("bottom_panel") +hide_panel = _mk_no_arg_no_return("hide_panel") +show_panel = _mk_no_arg_no_return("show_panel") +top_panel = _mk_no_arg_no_return("top_panel") +panel_hidden = _mk_no_arg_return_val("panel_hidden") +move_panel = _mk_args_no_return("move_panel") + + +_panels = [] + + +def _add_panel(panel): + _panels.insert(0, panel) + + +def _remove_panel(panel): + _panels.remove(panel) + + +def _find_panel(pan): + for panel in _panels: + if panel._pan == pan: + return panel + return None + + +class Panel(object): + def __init__(self, pan, window): + self._pan = pan + self._window = window + _add_panel(self) + + def __del__(self): + _remove_panel(self) + lib.del_panel(self._pan) + + def above(self): + pan = lib.panel_above(self._pan) + if pan == ffi.NULL: + return None + return _find_panel(pan) + + def below(self): + pan = lib.panel_below(self._pan) + if pan == ffi.NULL: + return None + return _find_panel(pan) + + def window(self): + return self._window + + def replace_panel(self, window): + panel = _find_panel(self._pan) + _check_ERR(lib.replace_panel(self._pan, window._win), "replace_panel") + panel._window = window + return None + + def set_panel_userptr(self, obj): + code = lib.set_panel_userptr(self._pan, ffi.cast("void *", obj)) + return _check_ERR(code, "set_panel_userptr") + + def userptr(self): + # XXX: This is probably wrong. + obj = lib.panel_userptr(self._pan) + if obj == ffi.NULL: + raise error("no userptr set") + return obj + + +def bottom_panel(): + _ensure_initialised() + pan = lib.panel_above(ffi.NULL) + if pan == ffi.NULL: + return None + return _find_panel(pan) + + +def new_panel(window): + pan = lib.new_panel(window._win) + return Panel(pan, window) + + +def panel_below(): + _ensure_initialised() + pan = lib.panel_below(ffi.NULL) + if pan == ffi.NULL: + return None + return _find_panel(pan) + + +def update_panels(): + _ensure_initialised() + lib.update_panels() + return None From noreply at buildbot.pypy.org Wed Apr 3 10:06:03 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 3 Apr 2013 10:06:03 +0200 (CEST) Subject: [pypy-commit] pypy default: fix whatsnew Message-ID: <20130403080603.DD4461C030B@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r62952:bb586782e481 Date: 2013-04-03 10:02 +0200 http://bitbucket.org/pypy/pypy/changeset/bb586782e481/ Log: fix whatsnew diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -115,3 +115,6 @@ .. branch: remove-list-smm .. branch: bridge-logging +.. branch: curses_cffi + +cffi implementation of _curses From noreply at buildbot.pypy.org Wed Apr 3 10:06:05 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 3 Apr 2013 10:06:05 +0200 (CEST) Subject: [pypy-commit] pypy default: Kill _minimal_curses mentions Message-ID: <20130403080605.16BAB1C030B@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r62953:084c46734a1c Date: 2013-04-03 10:04 +0200 http://bitbucket.org/pypy/pypy/changeset/084c46734a1c/ Log: Kill _minimal_curses mentions diff --git a/lib_pypy/_minimal_curses.py b/lib_pypy/_minimal_curses.py deleted file mode 100644 --- a/lib_pypy/_minimal_curses.py +++ /dev/null @@ -1,60 +0,0 @@ -"""Minimal '_curses' module, the low-level interface for curses module -which is not meant to be used directly. - -Based on ctypes. It's too incomplete to be really called '_curses', so -to use it, you have to import it and stick it in sys.modules['_curses'] -manually. - -Note that there is also a built-in module _minimal_curses which will -hide this one if compiled in. -""" - -import ctypes, ctypes.util - -class error(Exception): - pass - - -_clibpath = ctypes.util.find_library('curses') -if not _clibpath: - raise ImportError("curses library not found") -clib = ctypes.cdll.LoadLibrary(_clibpath) - -clib.setupterm.argtypes = [ctypes.c_char_p, ctypes.c_int, - ctypes.POINTER(ctypes.c_int)] -clib.setupterm.restype = ctypes.c_int - -clib.tigetstr.argtypes = [ctypes.c_char_p] -clib.tigetstr.restype = ctypes.POINTER(ctypes.c_char) - -clib.tparm.argtypes = [ctypes.c_char_p] + 9 * [ctypes.c_int] -clib.tparm.restype = ctypes.c_char_p - -OK = 0 -ERR = -1 - -# ____________________________________________________________ - -try: from __pypy__ import builtinify -except ImportError: builtinify = lambda f: f - - at builtinify -def setupterm(termstr, fd): - err = ctypes.c_int(0) - result = clib.setupterm(termstr, fd, ctypes.byref(err)) - if result == ERR: - raise error("setupterm() failed (err=%d)" % err.value) - - at builtinify -def tigetstr(cap): - result = clib.tigetstr(cap) - if ctypes.cast(result, ctypes.c_void_p).value == ERR: - return None - return ctypes.cast(result, ctypes.c_char_p).value - - at builtinify -def tparm(str, i1=0, i2=0, i3=0, i4=0, i5=0, i6=0, i7=0, i8=0, i9=0): - result = clib.tparm(str, i1, i2, i3, i4, i5, i6, i7, i8, i9) - if result is None: - raise error("tparm() returned NULL") - return result diff --git a/lib_pypy/pyrepl/curses.py b/lib_pypy/pyrepl/curses.py --- a/lib_pypy/pyrepl/curses.py +++ b/lib_pypy/pyrepl/curses.py @@ -19,15 +19,12 @@ # CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# Some try-import logic for two purposes: avoiding to bring in the whole -# pure Python curses package if possible; and, in _curses is not actually -# present, falling back to _minimal_curses (which is either a ctypes-based -# pure Python module or a PyPy built-in module). +# avoid importing the whole curses, if possible try: import _curses except ImportError: try: - import _minimal_curses as _curses + import curses except ImportError: # Who knows, maybe some environment has "curses" but not "_curses". # If not, at least the following import gives a clean ImportError. diff --git a/rpython/tool/terminal.py b/rpython/tool/terminal.py --- a/rpython/tool/terminal.py +++ b/rpython/tool/terminal.py @@ -75,16 +75,7 @@ return text % MODULE.__dict__ try: - if '__pypy__' in sys.builtin_module_names: - # this is not really the whole curses, but our _minimal_curses it's - # better than nothing - import _minimal_curses as curses - # a bit of a hack: we have tigetstr but not tigetnum, so we call - # default() to have default values, then setup() will overwrite the - # ones it can - default() - else: - import curses + import curses setup() except Exception, e: # There is a failure; set all attributes to default From noreply at buildbot.pypy.org Wed Apr 3 10:06:06 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 3 Apr 2013 10:06:06 +0200 (CEST) Subject: [pypy-commit] pypy default: actually kill _minimal_curses Message-ID: <20130403080606.60F2C1C030B@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r62954:b293049d40a5 Date: 2013-04-03 10:05 +0200 http://bitbucket.org/pypy/pypy/changeset/b293049d40a5/ Log: actually kill _minimal_curses diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py --- a/pypy/config/pypyoption.py +++ b/pypy/config/pypyoption.py @@ -31,7 +31,7 @@ ["_socket", "unicodedata", "mmap", "fcntl", "_locale", "pwd", "rctime" , "select", "zipimport", "_lsprof", "crypt", "signal", "_rawffi", "termios", "zlib", "bz2", - "struct", "_hashlib", "_md5", "_sha", "_minimal_curses", "cStringIO", + "struct", "_hashlib", "_md5", "_sha", "cStringIO", "thread", "itertools", "pyexpat", "_ssl", "cpyext", "array", "binascii", "_multiprocessing", '_warnings', "_collections", "_multibytecodec", "micronumpy", "_ffi", @@ -45,7 +45,7 @@ "binascii", # the following are needed for pyrepl (and hence for the # interactive prompt/pdb) - "termios", "_minimal_curses", + "termios", ])) working_oo_modules = default_modules.copy() @@ -62,7 +62,6 @@ del working_modules["fcntl"] del working_modules["pwd"] del working_modules["termios"] - del working_modules["_minimal_curses"] # The _locale module is needed by site.py on Windows default_modules["_locale"] = None @@ -72,7 +71,6 @@ del working_modules['rctime'] # depend on ctypes, missing tm_zone/tm_gmtoff del working_modules['signal'] # depend on ctypes, can't get at c-level 'errono' del working_modules['fcntl'] # LOCK_NB not defined - del working_modules["_minimal_curses"] del working_modules["termios"] del working_modules["_multiprocessing"] # depends on rctime @@ -103,7 +101,6 @@ "pyexpat" : ["pypy.module.pyexpat.interp_pyexpat"], "_ssl" : ["pypy.module._ssl.interp_ssl"], "_hashlib" : ["pypy.module._ssl.interp_ssl"], - "_minimal_curses": ["pypy.module._minimal_curses.fficurses"], "_continuation": ["rpython.rlib.rstacklet"], } diff --git a/pypy/module/_minimal_curses/__init__.py b/pypy/module/_minimal_curses/__init__.py deleted file mode 100644 --- a/pypy/module/_minimal_curses/__init__.py +++ /dev/null @@ -1,32 +0,0 @@ -try: - import _curses -except ImportError: - try: - import _minimal_curses as _curses # when running on top of pypy-c - except ImportError: - import py - py.test.skip("no _curses or _minimal_curses module") #no _curses at all - -from pypy.interpreter.mixedmodule import MixedModule -from pypy.module._minimal_curses import fficurses # for side effects - - -class Module(MixedModule): - """ Low-level interface for curses module, - not meant to be used directly - """ - - appleveldefs = { - 'error' : 'app_curses.error', - } - - interpleveldefs = { - 'setupterm' : 'interp_curses.setupterm', - 'tigetstr' : 'interp_curses.tigetstr', - 'tparm' : 'interp_curses.tparm', - } - -for i in dir(_curses): - val = getattr(_curses, i) - if i.isupper() and type(val) is int: - Module.interpleveldefs[i] = "space.wrap(%s)" % val diff --git a/pypy/module/_minimal_curses/app_curses.py b/pypy/module/_minimal_curses/app_curses.py deleted file mode 100644 --- a/pypy/module/_minimal_curses/app_curses.py +++ /dev/null @@ -1,3 +0,0 @@ - -class error(Exception): - pass diff --git a/pypy/module/_minimal_curses/fficurses.py b/pypy/module/_minimal_curses/fficurses.py deleted file mode 100644 --- a/pypy/module/_minimal_curses/fficurses.py +++ /dev/null @@ -1,113 +0,0 @@ - -""" The ffi for rpython, need to be imported for side effects -""" - -from rpython.rtyper.lltypesystem import rffi -from rpython.rtyper.lltypesystem import lltype -from rpython.rtyper.tool import rffi_platform -from rpython.rtyper.extfunc import register_external -from pypy.module._minimal_curses import interp_curses -from rpython.translator.tool.cbuild import ExternalCompilationInfo -from sys import platform -import os.path - -_CYGWIN = platform == 'cygwin' -_NCURSES_CURSES = os.path.isfile("/usr/include/ncurses/curses.h") - -if _CYGWIN or _NCURSES_CURSES: - eci = ExternalCompilationInfo( - includes = ['ncurses/curses.h', 'ncurses/term.h'], - libraries = ['curses'], - ) -else: - eci = ExternalCompilationInfo( - includes = ['curses.h', 'term.h'], - libraries = ['curses'], - ) - -rffi_platform.verify_eci(eci) - - -INT = rffi.INT -INTP = lltype.Ptr(lltype.Array(INT, hints={'nolength':True})) -c_setupterm = rffi.llexternal('setupterm', [rffi.CCHARP, INT, INTP], INT, - compilation_info=eci) -c_tigetstr = rffi.llexternal('tigetstr', [rffi.CCHARP], rffi.CCHARP, - compilation_info=eci) -c_tparm = rffi.llexternal('tparm', [rffi.CCHARP, INT, INT, INT, INT, INT, - INT, INT, INT, INT], rffi.CCHARP, - compilation_info=eci) - -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: - errret = rffi.cast(lltype.Signed, intp[0]) - if errret == 0: - msg = "setupterm: could not find terminal" - elif errret == -1: - msg = "setupterm: could not find terminfo database" - else: - msg = "setupterm: unknown error" - raise interp_curses.curses_error(msg) - interp_curses.module_info.setupterm_called = True - finally: - lltype.free(intp, flavor='raw') - -def curses_setupterm_null_llimpl(fd): - curses_setupterm(lltype.nullptr(rffi.CCHARP.TO), fd) - -def curses_setupterm_llimpl(term, fd): - ll_s = rffi.str2charp(term) - try: - curses_setupterm(ll_s, fd) - finally: - rffi.free_charp(ll_s) - -register_external(interp_curses._curses_setupterm_null, - [int], llimpl=curses_setupterm_null_llimpl, - export_name='_curses.setupterm_null') -register_external(interp_curses._curses_setupterm, - [str, int], llimpl=curses_setupterm_llimpl, - export_name='_curses.setupterm') - -def check_setup_invoked(): - if not interp_curses.module_info.setupterm_called: - raise interp_curses.curses_error("must call (at least) setupterm() first") - -def tigetstr_llimpl(cap): - check_setup_invoked() - ll_cap = rffi.str2charp(cap) - try: - ll_res = c_tigetstr(ll_cap) - num = lltype.cast_ptr_to_int(ll_res) - if num == 0 or num == -1: - raise interp_curses.TermError() - res = rffi.charp2str(ll_res) - return res - finally: - rffi.free_charp(ll_cap) - -register_external(interp_curses._curses_tigetstr, [str], str, - export_name='_curses.tigetstr', llimpl=tigetstr_llimpl) - -def tparm_llimpl(s, args): - check_setup_invoked() - l = [0, 0, 0, 0, 0, 0, 0, 0, 0] - for i in range(min(len(args), 9)): - l[i] = args[i] - ll_s = rffi.str2charp(s) - # XXX nasty trick stolen from CPython - ll_res = c_tparm(ll_s, l[0], l[1], l[2], l[3], l[4], l[5], l[6], - l[7], l[8]) - rffi.free_charp(ll_s) - res = rffi.charp2str(ll_res) - return res - -register_external(interp_curses._curses_tparm, [str, [int]], str, - export_name='_curses.tparm', llimpl=tparm_llimpl) - diff --git a/pypy/module/_minimal_curses/interp_curses.py b/pypy/module/_minimal_curses/interp_curses.py deleted file mode 100644 --- a/pypy/module/_minimal_curses/interp_curses.py +++ /dev/null @@ -1,94 +0,0 @@ - -from pypy.interpreter.gateway import unwrap_spec -from pypy.interpreter.error import OperationError -from pypy.module._minimal_curses import _curses - -class ModuleInfo: - def __init__(self): - self.setupterm_called = False - -module_info = ModuleInfo() - -class curses_error(Exception): - def __init__(self, msg): - self.msg = msg - -from rpython.annotator.classdef import FORCE_ATTRIBUTES_INTO_CLASSES -from rpython.annotator.model import SomeString - -# this is necessary due to annmixlevel -FORCE_ATTRIBUTES_INTO_CLASSES[curses_error] = {'msg': SomeString()} - -def convert_error(space, error): - msg = error.msg - w_module = space.getbuiltinmodule('_minimal_curses') - w_exception_class = space.getattr(w_module, space.wrap('error')) - w_exception = space.call_function(w_exception_class, space.wrap(msg)) - return OperationError(w_exception_class, w_exception) - -def _curses_setupterm_null(fd): - # NOT_RPYTHON - try: - _curses.setupterm(None, fd) - except _curses.error, e: - raise curses_error(e.args[0]) - -def _curses_setupterm(termname, fd): - # NOT_RPYTHON - try: - _curses.setupterm(termname, fd) - except _curses.error, e: - raise curses_error(e.args[0]) - - at unwrap_spec(fd=int) -def setupterm(space, w_termname=None, fd=-1): - if fd == -1: - w_stdout = space.getattr(space.getbuiltinmodule('sys'), - space.wrap('stdout')) - fd = space.int_w(space.call_function(space.getattr(w_stdout, - space.wrap('fileno')))) - try: - if space.is_none(w_termname): - _curses_setupterm_null(fd) - else: - _curses_setupterm(space.str_w(w_termname), fd) - except curses_error, e: - raise convert_error(space, e) - -class TermError(Exception): - pass - -def _curses_tigetstr(capname): - # NOT_RPYTHON - try: - res = _curses.tigetstr(capname) - except _curses.error, e: - raise curses_error(e.args[0]) - if res is None: - raise TermError - return res - -def _curses_tparm(s, args): - # NOT_RPYTHON - try: - return _curses.tparm(s, *args) - except _curses.error, e: - raise curses_error(e.args[0]) - - at unwrap_spec(capname=str) -def tigetstr(space, capname): - try: - result = _curses_tigetstr(capname) - except TermError: - return space.w_None - except curses_error, e: - raise convert_error(space, e) - return space.wrap(result) - - at unwrap_spec(s=str) -def tparm(space, s, args_w): - args = [space.int_w(a) for a in args_w] - try: - return space.wrap(_curses_tparm(s, args)) - except curses_error, e: - raise convert_error(space, e) diff --git a/pypy/module/_minimal_curses/test/__init__.py b/pypy/module/_minimal_curses/test/__init__.py deleted file mode 100644 diff --git a/pypy/module/_minimal_curses/test/test_curses.py b/pypy/module/_minimal_curses/test/test_curses.py deleted file mode 100644 --- a/pypy/module/_minimal_curses/test/test_curses.py +++ /dev/null @@ -1,108 +0,0 @@ -from pypy.conftest import pypydir -from rpython.tool.udir import udir -import py -import sys -# tests here are run as snippets through a pexpected python subprocess - - -def setup_module(mod): - try: - import curses - curses.setupterm() - except: - py.test.skip("Cannot test this here") - -class TestCurses(object): - """ We need to fork here, to prevent - the setup to be done - """ - def _spawn(self, *args, **kwds): - import pexpect - kwds.setdefault('timeout', 600) - print 'SPAWN:', args, kwds - child = pexpect.spawn(*args, **kwds) - child.logfile = sys.stdout - return child - - def spawn(self, argv): - py_py = py.path.local(pypydir).join('bin', 'pyinteractive.py') - return self._spawn(sys.executable, [str(py_py)] + argv) - - def setup_class(self): - try: - import pexpect - except ImportError: - py.test.skip('pexpect not found') - - def test_setupterm(self): - source = py.code.Source(""" - import _minimal_curses - try: - _minimal_curses.tigetstr('cup') - except _minimal_curses.error: - print 'ok!' - """) - f = udir.join("test_setupterm.py") - f.write(source) - child = self.spawn(['--withmod-_minimal_curses', str(f)]) - child.expect('ok!') - - def test_tigetstr(self): - source = py.code.Source(""" - import _minimal_curses - _minimal_curses.setupterm() - assert _minimal_curses.tigetstr('cup') == '\x1b[%i%p1%d;%p2%dH' - print 'ok!' - """) - f = udir.join("test_tigetstr.py") - f.write(source) - child = self.spawn(['--withmod-_minimal_curses', str(f)]) - child.expect('ok!') - - def test_tparm(self): - source = py.code.Source(""" - import _minimal_curses - _minimal_curses.setupterm() - assert _minimal_curses.tparm(_minimal_curses.tigetstr('cup'), 5, 3) == '\033[6;4H' - print 'ok!' - """) - f = udir.join("test_tparm.py") - f.write(source) - child = self.spawn(['--withmod-_minimal_curses', str(f)]) - child.expect('ok!') - -class TestCCurses(object): - """ Test compiled version - """ - def test_csetupterm(self): - from rpython.translator.c.test.test_genc import compile - from pypy.module._minimal_curses import interp_curses - def runs_setupterm(): - interp_curses._curses_setupterm_null(1) - - fn = compile(runs_setupterm, []) - fn() - - def test_ctgetstr(self): - from rpython.translator.c.test.test_genc import compile - from pypy.module._minimal_curses import interp_curses - def runs_ctgetstr(): - interp_curses._curses_setupterm("xterm", 1) - return interp_curses._curses_tigetstr('cup') - - fn = compile(runs_ctgetstr, []) - res = fn() - assert res == '\x1b[%i%p1%d;%p2%dH' - - def test_ctparm(self): - from rpython.translator.c.test.test_genc import compile - from pypy.module._minimal_curses import interp_curses - def runs_tparm(): - interp_curses._curses_setupterm("xterm", 1) - cup = interp_curses._curses_tigetstr('cup') - return interp_curses._curses_tparm(cup, [5, 3]) - - fn = compile(runs_tparm, []) - res = fn() - assert res == '\033[6;4H' - From noreply at buildbot.pypy.org Wed Apr 3 10:06:07 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 3 Apr 2013 10:06:07 +0200 (CEST) Subject: [pypy-commit] pypy default: merge Message-ID: <20130403080607.9C24F1C030B@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r62955:40c31c512b2a Date: 2013-04-03 10:05 +0200 http://bitbucket.org/pypy/pypy/changeset/40c31c512b2a/ Log: merge diff --git a/lib-python/2/site.py b/lib-python/2/site.py --- a/lib-python/2/site.py +++ b/lib-python/2/site.py @@ -554,6 +554,8 @@ def import_builtin_stuff(): """PyPy specific: pre-import a few built-in modules, because some programs actually rely on them to be in sys.modules :-(""" + # encodings is imported sometimes but not always by app_main + import encodings import exceptions if 'zipimport' in sys.builtin_module_names: import zipimport diff --git a/pypy/module/test_lib_pypy/test_site_extra.py b/pypy/module/test_lib_pypy/test_site_extra.py --- a/pypy/module/test_lib_pypy/test_site_extra.py +++ b/pypy/module/test_lib_pypy/test_site_extra.py @@ -2,7 +2,7 @@ def test_preimported_modules(): - lst = ['__builtin__', '_warnings', + lst = ['__builtin__', '_codecs', '_warnings', 'codecs', 'encodings', 'exceptions', 'signal', 'sys', 'zipimport'] g = os.popen("'%s' -c 'import sys; print sorted(sys.modules)'" % (sys.executable,)) From noreply at buildbot.pypy.org Wed Apr 3 10:10:18 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Wed, 3 Apr 2013 10:10:18 +0200 (CEST) Subject: [pypy-commit] pypy default: move cffi egg-info next to cffi dir Message-ID: <20130403081018.73E741C01E1@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r62956:459eee432bb3 Date: 2013-04-03 04:10 -0400 http://bitbucket.org/pypy/pypy/changeset/459eee432bb3/ Log: move cffi egg-info next to cffi dir diff --git a/lib-python/2/cffi.egg-info b/lib_pypy/cffi.egg-info rename from lib-python/2/cffi.egg-info rename to lib_pypy/cffi.egg-info From noreply at buildbot.pypy.org Wed Apr 3 10:32:43 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 3 Apr 2013 10:32:43 +0200 (CEST) Subject: [pypy-commit] pypy default: fix the test Message-ID: <20130403083243.42CCE1C0228@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r62957:9c17279f5949 Date: 2013-04-03 10:31 +0200 http://bitbucket.org/pypy/pypy/changeset/9c17279f5949/ Log: fix the test diff --git a/pypy/tool/jitlogparser/test/logtest.log b/pypy/tool/jitlogparser/test/logtest.log --- a/pypy/tool/jitlogparser/test/logtest.log +++ b/pypy/tool/jitlogparser/test/logtest.log @@ -15,7 +15,7 @@ debug_merge_point(0, ' #12 LOAD_CONST') debug_merge_point(0, ' #15 COMPARE_OP') +166: i6 = int_lt(i4, 10000) -guard_true(i6, descr=) [p1, p0, p2, p3, i4] +guard_true(i6, descr=) [p1, p0, p2, p3, i4] debug_merge_point(0, ' #18 POP_JUMP_IF_FALSE') debug_merge_point(0, ' #21 LOAD_FAST') debug_merge_point(0, ' #24 LOAD_CONST') @@ -27,7 +27,7 @@ +191: i12 = int_sub(i10, 1) +195: setfield_raw(40564608, i12, descr=) +203: i14 = int_lt(i12, 0) -guard_false(i14, descr=) [p1, p0, p2, p3, i8, None] +guard_false(i14, descr=) [p1, p0, p2, p3, i8, None] debug_merge_point(0, ' #9 LOAD_FAST') +213: jump(p0, p1, p2, p3, i8, descr=) +218: --end of the loop-- From noreply at buildbot.pypy.org Wed Apr 3 10:32:44 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 3 Apr 2013 10:32:44 +0200 (CEST) Subject: [pypy-commit] pypy default: merge Message-ID: <20130403083244.8E5371C0228@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r62958:ddf565617f3d Date: 2013-04-03 10:32 +0200 http://bitbucket.org/pypy/pypy/changeset/ddf565617f3d/ Log: merge diff --git a/lib-python/2/cffi.egg-info b/lib_pypy/cffi.egg-info rename from lib-python/2/cffi.egg-info rename to lib_pypy/cffi.egg-info From noreply at buildbot.pypy.org Wed Apr 3 11:10:03 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 3 Apr 2013 11:10:03 +0200 (CEST) Subject: [pypy-commit] pypy default: try to use minimal curses Message-ID: <20130403091003.91BCE1C030B@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r62960:9c11c99803b8 Date: 2013-04-03 11:09 +0200 http://bitbucket.org/pypy/pypy/changeset/9c11c99803b8/ Log: try to use minimal curses diff --git a/lib_pypy/pyrepl/curses.py b/lib_pypy/pyrepl/curses.py --- a/lib_pypy/pyrepl/curses.py +++ b/lib_pypy/pyrepl/curses.py @@ -21,14 +21,18 @@ # avoid importing the whole curses, if possible try: - import _curses + # pypy case + import _minimal_curses as _curses except ImportError: try: - import curses + import _curses except ImportError: # Who knows, maybe some environment has "curses" but not "_curses". # If not, at least the following import gives a clean ImportError. - import _curses + try: + import curses as _curses + except ImportError: + import _curses setupterm = _curses.setupterm tigetstr = _curses.tigetstr From noreply at buildbot.pypy.org Wed Apr 3 11:10:02 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 3 Apr 2013 11:10:02 +0200 (CEST) Subject: [pypy-commit] pypy default: readd _minimal_curses Message-ID: <20130403091002.621EE1C01E1@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r62959:3dcd89310152 Date: 2013-04-03 11:08 +0200 http://bitbucket.org/pypy/pypy/changeset/3dcd89310152/ Log: readd _minimal_curses diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py --- a/pypy/config/pypyoption.py +++ b/pypy/config/pypyoption.py @@ -31,7 +31,7 @@ ["_socket", "unicodedata", "mmap", "fcntl", "_locale", "pwd", "rctime" , "select", "zipimport", "_lsprof", "crypt", "signal", "_rawffi", "termios", "zlib", "bz2", - "struct", "_hashlib", "_md5", "_sha", "cStringIO", + "struct", "_hashlib", "_md5", "_sha", "_minimal_curses", "cStringIO", "thread", "itertools", "pyexpat", "_ssl", "cpyext", "array", "binascii", "_multiprocessing", '_warnings', "_collections", "_multibytecodec", "micronumpy", "_ffi", @@ -45,7 +45,7 @@ "binascii", # the following are needed for pyrepl (and hence for the # interactive prompt/pdb) - "termios", + "termios", "_minimal_curses", ])) working_oo_modules = default_modules.copy() @@ -62,6 +62,7 @@ del working_modules["fcntl"] del working_modules["pwd"] del working_modules["termios"] + del working_modules["_minimal_curses"] # The _locale module is needed by site.py on Windows default_modules["_locale"] = None @@ -71,6 +72,7 @@ del working_modules['rctime'] # depend on ctypes, missing tm_zone/tm_gmtoff del working_modules['signal'] # depend on ctypes, can't get at c-level 'errono' del working_modules['fcntl'] # LOCK_NB not defined + del working_modules["_minimal_curses"] del working_modules["termios"] del working_modules["_multiprocessing"] # depends on rctime @@ -101,6 +103,7 @@ "pyexpat" : ["pypy.module.pyexpat.interp_pyexpat"], "_ssl" : ["pypy.module._ssl.interp_ssl"], "_hashlib" : ["pypy.module._ssl.interp_ssl"], + "_minimal_curses": ["pypy.module._minimal_curses.fficurses"], "_continuation": ["rpython.rlib.rstacklet"], } diff --git a/pypy/module/_minimal_curses/__init__.py b/pypy/module/_minimal_curses/__init__.py new file mode 100644 --- /dev/null +++ b/pypy/module/_minimal_curses/__init__.py @@ -0,0 +1,32 @@ +try: + import _curses +except ImportError: + try: + import _minimal_curses as _curses # when running on top of pypy-c + except ImportError: + import py + py.test.skip("no _curses or _minimal_curses module") #no _curses at all + +from pypy.interpreter.mixedmodule import MixedModule +from pypy.module._minimal_curses import fficurses # for side effects + + +class Module(MixedModule): + """ Low-level interface for curses module, + not meant to be used directly + """ + + appleveldefs = { + 'error' : 'app_curses.error', + } + + interpleveldefs = { + 'setupterm' : 'interp_curses.setupterm', + 'tigetstr' : 'interp_curses.tigetstr', + 'tparm' : 'interp_curses.tparm', + } + +for i in dir(_curses): + val = getattr(_curses, i) + if i.isupper() and type(val) is int: + Module.interpleveldefs[i] = "space.wrap(%s)" % val diff --git a/pypy/module/_minimal_curses/app_curses.py b/pypy/module/_minimal_curses/app_curses.py new file mode 100644 --- /dev/null +++ b/pypy/module/_minimal_curses/app_curses.py @@ -0,0 +1,3 @@ + +class error(Exception): + pass diff --git a/pypy/module/_minimal_curses/fficurses.py b/pypy/module/_minimal_curses/fficurses.py new file mode 100644 --- /dev/null +++ b/pypy/module/_minimal_curses/fficurses.py @@ -0,0 +1,113 @@ + +""" The ffi for rpython, need to be imported for side effects +""" + +from rpython.rtyper.lltypesystem import rffi +from rpython.rtyper.lltypesystem import lltype +from rpython.rtyper.tool import rffi_platform +from rpython.rtyper.extfunc import register_external +from pypy.module._minimal_curses import interp_curses +from rpython.translator.tool.cbuild import ExternalCompilationInfo +from sys import platform +import os.path + +_CYGWIN = platform == 'cygwin' +_NCURSES_CURSES = os.path.isfile("/usr/include/ncurses/curses.h") + +if _CYGWIN or _NCURSES_CURSES: + eci = ExternalCompilationInfo( + includes = ['ncurses/curses.h', 'ncurses/term.h'], + libraries = ['curses'], + ) +else: + eci = ExternalCompilationInfo( + includes = ['curses.h', 'term.h'], + libraries = ['curses'], + ) + +rffi_platform.verify_eci(eci) + + +INT = rffi.INT +INTP = lltype.Ptr(lltype.Array(INT, hints={'nolength':True})) +c_setupterm = rffi.llexternal('setupterm', [rffi.CCHARP, INT, INTP], INT, + compilation_info=eci) +c_tigetstr = rffi.llexternal('tigetstr', [rffi.CCHARP], rffi.CCHARP, + compilation_info=eci) +c_tparm = rffi.llexternal('tparm', [rffi.CCHARP, INT, INT, INT, INT, INT, + INT, INT, INT, INT], rffi.CCHARP, + compilation_info=eci) + +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: + errret = rffi.cast(lltype.Signed, intp[0]) + if errret == 0: + msg = "setupterm: could not find terminal" + elif errret == -1: + msg = "setupterm: could not find terminfo database" + else: + msg = "setupterm: unknown error" + raise interp_curses.curses_error(msg) + interp_curses.module_info.setupterm_called = True + finally: + lltype.free(intp, flavor='raw') + +def curses_setupterm_null_llimpl(fd): + curses_setupterm(lltype.nullptr(rffi.CCHARP.TO), fd) + +def curses_setupterm_llimpl(term, fd): + ll_s = rffi.str2charp(term) + try: + curses_setupterm(ll_s, fd) + finally: + rffi.free_charp(ll_s) + +register_external(interp_curses._curses_setupterm_null, + [int], llimpl=curses_setupterm_null_llimpl, + export_name='_curses.setupterm_null') +register_external(interp_curses._curses_setupterm, + [str, int], llimpl=curses_setupterm_llimpl, + export_name='_curses.setupterm') + +def check_setup_invoked(): + if not interp_curses.module_info.setupterm_called: + raise interp_curses.curses_error("must call (at least) setupterm() first") + +def tigetstr_llimpl(cap): + check_setup_invoked() + ll_cap = rffi.str2charp(cap) + try: + ll_res = c_tigetstr(ll_cap) + num = lltype.cast_ptr_to_int(ll_res) + if num == 0 or num == -1: + raise interp_curses.TermError() + res = rffi.charp2str(ll_res) + return res + finally: + rffi.free_charp(ll_cap) + +register_external(interp_curses._curses_tigetstr, [str], str, + export_name='_curses.tigetstr', llimpl=tigetstr_llimpl) + +def tparm_llimpl(s, args): + check_setup_invoked() + l = [0, 0, 0, 0, 0, 0, 0, 0, 0] + for i in range(min(len(args), 9)): + l[i] = args[i] + ll_s = rffi.str2charp(s) + # XXX nasty trick stolen from CPython + ll_res = c_tparm(ll_s, l[0], l[1], l[2], l[3], l[4], l[5], l[6], + l[7], l[8]) + rffi.free_charp(ll_s) + res = rffi.charp2str(ll_res) + return res + +register_external(interp_curses._curses_tparm, [str, [int]], str, + export_name='_curses.tparm', llimpl=tparm_llimpl) + diff --git a/pypy/module/_minimal_curses/interp_curses.py b/pypy/module/_minimal_curses/interp_curses.py new file mode 100644 --- /dev/null +++ b/pypy/module/_minimal_curses/interp_curses.py @@ -0,0 +1,94 @@ + +from pypy.interpreter.gateway import unwrap_spec +from pypy.interpreter.error import OperationError +from pypy.module._minimal_curses import _curses + +class ModuleInfo: + def __init__(self): + self.setupterm_called = False + +module_info = ModuleInfo() + +class curses_error(Exception): + def __init__(self, msg): + self.msg = msg + +from rpython.annotator.classdef import FORCE_ATTRIBUTES_INTO_CLASSES +from rpython.annotator.model import SomeString + +# this is necessary due to annmixlevel +FORCE_ATTRIBUTES_INTO_CLASSES[curses_error] = {'msg': SomeString()} + +def convert_error(space, error): + msg = error.msg + w_module = space.getbuiltinmodule('_minimal_curses') + w_exception_class = space.getattr(w_module, space.wrap('error')) + w_exception = space.call_function(w_exception_class, space.wrap(msg)) + return OperationError(w_exception_class, w_exception) + +def _curses_setupterm_null(fd): + # NOT_RPYTHON + try: + _curses.setupterm(None, fd) + except _curses.error, e: + raise curses_error(e.args[0]) + +def _curses_setupterm(termname, fd): + # NOT_RPYTHON + try: + _curses.setupterm(termname, fd) + except _curses.error, e: + raise curses_error(e.args[0]) + + at unwrap_spec(fd=int) +def setupterm(space, w_termname=None, fd=-1): + if fd == -1: + w_stdout = space.getattr(space.getbuiltinmodule('sys'), + space.wrap('stdout')) + fd = space.int_w(space.call_function(space.getattr(w_stdout, + space.wrap('fileno')))) + try: + if space.is_none(w_termname): + _curses_setupterm_null(fd) + else: + _curses_setupterm(space.str_w(w_termname), fd) + except curses_error, e: + raise convert_error(space, e) + +class TermError(Exception): + pass + +def _curses_tigetstr(capname): + # NOT_RPYTHON + try: + res = _curses.tigetstr(capname) + except _curses.error, e: + raise curses_error(e.args[0]) + if res is None: + raise TermError + return res + +def _curses_tparm(s, args): + # NOT_RPYTHON + try: + return _curses.tparm(s, *args) + except _curses.error, e: + raise curses_error(e.args[0]) + + at unwrap_spec(capname=str) +def tigetstr(space, capname): + try: + result = _curses_tigetstr(capname) + except TermError: + return space.w_None + except curses_error, e: + raise convert_error(space, e) + return space.wrap(result) + + at unwrap_spec(s=str) +def tparm(space, s, args_w): + args = [space.int_w(a) for a in args_w] + try: + return space.wrap(_curses_tparm(s, args)) + except curses_error, e: + raise convert_error(space, e) diff --git a/pypy/module/_minimal_curses/test/__init__.py b/pypy/module/_minimal_curses/test/__init__.py new file mode 100644 diff --git a/pypy/module/_minimal_curses/test/test_curses.py b/pypy/module/_minimal_curses/test/test_curses.py new file mode 100644 --- /dev/null +++ b/pypy/module/_minimal_curses/test/test_curses.py @@ -0,0 +1,108 @@ +from pypy.conftest import pypydir +from rpython.tool.udir import udir +import py +import sys +# tests here are run as snippets through a pexpected python subprocess + + +def setup_module(mod): + try: + import curses + curses.setupterm() + except: + py.test.skip("Cannot test this here") + +class TestCurses(object): + """ We need to fork here, to prevent + the setup to be done + """ + def _spawn(self, *args, **kwds): + import pexpect + kwds.setdefault('timeout', 600) + print 'SPAWN:', args, kwds + child = pexpect.spawn(*args, **kwds) + child.logfile = sys.stdout + return child + + def spawn(self, argv): + py_py = py.path.local(pypydir).join('bin', 'pyinteractive.py') + return self._spawn(sys.executable, [str(py_py)] + argv) + + def setup_class(self): + try: + import pexpect + except ImportError: + py.test.skip('pexpect not found') + + def test_setupterm(self): + source = py.code.Source(""" + import _minimal_curses + try: + _minimal_curses.tigetstr('cup') + except _minimal_curses.error: + print 'ok!' + """) + f = udir.join("test_setupterm.py") + f.write(source) + child = self.spawn(['--withmod-_minimal_curses', str(f)]) + child.expect('ok!') + + def test_tigetstr(self): + source = py.code.Source(""" + import _minimal_curses + _minimal_curses.setupterm() + assert _minimal_curses.tigetstr('cup') == '\x1b[%i%p1%d;%p2%dH' + print 'ok!' + """) + f = udir.join("test_tigetstr.py") + f.write(source) + child = self.spawn(['--withmod-_minimal_curses', str(f)]) + child.expect('ok!') + + def test_tparm(self): + source = py.code.Source(""" + import _minimal_curses + _minimal_curses.setupterm() + assert _minimal_curses.tparm(_minimal_curses.tigetstr('cup'), 5, 3) == '\033[6;4H' + print 'ok!' + """) + f = udir.join("test_tparm.py") + f.write(source) + child = self.spawn(['--withmod-_minimal_curses', str(f)]) + child.expect('ok!') + +class TestCCurses(object): + """ Test compiled version + """ + def test_csetupterm(self): + from rpython.translator.c.test.test_genc import compile + from pypy.module._minimal_curses import interp_curses + def runs_setupterm(): + interp_curses._curses_setupterm_null(1) + + fn = compile(runs_setupterm, []) + fn() + + def test_ctgetstr(self): + from rpython.translator.c.test.test_genc import compile + from pypy.module._minimal_curses import interp_curses + def runs_ctgetstr(): + interp_curses._curses_setupterm("xterm", 1) + return interp_curses._curses_tigetstr('cup') + + fn = compile(runs_ctgetstr, []) + res = fn() + assert res == '\x1b[%i%p1%d;%p2%dH' + + def test_ctparm(self): + from rpython.translator.c.test.test_genc import compile + from pypy.module._minimal_curses import interp_curses + def runs_tparm(): + interp_curses._curses_setupterm("xterm", 1) + cup = interp_curses._curses_tigetstr('cup') + return interp_curses._curses_tparm(cup, [5, 3]) + + fn = compile(runs_tparm, []) + res = fn() + assert res == '\033[6;4H' + From noreply at buildbot.pypy.org Wed Apr 3 11:41:31 2013 From: noreply at buildbot.pypy.org (arigo) Date: Wed, 3 Apr 2013 11:41:31 +0200 (CEST) Subject: [pypy-commit] cffi default: Backed out changeset 982940f8c484 Message-ID: <20130403094131.553821C0228@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r1227:822523ca9c65 Date: 2013-04-03 11:40 +0200 http://bitbucket.org/cffi/cffi/changeset/822523ca9c65/ Log: Backed out changeset 982940f8c484 Should not be needed any more after PyPy's revert to "lib- python/2.7". diff --git a/testing/test_zintegration.py b/testing/test_zintegration.py --- a/testing/test_zintegration.py +++ b/testing/test_zintegration.py @@ -3,18 +3,6 @@ import subprocess from testing.udir import udir -def setup_module(mod): - if '__pypy__' in sys.builtin_module_names: - try: - ver = subprocess.check_output(['virtualenv', '--version']) - except OSError as e: - py.test.skip("Cannot execute virtualenv: %s" % (e,)) - # this check is absolutely broken, but I can't think about a better - # idea - if ((ver.startswith('1.9') and ver <= "1.9.1") or - ver[2] != '1'): - py.test.skip("pypy requires virtualenv >= 1.9.2") - def create_venv(name): tmpdir = udir.join(name) try: From noreply at buildbot.pypy.org Wed Apr 3 11:50:53 2013 From: noreply at buildbot.pypy.org (arigo) Date: Wed, 3 Apr 2013 11:50:53 +0200 (CEST) Subject: [pypy-commit] pypy default: Remove the mention of vendor-rename in whatsnew-head.rst. Message-ID: <20130403095053.C4E691C0228@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r62965:e62d26e480f0 Date: 2013-04-03 11:49 +0200 http://bitbucket.org/pypy/pypy/changeset/e62d26e480f0/ Log: Remove the mention of vendor-rename in whatsnew-head.rst. diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -101,7 +101,6 @@ Random cleanups to hide FlowObjSpace from public view. .. branch: vendor-rename -Remove minor verison number from lib-python dirs to simplify stdlib upgrades. .. branch: jitframe-on-heap Moves optimized JIT frames from stack to heap. As a side effect it enables From noreply at buildbot.pypy.org Wed Apr 3 11:55:15 2013 From: noreply at buildbot.pypy.org (arigo) Date: Wed, 3 Apr 2013 11:55:15 +0200 (CEST) Subject: [pypy-commit] pypy default: Run pypy/tool/import_cffi.py. Message-ID: <20130403095515.D358E1C0334@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r62966:81d0d321b500 Date: 2013-04-03 11:54 +0200 http://bitbucket.org/pypy/pypy/changeset/81d0d321b500/ Log: Run pypy/tool/import_cffi.py. diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_zintegration.py b/pypy/module/test_lib_pypy/cffi_tests/test_zintegration.py --- a/pypy/module/test_lib_pypy/cffi_tests/test_zintegration.py +++ b/pypy/module/test_lib_pypy/cffi_tests/test_zintegration.py @@ -3,18 +3,6 @@ import subprocess from pypy.module.test_lib_pypy.cffi_tests.udir import udir -def setup_module(mod): - if '__pypy__' in sys.builtin_module_names: - try: - ver = subprocess.check_output(['virtualenv', '--version']) - except OSError as e: - py.test.skip("Cannot execute virtualenv: %s" % (e,)) - # this check is absolutely broken, but I can't think about a better - # idea - if ((ver.startswith('1.9') and ver <= "1.9.1") or - ver[2] != '1'): - py.test.skip("pypy requires virtualenv >= 1.9.2") - def create_venv(name): tmpdir = udir.join(name) try: From noreply at buildbot.pypy.org Wed Apr 3 11:58:10 2013 From: noreply at buildbot.pypy.org (arigo) Date: Wed, 3 Apr 2013 11:58:10 +0200 (CEST) Subject: [pypy-commit] pypy default: Add a header line to all files copied and mangled by import_cffi.py. Message-ID: <20130403095810.9E8E51C0228@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r62967:74e45c655eab Date: 2013-04-03 11:57 +0200 http://bitbucket.org/pypy/pypy/changeset/74e45c655eab/ Log: Add a header line to all files copied and mangled by import_cffi.py. diff --git a/pypy/module/test_lib_pypy/cffi_tests/__init__.py b/pypy/module/test_lib_pypy/cffi_tests/__init__.py --- a/pypy/module/test_lib_pypy/cffi_tests/__init__.py +++ b/pypy/module/test_lib_pypy/cffi_tests/__init__.py @@ -0,0 +1,1 @@ +# Generated by pypy/tool/import_cffi.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/backend_tests.py b/pypy/module/test_lib_pypy/cffi_tests/backend_tests.py --- a/pypy/module/test_lib_pypy/cffi_tests/backend_tests.py +++ b/pypy/module/test_lib_pypy/cffi_tests/backend_tests.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py import py import sys, ctypes from cffi import FFI, CDefError diff --git a/pypy/module/test_lib_pypy/cffi_tests/callback_in_thread.py b/pypy/module/test_lib_pypy/cffi_tests/callback_in_thread.py --- a/pypy/module/test_lib_pypy/cffi_tests/callback_in_thread.py +++ b/pypy/module/test_lib_pypy/cffi_tests/callback_in_thread.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py import sys, time sys.path.insert(0, sys.argv[1]) from cffi import FFI diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/setup.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/setup.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/setup.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py from distutils.core import setup import snip_basic_verify diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/snip_basic_verify.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/snip_basic_verify.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/snip_basic_verify.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/snip_basic_verify.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py from cffi import FFI import sys diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/setup.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/setup.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/setup.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py from distutils.core import setup import snip_basic_verify1 diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/snip_basic_verify1/__init__.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/snip_basic_verify1/__init__.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/snip_basic_verify1/__init__.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/snip_basic_verify1/__init__.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py from cffi import FFI import sys diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/setup.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/setup.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/setup.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py from distutils.core import setup import snip_basic_verify2 diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/snip_basic_verify2/__init__.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/snip_basic_verify2/__init__.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/snip_basic_verify2/__init__.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/snip_basic_verify2/__init__.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py from cffi import FFI import sys diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/build/lib/snip_infrastructure/__init__.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/build/lib/snip_infrastructure/__init__.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/build/lib/snip_infrastructure/__init__.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/build/lib/snip_infrastructure/__init__.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py def func(): return 42 diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/setup.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/setup.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/setup.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py from distutils.core import setup diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/snip_infrastructure/__init__.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/snip_infrastructure/__init__.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/snip_infrastructure/__init__.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/snip_infrastructure/__init__.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py def func(): return 42 diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/setup.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/setup.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/setup.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py from setuptools import setup import snip_setuptools_verify diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/snip_setuptools_verify.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/snip_setuptools_verify.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/snip_setuptools_verify.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/snip_setuptools_verify.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py from cffi import FFI import sys diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/setup.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/setup.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/setup.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py from setuptools import setup import snip_setuptools_verify1 diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/snip_setuptools_verify1/__init__.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/snip_setuptools_verify1/__init__.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/snip_setuptools_verify1/__init__.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/snip_setuptools_verify1/__init__.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py from cffi import FFI import sys diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/setup.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/setup.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/setup.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py from setuptools import setup import snip_setuptools_verify2 diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/snip_setuptools_verify2/__init__.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/snip_setuptools_verify2/__init__.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/snip_setuptools_verify2/__init__.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/snip_setuptools_verify2/__init__.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py from cffi import FFI import sys diff --git a/pypy/module/test_lib_pypy/cffi_tests/support.py b/pypy/module/test_lib_pypy/cffi_tests/support.py --- a/pypy/module/test_lib_pypy/cffi_tests/support.py +++ b/pypy/module/test_lib_pypy/cffi_tests/support.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py import sys if sys.version_info < (3,): diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_cdata.py b/pypy/module/test_lib_pypy/cffi_tests/test_cdata.py --- a/pypy/module/test_lib_pypy/cffi_tests/test_cdata.py +++ b/pypy/module/test_lib_pypy/cffi_tests/test_cdata.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py import py from cffi import FFI diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_ctypes.py b/pypy/module/test_lib_pypy/cffi_tests/test_ctypes.py --- a/pypy/module/test_lib_pypy/cffi_tests/test_ctypes.py +++ b/pypy/module/test_lib_pypy/cffi_tests/test_ctypes.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py import py, sys from pypy.module.test_lib_pypy.cffi_tests import backend_tests from cffi.backend_ctypes import CTypesBackend diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_ffi_backend.py b/pypy/module/test_lib_pypy/cffi_tests/test_ffi_backend.py --- a/pypy/module/test_lib_pypy/cffi_tests/test_ffi_backend.py +++ b/pypy/module/test_lib_pypy/cffi_tests/test_ffi_backend.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py import py from pypy.module.test_lib_pypy.cffi_tests import backend_tests, test_function, test_ownlib from cffi import FFI diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_function.py b/pypy/module/test_lib_pypy/cffi_tests/test_function.py --- a/pypy/module/test_lib_pypy/cffi_tests/test_function.py +++ b/pypy/module/test_lib_pypy/cffi_tests/test_function.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py import py from cffi import FFI import math, os, sys diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_model.py b/pypy/module/test_lib_pypy/cffi_tests/test_model.py --- a/pypy/module/test_lib_pypy/cffi_tests/test_model.py +++ b/pypy/module/test_lib_pypy/cffi_tests/test_model.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py from cffi.model import * diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_ownlib.py b/pypy/module/test_lib_pypy/cffi_tests/test_ownlib.py --- a/pypy/module/test_lib_pypy/cffi_tests/test_ownlib.py +++ b/pypy/module/test_lib_pypy/cffi_tests/test_ownlib.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py import py, sys import subprocess, weakref from cffi import FFI diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_parsing.py b/pypy/module/test_lib_pypy/cffi_tests/test_parsing.py --- a/pypy/module/test_lib_pypy/cffi_tests/test_parsing.py +++ b/pypy/module/test_lib_pypy/cffi_tests/test_parsing.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py import py, sys, re from cffi import FFI, FFIError, CDefError, VerificationError diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_platform.py b/pypy/module/test_lib_pypy/cffi_tests/test_platform.py --- a/pypy/module/test_lib_pypy/cffi_tests/test_platform.py +++ b/pypy/module/test_lib_pypy/cffi_tests/test_platform.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py import os from cffi.ffiplatform import maybe_relative_path, flatten diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_unicode_literals.py b/pypy/module/test_lib_pypy/cffi_tests/test_unicode_literals.py --- a/pypy/module/test_lib_pypy/cffi_tests/test_unicode_literals.py +++ b/pypy/module/test_lib_pypy/cffi_tests/test_unicode_literals.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py # # ---------------------------------------------- # WARNING, ALL LITERALS IN THIS FILE ARE UNICODE diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_verify.py b/pypy/module/test_lib_pypy/cffi_tests/test_verify.py --- a/pypy/module/test_lib_pypy/cffi_tests/test_verify.py +++ b/pypy/module/test_lib_pypy/cffi_tests/test_verify.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py import py import sys, os, math, weakref from cffi import FFI, VerificationError, VerificationMissing, model diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_verify2.py b/pypy/module/test_lib_pypy/cffi_tests/test_verify2.py --- a/pypy/module/test_lib_pypy/cffi_tests/test_verify2.py +++ b/pypy/module/test_lib_pypy/cffi_tests/test_verify2.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py from .test_verify import * # This test file runs normally after test_verify. We only clean up the .c diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_version.py b/pypy/module/test_lib_pypy/cffi_tests/test_version.py --- a/pypy/module/test_lib_pypy/cffi_tests/test_version.py +++ b/pypy/module/test_lib_pypy/cffi_tests/test_version.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py import py, os, sys import cffi, _cffi_backend diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_vgen.py b/pypy/module/test_lib_pypy/cffi_tests/test_vgen.py --- a/pypy/module/test_lib_pypy/cffi_tests/test_vgen.py +++ b/pypy/module/test_lib_pypy/cffi_tests/test_vgen.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py import cffi.verifier from .test_verify import * diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_vgen2.py b/pypy/module/test_lib_pypy/cffi_tests/test_vgen2.py --- a/pypy/module/test_lib_pypy/cffi_tests/test_vgen2.py +++ b/pypy/module/test_lib_pypy/cffi_tests/test_vgen2.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py import cffi.verifier from .test_vgen import * diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_zdistutils.py b/pypy/module/test_lib_pypy/cffi_tests/test_zdistutils.py --- a/pypy/module/test_lib_pypy/cffi_tests/test_zdistutils.py +++ b/pypy/module/test_lib_pypy/cffi_tests/test_zdistutils.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py import sys, os, imp, math, shutil import py from cffi import FFI, FFIError diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_zintegration.py b/pypy/module/test_lib_pypy/cffi_tests/test_zintegration.py --- a/pypy/module/test_lib_pypy/cffi_tests/test_zintegration.py +++ b/pypy/module/test_lib_pypy/cffi_tests/test_zintegration.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py import py, os, sys, shutil import imp import subprocess diff --git a/pypy/module/test_lib_pypy/cffi_tests/udir.py b/pypy/module/test_lib_pypy/cffi_tests/udir.py --- a/pypy/module/test_lib_pypy/cffi_tests/udir.py +++ b/pypy/module/test_lib_pypy/cffi_tests/udir.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py import py udir = py.path.local.make_numbered_dir(prefix = 'ffi-') diff --git a/pypy/tool/import_cffi.py b/pypy/tool/import_cffi.py --- a/pypy/tool/import_cffi.py +++ b/pypy/tool/import_cffi.py @@ -8,6 +8,7 @@ import sys, py def mangle(lines): + yield "# Generated by pypy/tool/import_cffi.py\n" for line in lines: line = line.replace('from testing', 'from pypy.module.test_lib_pypy.cffi_tests') yield line From noreply at buildbot.pypy.org Wed Apr 3 13:10:05 2013 From: noreply at buildbot.pypy.org (arigo) Date: Wed, 3 Apr 2013 13:10:05 +0200 (CEST) Subject: [pypy-commit] pypy default: Only keep the files that are checked in, in cffi. Not all the temporary Message-ID: <20130403111005.C1FE51C01E1@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r62968:94a1745b4347 Date: 2013-04-03 13:07 +0200 http://bitbucket.org/pypy/pypy/changeset/94a1745b4347/ Log: Only keep the files that are checked in, in cffi. Not all the temporary stuff. diff too long, truncating to 2000 out of 2764 lines diff --git a/pypy/module/test_lib_pypy/cffi_tests/conftest.py b/pypy/module/test_lib_pypy/cffi_tests/conftest.py deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/conftest.py +++ /dev/null @@ -1,6 +0,0 @@ - -def pytest_ignore_collect(path, config): - if config.option.runappdirect: - return False - # only run if -A is specified - return True diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/__pycache__/__pycache__/_cffi__gd39ab08bx8432a366.o b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/__pycache__/__pycache__/_cffi__gd39ab08bx8432a366.o deleted file mode 100644 Binary file pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/__pycache__/__pycache__/_cffi__gd39ab08bx8432a366.o has changed diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/__pycache__/_cffi__gd39ab08bx8432a366.c b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/__pycache__/_cffi__gd39ab08bx8432a366.c deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/__pycache__/_cffi__gd39ab08bx8432a366.c +++ /dev/null @@ -1,53 +0,0 @@ - -#include -#include -#include -#include -#include /* XXX for ssize_t on some platforms */ - -#ifdef _WIN32 -# include -# define snprintf _snprintf -typedef __int8 int8_t; -typedef __int16 int16_t; -typedef __int32 int32_t; -typedef __int64 int64_t; -typedef unsigned __int8 uint8_t; -typedef unsigned __int16 uint16_t; -typedef unsigned __int32 uint32_t; -typedef unsigned __int64 uint64_t; -typedef SSIZE_T ssize_t; -typedef unsigned char _Bool; -#else -# include -#endif - - // passed to the real C compiler -#include -#include - -struct passwd * _cffi_f_getpwuid(int x0) -{ - return getpwuid(x0); -} - -static void _cffi_check_struct_passwd(struct passwd *p) -{ - /* only to generate compile-time warnings or errors */ - { char * *tmp = &p->pw_name; (void)tmp; } -} -ssize_t _cffi_layout_struct_passwd(ssize_t i) -{ - struct _cffi_aligncheck { char x; struct passwd y; }; - static ssize_t nums[] = { - sizeof(struct passwd), - offsetof(struct _cffi_aligncheck, y), - offsetof(struct passwd, pw_name), - sizeof(((struct passwd *)0)->pw_name), - -1 - }; - return nums[i]; - /* the next line is not executed, but compiled */ - _cffi_check_struct_passwd(0); -} - diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/__pycache__/_cffi__gd39ab08bx8432a366.pypy-20.so b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/__pycache__/_cffi__gd39ab08bx8432a366.pypy-20.so deleted file mode 100755 Binary file pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/__pycache__/_cffi__gd39ab08bx8432a366.pypy-20.so has changed diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/build/lib.linux-x86_64-2.7/_cffi__gd39ab08bx8432a366.pypy-20.so b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/build/lib.linux-x86_64-2.7/_cffi__gd39ab08bx8432a366.pypy-20.so deleted file mode 100755 Binary file pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/build/lib.linux-x86_64-2.7/_cffi__gd39ab08bx8432a366.pypy-20.so has changed diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/build/lib.linux-x86_64-2.7/snip_basic_verify.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/build/lib.linux-x86_64-2.7/snip_basic_verify.py deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/build/lib.linux-x86_64-2.7/snip_basic_verify.py +++ /dev/null @@ -1,17 +0,0 @@ - -from cffi import FFI -import sys - -ffi = FFI() -ffi.cdef(""" // some declarations from the man page - struct passwd { - char *pw_name; - ...; - }; - struct passwd *getpwuid(int uid); -""") -C = ffi.verify(""" // passed to the real C compiler -#include -#include -""", libraries=[], # or a list of libraries to link with - force_generic_engine=hasattr(sys, '_force_generic_engine_')) diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/build/temp.linux-x86_64-2.7/__pycache__/_cffi__gd39ab08bx8432a366.o b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/build/temp.linux-x86_64-2.7/__pycache__/_cffi__gd39ab08bx8432a366.o deleted file mode 100644 Binary file pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/build/temp.linux-x86_64-2.7/__pycache__/_cffi__gd39ab08bx8432a366.o has changed diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/lextab.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/lextab.py deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/lextab.py +++ /dev/null @@ -1,9 +0,0 @@ -# pycparser.lextab.py. This file automatically created by PLY (version 3.4). Don't edit! -_tabversion = '3.4' -_lextokens = {'VOID': 1, 'LBRACKET': 1, 'WCHAR_CONST': 1, 'FLOAT_CONST': 1, 'MINUS': 1, 'RPAREN': 1, 'LONG': 1, 'PLUS': 1, 'ELLIPSIS': 1, 'GT': 1, 'GOTO': 1, 'ENUM': 1, 'PERIOD': 1, 'GE': 1, 'INT_CONST_DEC': 1, 'ARROW': 1, 'HEX_FLOAT_CONST': 1, 'DOUBLE': 1, 'MINUSEQUAL': 1, 'INT_CONST_OCT': 1, 'TIMESEQUAL': 1, 'OR': 1, 'SHORT': 1, 'RETURN': 1, 'RSHIFTEQUAL': 1, 'RESTRICT': 1, 'STATIC': 1, 'SIZEOF': 1, 'UNSIGNED': 1, 'UNION': 1, 'COLON': 1, 'WSTRING_LITERAL': 1, 'DIVIDE': 1, 'FOR': 1, 'PLUSPLUS': 1, 'EQUALS': 1, 'ELSE': 1, 'INLINE': 1, 'EQ': 1, 'AND': 1, 'TYPEID': 1, 'LBRACE': 1, 'PPHASH': 1, 'INT': 1, 'SIGNED': 1, 'CONTINUE': 1, 'NOT': 1, 'OREQUAL': 1, 'MOD': 1, 'RSHIFT': 1, 'DEFAULT': 1, 'CHAR': 1, 'WHILE': 1, 'DIVEQUAL': 1, 'EXTERN': 1, 'CASE': 1, 'LAND': 1, 'REGISTER': 1, 'MODEQUAL': 1, 'NE': 1, 'SWITCH': 1, 'INT_CONST_HEX': 1, '_COMPLEX': 1, 'PLUSEQUAL': 1, 'STRUCT': 1, 'CONDOP': 1, 'BREAK': 1, 'VOLATILE': 1, 'ANDEQUAL': 1, 'DO': 1, 'LNOT': 1, 'CONST': 1, 'LOR': 1, 'CHAR_CONST': 1, 'LSHIFT': 1, 'RBRACE': 1, '_BOOL': 1, 'LE': 1, 'SEMI': 1, 'LT': 1, 'COMMA': 1, 'TYPEDEF': 1, 'XOR': 1, 'AUTO': 1, 'TIMES': 1, 'LPAREN': 1, 'MINUSMINUS': 1, 'ID': 1, 'IF': 1, 'STRING_LITERAL': 1, 'FLOAT': 1, 'XOREQUAL': 1, 'LSHIFTEQUAL': 1, 'RBRACKET': 1} -_lexreflags = 0 -_lexliterals = '' -_lexstateinfo = {'ppline': 'exclusive', 'pppragma': 'exclusive', 'INITIAL': 'inclusive'} -_lexstatere = {'ppline': [('(?P"([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*")|(?P(0(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?)|([1-9][0-9]*(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?))|(?P\\n)|(?Pline)', [None, ('t_ppline_FILENAME', 'FILENAME'), None, None, None, None, None, None, ('t_ppline_LINE_NUMBER', 'LINE_NUMBER'), None, None, None, None, None, None, None, None, ('t_ppline_NEWLINE', 'NEWLINE'), ('t_ppline_PPLINE', 'PPLINE')])], 'pppragma': [('(?P\\n)|(?Ppragma)|(?P"([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*")|(?P[a-zA-Z_][0-9a-zA-Z_]*)', [None, ('t_pppragma_NEWLINE', 'NEWLINE'), ('t_pppragma_PPPRAGMA', 'PPPRAGMA'), ('t_pppragma_STR', 'STR'), None, None, None, None, None, None, ('t_pppragma_ID', 'ID')])], 'INITIAL': [('(?P[ \\t]*\\#)|(?P\\n+)|(?P((((([0-9]*\\.[0-9]+)|([0-9]+\\.))([eE][-+]?[0-9]+)?)|([0-9]+([eE][-+]?[0-9]+)))[FfLl]?))|(?P(0[xX]([0-9a-fA-F]+|((([0-9a-fA-F]+)?\\.[0-9a-fA-F]+)|([0-9a-fA-F]+\\.)))([pP][+-]?[0-9]+)[FfLl]?))|(?P0[xX][0-9a-fA-F]+(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?)|(?P0[0-7]*[89])|(?P0[0-7]*(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?)', [None, ('t_PPHASH', 'PPHASH'), ('t_NEWLINE', 'NEWLINE'), ('t_FLOAT_CONST', 'FLOAT_CONST'), None, None, None, None, None, None, None, None, None, ('t_HEX_FLOAT_CONST', 'HEX_FLOAT_CONST'), None, None, None, None, None, None, None, ('t_INT_CONST_HEX', 'INT_CONST_HEX'), None, None, None, ('t_BAD_CONST_OCT', 'BAD_CONST_OCT'), ('t_INT_CONST_OCT', 'INT_CONST_OCT')]), ('(?P(0(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?)|([1-9][0-9]*(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?))|(?P\'([^\'\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))\')|(?PL\'([^\'\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))\')|(?P(\'([^\'\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*\\n)|(\'([^\'\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*$))|(?P(\'([^\'\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))[^\'\n]+\')|(\'\')|(\'([\\\\][^a-zA-Z._~^!=&\\^\\-\\\\?\'"x0-7])[^\'\\n]*\'))|(?PL"([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*")|(?P"([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*([\\\\][^a-zA-Z._~^!=&\\^\\-\\\\?\'"x0-7])([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*")|(?P[a-zA-Z_][0-9a-zA-Z_]*)', [None, ('t_INT_CONST_DEC', 'INT_CONST_DEC'), None, None, None, None, None, None, None, None, ('t_CHAR_CONST', 'CHAR_CONST'), None, None, None, None, None, None, ('t_WCHAR_CONST', 'WCHAR_CONST'), None, None, None, None, None, None, ('t_UNMATCHED_QUOTE', 'UNMATCHED_QUOTE'), None, None, None, None, None, None, None, None, None, None, None, None, None, None, ('t_BAD_CHAR_CONST', 'BAD_CHAR_CONST'), None, None, None, None, None, None, None, None, None, None, ('t_WSTRING_LITERAL', 'WSTRING_LITERAL'), None, None, None, None, None, None, ('t_BAD_STRING_LITERAL', 'BAD_STRING_LITERAL'), None, None, None, None, None, None, None, None, None, None, None, None, None, ('t_ID', 'ID')]), ('(?P"([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*")|(?P\\.\\.\\.)|(?P\\+\\+)|(?P\\|\\|)|(?P\\^=)|(?P\\|=)|(?P<<=)|(?P>>=)|(?P\\+=)|(?P\\*=)|(?P\\+)|(?P%=)|(?P\\{)|(?P/=)|(?P\\])|(?P\\?)', [None, (None, 'STRING_LITERAL'), None, None, None, None, None, None, (None, 'ELLIPSIS'), (None, 'PLUSPLUS'), (None, 'LOR'), (None, 'XOREQUAL'), (None, 'OREQUAL'), (None, 'LSHIFTEQUAL'), (None, 'RSHIFTEQUAL'), (None, 'PLUSEQUAL'), (None, 'TIMESEQUAL'), (None, 'PLUS'), (None, 'MODEQUAL'), (None, 'LBRACE'), (None, 'DIVEQUAL'), (None, 'RBRACKET'), (None, 'CONDOP')]), ('(?P\\^)|(?P<<)|(?P<=)|(?P\\()|(?P->)|(?P==)|(?P\\})|(?P!=)|(?P--)|(?P\\|)|(?P\\*)|(?P\\[)|(?P>=)|(?P\\))|(?P&&)|(?P>>)|(?P&=)|(?P-=)|(?P\\.)|(?P=)|(?P<)|(?P,)|(?P/)|(?P&)|(?P%)|(?P;)|(?P-)|(?P>)|(?P:)|(?P~)|(?P!)', [None, (None, 'XOR'), (None, 'LSHIFT'), (None, 'LE'), (None, 'LPAREN'), (None, 'ARROW'), (None, 'EQ'), (None, 'RBRACE'), (None, 'NE'), (None, 'MINUSMINUS'), (None, 'OR'), (None, 'TIMES'), (None, 'LBRACKET'), (None, 'GE'), (None, 'RPAREN'), (None, 'LAND'), (None, 'RSHIFT'), (None, 'ANDEQUAL'), (None, 'MINUSEQUAL'), (None, 'PERIOD'), (None, 'EQUALS'), (None, 'LT'), (None, 'COMMA'), (None, 'DIVIDE'), (None, 'AND'), (None, 'MOD'), (None, 'SEMI'), (None, 'MINUS'), (None, 'GT'), (None, 'COLON'), (None, 'NOT'), (None, 'LNOT')])]} -_lexstateignore = {'ppline': ' \t', 'pppragma': ' \t<>.-{}();+-*/$%@&^~!?:,0123456789', 'INITIAL': ' \t'} -_lexstateerrorf = {'ppline': 't_ppline_error', 'pppragma': 't_pppragma_error', 'INITIAL': 't_error'} diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/setup.py deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/setup.py +++ /dev/null @@ -1,8 +0,0 @@ -# Generated by pypy/tool/import_cffi.py - -from distutils.core import setup -import snip_basic_verify - -setup( - py_modules=['snip_basic_verify'], - ext_modules=[snip_basic_verify.ffi.verifier.get_extension()]) diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/snip_basic_verify.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/snip_basic_verify.py deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/snip_basic_verify.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by pypy/tool/import_cffi.py - -from cffi import FFI -import sys - -ffi = FFI() -ffi.cdef(""" // some declarations from the man page - struct passwd { - char *pw_name; - ...; - }; - struct passwd *getpwuid(int uid); -""") -C = ffi.verify(""" // passed to the real C compiler -#include -#include -""", libraries=[], # or a list of libraries to link with - force_generic_engine=hasattr(sys, '_force_generic_engine_')) diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/yacctab.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/yacctab.py deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/yacctab.py +++ /dev/null @@ -1,280 +0,0 @@ - -# yacctab.py -# This file is automatically generated. Do not edit. -_tabversion = '3.2' - -_lr_method = 'LALR' - -_lr_signature = '\x9er\xf1|P\xb6\xbb\x13\xed\xf52\xa1\xb1\xc3J\x12' - -_lr_action_items = {'VOID':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[6,6,-61,-72,-71,-58,-54,-55,-33,-29,-59,6,-34,-53,-68,-63,-52,6,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,6,-67,6,-70,-74,6,-57,-82,-249,-81,6,-107,-30,6,-97,-96,6,-45,-46,6,-109,6,6,6,6,-88,6,6,-36,6,-47,6,6,-83,-89,-250,6,-110,6,6,-111,-113,-112,6,6,-98,-37,-39,-42,-38,-40,6,-148,-147,-43,-149,-41,-85,-84,-90,6,6,-100,-99,-167,-166,6,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'LBRACKET':([1,2,3,5,6,9,10,13,14,17,18,19,21,23,24,25,27,28,29,32,33,35,37,39,40,42,43,44,45,46,49,50,51,52,54,55,56,58,59,63,64,66,67,68,69,76,77,83,87,89,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,129,138,139,149,151,152,153,154,155,174,178,180,184,185,191,195,216,217,218,223,224,231,235,262,264,265,273,274,277,281,285,286,314,318,319,323,329,350,351,357,359,360,361,362,366,369,371,387,388,389,390,400,401,409,],[-251,-61,-72,-71,-58,-54,-55,-59,-251,-53,-68,-63,-52,-56,-170,61,-66,-251,-69,-73,-108,-64,-60,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-249,-81,-49,61,-97,-96,-116,-114,-26,-25,-48,-51,-109,-251,-251,-233,-243,-247,-244,-241,-231,-232,182,-240,-220,-237,-245,-238,-242,-239,-230,221,-115,-117,-83,-250,-21,-80,-22,-79,-248,-246,-226,-227,-110,-111,221,-113,-112,221,312,221,-98,325,-237,-85,-84,-225,-224,-223,-234,221,221,312,-100,-99,-132,325,-221,-222,325,-146,-140,-142,-144,-135,325,-133,-141,-143,-145,-134,325,-228,-229,]),'WCHAR_CONST':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,96,-45,-219,96,-217,96,-216,96,-215,96,96,-214,-218,96,96,-250,96,-176,-179,-177,-173,-174,-178,-180,96,-182,-183,-175,-181,96,-215,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,-251,-39,-42,-38,96,-40,96,96,-148,-147,-43,-149,96,-41,96,96,96,-215,96,-12,96,96,-11,-167,-166,96,-164,96,96,-150,96,-163,-151,96,96,96,96,-251,96,-215,-251,-131,-162,-165,96,-154,96,-152,96,96,96,-153,96,96,96,-251,96,-158,-157,-155,96,96,96,-159,-156,96,-161,-160,]),'FLOAT_CONST':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,97,-45,-219,97,-217,97,-216,97,-215,97,97,-214,-218,97,97,-250,97,-176,-179,-177,-173,-174,-178,-180,97,-182,-183,-175,-181,97,-215,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,-251,-39,-42,-38,97,-40,97,97,-148,-147,-43,-149,97,-41,97,97,97,-215,97,-12,97,97,-11,-167,-166,97,-164,97,97,-150,97,-163,-151,97,97,97,97,-251,97,-215,-251,-131,-162,-165,97,-154,97,-152,97,97,97,-153,97,97,97,-251,97,-158,-157,-155,97,97,97,-159,-156,97,-161,-160,]),'MINUS':([55,61,75,91,92,93,94,95,96,97,98,99,100,101,102,104,105,106,108,109,110,111,112,113,114,115,116,117,118,119,120,123,124,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,180,182,183,184,186,187,188,189,190,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,262,270,273,274,277,281,282,283,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,349,350,351,352,353,356,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[-249,100,-45,-219,-206,-233,-243,-247,-244,-241,-231,100,-217,-232,-208,-187,100,-216,100,-240,-215,-220,100,100,-237,-245,-214,-238,200,-242,-239,-218,-230,100,100,-250,100,-176,-179,-177,-173,-174,-178,-180,100,-182,-183,-175,-181,-248,100,-212,-215,-246,-226,100,100,-227,100,-206,-211,100,-209,-210,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,-251,-39,-42,-38,100,-40,100,100,-148,-147,-43,-149,100,-41,-237,100,-225,-224,-223,-234,100,100,200,200,200,-192,200,200,200,-191,200,200,-189,-188,200,200,200,200,200,-190,-215,100,-12,100,100,-11,-167,-166,100,-164,100,100,-150,100,-163,-151,100,100,-213,-221,-222,100,100,-207,-251,100,-215,-251,-131,-162,-165,100,-154,100,-152,100,100,100,-153,100,100,100,-251,-228,100,-158,-157,-155,-229,100,100,100,-159,-156,100,-161,-160,]),'RPAREN':([1,2,3,5,6,9,10,13,14,17,18,19,21,23,24,25,27,28,29,32,33,35,37,39,40,42,43,44,45,46,49,50,51,52,53,54,56,58,59,62,63,64,66,67,68,69,76,77,83,87,89,92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,122,124,125,126,127,128,129,130,131,132,138,139,149,151,152,153,154,155,174,176,178,180,183,184,185,187,188,190,191,192,193,194,195,196,216,217,218,219,220,222,223,224,225,231,247,264,265,271,272,273,274,276,277,278,279,280,281,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,306,307,308,309,313,314,315,316,317,318,319,339,349,350,351,355,356,359,360,361,362,365,378,380,383,384,386,387,388,389,401,404,407,409,410,411,414,],[-251,-61,-72,-71,-58,-54,-55,-59,-251,-53,-68,-63,-52,-56,-170,-106,-66,-251,-69,-73,-108,-64,-60,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,83,-82,-81,-49,-107,-251,-97,-96,-116,-114,-26,-25,-48,-51,-109,-251,-251,-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,-185,-242,-239,-171,-230,216,-15,217,-120,-251,-16,-118,-124,-115,-117,-83,-250,-21,-80,-22,-79,-248,-212,-246,-226,277,-227,-110,-206,-211,-209,-111,281,283,-168,-251,-210,-113,-112,-251,-123,-2,-122,-139,-137,-1,-98,-14,-85,-84,-172,349,-225,-224,-235,-223,351,353,354,-234,-136,-251,-137,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-19,-20,359,360,-251,-138,-125,-119,-121,-100,-99,-13,-213,-221,-222,-169,-207,-146,-140,-142,-144,389,395,397,399,-236,-186,-141,-143,-145,-228,-251,412,-229,-251,415,418,]),'LONG':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[19,19,-61,-72,-71,-58,-54,-55,-33,-29,-59,19,-34,-53,-68,-63,-52,19,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,19,-67,19,-70,-74,19,-57,-82,-249,-81,19,-107,-30,19,-97,-96,19,-45,-46,19,-109,19,19,19,19,-88,19,19,-36,19,-47,19,19,-83,-89,-250,19,-110,19,19,-111,-113,-112,19,19,-98,-37,-39,-42,-38,-40,19,-148,-147,-43,-149,-41,-85,-84,-90,19,19,-100,-99,-167,-166,19,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'PLUS':([55,61,75,91,92,93,94,95,96,97,98,99,100,101,102,104,105,106,108,109,110,111,112,113,114,115,116,117,118,119,120,123,124,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,180,182,183,184,186,187,188,189,190,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,262,270,273,274,277,281,282,283,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,349,350,351,352,353,356,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[-249,106,-45,-219,-206,-233,-243,-247,-244,-241,-231,106,-217,-232,-208,-187,106,-216,106,-240,-215,-220,106,106,-237,-245,-214,-238,204,-242,-239,-218,-230,106,106,-250,106,-176,-179,-177,-173,-174,-178,-180,106,-182,-183,-175,-181,-248,106,-212,-215,-246,-226,106,106,-227,106,-206,-211,106,-209,-210,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,-251,-39,-42,-38,106,-40,106,106,-148,-147,-43,-149,106,-41,-237,106,-225,-224,-223,-234,106,106,204,204,204,-192,204,204,204,-191,204,204,-189,-188,204,204,204,204,204,-190,-215,106,-12,106,106,-11,-167,-166,106,-164,106,106,-150,106,-163,-151,106,106,-213,-221,-222,106,106,-207,-251,106,-215,-251,-131,-162,-165,106,-154,106,-152,106,106,106,-153,106,106,106,-251,-228,106,-158,-157,-155,-229,106,106,106,-159,-156,106,-161,-160,]),'ELLIPSIS':([227,],[316,]),'GT':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,205,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,205,-194,-192,-196,205,-195,-191,-198,205,-189,-188,-197,205,205,205,205,-190,-213,-221,-222,-207,-228,-229,]),'GOTO':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,240,-250,-39,-42,-38,-40,240,-148,-147,-43,-149,240,-41,-167,-166,-164,240,-150,-163,-151,240,-162,-165,-154,240,-152,240,-153,240,240,-158,-157,-155,240,240,-159,-156,240,-161,-160,]),'ENUM':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[26,26,-61,-72,-71,-58,-54,-55,-33,-29,-59,26,-34,-53,-68,-63,-52,26,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,26,-67,26,-70,-74,26,-57,-82,-249,-81,26,-107,-30,26,-97,-96,26,-45,-46,26,-109,26,26,26,26,-88,26,26,-36,26,-47,26,26,-83,-89,-250,26,-110,26,26,-111,-113,-112,26,26,-98,-37,-39,-42,-38,-40,26,-148,-147,-43,-149,-41,-85,-84,-90,26,26,-100,-99,-167,-166,26,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'PERIOD':([55,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,178,180,184,235,262,273,274,277,281,323,329,350,351,357,366,369,371,390,400,401,409,],[-249,-233,-243,-247,-244,-241,-231,-232,181,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-246,-226,-227,324,-237,-225,-224,-223,-234,-132,324,-221,-222,324,-135,324,-133,-134,324,-228,-229,]),'GE':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,209,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,209,-194,-192,-196,209,-195,-191,-198,209,-189,-188,-197,209,209,209,209,-190,-213,-221,-222,-207,-228,-229,]),'INT_CONST_DEC':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,117,-45,-219,117,-217,117,-216,117,-215,117,117,-214,-218,117,117,-250,117,-176,-179,-177,-173,-174,-178,-180,117,-182,-183,-175,-181,117,-215,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,-251,-39,-42,-38,117,-40,117,117,-148,-147,-43,-149,117,-41,117,117,117,-215,117,-12,117,117,-11,-167,-166,117,-164,117,117,-150,117,-163,-151,117,117,117,117,-251,117,-215,-251,-131,-162,-165,117,-154,117,-152,117,117,117,-153,117,117,117,-251,117,-158,-157,-155,117,117,117,-159,-156,117,-161,-160,]),'ARROW':([93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,178,180,184,262,273,274,277,281,350,351,401,409,],[-233,-243,-247,-244,-241,-231,-232,179,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-246,-226,-227,-237,-225,-224,-223,-234,-221,-222,-228,-229,]),'HEX_FLOAT_CONST':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,119,-45,-219,119,-217,119,-216,119,-215,119,119,-214,-218,119,119,-250,119,-176,-179,-177,-173,-174,-178,-180,119,-182,-183,-175,-181,119,-215,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,-251,-39,-42,-38,119,-40,119,119,-148,-147,-43,-149,119,-41,119,119,119,-215,119,-12,119,119,-11,-167,-166,119,-164,119,119,-150,119,-163,-151,119,119,119,119,-251,119,-215,-251,-131,-162,-165,119,-154,119,-152,119,119,119,-153,119,119,119,-251,119,-158,-157,-155,119,119,119,-159,-156,119,-161,-160,]),'DOUBLE':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[40,40,-61,-72,-71,-58,-54,-55,-33,-29,-59,40,-34,-53,-68,-63,-52,40,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,40,-67,40,-70,-74,40,-57,-82,-249,-81,40,-107,-30,40,-97,-96,40,-45,-46,40,-109,40,40,40,40,-88,40,40,-36,40,-47,40,40,-83,-89,-250,40,-110,40,40,-111,-113,-112,40,40,-98,-37,-39,-42,-38,-40,40,-148,-147,-43,-149,-41,-85,-84,-90,40,40,-100,-99,-167,-166,40,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'MINUSEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[163,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'INT_CONST_OCT':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,120,-45,-219,120,-217,120,-216,120,-215,120,120,-214,-218,120,120,-250,120,-176,-179,-177,-173,-174,-178,-180,120,-182,-183,-175,-181,120,-215,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,-251,-39,-42,-38,120,-40,120,120,-148,-147,-43,-149,120,-41,120,120,120,-215,120,-12,120,120,-11,-167,-166,120,-164,120,120,-150,120,-163,-151,120,120,120,120,-251,120,-215,-251,-131,-162,-165,120,-154,120,-152,120,120,120,-153,120,120,120,-251,120,-158,-157,-155,120,120,120,-159,-156,120,-161,-160,]),'TIMESEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[172,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'OR':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,214,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,214,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,214,-199,-201,-202,-190,-213,-221,-222,-207,-228,-229,]),'SHORT':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[2,2,-61,-72,-71,-58,-54,-55,-33,-29,-59,2,-34,-53,-68,-63,-52,2,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,2,-67,2,-70,-74,2,-57,-82,-249,-81,2,-107,-30,2,-97,-96,2,-45,-46,2,-109,2,2,2,2,-88,2,2,-36,2,-47,2,2,-83,-89,-250,2,-110,2,2,-111,-113,-112,2,2,-98,-37,-39,-42,-38,-40,2,-148,-147,-43,-149,-41,-85,-84,-90,2,2,-100,-99,-167,-166,2,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'RETURN':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,243,-250,-39,-42,-38,-40,243,-148,-147,-43,-149,243,-41,-167,-166,-164,243,-150,-163,-151,243,-162,-165,-154,243,-152,243,-153,243,243,-158,-157,-155,243,243,-159,-156,243,-161,-160,]),'RSHIFTEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[173,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'RESTRICT':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,28,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,66,68,73,75,80,82,83,84,85,86,87,88,89,112,139,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[32,32,-61,-72,-71,-58,-54,-55,-33,-29,-59,32,-34,-53,-68,-63,-52,32,-56,-170,-106,-66,32,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,32,-67,32,-70,-74,32,-57,-82,-249,-81,32,-107,-30,32,-97,-96,-116,32,32,-45,-46,32,-109,32,32,32,32,-88,32,32,-117,-36,32,-47,32,32,-83,-89,-250,32,-110,32,32,-111,-113,-112,32,32,-98,-37,-39,-42,-38,-40,32,-148,-147,-43,-149,-41,-85,-84,-90,32,32,-100,-99,-167,-166,32,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'STATIC':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[9,9,-61,-72,-71,-58,-54,-55,-33,-29,-59,9,-34,-53,-68,-63,-52,9,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,9,-67,9,-70,-74,9,-57,-82,-249,-81,-107,-30,9,-97,-96,9,-45,-46,9,-109,-36,9,-47,-83,-250,-110,-111,-113,-112,9,9,-98,-37,-39,-42,-38,-40,9,-148,-147,-43,-149,-41,-85,-84,9,9,-100,-99,-167,-166,9,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'SIZEOF':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,99,-45,-219,99,-217,99,-216,99,-215,99,99,-214,-218,99,99,-250,99,-176,-179,-177,-173,-174,-178,-180,99,-182,-183,-175,-181,99,-215,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,-251,-39,-42,-38,99,-40,99,99,-148,-147,-43,-149,99,-41,99,99,99,-215,99,-12,99,99,-11,-167,-166,99,-164,99,99,-150,99,-163,-151,99,99,99,99,-251,99,-215,-251,-131,-162,-165,99,-154,99,-152,99,99,99,-153,99,99,99,-251,99,-158,-157,-155,99,99,99,-159,-156,99,-161,-160,]),'UNSIGNED':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[18,18,-61,-72,-71,-58,-54,-55,-33,-29,-59,18,-34,-53,-68,-63,-52,18,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,18,-67,18,-70,-74,18,-57,-82,-249,-81,18,-107,-30,18,-97,-96,18,-45,-46,18,-109,18,18,18,18,-88,18,18,-36,18,-47,18,18,-83,-89,-250,18,-110,18,18,-111,-113,-112,18,18,-98,-37,-39,-42,-38,-40,18,-148,-147,-43,-149,-41,-85,-84,-90,18,18,-100,-99,-167,-166,18,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'UNION':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[20,20,-61,-72,-71,-58,-54,-55,-33,-29,-59,20,-34,-53,-68,-63,-52,20,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,20,-67,20,-70,-74,20,-57,-82,-249,-81,20,-107,-30,20,-97,-96,20,-45,-46,20,-109,20,20,20,20,-88,20,20,-36,20,-47,20,20,-83,-89,-250,20,-110,20,20,-111,-113,-112,20,20,-98,-37,-39,-42,-38,-40,20,-148,-147,-43,-149,-41,-85,-84,-90,20,20,-100,-99,-167,-166,20,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'COLON':([2,3,5,6,13,18,19,24,25,27,29,32,33,35,37,39,40,43,45,46,54,56,59,63,64,83,87,89,90,92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,122,124,149,151,152,153,154,155,161,174,176,178,180,184,185,187,188,190,191,194,196,216,217,231,248,262,264,265,267,268,271,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,318,319,338,349,350,351,355,356,386,401,409,],[-61,-72,-71,-58,-59,-68,-63,-170,-106,-66,-69,-73,-108,-64,-60,-62,-65,-67,-70,-74,-82,-81,-107,-97,-96,-109,-251,-251,156,-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,-185,-242,-239,-171,-230,-83,-250,-21,-80,-22,-79,270,-248,-212,-246,-226,-227,-110,-206,-211,-209,-111,-168,-210,-113,-112,-98,336,345,-85,-84,-184,156,-172,-225,-224,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,358,-202,-190,-100,-99,379,-213,-221,-222,-169,-207,-186,-228,-229,]),'$end':([0,8,11,12,15,22,31,36,38,47,60,75,144,151,237,344,],[-251,0,-33,-29,-34,-27,-32,-31,-35,-28,-30,-45,-36,-250,-37,-151,]),'WSTRING_LITERAL':([55,61,75,91,93,95,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,95,-45,-219,174,-247,95,-217,95,-216,95,-215,95,95,-214,-218,95,95,-250,95,-176,-179,-177,-173,-174,-178,-180,95,-182,-183,-175,-181,-248,95,-215,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,-251,-39,-42,-38,95,-40,95,95,-148,-147,-43,-149,95,-41,95,95,95,-215,95,-12,95,95,-11,-167,-166,95,-164,95,95,-150,95,-163,-151,95,95,95,95,-251,95,-215,-251,-131,-162,-165,95,-154,95,-152,95,95,95,-153,95,95,95,-251,95,-158,-157,-155,95,95,95,-159,-156,95,-161,-160,]),'DIVIDE':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,207,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,207,207,207,207,207,207,207,207,207,207,-189,-188,207,207,207,207,207,-190,-213,-221,-222,-207,-228,-229,]),'FOR':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,245,-250,-39,-42,-38,-40,245,-148,-147,-43,-149,245,-41,-167,-166,-164,245,-150,-163,-151,245,-162,-165,-154,245,-152,245,-153,245,245,-158,-157,-155,245,245,-159,-156,245,-161,-160,]),'PLUSPLUS':([55,61,75,91,93,94,95,96,97,98,99,100,101,102,105,106,108,109,110,111,112,113,114,115,116,117,119,120,123,124,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,177,178,180,182,183,184,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,262,270,273,274,277,281,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,350,351,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[-249,108,-45,-219,-233,-243,-247,-244,-241,-231,108,-217,-232,180,108,-216,108,-240,-215,-220,108,108,-237,-245,-214,-238,-242,-239,-218,-230,108,108,-250,108,-176,-179,-177,-173,-174,-178,-180,108,-182,-183,-175,-181,-248,108,-215,-246,-226,108,108,-227,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,-251,-39,-42,-38,108,-40,108,108,-148,-147,-43,-149,108,-41,-237,108,-225,-224,-223,-234,108,108,-215,108,-12,108,108,-11,-167,-166,108,-164,108,108,-150,108,-163,-151,108,108,-221,-222,108,108,-251,108,-215,-251,-131,-162,-165,108,-154,108,-152,108,108,108,-153,108,108,108,-251,-228,108,-158,-157,-155,-229,108,108,108,-159,-156,108,-161,-160,]),'EQUALS':([25,33,59,73,83,92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,137,143,151,174,176,178,180,184,185,187,188,190,191,196,216,217,262,273,274,277,281,323,329,349,350,351,356,366,371,390,401,409,],[-106,-108,-107,141,-109,165,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,232,141,-250,-248,-212,-246,-226,-227,-110,-206,-211,-209,-111,-210,-113,-112,-237,-225,-224,-223,-234,-132,372,-213,-221,-222,-207,-135,-133,-134,-228,-229,]),'ELSE':([151,238,239,242,244,255,260,331,332,335,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[-250,-39,-42,-38,-40,-43,-41,-167,-166,-164,-163,-151,-162,-165,-154,-152,-153,-158,-157,413,-159,-156,-161,-160,]),'ANDEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[170,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'EQ':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,211,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,211,-194,-192,-196,-200,-195,-191,-198,211,-189,-188,-197,211,-199,211,211,-190,-213,-221,-222,-207,-228,-229,]),'AND':([55,61,75,91,92,93,94,95,96,97,98,99,100,101,102,104,105,106,108,109,110,111,112,113,114,115,116,117,118,119,120,123,124,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,180,182,183,184,186,187,188,189,190,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,262,270,273,274,277,281,282,283,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,349,350,351,352,353,356,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[-249,116,-45,-219,-206,-233,-243,-247,-244,-241,-231,116,-217,-232,-208,-187,116,-216,116,-240,-215,-220,116,116,-237,-245,-214,-238,212,-242,-239,-218,-230,116,116,-250,116,-176,-179,-177,-173,-174,-178,-180,116,-182,-183,-175,-181,-248,116,-212,-215,-246,-226,116,116,-227,116,-206,-211,116,-209,-210,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,-251,-39,-42,-38,116,-40,116,116,-148,-147,-43,-149,116,-41,-237,116,-225,-224,-223,-234,116,116,-193,212,-194,-192,-196,-200,-195,-191,-198,212,-189,-188,-197,212,-199,-201,212,-190,-215,116,-12,116,116,-11,-167,-166,116,-164,116,116,-150,116,-163,-151,116,116,-213,-221,-222,116,116,-207,-251,116,-215,-251,-131,-162,-165,116,-154,116,-152,116,116,116,-153,116,116,116,-251,-228,116,-158,-157,-155,-229,116,116,116,-159,-156,116,-161,-160,]),'TYPEID':([0,1,2,3,5,6,7,9,10,11,12,13,14,15,17,18,19,20,21,22,23,24,25,26,27,29,31,32,33,34,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[24,24,-61,-72,-71,-58,54,-54,-55,-33,-29,-59,24,-34,-53,-68,-63,-87,-52,24,-56,-170,-106,63,-66,-69,-32,-73,-108,-86,-64,-31,-60,-35,-62,-65,24,-67,24,-70,-74,24,-57,-82,-249,-81,24,-107,-30,24,-97,-96,24,-45,-46,24,-109,24,24,24,24,-88,24,24,-36,24,-47,24,24,-83,-89,-250,24,-110,24,24,-111,-113,-112,24,24,-98,-37,-39,-42,-38,-40,24,-148,-147,-43,-149,-41,-85,-84,-90,24,24,-100,-99,-167,-166,24,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'LBRACE':([7,20,25,26,33,34,48,54,55,56,59,63,64,73,75,78,80,81,82,83,141,142,145,146,151,185,191,216,217,235,238,239,242,244,251,253,254,255,257,259,260,283,322,326,327,331,332,335,336,340,342,344,345,349,353,354,357,369,372,373,374,377,379,382,391,395,396,397,399,400,405,406,408,413,415,416,417,418,419,420,],[55,-87,-106,55,-108,-86,-251,55,-249,55,-107,55,55,-251,-45,-7,-46,55,-8,-109,55,55,55,-47,-250,-110,-111,-113,-112,-251,-39,-42,-38,-40,55,-148,-147,-43,-149,55,-41,55,-12,55,-11,-167,-166,-164,55,-150,-163,-151,55,55,55,55,-251,-251,-131,-162,-165,-154,55,-152,55,55,-153,55,55,-251,-158,-157,-155,55,55,-159,-156,55,-161,-160,]),'PPHASH':([0,11,12,15,22,31,36,38,60,75,144,151,237,344,],[38,-33,-29,-34,38,-32,-31,-35,-30,-45,-36,-250,-37,-151,]),'INT':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[39,39,-61,-72,-71,-58,-54,-55,-33,-29,-59,39,-34,-53,-68,-63,-52,39,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,39,-67,39,-70,-74,39,-57,-82,-249,-81,39,-107,-30,39,-97,-96,39,-45,-46,39,-109,39,39,39,39,-88,39,39,-36,39,-47,39,39,-83,-89,-250,39,-110,39,39,-111,-113,-112,39,39,-98,-37,-39,-42,-38,-40,39,-148,-147,-43,-149,-41,-85,-84,-90,39,39,-100,-99,-167,-166,39,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'SIGNED':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[43,43,-61,-72,-71,-58,-54,-55,-33,-29,-59,43,-34,-53,-68,-63,-52,43,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,43,-67,43,-70,-74,43,-57,-82,-249,-81,43,-107,-30,43,-97,-96,43,-45,-46,43,-109,43,43,43,43,-88,43,43,-36,43,-47,43,43,-83,-89,-250,43,-110,43,43,-111,-113,-112,43,43,-98,-37,-39,-42,-38,-40,43,-148,-147,-43,-149,-41,-85,-84,-90,43,43,-100,-99,-167,-166,43,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'CONTINUE':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,246,-250,-39,-42,-38,-40,246,-148,-147,-43,-149,246,-41,-167,-166,-164,246,-150,-163,-151,246,-162,-165,-154,246,-152,246,-153,246,246,-158,-157,-155,246,246,-159,-156,246,-161,-160,]),'NOT':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,123,-45,-219,123,-217,123,-216,123,-215,123,123,-214,-218,123,123,-250,123,-176,-179,-177,-173,-174,-178,-180,123,-182,-183,-175,-181,123,-215,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,-251,-39,-42,-38,123,-40,123,123,-148,-147,-43,-149,123,-41,123,123,123,-215,123,-12,123,123,-11,-167,-166,123,-164,123,123,-150,123,-163,-151,123,123,123,123,-251,123,-215,-251,-131,-162,-165,123,-154,123,-152,123,123,123,-153,123,123,123,-251,123,-158,-157,-155,123,123,123,-159,-156,123,-161,-160,]),'OREQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[171,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'MOD':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,215,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,215,215,215,215,215,215,215,215,215,215,-189,-188,215,215,215,215,215,-190,-213,-221,-222,-207,-228,-229,]),'RSHIFT':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,197,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,197,-194,-192,197,197,197,-191,197,197,-189,-188,197,197,197,197,197,-190,-213,-221,-222,-207,-228,-229,]),'DEFAULT':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,248,-250,-39,-42,-38,-40,248,-148,-147,-43,-149,248,-41,-167,-166,-164,248,-150,-163,-151,248,-162,-165,-154,248,-152,248,-153,248,248,-158,-157,-155,248,248,-159,-156,248,-161,-160,]),'CHAR':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[37,37,-61,-72,-71,-58,-54,-55,-33,-29,-59,37,-34,-53,-68,-63,-52,37,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,37,-67,37,-70,-74,37,-57,-82,-249,-81,37,-107,-30,37,-97,-96,37,-45,-46,37,-109,37,37,37,37,-88,37,37,-36,37,-47,37,37,-83,-89,-250,37,-110,37,37,-111,-113,-112,37,37,-98,-37,-39,-42,-38,-40,37,-148,-147,-43,-149,-41,-85,-84,-90,37,37,-100,-99,-167,-166,37,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'WHILE':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,343,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,249,-250,-39,-42,-38,-40,249,-148,-147,-43,-149,249,-41,-167,-166,-164,249,-150,-163,381,-151,249,-162,-165,-154,249,-152,249,-153,249,249,-158,-157,-155,249,249,-159,-156,249,-161,-160,]),'DIVEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[162,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'EXTERN':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[10,10,-61,-72,-71,-58,-54,-55,-33,-29,-59,10,-34,-53,-68,-63,-52,10,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,10,-67,10,-70,-74,10,-57,-82,-249,-81,-107,-30,10,-97,-96,10,-45,-46,10,-109,-36,10,-47,-83,-250,-110,-111,-113,-112,10,10,-98,-37,-39,-42,-38,-40,10,-148,-147,-43,-149,-41,-85,-84,10,10,-100,-99,-167,-166,10,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'CASE':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,250,-250,-39,-42,-38,-40,250,-148,-147,-43,-149,250,-41,-167,-166,-164,250,-150,-163,-151,250,-162,-165,-154,250,-152,250,-153,250,250,-158,-157,-155,250,250,-159,-156,250,-161,-160,]),'LAND':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,210,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,210,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-213,-221,-222,-207,-228,-229,]),'REGISTER':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[17,17,-61,-72,-71,-58,-54,-55,-33,-29,-59,17,-34,-53,-68,-63,-52,17,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,17,-67,17,-70,-74,17,-57,-82,-249,-81,-107,-30,17,-97,-96,17,-45,-46,17,-109,-36,17,-47,-83,-250,-110,-111,-113,-112,17,17,-98,-37,-39,-42,-38,-40,17,-148,-147,-43,-149,-41,-85,-84,17,17,-100,-99,-167,-166,17,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'MODEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[164,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'NE':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,202,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,202,-194,-192,-196,-200,-195,-191,-198,202,-189,-188,-197,202,-199,202,202,-190,-213,-221,-222,-207,-228,-229,]),'SWITCH':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,252,-250,-39,-42,-38,-40,252,-148,-147,-43,-149,252,-41,-167,-166,-164,252,-150,-163,-151,252,-162,-165,-154,252,-152,252,-153,252,252,-158,-157,-155,252,252,-159,-156,252,-161,-160,]),'INT_CONST_HEX':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,109,-45,-219,109,-217,109,-216,109,-215,109,109,-214,-218,109,109,-250,109,-176,-179,-177,-173,-174,-178,-180,109,-182,-183,-175,-181,109,-215,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,-251,-39,-42,-38,109,-40,109,109,-148,-147,-43,-149,109,-41,109,109,109,-215,109,-12,109,109,-11,-167,-166,109,-164,109,109,-150,109,-163,-151,109,109,109,109,-251,109,-215,-251,-131,-162,-165,109,-154,109,-152,109,109,109,-153,109,109,109,-251,109,-158,-157,-155,109,109,109,-159,-156,109,-161,-160,]),'_COMPLEX':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[27,27,-61,-72,-71,-58,-54,-55,-33,-29,-59,27,-34,-53,-68,-63,-52,27,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,27,-67,27,-70,-74,27,-57,-82,-249,-81,27,-107,-30,27,-97,-96,27,-45,-46,27,-109,27,27,27,27,-88,27,27,-36,27,-47,27,27,-83,-89,-250,27,-110,27,27,-111,-113,-112,27,27,-98,-37,-39,-42,-38,-40,27,-148,-147,-43,-149,-41,-85,-84,-90,27,27,-100,-99,-167,-166,27,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'PLUSEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[167,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'STRUCT':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[34,34,-61,-72,-71,-58,-54,-55,-33,-29,-59,34,-34,-53,-68,-63,-52,34,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,34,-67,34,-70,-74,34,-57,-82,-249,-81,34,-107,-30,34,-97,-96,34,-45,-46,34,-109,34,34,34,34,-88,34,34,-36,34,-47,34,34,-83,-89,-250,34,-110,34,34,-111,-113,-112,34,34,-98,-37,-39,-42,-38,-40,34,-148,-147,-43,-149,-41,-85,-84,-90,34,34,-100,-99,-167,-166,34,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'CONDOP':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,213,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-213,-221,-222,-207,-228,-229,]),'BREAK':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,256,-250,-39,-42,-38,-40,256,-148,-147,-43,-149,256,-41,-167,-166,-164,256,-150,-163,-151,256,-162,-165,-154,256,-152,256,-153,256,256,-158,-157,-155,256,256,-159,-156,256,-161,-160,]),'VOLATILE':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,28,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,66,68,73,75,80,82,83,84,85,86,87,88,89,112,139,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[46,46,-61,-72,-71,-58,-54,-55,-33,-29,-59,46,-34,-53,-68,-63,-52,46,-56,-170,-106,-66,46,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,46,-67,46,-70,-74,46,-57,-82,-249,-81,46,-107,-30,46,-97,-96,-116,46,46,-45,-46,46,-109,46,46,46,46,-88,46,46,-117,-36,46,-47,46,46,-83,-89,-250,46,-110,46,46,-111,-113,-112,46,46,-98,-37,-39,-42,-38,-40,46,-148,-147,-43,-149,-41,-85,-84,-90,46,46,-100,-99,-167,-166,46,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'INLINE':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[49,49,-61,-72,-71,-58,-54,-55,-33,-29,-59,49,-34,-53,-68,-63,-52,49,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,49,-67,49,-70,-74,49,-57,-82,-249,-81,-107,-30,49,-97,-96,49,-45,-46,49,-109,-36,49,-47,-83,-250,-110,-111,-113,-112,49,49,-98,-37,-39,-42,-38,-40,49,-148,-147,-43,-149,-41,-85,-84,49,49,-100,-99,-167,-166,49,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'DO':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,259,-250,-39,-42,-38,-40,259,-148,-147,-43,-149,259,-41,-167,-166,-164,259,-150,-163,-151,259,-162,-165,-154,259,-152,259,-153,259,259,-158,-157,-155,259,259,-159,-156,259,-161,-160,]),'LNOT':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,91,-45,-219,91,-217,91,-216,91,-215,91,91,-214,-218,91,91,-250,91,-176,-179,-177,-173,-174,-178,-180,91,-182,-183,-175,-181,91,-215,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,-251,-39,-42,-38,91,-40,91,91,-148,-147,-43,-149,91,-41,91,91,91,-215,91,-12,91,91,-11,-167,-166,91,-164,91,91,-150,91,-163,-151,91,91,91,91,-251,91,-215,-251,-131,-162,-165,91,-154,91,-152,91,91,91,-153,91,91,91,-251,91,-158,-157,-155,91,91,91,-159,-156,91,-161,-160,]),'CONST':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,28,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,66,68,73,75,80,82,83,84,85,86,87,88,89,112,139,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[3,3,-61,-72,-71,-58,-54,-55,-33,-29,-59,3,-34,-53,-68,-63,-52,3,-56,-170,-106,-66,3,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,3,-67,3,-70,-74,3,-57,-82,-249,-81,3,-107,-30,3,-97,-96,-116,3,3,-45,-46,3,-109,3,3,3,3,-88,3,3,-117,-36,3,-47,3,3,-83,-89,-250,3,-110,3,3,-111,-113,-112,3,3,-98,-37,-39,-42,-38,-40,3,-148,-147,-43,-149,-41,-85,-84,-90,3,3,-100,-99,-167,-166,3,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'LOR':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,198,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-213,-221,-222,-207,-228,-229,]),'CHAR_CONST':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,94,-45,-219,94,-217,94,-216,94,-215,94,94,-214,-218,94,94,-250,94,-176,-179,-177,-173,-174,-178,-180,94,-182,-183,-175,-181,94,-215,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,-251,-39,-42,-38,94,-40,94,94,-148,-147,-43,-149,94,-41,94,94,94,-215,94,-12,94,94,-11,-167,-166,94,-164,94,94,-150,94,-163,-151,94,94,94,94,-251,94,-215,-251,-131,-162,-165,94,-154,94,-152,94,94,94,-153,94,94,94,-251,94,-158,-157,-155,94,94,94,-159,-156,94,-161,-160,]),'LSHIFT':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,199,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,199,-194,-192,199,199,199,-191,199,199,-189,-188,199,199,199,199,199,-190,-213,-221,-222,-207,-228,-229,]),'RBRACE':([55,75,86,88,92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,122,124,135,136,137,145,147,148,150,151,174,176,178,180,184,187,188,190,196,228,229,230,236,238,239,242,244,251,253,254,255,257,258,260,261,267,269,271,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,320,321,328,331,332,335,340,342,344,349,350,351,356,368,369,370,373,374,377,382,385,386,392,396,400,401,402,405,406,408,409,416,417,419,420,],[-249,-45,151,-88,-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,-185,-242,-239,-171,-230,-101,151,-104,-251,151,151,-89,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,151,151,-102,-126,-39,-42,-38,-40,-6,-148,-147,-43,-149,-5,-41,151,-184,-90,-172,-225,-224,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-103,-105,151,-167,-166,-164,-150,-163,-151,-213,-221,-222,-207,-129,151,-127,-162,-165,-154,-152,151,-186,-128,-153,151,-228,-130,-158,-157,-155,-229,-159,-156,-161,-160,]),'_BOOL':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[13,13,-61,-72,-71,-58,-54,-55,-33,-29,-59,13,-34,-53,-68,-63,-52,13,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,13,-67,13,-70,-74,13,-57,-82,-249,-81,13,-107,-30,13,-97,-96,13,-45,-46,13,-109,13,13,13,13,-88,13,13,-36,13,-47,13,13,-83,-89,-250,13,-110,13,13,-111,-113,-112,13,13,-98,-37,-39,-42,-38,-40,13,-148,-147,-43,-149,-41,-85,-84,-90,13,13,-100,-99,-167,-166,13,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'LE':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,201,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,201,-194,-192,-196,201,-195,-191,-198,201,-189,-188,-197,201,201,201,201,-190,-213,-221,-222,-207,-228,-229,]),'SEMI':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,30,31,32,33,35,36,37,38,39,40,41,42,43,44,45,46,49,50,51,52,54,55,56,58,59,60,63,64,70,71,72,73,74,75,76,77,79,83,87,89,90,92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,122,124,143,144,145,149,151,152,153,154,155,157,158,159,160,161,174,176,178,180,184,185,187,188,190,191,194,196,216,217,231,233,234,236,237,238,239,241,242,243,244,246,247,251,253,254,255,256,257,258,259,260,262,264,265,266,267,271,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,318,319,330,331,332,333,334,335,336,339,340,342,344,345,347,348,349,350,351,355,356,370,373,374,375,376,377,379,382,386,392,393,394,395,396,397,399,401,403,405,406,408,409,412,413,415,416,417,418,419,420,],[15,-251,-61,-72,-71,-58,-54,-55,-33,-29,-59,-251,-34,-53,-68,-63,-52,15,-56,-170,-106,-66,-69,-251,-32,-73,-108,-64,-31,-60,-35,-62,-65,75,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-249,-81,-49,-107,-30,-97,-96,-18,-44,-17,-77,-75,-45,-48,-51,-251,-109,-251,-251,-251,-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,-185,-242,-239,-171,-230,-77,-36,-251,-83,-250,-21,-80,-22,-79,-24,269,-91,-23,-93,-248,-212,-246,-226,-227,-110,-206,-211,-209,-111,-168,-210,-113,-112,-98,-76,-78,-126,-37,-39,-42,331,-38,332,-40,335,-14,-251,-148,-147,-43,342,-149,-13,-251,-41,-237,-85,-84,-95,-184,-172,-225,-224,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-100,-99,373,-167,-166,374,-251,-164,-251,-13,-150,-163,-151,-251,-92,-94,-213,-221,-222,-169,-207,-127,-162,-165,393,-251,-154,-251,-152,-186,-128,-251,404,-251,-153,-251,-251,-228,410,-158,-157,-155,-229,416,-251,-251,-159,-156,-251,-161,-160,]),'LT':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,203,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,203,-194,-192,-196,203,-195,-191,-198,203,-189,-188,-197,203,203,203,203,-190,-213,-221,-222,-207,-228,-229,]),'COMMA':([1,2,3,5,6,9,10,13,14,17,18,19,21,23,24,25,27,28,29,32,33,35,37,39,40,42,43,44,45,46,49,50,51,52,54,56,58,59,63,64,66,67,68,69,70,73,74,76,77,83,92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,122,124,128,129,130,131,132,135,136,137,138,139,143,149,151,157,159,161,174,176,178,180,184,185,187,188,190,191,192,194,196,216,217,219,220,222,223,224,225,228,229,230,231,233,234,236,247,262,264,265,266,267,271,273,274,275,276,277,278,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,314,315,317,318,319,320,321,328,333,347,348,349,350,351,355,356,359,360,361,362,368,370,378,380,383,384,385,386,387,388,389,392,401,402,407,409,],[-251,-61,-72,-71,-58,-54,-55,-59,-251,-53,-68,-63,-52,-56,-170,-106,-66,-251,-69,-73,-108,-64,-60,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-81,-49,-107,-97,-96,-116,-114,-26,-25,140,-77,-75,-48,-51,-109,-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,-185,-242,-239,-171,-230,-120,-251,226,227,-124,-101,230,-104,-115,-117,-77,-83,-250,268,-91,-93,-248,-212,-246,-226,-227,-110,-206,-211,-209,-111,282,-168,-210,-113,-112,-123,-2,-122,-139,-137,-1,230,230,-102,-98,-76,-78,-126,282,-237,-85,-84,-95,-184,-172,-225,-224,282,-235,-223,352,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,282,-202,-190,-138,-125,-121,-100,-99,-103,-105,369,282,-92,-94,-213,-221,-222,-169,-207,-146,-140,-142,-144,-129,-127,282,282,282,-236,400,-186,-141,-143,-145,-128,-228,-130,282,-229,]),'TYPEDEF':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[23,23,-61,-72,-71,-58,-54,-55,-33,-29,-59,23,-34,-53,-68,-63,-52,23,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,23,-67,23,-70,-74,23,-57,-82,-249,-81,-107,-30,23,-97,-96,23,-45,-46,23,-109,-36,23,-47,-83,-250,-110,-111,-113,-112,23,23,-98,-37,-39,-42,-38,-40,23,-148,-147,-43,-149,-41,-85,-84,23,23,-100,-99,-167,-166,23,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'XOR':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,206,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,206,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,206,-199,-201,206,-190,-213,-221,-222,-207,-228,-229,]),'AUTO':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[21,21,-61,-72,-71,-58,-54,-55,-33,-29,-59,21,-34,-53,-68,-63,-52,21,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,21,-67,21,-70,-74,21,-57,-82,-249,-81,-107,-30,21,-97,-96,21,-45,-46,21,-109,-36,21,-47,-83,-250,-110,-111,-113,-112,21,21,-98,-37,-39,-42,-38,-40,21,-148,-147,-43,-149,-41,-85,-84,21,21,-100,-99,-167,-166,21,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'TIMES':([0,1,2,3,4,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,27,28,29,30,31,32,35,36,37,38,39,40,42,43,44,45,46,49,50,51,52,54,55,56,58,60,61,63,64,66,67,68,69,75,76,77,79,87,89,90,91,92,93,94,95,96,97,98,99,100,101,102,104,105,106,108,109,110,111,112,113,114,115,116,117,118,119,120,123,124,129,139,140,141,144,145,149,151,152,153,154,155,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,180,182,183,184,186,187,188,189,190,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,218,221,231,232,235,237,238,239,242,243,244,250,251,253,254,255,257,259,260,262,264,265,268,270,273,274,277,281,282,283,285,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,311,312,318,319,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,349,350,351,352,353,356,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[28,-251,-61,-72,28,-71,-58,-54,-55,-33,-29,-59,-251,-34,-53,-68,-63,-52,28,-56,-170,-66,-251,-69,28,-32,-73,-64,-31,-60,-35,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-249,-81,-49,-30,110,-97,-96,-116,28,-26,-25,-45,-48,-51,28,-251,-251,28,-219,-206,-233,-243,-247,-244,-241,-231,177,-217,-232,-208,-187,177,-216,177,-240,-215,-220,177,177,-237,-245,-214,-238,208,-242,-239,-218,-230,28,-117,28,177,-36,177,-83,-250,-21,-80,-22,-79,177,-176,-179,-177,-173,-174,-178,-180,177,-182,-183,-175,-181,-248,177,-212,-215,-246,-226,177,177,-227,177,-206,-211,177,-209,28,-210,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,28,311,-98,177,-251,-37,-39,-42,-38,177,-40,177,177,-148,-147,-43,-149,177,-41,-237,-85,-84,28,177,-225,-224,-223,-234,177,177,28,208,208,208,208,208,208,208,208,208,208,-189,-188,208,208,208,208,208,-190,-215,364,-100,-99,-12,177,177,-11,-167,-166,177,-164,177,177,-150,177,-163,-151,177,177,-213,-221,-222,177,177,-207,-251,177,-215,-251,-131,-162,-165,177,-154,177,-152,177,177,177,-153,177,177,177,-251,-228,177,-158,-157,-155,-229,177,177,177,-159,-156,177,-161,-160,]),'LPAREN':([0,1,2,3,4,5,6,9,10,11,12,13,14,15,16,17,18,19,21,22,23,24,25,27,28,29,30,31,32,33,35,36,37,38,39,40,42,43,44,45,46,49,50,51,52,54,55,56,58,59,60,61,63,64,66,67,68,69,75,76,77,79,83,87,89,90,91,93,94,95,96,97,98,99,100,101,102,105,106,108,109,110,111,112,113,114,115,116,117,119,120,123,124,129,138,139,140,141,144,145,149,151,152,153,154,155,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,177,178,180,182,183,184,185,186,189,191,195,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,221,223,224,231,232,235,237,238,239,242,243,244,245,249,250,251,252,253,254,255,257,259,260,262,263,264,265,268,270,273,274,277,281,282,283,285,286,311,312,314,318,319,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,350,351,352,353,357,358,359,360,361,362,364,369,372,373,374,376,377,379,381,382,387,388,389,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[4,-251,-61,-72,4,-71,-58,-54,-55,-33,-29,-59,-251,-34,4,-53,-68,-63,-52,4,-56,-170,62,-66,-251,-69,4,-32,-73,-108,-64,-31,-60,-35,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-249,-81,-49,62,-30,112,-97,-96,-116,-114,-26,-25,-45,-48,-51,4,-109,-251,-251,4,-219,-233,-243,-247,-244,-241,-231,175,-217,-232,183,186,-216,189,-240,-215,-220,112,189,-237,-245,-214,-238,-242,-239,-218,-230,218,-115,-117,4,112,-36,112,-83,-250,-21,-80,-22,-79,186,-176,-179,-177,-173,-174,-178,-180,112,-182,-183,-175,-181,-248,112,-215,-246,-226,112,112,-227,-110,112,112,-111,285,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,112,186,186,-113,-112,218,112,313,218,-98,186,-251,-37,-39,-42,-38,112,-40,334,337,186,112,341,-148,-147,-43,-149,112,-41,-237,346,-85,-84,4,186,-225,-224,-223,-234,112,186,285,285,-215,112,313,-100,-99,-12,186,112,-11,-167,-166,112,-164,112,112,-150,112,-163,-151,112,112,-221,-222,112,186,-251,186,-146,-140,-142,-144,-215,-251,-131,-162,-165,112,-154,112,398,-152,-141,-143,-145,112,112,112,-153,112,112,112,-251,-228,112,-158,-157,-155,-229,112,112,112,-159,-156,112,-161,-160,]),'MINUSMINUS':([55,61,75,91,93,94,95,96,97,98,99,100,101,102,105,106,108,109,110,111,112,113,114,115,116,117,119,120,123,124,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,177,178,180,182,183,184,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,262,270,273,274,277,281,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,350,351,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[-249,113,-45,-219,-233,-243,-247,-244,-241,-231,113,-217,-232,184,113,-216,113,-240,-215,-220,113,113,-237,-245,-214,-238,-242,-239,-218,-230,113,113,-250,113,-176,-179,-177,-173,-174,-178,-180,113,-182,-183,-175,-181,-248,113,-215,-246,-226,113,113,-227,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,-251,-39,-42,-38,113,-40,113,113,-148,-147,-43,-149,113,-41,-237,113,-225,-224,-223,-234,113,113,-215,113,-12,113,113,-11,-167,-166,113,-164,113,113,-150,113,-163,-151,113,113,-221,-222,113,113,-251,113,-215,-251,-131,-162,-165,113,-154,113,-152,113,113,113,-153,113,113,113,-251,-228,113,-158,-157,-155,-229,113,113,113,-159,-156,113,-161,-160,]),'ID':([0,1,2,3,4,5,6,7,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,39,40,42,43,44,45,46,49,50,51,52,54,55,56,58,60,61,62,63,64,65,66,67,68,69,75,76,77,79,87,89,90,91,99,100,105,106,108,110,112,113,116,123,129,133,134,138,139,140,141,144,145,149,151,152,153,154,155,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,179,181,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,218,221,224,226,230,231,232,235,237,238,239,240,242,243,244,250,251,253,254,255,257,259,260,264,265,268,270,282,283,311,312,318,319,322,324,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[33,-251,-61,-72,33,-71,-58,56,-54,-55,-33,-29,-59,-251,-34,33,-53,-68,-63,-87,-52,33,-56,-170,64,-66,-251,-69,33,-32,-73,-86,-64,-31,-60,-35,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-249,-81,-49,-30,114,114,-97,-96,137,-116,-114,-26,-25,-45,-48,-51,33,-251,-251,33,-219,114,-217,114,-216,114,-215,114,114,-214,-218,33,137,137,-115,-117,33,114,-36,262,-83,-250,-21,-80,-22,-79,114,-176,-179,-177,-173,-174,-178,-180,114,-182,-183,-175,-181,114,-215,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,33,114,33,114,137,-98,114,-251,-37,-39,-42,330,-38,114,-40,114,262,-148,-147,-43,-149,262,-41,-85,-84,33,114,114,114,-215,114,-100,-99,-12,114,114,114,-11,-167,-166,114,-164,262,114,-150,114,-163,-151,262,114,114,114,-251,114,-215,-251,-131,-162,-165,114,-154,262,-152,114,114,262,-153,262,114,262,-251,114,-158,-157,-155,114,262,262,-159,-156,262,-161,-160,]),'IF':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,263,-250,-39,-42,-38,-40,263,-148,-147,-43,-149,263,-41,-167,-166,-164,263,-150,-163,-151,263,-162,-165,-154,263,-152,263,-153,263,263,-158,-157,-155,263,263,-159,-156,263,-161,-160,]),'STRING_LITERAL':([55,61,75,91,99,100,101,105,106,108,110,112,113,115,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,178,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,115,-45,-219,115,-217,178,115,-216,115,-215,115,115,-245,-214,-218,115,115,-250,115,-176,-179,-177,-173,-174,-178,-180,115,-182,-183,-175,-181,115,-215,-246,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,-251,-39,-42,-38,115,-40,115,115,-148,-147,-43,-149,115,-41,115,115,115,-215,115,-12,115,115,-11,-167,-166,115,-164,115,115,-150,115,-163,-151,115,115,115,115,-251,115,-215,-251,-131,-162,-165,115,-154,115,-152,115,115,115,-153,115,115,115,-251,115,-158,-157,-155,115,115,115,-159,-156,115,-161,-160,]),'FLOAT':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[35,35,-61,-72,-71,-58,-54,-55,-33,-29,-59,35,-34,-53,-68,-63,-52,35,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,35,-67,35,-70,-74,35,-57,-82,-249,-81,35,-107,-30,35,-97,-96,35,-45,-46,35,-109,35,35,35,35,-88,35,35,-36,35,-47,35,35,-83,-89,-250,35,-110,35,35,-111,-113,-112,35,35,-98,-37,-39,-42,-38,-40,35,-148,-147,-43,-149,-41,-85,-84,-90,35,35,-100,-99,-167,-166,35,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'XOREQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[166,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'LSHIFTEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[168,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'RBRACKET':([61,92,93,94,95,96,97,98,101,102,103,104,107,109,110,111,114,115,117,118,119,120,121,122,124,151,174,176,178,180,184,187,188,190,194,196,221,267,271,273,274,275,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,310,311,312,349,350,351,355,356,363,364,367,386,401,409,],[-251,-206,-233,-243,-247,-244,-241,-231,-232,-208,185,-187,-4,-240,191,-220,-237,-245,-238,-185,-242,-239,-3,-171,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-168,-210,-251,-184,-172,-225,-224,350,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,361,362,-251,-213,-221,-222,-169,-207,387,388,390,-186,-228,-229,]),} - -_lr_action = { } -for _k, _v in _lr_action_items.items(): - for _x,_y in zip(_v[0],_v[1]): - if not _x in _lr_action: _lr_action[_x] = { } - _lr_action[_x][_k] = _y -del _lr_action_items - -_lr_goto_items = {'storage_class_specifier':([0,1,14,22,42,44,48,62,73,82,145,218,227,251,285,313,334,],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,]),'identifier_list_opt':([62,],[125,]),'selection_statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[260,260,260,260,260,260,260,260,260,260,260,260,]),'constant':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,]),'unary_expression':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[92,176,187,190,92,196,92,92,187,92,92,92,92,92,92,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,92,187,187,92,187,92,187,92,92,187,92,187,92,187,92,92,92,92,92,92,92,92,187,187,92,92,92,92,92,92,92,92,92,92,92,92,92,]),'conditional_expression':([61,112,141,145,156,169,175,182,183,186,189,213,221,232,243,250,251,259,270,282,312,325,326,334,336,337,341,345,346,352,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[122,122,122,122,267,122,122,122,122,122,122,122,122,267,122,267,122,122,267,122,122,267,122,122,122,122,122,122,122,122,386,122,122,122,122,122,122,122,122,122,122,122,122,122,]),'brace_close':([86,136,147,148,228,229,261,328,369,385,400,],[149,231,264,265,318,319,344,370,392,401,409,]),'struct_or_union_specifier':([0,1,14,22,42,44,48,57,62,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,]),'unified_wstring_literal':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,]),'abstract_declarator_opt':([129,195,],[219,284,]),'iteration_statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[239,239,239,239,239,239,239,239,239,239,239,239,]),'init_declarator_list':([30,79,],[70,70,]),'translation_unit_or_empty':([0,],[8,]),'struct_declaration_list':([57,84,85,],[86,147,148,]),'enumerator':([65,133,134,230,],[135,135,135,320,]),'pp_directive':([0,22,],[11,11,]),'declaration_list':([48,73,],[82,82,]),'declaration_specifiers_opt':([1,14,42,44,],[50,58,76,77,]),'abstract_declarator':([129,195,218,285,],[220,220,309,309,]),'external_declaration':([0,22,],[12,60,]),'type_specifier':([0,1,14,22,42,44,48,57,62,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[14,14,14,14,14,14,14,87,14,14,14,87,87,87,87,87,87,14,87,87,87,87,87,14,14,14,14,14,14,]),'designation':([235,357,369,400,],[322,322,322,322,]),'compound_statement':([81,142,145,251,259,336,345,379,395,397,399,413,415,418,],[144,237,244,244,244,244,244,244,244,244,244,244,244,244,]),'pointer':([0,4,22,30,67,79,90,129,140,195,218,268,285,],[16,16,16,16,138,16,16,224,16,286,224,16,286,]),'type_name':([112,175,186,189,],[193,272,279,280,]),'unified_string_literal':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,]),'postfix_expression':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,]),'assignment_expression_opt':([61,221,312,],[103,310,363,]),'designation_opt':([235,357,369,400,],[326,326,391,391,]),'expression_statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[238,238,238,238,238,238,238,238,238,238,238,238,]),'unary_operator':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,]),'cast_expression':([61,105,112,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[104,188,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,356,104,104,104,104,104,104,104,104,104,104,356,104,104,104,104,104,104,104,104,104,104,104,104,104,104,]),'brace_open':([7,26,54,56,63,64,81,141,142,145,251,259,283,326,336,345,349,353,354,379,391,395,397,399,413,415,418,],[57,65,84,85,133,134,145,235,145,145,145,145,357,235,145,145,357,357,357,145,235,145,145,145,145,145,145,]),'init_declarator':([30,79,140,],[74,74,233,]),'translation_unit':([0,],[22,]),'assignment_operator':([92,],[169,]),'struct_or_union':([0,1,14,22,42,44,48,57,62,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,]),'block_item_list_opt':([145,],[261,]),'struct_declaration':([57,84,85,86,147,148,],[88,88,88,150,150,150,]),'assignment_expression':([61,112,141,145,169,175,182,183,186,189,213,221,243,251,259,282,312,326,334,336,337,341,345,346,352,376,379,391,393,395,397,398,399,404,410,413,415,418,],[107,194,236,194,271,194,194,276,194,194,194,107,194,194,194,355,107,236,194,194,194,194,194,194,384,194,194,236,194,194,194,194,194,194,194,194,194,194,]),'parameter_type_list':([62,218,285,313,],[127,307,307,307,]),'type_qualifier_list_opt':([28,],[67,]),'direct_declarator':([0,4,16,22,30,79,90,129,140,218,224,268,],[25,25,59,25,25,25,25,25,25,25,59,25,]),'type_qualifier_list':([28,],[68,]),'designator':([235,329,357,369,400,],[323,371,323,323,323,]),'argument_expression_list':([183,],[278,]),'initializer':([141,326,391,],[234,368,402,]),'direct_abstract_declarator':([129,195,218,224,285,286,],[223,223,223,314,223,314,]),'specifier_qualifier_list_opt':([87,89,],[153,155,]),'constant_expression':([156,232,250,270,325,],[266,321,338,348,367,]),'expression_opt':([145,251,259,334,336,345,376,379,393,395,397,399,404,410,413,415,418,],[241,241,241,375,241,241,394,241,403,241,241,241,411,414,241,241,241,]),'primary_expression':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,]),'declaration_specifiers':([0,1,14,22,42,44,48,62,73,82,145,218,227,251,285,313,334,],[30,52,52,30,52,52,79,129,79,79,79,129,129,79,129,129,79,]),'declaration':([0,22,48,73,82,145,251,334,],[31,31,80,80,146,254,254,376,]),'struct_declarator_list_opt':([90,],[158,]),'identifier_list':([62,],[130,]),'typedef_name':([0,1,14,22,42,44,48,57,62,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,]),'parameter_type_list_opt':([218,285,313,],[308,308,365,]),'jump_statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[255,255,255,255,255,255,255,255,255,255,255,255,]),'declaration_list_opt':([48,73,],[81,142,]),'struct_declarator':([90,268,],[159,347,]),'function_definition':([0,22,],[36,36,]),'binary_expression':([61,112,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,312,325,326,334,336,337,341,345,346,352,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[118,118,118,118,118,118,118,118,118,118,118,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,118,304,305,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,]),'parameter_list':([62,218,285,313,],[131,131,131,131,]),'init_declarator_list_opt':([30,79,],[71,71,]),'enum_specifier':([0,1,14,22,42,44,48,57,62,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,]),'struct_declarator_list':([90,],[157,]),'decl_body':([0,22,48,73,82,145,251,334,],[41,41,41,41,41,41,41,41,]),'type_qualifier':([0,1,14,22,28,42,44,48,57,62,68,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[42,42,42,42,66,42,42,42,89,42,139,42,42,89,89,89,89,89,89,42,89,89,89,89,89,42,42,42,42,42,42,]),'enumerator_list':([65,133,134,],[136,228,229,]),'labeled_statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[242,242,242,242,242,242,242,242,242,242,242,242,]),'function_specifier':([0,1,14,22,42,44,48,62,73,82,145,218,227,251,285,313,334,],[44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,]),'specifier_qualifier_list':([57,84,85,86,87,89,112,147,148,175,186,189,],[90,90,90,90,154,154,195,90,90,195,195,195,]),'block_item':([145,251,],[257,340,]),'block_item_list':([145,],[251,]),'statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[253,253,343,377,382,396,405,406,408,417,419,420,]),'empty':([0,1,14,28,30,42,44,48,61,62,73,79,87,89,90,129,145,195,218,221,235,251,259,285,312,313,334,336,345,357,369,376,379,393,395,397,399,400,404,410,413,415,418,],[47,51,51,69,72,51,51,78,121,126,78,72,152,152,160,225,258,225,306,121,327,339,339,306,121,306,339,339,339,327,327,339,339,339,339,339,339,327,339,339,339,339,339,]),'initializer_list':([235,357,],[328,385,]),'declarator':([0,4,22,30,79,90,129,140,218,268,],[48,53,48,73,143,161,222,143,53,161,]),'parameter_declaration':([62,218,227,285,313,],[128,128,317,128,128,]),'designator_list':([235,357,369,400,],[329,329,329,329,]),'identifier':([61,62,99,105,108,112,113,141,145,156,169,175,179,181,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,226,232,243,250,251,259,270,282,283,312,324,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[124,132,124,124,124,124,124,124,124,124,124,124,273,274,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,315,124,124,124,124,124,124,124,124,124,366,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,]),'expression':([112,145,175,182,186,189,213,243,251,259,334,336,337,341,345,346,376,379,393,395,397,398,399,404,410,413,415,418,],[192,247,192,275,192,192,303,333,247,247,247,247,378,380,247,383,247,247,247,247,247,407,247,247,247,247,247,247,]),} - -_lr_goto = { } -for _k, _v in _lr_goto_items.items(): - for _x,_y in zip(_v[0],_v[1]): - if not _x in _lr_goto: _lr_goto[_x] = { } - _lr_goto[_x][_k] = _y -del _lr_goto_items -_lr_productions = [ - ("S' -> translation_unit_or_empty","S'",1,None,None,None), - ('abstract_declarator_opt -> empty','abstract_declarator_opt',1,'p_abstract_declarator_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('abstract_declarator_opt -> abstract_declarator','abstract_declarator_opt',1,'p_abstract_declarator_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('assignment_expression_opt -> empty','assignment_expression_opt',1,'p_assignment_expression_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('assignment_expression_opt -> assignment_expression','assignment_expression_opt',1,'p_assignment_expression_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('block_item_list_opt -> empty','block_item_list_opt',1,'p_block_item_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('block_item_list_opt -> block_item_list','block_item_list_opt',1,'p_block_item_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('declaration_list_opt -> empty','declaration_list_opt',1,'p_declaration_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('declaration_list_opt -> declaration_list','declaration_list_opt',1,'p_declaration_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('declaration_specifiers_opt -> empty','declaration_specifiers_opt',1,'p_declaration_specifiers_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('declaration_specifiers_opt -> declaration_specifiers','declaration_specifiers_opt',1,'p_declaration_specifiers_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('designation_opt -> empty','designation_opt',1,'p_designation_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('designation_opt -> designation','designation_opt',1,'p_designation_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('expression_opt -> empty','expression_opt',1,'p_expression_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('expression_opt -> expression','expression_opt',1,'p_expression_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('identifier_list_opt -> empty','identifier_list_opt',1,'p_identifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('identifier_list_opt -> identifier_list','identifier_list_opt',1,'p_identifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('init_declarator_list_opt -> empty','init_declarator_list_opt',1,'p_init_declarator_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('init_declarator_list_opt -> init_declarator_list','init_declarator_list_opt',1,'p_init_declarator_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('parameter_type_list_opt -> empty','parameter_type_list_opt',1,'p_parameter_type_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('parameter_type_list_opt -> parameter_type_list','parameter_type_list_opt',1,'p_parameter_type_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('specifier_qualifier_list_opt -> empty','specifier_qualifier_list_opt',1,'p_specifier_qualifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('specifier_qualifier_list_opt -> specifier_qualifier_list','specifier_qualifier_list_opt',1,'p_specifier_qualifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('struct_declarator_list_opt -> empty','struct_declarator_list_opt',1,'p_struct_declarator_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('struct_declarator_list_opt -> struct_declarator_list','struct_declarator_list_opt',1,'p_struct_declarator_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('type_qualifier_list_opt -> empty','type_qualifier_list_opt',1,'p_type_qualifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('type_qualifier_list_opt -> type_qualifier_list','type_qualifier_list_opt',1,'p_type_qualifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('translation_unit_or_empty -> translation_unit','translation_unit_or_empty',1,'p_translation_unit_or_empty','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',355), - ('translation_unit_or_empty -> empty','translation_unit_or_empty',1,'p_translation_unit_or_empty','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',356), - ('translation_unit -> external_declaration','translation_unit',1,'p_translation_unit_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',364), - ('translation_unit -> translation_unit external_declaration','translation_unit',2,'p_translation_unit_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',371), - ('external_declaration -> function_definition','external_declaration',1,'p_external_declaration_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',383), - ('external_declaration -> declaration','external_declaration',1,'p_external_declaration_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',388), - ('external_declaration -> pp_directive','external_declaration',1,'p_external_declaration_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',393), - ('external_declaration -> SEMI','external_declaration',1,'p_external_declaration_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',398), - ('pp_directive -> PPHASH','pp_directive',1,'p_pp_directive','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',403), - ('function_definition -> declarator declaration_list_opt compound_statement','function_definition',3,'p_function_definition_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',412), - ('function_definition -> declaration_specifiers declarator declaration_list_opt compound_statement','function_definition',4,'p_function_definition_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',424), - ('statement -> labeled_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',435), - ('statement -> expression_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',436), - ('statement -> compound_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',437), - ('statement -> selection_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',438), - ('statement -> iteration_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',439), - ('statement -> jump_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',440), - ('decl_body -> declaration_specifiers init_declarator_list_opt','decl_body',2,'p_decl_body','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',454), - ('declaration -> decl_body SEMI','declaration',2,'p_declaration','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',537), - ('declaration_list -> declaration','declaration_list',1,'p_declaration_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',546), - ('declaration_list -> declaration_list declaration','declaration_list',2,'p_declaration_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',547), - ('declaration_specifiers -> type_qualifier declaration_specifiers_opt','declaration_specifiers',2,'p_declaration_specifiers_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',552), - ('declaration_specifiers -> type_specifier declaration_specifiers_opt','declaration_specifiers',2,'p_declaration_specifiers_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',557), - ('declaration_specifiers -> storage_class_specifier declaration_specifiers_opt','declaration_specifiers',2,'p_declaration_specifiers_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',562), - ('declaration_specifiers -> function_specifier declaration_specifiers_opt','declaration_specifiers',2,'p_declaration_specifiers_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',567), - ('storage_class_specifier -> AUTO','storage_class_specifier',1,'p_storage_class_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',572), - ('storage_class_specifier -> REGISTER','storage_class_specifier',1,'p_storage_class_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',573), - ('storage_class_specifier -> STATIC','storage_class_specifier',1,'p_storage_class_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',574), - ('storage_class_specifier -> EXTERN','storage_class_specifier',1,'p_storage_class_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',575), - ('storage_class_specifier -> TYPEDEF','storage_class_specifier',1,'p_storage_class_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',576), - ('function_specifier -> INLINE','function_specifier',1,'p_function_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',581), - ('type_specifier -> VOID','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',586), - ('type_specifier -> _BOOL','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',587), - ('type_specifier -> CHAR','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',588), - ('type_specifier -> SHORT','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',589), - ('type_specifier -> INT','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',590), - ('type_specifier -> LONG','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',591), - ('type_specifier -> FLOAT','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',592), - ('type_specifier -> DOUBLE','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',593), - ('type_specifier -> _COMPLEX','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',594), - ('type_specifier -> SIGNED','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',595), - ('type_specifier -> UNSIGNED','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',596), - ('type_specifier -> typedef_name','type_specifier',1,'p_type_specifier_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',601), - ('type_specifier -> enum_specifier','type_specifier',1,'p_type_specifier_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',602), - ('type_specifier -> struct_or_union_specifier','type_specifier',1,'p_type_specifier_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',603), - ('type_qualifier -> CONST','type_qualifier',1,'p_type_qualifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',608), - ('type_qualifier -> RESTRICT','type_qualifier',1,'p_type_qualifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',609), - ('type_qualifier -> VOLATILE','type_qualifier',1,'p_type_qualifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',610), - ('init_declarator_list -> init_declarator','init_declarator_list',1,'p_init_declarator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',615), - ('init_declarator_list -> init_declarator_list COMMA init_declarator','init_declarator_list',3,'p_init_declarator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',616), - ('init_declarator -> declarator','init_declarator',1,'p_init_declarator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',624), - ('init_declarator -> declarator EQUALS initializer','init_declarator',3,'p_init_declarator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',625), - ('specifier_qualifier_list -> type_qualifier specifier_qualifier_list_opt','specifier_qualifier_list',2,'p_specifier_qualifier_list_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',630), - ('specifier_qualifier_list -> type_specifier specifier_qualifier_list_opt','specifier_qualifier_list',2,'p_specifier_qualifier_list_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',635), - ('struct_or_union_specifier -> struct_or_union ID','struct_or_union_specifier',2,'p_struct_or_union_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',643), - ('struct_or_union_specifier -> struct_or_union TYPEID','struct_or_union_specifier',2,'p_struct_or_union_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',644), - ('struct_or_union_specifier -> struct_or_union brace_open struct_declaration_list brace_close','struct_or_union_specifier',4,'p_struct_or_union_specifier_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',653), - ('struct_or_union_specifier -> struct_or_union ID brace_open struct_declaration_list brace_close','struct_or_union_specifier',5,'p_struct_or_union_specifier_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',662), - ('struct_or_union_specifier -> struct_or_union TYPEID brace_open struct_declaration_list brace_close','struct_or_union_specifier',5,'p_struct_or_union_specifier_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',663), - ('struct_or_union -> STRUCT','struct_or_union',1,'p_struct_or_union','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',672), - ('struct_or_union -> UNION','struct_or_union',1,'p_struct_or_union','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',673), - ('struct_declaration_list -> struct_declaration','struct_declaration_list',1,'p_struct_declaration_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',680), - ('struct_declaration_list -> struct_declaration_list struct_declaration','struct_declaration_list',2,'p_struct_declaration_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',681), - ('struct_declaration -> specifier_qualifier_list struct_declarator_list_opt SEMI','struct_declaration',3,'p_struct_declaration_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',686), - ('struct_declarator_list -> struct_declarator','struct_declarator_list',1,'p_struct_declarator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',737), - ('struct_declarator_list -> struct_declarator_list COMMA struct_declarator','struct_declarator_list',3,'p_struct_declarator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',738), - ('struct_declarator -> declarator','struct_declarator',1,'p_struct_declarator_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',746), - ('struct_declarator -> declarator COLON constant_expression','struct_declarator',3,'p_struct_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',751), - ('struct_declarator -> COLON constant_expression','struct_declarator',2,'p_struct_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',752), - ('enum_specifier -> ENUM ID','enum_specifier',2,'p_enum_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',760), - ('enum_specifier -> ENUM TYPEID','enum_specifier',2,'p_enum_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',761), - ('enum_specifier -> ENUM brace_open enumerator_list brace_close','enum_specifier',4,'p_enum_specifier_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',766), - ('enum_specifier -> ENUM ID brace_open enumerator_list brace_close','enum_specifier',5,'p_enum_specifier_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',771), - ('enum_specifier -> ENUM TYPEID brace_open enumerator_list brace_close','enum_specifier',5,'p_enum_specifier_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',772), - ('enumerator_list -> enumerator','enumerator_list',1,'p_enumerator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',777), - ('enumerator_list -> enumerator_list COMMA','enumerator_list',2,'p_enumerator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',778), - ('enumerator_list -> enumerator_list COMMA enumerator','enumerator_list',3,'p_enumerator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',779), - ('enumerator -> ID','enumerator',1,'p_enumerator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',790), - ('enumerator -> ID EQUALS constant_expression','enumerator',3,'p_enumerator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',791), - ('declarator -> direct_declarator','declarator',1,'p_declarator_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',803), - ('declarator -> pointer direct_declarator','declarator',2,'p_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',808), - ('direct_declarator -> ID','direct_declarator',1,'p_direct_declarator_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',813), - ('direct_declarator -> LPAREN declarator RPAREN','direct_declarator',3,'p_direct_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',822), - ('direct_declarator -> direct_declarator LBRACKET assignment_expression_opt RBRACKET','direct_declarator',4,'p_direct_declarator_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',827), - ('direct_declarator -> direct_declarator LBRACKET TIMES RBRACKET','direct_declarator',4,'p_direct_declarator_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',839), - ('direct_declarator -> direct_declarator LPAREN parameter_type_list RPAREN','direct_declarator',4,'p_direct_declarator_5','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',849), - ('direct_declarator -> direct_declarator LPAREN identifier_list_opt RPAREN','direct_declarator',4,'p_direct_declarator_5','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',850), - ('pointer -> TIMES type_qualifier_list_opt','pointer',2,'p_pointer','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',860), - ('pointer -> TIMES type_qualifier_list_opt pointer','pointer',3,'p_pointer','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',861), - ('type_qualifier_list -> type_qualifier','type_qualifier_list',1,'p_type_qualifier_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',871), - ('type_qualifier_list -> type_qualifier_list type_qualifier','type_qualifier_list',2,'p_type_qualifier_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',872), - ('parameter_type_list -> parameter_list','parameter_type_list',1,'p_parameter_type_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',877), - ('parameter_type_list -> parameter_list COMMA ELLIPSIS','parameter_type_list',3,'p_parameter_type_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',878), - ('parameter_list -> parameter_declaration','parameter_list',1,'p_parameter_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',886), - ('parameter_list -> parameter_list COMMA parameter_declaration','parameter_list',3,'p_parameter_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',887), - ('parameter_declaration -> declaration_specifiers declarator','parameter_declaration',2,'p_parameter_declaration_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',896), - ('parameter_declaration -> declaration_specifiers abstract_declarator_opt','parameter_declaration',2,'p_parameter_declaration_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',915), - ('identifier_list -> identifier','identifier_list',1,'p_identifier_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',927), - ('identifier_list -> identifier_list COMMA identifier','identifier_list',3,'p_identifier_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',928), - ('initializer -> assignment_expression','initializer',1,'p_initializer_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',937), - ('initializer -> brace_open initializer_list brace_close','initializer',3,'p_initializer_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',942), - ('initializer -> brace_open initializer_list COMMA brace_close','initializer',4,'p_initializer_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',943), - ('initializer_list -> designation_opt initializer','initializer_list',2,'p_initializer_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',948), - ('initializer_list -> initializer_list COMMA designation_opt initializer','initializer_list',4,'p_initializer_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',949), - ('designation -> designator_list EQUALS','designation',2,'p_designation','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',960), - ('designator_list -> designator','designator_list',1,'p_designator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',968), - ('designator_list -> designator_list designator','designator_list',2,'p_designator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',969), - ('designator -> LBRACKET constant_expression RBRACKET','designator',3,'p_designator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',974), - ('designator -> PERIOD identifier','designator',2,'p_designator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',975), - ('type_name -> specifier_qualifier_list abstract_declarator_opt','type_name',2,'p_type_name','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',980), - ('abstract_declarator -> pointer','abstract_declarator',1,'p_abstract_declarator_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',996), - ('abstract_declarator -> pointer direct_abstract_declarator','abstract_declarator',2,'p_abstract_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1004), - ('abstract_declarator -> direct_abstract_declarator','abstract_declarator',1,'p_abstract_declarator_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1009), - ('direct_abstract_declarator -> LPAREN abstract_declarator RPAREN','direct_abstract_declarator',3,'p_direct_abstract_declarator_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1019), - ('direct_abstract_declarator -> direct_abstract_declarator LBRACKET assignment_expression_opt RBRACKET','direct_abstract_declarator',4,'p_direct_abstract_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1023), - ('direct_abstract_declarator -> LBRACKET assignment_expression_opt RBRACKET','direct_abstract_declarator',3,'p_direct_abstract_declarator_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1033), - ('direct_abstract_declarator -> direct_abstract_declarator LBRACKET TIMES RBRACKET','direct_abstract_declarator',4,'p_direct_abstract_declarator_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1041), - ('direct_abstract_declarator -> LBRACKET TIMES RBRACKET','direct_abstract_declarator',3,'p_direct_abstract_declarator_5','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1051), - ('direct_abstract_declarator -> direct_abstract_declarator LPAREN parameter_type_list_opt RPAREN','direct_abstract_declarator',4,'p_direct_abstract_declarator_6','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1059), - ('direct_abstract_declarator -> LPAREN parameter_type_list_opt RPAREN','direct_abstract_declarator',3,'p_direct_abstract_declarator_7','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1069), - ('block_item -> declaration','block_item',1,'p_block_item','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1080), - ('block_item -> statement','block_item',1,'p_block_item','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1081), - ('block_item_list -> block_item','block_item_list',1,'p_block_item_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1088), - ('block_item_list -> block_item_list block_item','block_item_list',2,'p_block_item_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1089), - ('compound_statement -> brace_open block_item_list_opt brace_close','compound_statement',3,'p_compound_statement_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1095), - ('labeled_statement -> ID COLON statement','labeled_statement',3,'p_labeled_statement_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1101), - ('labeled_statement -> CASE constant_expression COLON statement','labeled_statement',4,'p_labeled_statement_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1105), - ('labeled_statement -> DEFAULT COLON statement','labeled_statement',3,'p_labeled_statement_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1109), - ('selection_statement -> IF LPAREN expression RPAREN statement','selection_statement',5,'p_selection_statement_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1113), - ('selection_statement -> IF LPAREN expression RPAREN statement ELSE statement','selection_statement',7,'p_selection_statement_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1117), - ('selection_statement -> SWITCH LPAREN expression RPAREN statement','selection_statement',5,'p_selection_statement_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1121), - ('iteration_statement -> WHILE LPAREN expression RPAREN statement','iteration_statement',5,'p_iteration_statement_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1126), - ('iteration_statement -> DO statement WHILE LPAREN expression RPAREN SEMI','iteration_statement',7,'p_iteration_statement_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1130), - ('iteration_statement -> FOR LPAREN expression_opt SEMI expression_opt SEMI expression_opt RPAREN statement','iteration_statement',9,'p_iteration_statement_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1134), - ('iteration_statement -> FOR LPAREN declaration expression_opt SEMI expression_opt RPAREN statement','iteration_statement',8,'p_iteration_statement_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1138), - ('jump_statement -> GOTO ID SEMI','jump_statement',3,'p_jump_statement_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1142), - ('jump_statement -> BREAK SEMI','jump_statement',2,'p_jump_statement_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1146), - ('jump_statement -> CONTINUE SEMI','jump_statement',2,'p_jump_statement_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1150), - ('jump_statement -> RETURN expression SEMI','jump_statement',3,'p_jump_statement_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1154), - ('jump_statement -> RETURN SEMI','jump_statement',2,'p_jump_statement_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1155), - ('expression_statement -> expression_opt SEMI','expression_statement',2,'p_expression_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1160), - ('expression -> assignment_expression','expression',1,'p_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1167), - ('expression -> expression COMMA assignment_expression','expression',3,'p_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1168), - ('typedef_name -> TYPEID','typedef_name',1,'p_typedef_name','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1180), - ('assignment_expression -> conditional_expression','assignment_expression',1,'p_assignment_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1184), - ('assignment_expression -> unary_expression assignment_operator assignment_expression','assignment_expression',3,'p_assignment_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1185), - ('assignment_operator -> EQUALS','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1198), - ('assignment_operator -> XOREQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1199), - ('assignment_operator -> TIMESEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1200), - ('assignment_operator -> DIVEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1201), - ('assignment_operator -> MODEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1202), - ('assignment_operator -> PLUSEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1203), - ('assignment_operator -> MINUSEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1204), - ('assignment_operator -> LSHIFTEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1205), - ('assignment_operator -> RSHIFTEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1206), - ('assignment_operator -> ANDEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1207), - ('assignment_operator -> OREQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1208), - ('constant_expression -> conditional_expression','constant_expression',1,'p_constant_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1213), - ('conditional_expression -> binary_expression','conditional_expression',1,'p_conditional_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1217), - ('conditional_expression -> binary_expression CONDOP expression COLON conditional_expression','conditional_expression',5,'p_conditional_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1218), - ('binary_expression -> cast_expression','binary_expression',1,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1226), - ('binary_expression -> binary_expression TIMES binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1227), - ('binary_expression -> binary_expression DIVIDE binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1228), - ('binary_expression -> binary_expression MOD binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1229), - ('binary_expression -> binary_expression PLUS binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1230), - ('binary_expression -> binary_expression MINUS binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1231), - ('binary_expression -> binary_expression RSHIFT binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1232), - ('binary_expression -> binary_expression LSHIFT binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1233), - ('binary_expression -> binary_expression LT binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1234), - ('binary_expression -> binary_expression LE binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1235), - ('binary_expression -> binary_expression GE binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1236), - ('binary_expression -> binary_expression GT binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1237), - ('binary_expression -> binary_expression EQ binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1238), - ('binary_expression -> binary_expression NE binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1239), - ('binary_expression -> binary_expression AND binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1240), - ('binary_expression -> binary_expression OR binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1241), - ('binary_expression -> binary_expression XOR binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1242), - ('binary_expression -> binary_expression LAND binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1243), - ('binary_expression -> binary_expression LOR binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1244), - ('cast_expression -> unary_expression','cast_expression',1,'p_cast_expression_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1252), - ('cast_expression -> LPAREN type_name RPAREN cast_expression','cast_expression',4,'p_cast_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1256), - ('unary_expression -> postfix_expression','unary_expression',1,'p_unary_expression_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1260), - ('unary_expression -> PLUSPLUS unary_expression','unary_expression',2,'p_unary_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1264), - ('unary_expression -> MINUSMINUS unary_expression','unary_expression',2,'p_unary_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1265), - ('unary_expression -> unary_operator cast_expression','unary_expression',2,'p_unary_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1266), - ('unary_expression -> SIZEOF unary_expression','unary_expression',2,'p_unary_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1271), - ('unary_expression -> SIZEOF LPAREN type_name RPAREN','unary_expression',4,'p_unary_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1272), - ('unary_operator -> AND','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1280), - ('unary_operator -> TIMES','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1281), - ('unary_operator -> PLUS','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1282), - ('unary_operator -> MINUS','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1283), - ('unary_operator -> NOT','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1284), - ('unary_operator -> LNOT','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1285), - ('postfix_expression -> primary_expression','postfix_expression',1,'p_postfix_expression_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1290), - ('postfix_expression -> postfix_expression LBRACKET expression RBRACKET','postfix_expression',4,'p_postfix_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1294), - ('postfix_expression -> postfix_expression LPAREN argument_expression_list RPAREN','postfix_expression',4,'p_postfix_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1298), - ('postfix_expression -> postfix_expression LPAREN RPAREN','postfix_expression',3,'p_postfix_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1299), - ('postfix_expression -> postfix_expression PERIOD identifier','postfix_expression',3,'p_postfix_expression_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1304), - ('postfix_expression -> postfix_expression ARROW identifier','postfix_expression',3,'p_postfix_expression_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1305), - ('postfix_expression -> postfix_expression PLUSPLUS','postfix_expression',2,'p_postfix_expression_5','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1310), - ('postfix_expression -> postfix_expression MINUSMINUS','postfix_expression',2,'p_postfix_expression_5','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1311), - ('postfix_expression -> LPAREN type_name RPAREN brace_open initializer_list brace_close','postfix_expression',6,'p_postfix_expression_6','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1316), - ('postfix_expression -> LPAREN type_name RPAREN brace_open initializer_list COMMA brace_close','postfix_expression',7,'p_postfix_expression_6','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1317), - ('primary_expression -> identifier','primary_expression',1,'p_primary_expression_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1322), - ('primary_expression -> constant','primary_expression',1,'p_primary_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1326), - ('primary_expression -> unified_string_literal','primary_expression',1,'p_primary_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1330), - ('primary_expression -> unified_wstring_literal','primary_expression',1,'p_primary_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1331), - ('primary_expression -> LPAREN expression RPAREN','primary_expression',3,'p_primary_expression_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1336), - ('argument_expression_list -> assignment_expression','argument_expression_list',1,'p_argument_expression_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1340), - ('argument_expression_list -> argument_expression_list COMMA assignment_expression','argument_expression_list',3,'p_argument_expression_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1341), - ('identifier -> ID','identifier',1,'p_identifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1350), - ('constant -> INT_CONST_DEC','constant',1,'p_constant_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1354), - ('constant -> INT_CONST_OCT','constant',1,'p_constant_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1355), - ('constant -> INT_CONST_HEX','constant',1,'p_constant_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1356), - ('constant -> FLOAT_CONST','constant',1,'p_constant_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1362), - ('constant -> HEX_FLOAT_CONST','constant',1,'p_constant_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1363), - ('constant -> CHAR_CONST','constant',1,'p_constant_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1369), - ('constant -> WCHAR_CONST','constant',1,'p_constant_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1370), - ('unified_string_literal -> STRING_LITERAL','unified_string_literal',1,'p_unified_string_literal','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1381), - ('unified_string_literal -> unified_string_literal STRING_LITERAL','unified_string_literal',2,'p_unified_string_literal','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1382), - ('unified_wstring_literal -> WSTRING_LITERAL','unified_wstring_literal',1,'p_unified_wstring_literal','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1392), - ('unified_wstring_literal -> unified_wstring_literal WSTRING_LITERAL','unified_wstring_literal',2,'p_unified_wstring_literal','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1393), - ('brace_open -> LBRACE','brace_open',1,'p_brace_open','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1403), - ('brace_close -> RBRACE','brace_close',1,'p_brace_close','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1409), - ('empty -> ','empty',0,'p_empty','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1415), -] diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/build/lib.linux-x86_64-2.7/_cffi__gd39ab08bx8432a366.pypy-20.so b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/build/lib.linux-x86_64-2.7/_cffi__gd39ab08bx8432a366.pypy-20.so deleted file mode 100755 Binary file pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/build/lib.linux-x86_64-2.7/_cffi__gd39ab08bx8432a366.pypy-20.so has changed diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/build/lib.linux-x86_64-2.7/snip_basic_verify1/__init__.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/build/lib.linux-x86_64-2.7/snip_basic_verify1/__init__.py deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/build/lib.linux-x86_64-2.7/snip_basic_verify1/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ - -from cffi import FFI -import sys - -ffi = FFI() -ffi.cdef(""" // some declarations from the man page - struct passwd { - char *pw_name; - ...; - }; - struct passwd *getpwuid(int uid); -""") -C = ffi.verify(""" // passed to the real C compiler -#include -#include -""", libraries=[], # or a list of libraries to link with - force_generic_engine=hasattr(sys, '_force_generic_engine_')) diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/build/temp.linux-x86_64-2.7/snip_basic_verify1/__pycache__/_cffi__gd39ab08bx8432a366.o b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/build/temp.linux-x86_64-2.7/snip_basic_verify1/__pycache__/_cffi__gd39ab08bx8432a366.o deleted file mode 100644 Binary file pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/build/temp.linux-x86_64-2.7/snip_basic_verify1/__pycache__/_cffi__gd39ab08bx8432a366.o has changed diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/lextab.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/lextab.py deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/lextab.py +++ /dev/null @@ -1,9 +0,0 @@ -# pycparser.lextab.py. This file automatically created by PLY (version 3.4). Don't edit! -_tabversion = '3.4' -_lextokens = {'VOID': 1, 'LBRACKET': 1, 'WCHAR_CONST': 1, 'FLOAT_CONST': 1, 'MINUS': 1, 'RPAREN': 1, 'LONG': 1, 'PLUS': 1, 'ELLIPSIS': 1, 'GT': 1, 'GOTO': 1, 'ENUM': 1, 'PERIOD': 1, 'GE': 1, 'INT_CONST_DEC': 1, 'ARROW': 1, 'HEX_FLOAT_CONST': 1, 'DOUBLE': 1, 'MINUSEQUAL': 1, 'INT_CONST_OCT': 1, 'TIMESEQUAL': 1, 'OR': 1, 'SHORT': 1, 'RETURN': 1, 'RSHIFTEQUAL': 1, 'RESTRICT': 1, 'STATIC': 1, 'SIZEOF': 1, 'UNSIGNED': 1, 'UNION': 1, 'COLON': 1, 'WSTRING_LITERAL': 1, 'DIVIDE': 1, 'FOR': 1, 'PLUSPLUS': 1, 'EQUALS': 1, 'ELSE': 1, 'INLINE': 1, 'EQ': 1, 'AND': 1, 'TYPEID': 1, 'LBRACE': 1, 'PPHASH': 1, 'INT': 1, 'SIGNED': 1, 'CONTINUE': 1, 'NOT': 1, 'OREQUAL': 1, 'MOD': 1, 'RSHIFT': 1, 'DEFAULT': 1, 'CHAR': 1, 'WHILE': 1, 'DIVEQUAL': 1, 'EXTERN': 1, 'CASE': 1, 'LAND': 1, 'REGISTER': 1, 'MODEQUAL': 1, 'NE': 1, 'SWITCH': 1, 'INT_CONST_HEX': 1, '_COMPLEX': 1, 'PLUSEQUAL': 1, 'STRUCT': 1, 'CONDOP': 1, 'BREAK': 1, 'VOLATILE': 1, 'ANDEQUAL': 1, 'DO': 1, 'LNOT': 1, 'CONST': 1, 'LOR': 1, 'CHAR_CONST': 1, 'LSHIFT': 1, 'RBRACE': 1, '_BOOL': 1, 'LE': 1, 'SEMI': 1, 'LT': 1, 'COMMA': 1, 'TYPEDEF': 1, 'XOR': 1, 'AUTO': 1, 'TIMES': 1, 'LPAREN': 1, 'MINUSMINUS': 1, 'ID': 1, 'IF': 1, 'STRING_LITERAL': 1, 'FLOAT': 1, 'XOREQUAL': 1, 'LSHIFTEQUAL': 1, 'RBRACKET': 1} -_lexreflags = 0 -_lexliterals = '' -_lexstateinfo = {'ppline': 'exclusive', 'pppragma': 'exclusive', 'INITIAL': 'inclusive'} -_lexstatere = {'ppline': [('(?P"([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*")|(?P(0(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?)|([1-9][0-9]*(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?))|(?P\\n)|(?Pline)', [None, ('t_ppline_FILENAME', 'FILENAME'), None, None, None, None, None, None, ('t_ppline_LINE_NUMBER', 'LINE_NUMBER'), None, None, None, None, None, None, None, None, ('t_ppline_NEWLINE', 'NEWLINE'), ('t_ppline_PPLINE', 'PPLINE')])], 'pppragma': [('(?P\\n)|(?Ppragma)|(?P"([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*")|(?P[a-zA-Z_][0-9a-zA-Z_]*)', [None, ('t_pppragma_NEWLINE', 'NEWLINE'), ('t_pppragma_PPPRAGMA', 'PPPRAGMA'), ('t_pppragma_STR', 'STR'), None, None, None, None, None, None, ('t_pppragma_ID', 'ID')])], 'INITIAL': [('(?P[ \\t]*\\#)|(?P\\n+)|(?P((((([0-9]*\\.[0-9]+)|([0-9]+\\.))([eE][-+]?[0-9]+)?)|([0-9]+([eE][-+]?[0-9]+)))[FfLl]?))|(?P(0[xX]([0-9a-fA-F]+|((([0-9a-fA-F]+)?\\.[0-9a-fA-F]+)|([0-9a-fA-F]+\\.)))([pP][+-]?[0-9]+)[FfLl]?))|(?P0[xX][0-9a-fA-F]+(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?)|(?P0[0-7]*[89])|(?P0[0-7]*(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?)', [None, ('t_PPHASH', 'PPHASH'), ('t_NEWLINE', 'NEWLINE'), ('t_FLOAT_CONST', 'FLOAT_CONST'), None, None, None, None, None, None, None, None, None, ('t_HEX_FLOAT_CONST', 'HEX_FLOAT_CONST'), None, None, None, None, None, None, None, ('t_INT_CONST_HEX', 'INT_CONST_HEX'), None, None, None, ('t_BAD_CONST_OCT', 'BAD_CONST_OCT'), ('t_INT_CONST_OCT', 'INT_CONST_OCT')]), ('(?P(0(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?)|([1-9][0-9]*(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?))|(?P\'([^\'\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))\')|(?PL\'([^\'\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))\')|(?P(\'([^\'\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*\\n)|(\'([^\'\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*$))|(?P(\'([^\'\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))[^\'\n]+\')|(\'\')|(\'([\\\\][^a-zA-Z._~^!=&\\^\\-\\\\?\'"x0-7])[^\'\\n]*\'))|(?PL"([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*")|(?P"([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*([\\\\][^a-zA-Z._~^!=&\\^\\-\\\\?\'"x0-7])([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*")|(?P[a-zA-Z_][0-9a-zA-Z_]*)', [None, ('t_INT_CONST_DEC', 'INT_CONST_DEC'), None, None, None, None, None, None, None, None, ('t_CHAR_CONST', 'CHAR_CONST'), None, None, None, None, None, None, ('t_WCHAR_CONST', 'WCHAR_CONST'), None, None, None, None, None, None, ('t_UNMATCHED_QUOTE', 'UNMATCHED_QUOTE'), None, None, None, None, None, None, None, None, None, None, None, None, None, None, ('t_BAD_CHAR_CONST', 'BAD_CHAR_CONST'), None, None, None, None, None, None, None, None, None, None, ('t_WSTRING_LITERAL', 'WSTRING_LITERAL'), None, None, None, None, None, None, ('t_BAD_STRING_LITERAL', 'BAD_STRING_LITERAL'), None, None, None, None, None, None, None, None, None, None, None, None, None, ('t_ID', 'ID')]), ('(?P"([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*")|(?P\\.\\.\\.)|(?P\\+\\+)|(?P\\|\\|)|(?P\\^=)|(?P\\|=)|(?P<<=)|(?P>>=)|(?P\\+=)|(?P\\*=)|(?P\\+)|(?P%=)|(?P\\{)|(?P/=)|(?P\\])|(?P\\?)', [None, (None, 'STRING_LITERAL'), None, None, None, None, None, None, (None, 'ELLIPSIS'), (None, 'PLUSPLUS'), (None, 'LOR'), (None, 'XOREQUAL'), (None, 'OREQUAL'), (None, 'LSHIFTEQUAL'), (None, 'RSHIFTEQUAL'), (None, 'PLUSEQUAL'), (None, 'TIMESEQUAL'), (None, 'PLUS'), (None, 'MODEQUAL'), (None, 'LBRACE'), (None, 'DIVEQUAL'), (None, 'RBRACKET'), (None, 'CONDOP')]), ('(?P\\^)|(?P<<)|(?P<=)|(?P\\()|(?P->)|(?P==)|(?P\\})|(?P!=)|(?P--)|(?P\\|)|(?P\\*)|(?P\\[)|(?P>=)|(?P\\))|(?P&&)|(?P>>)|(?P&=)|(?P-=)|(?P\\.)|(?P=)|(?P<)|(?P,)|(?P/)|(?P&)|(?P%)|(?P;)|(?P-)|(?P>)|(?P:)|(?P~)|(?P!)', [None, (None, 'XOR'), (None, 'LSHIFT'), (None, 'LE'), (None, 'LPAREN'), (None, 'ARROW'), (None, 'EQ'), (None, 'RBRACE'), (None, 'NE'), (None, 'MINUSMINUS'), (None, 'OR'), (None, 'TIMES'), (None, 'LBRACKET'), (None, 'GE'), (None, 'RPAREN'), (None, 'LAND'), (None, 'RSHIFT'), (None, 'ANDEQUAL'), (None, 'MINUSEQUAL'), (None, 'PERIOD'), (None, 'EQUALS'), (None, 'LT'), (None, 'COMMA'), (None, 'DIVIDE'), (None, 'AND'), (None, 'MOD'), (None, 'SEMI'), (None, 'MINUS'), (None, 'GT'), (None, 'COLON'), (None, 'NOT'), (None, 'LNOT')])]} -_lexstateignore = {'ppline': ' \t', 'pppragma': ' \t<>.-{}();+-*/$%@&^~!?:,0123456789', 'INITIAL': ' \t'} -_lexstateerrorf = {'ppline': 't_ppline_error', 'pppragma': 't_pppragma_error', 'INITIAL': 't_error'} diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/setup.py deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/setup.py +++ /dev/null @@ -1,8 +0,0 @@ -# Generated by pypy/tool/import_cffi.py - -from distutils.core import setup -import snip_basic_verify1 - -setup( - packages=['snip_basic_verify1'], - ext_modules=[snip_basic_verify1.ffi.verifier.get_extension()]) diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/snip_basic_verify1/__init__.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/snip_basic_verify1/__init__.py deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/snip_basic_verify1/__init__.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by pypy/tool/import_cffi.py - -from cffi import FFI -import sys - -ffi = FFI() -ffi.cdef(""" // some declarations from the man page - struct passwd { - char *pw_name; - ...; - }; - struct passwd *getpwuid(int uid); -""") -C = ffi.verify(""" // passed to the real C compiler -#include -#include -""", libraries=[], # or a list of libraries to link with - force_generic_engine=hasattr(sys, '_force_generic_engine_')) diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/snip_basic_verify1/__pycache__/_cffi__gd39ab08bx8432a366.c b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/snip_basic_verify1/__pycache__/_cffi__gd39ab08bx8432a366.c deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/snip_basic_verify1/__pycache__/_cffi__gd39ab08bx8432a366.c +++ /dev/null @@ -1,53 +0,0 @@ - -#include -#include -#include -#include -#include /* XXX for ssize_t on some platforms */ - -#ifdef _WIN32 -# include -# define snprintf _snprintf -typedef __int8 int8_t; -typedef __int16 int16_t; -typedef __int32 int32_t; -typedef __int64 int64_t; -typedef unsigned __int8 uint8_t; -typedef unsigned __int16 uint16_t; -typedef unsigned __int32 uint32_t; -typedef unsigned __int64 uint64_t; -typedef SSIZE_T ssize_t; -typedef unsigned char _Bool; -#else -# include -#endif - - // passed to the real C compiler -#include -#include - -struct passwd * _cffi_f_getpwuid(int x0) -{ - return getpwuid(x0); -} - -static void _cffi_check_struct_passwd(struct passwd *p) -{ - /* only to generate compile-time warnings or errors */ - { char * *tmp = &p->pw_name; (void)tmp; } -} -ssize_t _cffi_layout_struct_passwd(ssize_t i) -{ - struct _cffi_aligncheck { char x; struct passwd y; }; - static ssize_t nums[] = { - sizeof(struct passwd), - offsetof(struct _cffi_aligncheck, y), - offsetof(struct passwd, pw_name), - sizeof(((struct passwd *)0)->pw_name), - -1 - }; - return nums[i]; - /* the next line is not executed, but compiled */ - _cffi_check_struct_passwd(0); -} - diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/snip_basic_verify1/__pycache__/_cffi__gd39ab08bx8432a366.pypy-20.so b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/snip_basic_verify1/__pycache__/_cffi__gd39ab08bx8432a366.pypy-20.so deleted file mode 100755 Binary file pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/snip_basic_verify1/__pycache__/_cffi__gd39ab08bx8432a366.pypy-20.so has changed diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/snip_basic_verify1/__pycache__/snip_basic_verify1/__pycache__/_cffi__gd39ab08bx8432a366.o b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/snip_basic_verify1/__pycache__/snip_basic_verify1/__pycache__/_cffi__gd39ab08bx8432a366.o deleted file mode 100644 Binary file pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/snip_basic_verify1/__pycache__/snip_basic_verify1/__pycache__/_cffi__gd39ab08bx8432a366.o has changed diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/yacctab.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/yacctab.py deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/yacctab.py +++ /dev/null @@ -1,280 +0,0 @@ - -# yacctab.py -# This file is automatically generated. Do not edit. -_tabversion = '3.2' - -_lr_method = 'LALR' - -_lr_signature = '\x9er\xf1|P\xb6\xbb\x13\xed\xf52\xa1\xb1\xc3J\x12' - -_lr_action_items = {'VOID':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[6,6,-61,-72,-71,-58,-54,-55,-33,-29,-59,6,-34,-53,-68,-63,-52,6,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,6,-67,6,-70,-74,6,-57,-82,-249,-81,6,-107,-30,6,-97,-96,6,-45,-46,6,-109,6,6,6,6,-88,6,6,-36,6,-47,6,6,-83,-89,-250,6,-110,6,6,-111,-113,-112,6,6,-98,-37,-39,-42,-38,-40,6,-148,-147,-43,-149,-41,-85,-84,-90,6,6,-100,-99,-167,-166,6,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'LBRACKET':([1,2,3,5,6,9,10,13,14,17,18,19,21,23,24,25,27,28,29,32,33,35,37,39,40,42,43,44,45,46,49,50,51,52,54,55,56,58,59,63,64,66,67,68,69,76,77,83,87,89,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,129,138,139,149,151,152,153,154,155,174,178,180,184,185,191,195,216,217,218,223,224,231,235,262,264,265,273,274,277,281,285,286,314,318,319,323,329,350,351,357,359,360,361,362,366,369,371,387,388,389,390,400,401,409,],[-251,-61,-72,-71,-58,-54,-55,-59,-251,-53,-68,-63,-52,-56,-170,61,-66,-251,-69,-73,-108,-64,-60,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-249,-81,-49,61,-97,-96,-116,-114,-26,-25,-48,-51,-109,-251,-251,-233,-243,-247,-244,-241,-231,-232,182,-240,-220,-237,-245,-238,-242,-239,-230,221,-115,-117,-83,-250,-21,-80,-22,-79,-248,-246,-226,-227,-110,-111,221,-113,-112,221,312,221,-98,325,-237,-85,-84,-225,-224,-223,-234,221,221,312,-100,-99,-132,325,-221,-222,325,-146,-140,-142,-144,-135,325,-133,-141,-143,-145,-134,325,-228,-229,]),'WCHAR_CONST':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,96,-45,-219,96,-217,96,-216,96,-215,96,96,-214,-218,96,96,-250,96,-176,-179,-177,-173,-174,-178,-180,96,-182,-183,-175,-181,96,-215,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,-251,-39,-42,-38,96,-40,96,96,-148,-147,-43,-149,96,-41,96,96,96,-215,96,-12,96,96,-11,-167,-166,96,-164,96,96,-150,96,-163,-151,96,96,96,96,-251,96,-215,-251,-131,-162,-165,96,-154,96,-152,96,96,96,-153,96,96,96,-251,96,-158,-157,-155,96,96,96,-159,-156,96,-161,-160,]),'FLOAT_CONST':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,97,-45,-219,97,-217,97,-216,97,-215,97,97,-214,-218,97,97,-250,97,-176,-179,-177,-173,-174,-178,-180,97,-182,-183,-175,-181,97,-215,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,-251,-39,-42,-38,97,-40,97,97,-148,-147,-43,-149,97,-41,97,97,97,-215,97,-12,97,97,-11,-167,-166,97,-164,97,97,-150,97,-163,-151,97,97,97,97,-251,97,-215,-251,-131,-162,-165,97,-154,97,-152,97,97,97,-153,97,97,97,-251,97,-158,-157,-155,97,97,97,-159,-156,97,-161,-160,]),'MINUS':([55,61,75,91,92,93,94,95,96,97,98,99,100,101,102,104,105,106,108,109,110,111,112,113,114,115,116,117,118,119,120,123,124,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,180,182,183,184,186,187,188,189,190,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,262,270,273,274,277,281,282,283,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,349,350,351,352,353,356,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[-249,100,-45,-219,-206,-233,-243,-247,-244,-241,-231,100,-217,-232,-208,-187,100,-216,100,-240,-215,-220,100,100,-237,-245,-214,-238,200,-242,-239,-218,-230,100,100,-250,100,-176,-179,-177,-173,-174,-178,-180,100,-182,-183,-175,-181,-248,100,-212,-215,-246,-226,100,100,-227,100,-206,-211,100,-209,-210,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,-251,-39,-42,-38,100,-40,100,100,-148,-147,-43,-149,100,-41,-237,100,-225,-224,-223,-234,100,100,200,200,200,-192,200,200,200,-191,200,200,-189,-188,200,200,200,200,200,-190,-215,100,-12,100,100,-11,-167,-166,100,-164,100,100,-150,100,-163,-151,100,100,-213,-221,-222,100,100,-207,-251,100,-215,-251,-131,-162,-165,100,-154,100,-152,100,100,100,-153,100,100,100,-251,-228,100,-158,-157,-155,-229,100,100,100,-159,-156,100,-161,-160,]),'RPAREN':([1,2,3,5,6,9,10,13,14,17,18,19,21,23,24,25,27,28,29,32,33,35,37,39,40,42,43,44,45,46,49,50,51,52,53,54,56,58,59,62,63,64,66,67,68,69,76,77,83,87,89,92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,122,124,125,126,127,128,129,130,131,132,138,139,149,151,152,153,154,155,174,176,178,180,183,184,185,187,188,190,191,192,193,194,195,196,216,217,218,219,220,222,223,224,225,231,247,264,265,271,272,273,274,276,277,278,279,280,281,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,306,307,308,309,313,314,315,316,317,318,319,339,349,350,351,355,356,359,360,361,362,365,378,380,383,384,386,387,388,389,401,404,407,409,410,411,414,],[-251,-61,-72,-71,-58,-54,-55,-59,-251,-53,-68,-63,-52,-56,-170,-106,-66,-251,-69,-73,-108,-64,-60,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,83,-82,-81,-49,-107,-251,-97,-96,-116,-114,-26,-25,-48,-51,-109,-251,-251,-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,-185,-242,-239,-171,-230,216,-15,217,-120,-251,-16,-118,-124,-115,-117,-83,-250,-21,-80,-22,-79,-248,-212,-246,-226,277,-227,-110,-206,-211,-209,-111,281,283,-168,-251,-210,-113,-112,-251,-123,-2,-122,-139,-137,-1,-98,-14,-85,-84,-172,349,-225,-224,-235,-223,351,353,354,-234,-136,-251,-137,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-19,-20,359,360,-251,-138,-125,-119,-121,-100,-99,-13,-213,-221,-222,-169,-207,-146,-140,-142,-144,389,395,397,399,-236,-186,-141,-143,-145,-228,-251,412,-229,-251,415,418,]),'LONG':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[19,19,-61,-72,-71,-58,-54,-55,-33,-29,-59,19,-34,-53,-68,-63,-52,19,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,19,-67,19,-70,-74,19,-57,-82,-249,-81,19,-107,-30,19,-97,-96,19,-45,-46,19,-109,19,19,19,19,-88,19,19,-36,19,-47,19,19,-83,-89,-250,19,-110,19,19,-111,-113,-112,19,19,-98,-37,-39,-42,-38,-40,19,-148,-147,-43,-149,-41,-85,-84,-90,19,19,-100,-99,-167,-166,19,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'PLUS':([55,61,75,91,92,93,94,95,96,97,98,99,100,101,102,104,105,106,108,109,110,111,112,113,114,115,116,117,118,119,120,123,124,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,180,182,183,184,186,187,188,189,190,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,262,270,273,274,277,281,282,283,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,349,350,351,352,353,356,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[-249,106,-45,-219,-206,-233,-243,-247,-244,-241,-231,106,-217,-232,-208,-187,106,-216,106,-240,-215,-220,106,106,-237,-245,-214,-238,204,-242,-239,-218,-230,106,106,-250,106,-176,-179,-177,-173,-174,-178,-180,106,-182,-183,-175,-181,-248,106,-212,-215,-246,-226,106,106,-227,106,-206,-211,106,-209,-210,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,-251,-39,-42,-38,106,-40,106,106,-148,-147,-43,-149,106,-41,-237,106,-225,-224,-223,-234,106,106,204,204,204,-192,204,204,204,-191,204,204,-189,-188,204,204,204,204,204,-190,-215,106,-12,106,106,-11,-167,-166,106,-164,106,106,-150,106,-163,-151,106,106,-213,-221,-222,106,106,-207,-251,106,-215,-251,-131,-162,-165,106,-154,106,-152,106,106,106,-153,106,106,106,-251,-228,106,-158,-157,-155,-229,106,106,106,-159,-156,106,-161,-160,]),'ELLIPSIS':([227,],[316,]),'GT':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,205,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,205,-194,-192,-196,205,-195,-191,-198,205,-189,-188,-197,205,205,205,205,-190,-213,-221,-222,-207,-228,-229,]),'GOTO':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,240,-250,-39,-42,-38,-40,240,-148,-147,-43,-149,240,-41,-167,-166,-164,240,-150,-163,-151,240,-162,-165,-154,240,-152,240,-153,240,240,-158,-157,-155,240,240,-159,-156,240,-161,-160,]),'ENUM':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[26,26,-61,-72,-71,-58,-54,-55,-33,-29,-59,26,-34,-53,-68,-63,-52,26,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,26,-67,26,-70,-74,26,-57,-82,-249,-81,26,-107,-30,26,-97,-96,26,-45,-46,26,-109,26,26,26,26,-88,26,26,-36,26,-47,26,26,-83,-89,-250,26,-110,26,26,-111,-113,-112,26,26,-98,-37,-39,-42,-38,-40,26,-148,-147,-43,-149,-41,-85,-84,-90,26,26,-100,-99,-167,-166,26,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'PERIOD':([55,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,178,180,184,235,262,273,274,277,281,323,329,350,351,357,366,369,371,390,400,401,409,],[-249,-233,-243,-247,-244,-241,-231,-232,181,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-246,-226,-227,324,-237,-225,-224,-223,-234,-132,324,-221,-222,324,-135,324,-133,-134,324,-228,-229,]),'GE':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,209,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,209,-194,-192,-196,209,-195,-191,-198,209,-189,-188,-197,209,209,209,209,-190,-213,-221,-222,-207,-228,-229,]),'INT_CONST_DEC':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,117,-45,-219,117,-217,117,-216,117,-215,117,117,-214,-218,117,117,-250,117,-176,-179,-177,-173,-174,-178,-180,117,-182,-183,-175,-181,117,-215,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,-251,-39,-42,-38,117,-40,117,117,-148,-147,-43,-149,117,-41,117,117,117,-215,117,-12,117,117,-11,-167,-166,117,-164,117,117,-150,117,-163,-151,117,117,117,117,-251,117,-215,-251,-131,-162,-165,117,-154,117,-152,117,117,117,-153,117,117,117,-251,117,-158,-157,-155,117,117,117,-159,-156,117,-161,-160,]),'ARROW':([93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,178,180,184,262,273,274,277,281,350,351,401,409,],[-233,-243,-247,-244,-241,-231,-232,179,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-246,-226,-227,-237,-225,-224,-223,-234,-221,-222,-228,-229,]),'HEX_FLOAT_CONST':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,119,-45,-219,119,-217,119,-216,119,-215,119,119,-214,-218,119,119,-250,119,-176,-179,-177,-173,-174,-178,-180,119,-182,-183,-175,-181,119,-215,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,-251,-39,-42,-38,119,-40,119,119,-148,-147,-43,-149,119,-41,119,119,119,-215,119,-12,119,119,-11,-167,-166,119,-164,119,119,-150,119,-163,-151,119,119,119,119,-251,119,-215,-251,-131,-162,-165,119,-154,119,-152,119,119,119,-153,119,119,119,-251,119,-158,-157,-155,119,119,119,-159,-156,119,-161,-160,]),'DOUBLE':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[40,40,-61,-72,-71,-58,-54,-55,-33,-29,-59,40,-34,-53,-68,-63,-52,40,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,40,-67,40,-70,-74,40,-57,-82,-249,-81,40,-107,-30,40,-97,-96,40,-45,-46,40,-109,40,40,40,40,-88,40,40,-36,40,-47,40,40,-83,-89,-250,40,-110,40,40,-111,-113,-112,40,40,-98,-37,-39,-42,-38,-40,40,-148,-147,-43,-149,-41,-85,-84,-90,40,40,-100,-99,-167,-166,40,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'MINUSEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[163,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'INT_CONST_OCT':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,120,-45,-219,120,-217,120,-216,120,-215,120,120,-214,-218,120,120,-250,120,-176,-179,-177,-173,-174,-178,-180,120,-182,-183,-175,-181,120,-215,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,-251,-39,-42,-38,120,-40,120,120,-148,-147,-43,-149,120,-41,120,120,120,-215,120,-12,120,120,-11,-167,-166,120,-164,120,120,-150,120,-163,-151,120,120,120,120,-251,120,-215,-251,-131,-162,-165,120,-154,120,-152,120,120,120,-153,120,120,120,-251,120,-158,-157,-155,120,120,120,-159,-156,120,-161,-160,]),'TIMESEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[172,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'OR':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,214,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,214,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,214,-199,-201,-202,-190,-213,-221,-222,-207,-228,-229,]),'SHORT':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[2,2,-61,-72,-71,-58,-54,-55,-33,-29,-59,2,-34,-53,-68,-63,-52,2,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,2,-67,2,-70,-74,2,-57,-82,-249,-81,2,-107,-30,2,-97,-96,2,-45,-46,2,-109,2,2,2,2,-88,2,2,-36,2,-47,2,2,-83,-89,-250,2,-110,2,2,-111,-113,-112,2,2,-98,-37,-39,-42,-38,-40,2,-148,-147,-43,-149,-41,-85,-84,-90,2,2,-100,-99,-167,-166,2,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'RETURN':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,243,-250,-39,-42,-38,-40,243,-148,-147,-43,-149,243,-41,-167,-166,-164,243,-150,-163,-151,243,-162,-165,-154,243,-152,243,-153,243,243,-158,-157,-155,243,243,-159,-156,243,-161,-160,]),'RSHIFTEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[173,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'RESTRICT':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,28,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,66,68,73,75,80,82,83,84,85,86,87,88,89,112,139,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[32,32,-61,-72,-71,-58,-54,-55,-33,-29,-59,32,-34,-53,-68,-63,-52,32,-56,-170,-106,-66,32,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,32,-67,32,-70,-74,32,-57,-82,-249,-81,32,-107,-30,32,-97,-96,-116,32,32,-45,-46,32,-109,32,32,32,32,-88,32,32,-117,-36,32,-47,32,32,-83,-89,-250,32,-110,32,32,-111,-113,-112,32,32,-98,-37,-39,-42,-38,-40,32,-148,-147,-43,-149,-41,-85,-84,-90,32,32,-100,-99,-167,-166,32,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'STATIC':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[9,9,-61,-72,-71,-58,-54,-55,-33,-29,-59,9,-34,-53,-68,-63,-52,9,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,9,-67,9,-70,-74,9,-57,-82,-249,-81,-107,-30,9,-97,-96,9,-45,-46,9,-109,-36,9,-47,-83,-250,-110,-111,-113,-112,9,9,-98,-37,-39,-42,-38,-40,9,-148,-147,-43,-149,-41,-85,-84,9,9,-100,-99,-167,-166,9,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'SIZEOF':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,99,-45,-219,99,-217,99,-216,99,-215,99,99,-214,-218,99,99,-250,99,-176,-179,-177,-173,-174,-178,-180,99,-182,-183,-175,-181,99,-215,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,-251,-39,-42,-38,99,-40,99,99,-148,-147,-43,-149,99,-41,99,99,99,-215,99,-12,99,99,-11,-167,-166,99,-164,99,99,-150,99,-163,-151,99,99,99,99,-251,99,-215,-251,-131,-162,-165,99,-154,99,-152,99,99,99,-153,99,99,99,-251,99,-158,-157,-155,99,99,99,-159,-156,99,-161,-160,]),'UNSIGNED':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[18,18,-61,-72,-71,-58,-54,-55,-33,-29,-59,18,-34,-53,-68,-63,-52,18,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,18,-67,18,-70,-74,18,-57,-82,-249,-81,18,-107,-30,18,-97,-96,18,-45,-46,18,-109,18,18,18,18,-88,18,18,-36,18,-47,18,18,-83,-89,-250,18,-110,18,18,-111,-113,-112,18,18,-98,-37,-39,-42,-38,-40,18,-148,-147,-43,-149,-41,-85,-84,-90,18,18,-100,-99,-167,-166,18,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'UNION':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[20,20,-61,-72,-71,-58,-54,-55,-33,-29,-59,20,-34,-53,-68,-63,-52,20,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,20,-67,20,-70,-74,20,-57,-82,-249,-81,20,-107,-30,20,-97,-96,20,-45,-46,20,-109,20,20,20,20,-88,20,20,-36,20,-47,20,20,-83,-89,-250,20,-110,20,20,-111,-113,-112,20,20,-98,-37,-39,-42,-38,-40,20,-148,-147,-43,-149,-41,-85,-84,-90,20,20,-100,-99,-167,-166,20,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'COLON':([2,3,5,6,13,18,19,24,25,27,29,32,33,35,37,39,40,43,45,46,54,56,59,63,64,83,87,89,90,92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,122,124,149,151,152,153,154,155,161,174,176,178,180,184,185,187,188,190,191,194,196,216,217,231,248,262,264,265,267,268,271,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,318,319,338,349,350,351,355,356,386,401,409,],[-61,-72,-71,-58,-59,-68,-63,-170,-106,-66,-69,-73,-108,-64,-60,-62,-65,-67,-70,-74,-82,-81,-107,-97,-96,-109,-251,-251,156,-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,-185,-242,-239,-171,-230,-83,-250,-21,-80,-22,-79,270,-248,-212,-246,-226,-227,-110,-206,-211,-209,-111,-168,-210,-113,-112,-98,336,345,-85,-84,-184,156,-172,-225,-224,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,358,-202,-190,-100,-99,379,-213,-221,-222,-169,-207,-186,-228,-229,]),'$end':([0,8,11,12,15,22,31,36,38,47,60,75,144,151,237,344,],[-251,0,-33,-29,-34,-27,-32,-31,-35,-28,-30,-45,-36,-250,-37,-151,]),'WSTRING_LITERAL':([55,61,75,91,93,95,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,95,-45,-219,174,-247,95,-217,95,-216,95,-215,95,95,-214,-218,95,95,-250,95,-176,-179,-177,-173,-174,-178,-180,95,-182,-183,-175,-181,-248,95,-215,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,-251,-39,-42,-38,95,-40,95,95,-148,-147,-43,-149,95,-41,95,95,95,-215,95,-12,95,95,-11,-167,-166,95,-164,95,95,-150,95,-163,-151,95,95,95,95,-251,95,-215,-251,-131,-162,-165,95,-154,95,-152,95,95,95,-153,95,95,95,-251,95,-158,-157,-155,95,95,95,-159,-156,95,-161,-160,]),'DIVIDE':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,207,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,207,207,207,207,207,207,207,207,207,207,-189,-188,207,207,207,207,207,-190,-213,-221,-222,-207,-228,-229,]),'FOR':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,245,-250,-39,-42,-38,-40,245,-148,-147,-43,-149,245,-41,-167,-166,-164,245,-150,-163,-151,245,-162,-165,-154,245,-152,245,-153,245,245,-158,-157,-155,245,245,-159,-156,245,-161,-160,]),'PLUSPLUS':([55,61,75,91,93,94,95,96,97,98,99,100,101,102,105,106,108,109,110,111,112,113,114,115,116,117,119,120,123,124,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,177,178,180,182,183,184,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,262,270,273,274,277,281,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,350,351,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[-249,108,-45,-219,-233,-243,-247,-244,-241,-231,108,-217,-232,180,108,-216,108,-240,-215,-220,108,108,-237,-245,-214,-238,-242,-239,-218,-230,108,108,-250,108,-176,-179,-177,-173,-174,-178,-180,108,-182,-183,-175,-181,-248,108,-215,-246,-226,108,108,-227,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,-251,-39,-42,-38,108,-40,108,108,-148,-147,-43,-149,108,-41,-237,108,-225,-224,-223,-234,108,108,-215,108,-12,108,108,-11,-167,-166,108,-164,108,108,-150,108,-163,-151,108,108,-221,-222,108,108,-251,108,-215,-251,-131,-162,-165,108,-154,108,-152,108,108,108,-153,108,108,108,-251,-228,108,-158,-157,-155,-229,108,108,108,-159,-156,108,-161,-160,]),'EQUALS':([25,33,59,73,83,92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,137,143,151,174,176,178,180,184,185,187,188,190,191,196,216,217,262,273,274,277,281,323,329,349,350,351,356,366,371,390,401,409,],[-106,-108,-107,141,-109,165,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,232,141,-250,-248,-212,-246,-226,-227,-110,-206,-211,-209,-111,-210,-113,-112,-237,-225,-224,-223,-234,-132,372,-213,-221,-222,-207,-135,-133,-134,-228,-229,]),'ELSE':([151,238,239,242,244,255,260,331,332,335,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[-250,-39,-42,-38,-40,-43,-41,-167,-166,-164,-163,-151,-162,-165,-154,-152,-153,-158,-157,413,-159,-156,-161,-160,]),'ANDEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[170,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'EQ':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,211,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,211,-194,-192,-196,-200,-195,-191,-198,211,-189,-188,-197,211,-199,211,211,-190,-213,-221,-222,-207,-228,-229,]),'AND':([55,61,75,91,92,93,94,95,96,97,98,99,100,101,102,104,105,106,108,109,110,111,112,113,114,115,116,117,118,119,120,123,124,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,180,182,183,184,186,187,188,189,190,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,262,270,273,274,277,281,282,283,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,349,350,351,352,353,356,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[-249,116,-45,-219,-206,-233,-243,-247,-244,-241,-231,116,-217,-232,-208,-187,116,-216,116,-240,-215,-220,116,116,-237,-245,-214,-238,212,-242,-239,-218,-230,116,116,-250,116,-176,-179,-177,-173,-174,-178,-180,116,-182,-183,-175,-181,-248,116,-212,-215,-246,-226,116,116,-227,116,-206,-211,116,-209,-210,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,-251,-39,-42,-38,116,-40,116,116,-148,-147,-43,-149,116,-41,-237,116,-225,-224,-223,-234,116,116,-193,212,-194,-192,-196,-200,-195,-191,-198,212,-189,-188,-197,212,-199,-201,212,-190,-215,116,-12,116,116,-11,-167,-166,116,-164,116,116,-150,116,-163,-151,116,116,-213,-221,-222,116,116,-207,-251,116,-215,-251,-131,-162,-165,116,-154,116,-152,116,116,116,-153,116,116,116,-251,-228,116,-158,-157,-155,-229,116,116,116,-159,-156,116,-161,-160,]),'TYPEID':([0,1,2,3,5,6,7,9,10,11,12,13,14,15,17,18,19,20,21,22,23,24,25,26,27,29,31,32,33,34,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[24,24,-61,-72,-71,-58,54,-54,-55,-33,-29,-59,24,-34,-53,-68,-63,-87,-52,24,-56,-170,-106,63,-66,-69,-32,-73,-108,-86,-64,-31,-60,-35,-62,-65,24,-67,24,-70,-74,24,-57,-82,-249,-81,24,-107,-30,24,-97,-96,24,-45,-46,24,-109,24,24,24,24,-88,24,24,-36,24,-47,24,24,-83,-89,-250,24,-110,24,24,-111,-113,-112,24,24,-98,-37,-39,-42,-38,-40,24,-148,-147,-43,-149,-41,-85,-84,-90,24,24,-100,-99,-167,-166,24,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'LBRACE':([7,20,25,26,33,34,48,54,55,56,59,63,64,73,75,78,80,81,82,83,141,142,145,146,151,185,191,216,217,235,238,239,242,244,251,253,254,255,257,259,260,283,322,326,327,331,332,335,336,340,342,344,345,349,353,354,357,369,372,373,374,377,379,382,391,395,396,397,399,400,405,406,408,413,415,416,417,418,419,420,],[55,-87,-106,55,-108,-86,-251,55,-249,55,-107,55,55,-251,-45,-7,-46,55,-8,-109,55,55,55,-47,-250,-110,-111,-113,-112,-251,-39,-42,-38,-40,55,-148,-147,-43,-149,55,-41,55,-12,55,-11,-167,-166,-164,55,-150,-163,-151,55,55,55,55,-251,-251,-131,-162,-165,-154,55,-152,55,55,-153,55,55,-251,-158,-157,-155,55,55,-159,-156,55,-161,-160,]),'PPHASH':([0,11,12,15,22,31,36,38,60,75,144,151,237,344,],[38,-33,-29,-34,38,-32,-31,-35,-30,-45,-36,-250,-37,-151,]),'INT':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[39,39,-61,-72,-71,-58,-54,-55,-33,-29,-59,39,-34,-53,-68,-63,-52,39,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,39,-67,39,-70,-74,39,-57,-82,-249,-81,39,-107,-30,39,-97,-96,39,-45,-46,39,-109,39,39,39,39,-88,39,39,-36,39,-47,39,39,-83,-89,-250,39,-110,39,39,-111,-113,-112,39,39,-98,-37,-39,-42,-38,-40,39,-148,-147,-43,-149,-41,-85,-84,-90,39,39,-100,-99,-167,-166,39,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'SIGNED':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[43,43,-61,-72,-71,-58,-54,-55,-33,-29,-59,43,-34,-53,-68,-63,-52,43,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,43,-67,43,-70,-74,43,-57,-82,-249,-81,43,-107,-30,43,-97,-96,43,-45,-46,43,-109,43,43,43,43,-88,43,43,-36,43,-47,43,43,-83,-89,-250,43,-110,43,43,-111,-113,-112,43,43,-98,-37,-39,-42,-38,-40,43,-148,-147,-43,-149,-41,-85,-84,-90,43,43,-100,-99,-167,-166,43,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'CONTINUE':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,246,-250,-39,-42,-38,-40,246,-148,-147,-43,-149,246,-41,-167,-166,-164,246,-150,-163,-151,246,-162,-165,-154,246,-152,246,-153,246,246,-158,-157,-155,246,246,-159,-156,246,-161,-160,]),'NOT':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,123,-45,-219,123,-217,123,-216,123,-215,123,123,-214,-218,123,123,-250,123,-176,-179,-177,-173,-174,-178,-180,123,-182,-183,-175,-181,123,-215,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,-251,-39,-42,-38,123,-40,123,123,-148,-147,-43,-149,123,-41,123,123,123,-215,123,-12,123,123,-11,-167,-166,123,-164,123,123,-150,123,-163,-151,123,123,123,123,-251,123,-215,-251,-131,-162,-165,123,-154,123,-152,123,123,123,-153,123,123,123,-251,123,-158,-157,-155,123,123,123,-159,-156,123,-161,-160,]),'OREQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[171,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'MOD':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,215,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,215,215,215,215,215,215,215,215,215,215,-189,-188,215,215,215,215,215,-190,-213,-221,-222,-207,-228,-229,]),'RSHIFT':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,197,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,197,-194,-192,197,197,197,-191,197,197,-189,-188,197,197,197,197,197,-190,-213,-221,-222,-207,-228,-229,]),'DEFAULT':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,248,-250,-39,-42,-38,-40,248,-148,-147,-43,-149,248,-41,-167,-166,-164,248,-150,-163,-151,248,-162,-165,-154,248,-152,248,-153,248,248,-158,-157,-155,248,248,-159,-156,248,-161,-160,]),'CHAR':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[37,37,-61,-72,-71,-58,-54,-55,-33,-29,-59,37,-34,-53,-68,-63,-52,37,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,37,-67,37,-70,-74,37,-57,-82,-249,-81,37,-107,-30,37,-97,-96,37,-45,-46,37,-109,37,37,37,37,-88,37,37,-36,37,-47,37,37,-83,-89,-250,37,-110,37,37,-111,-113,-112,37,37,-98,-37,-39,-42,-38,-40,37,-148,-147,-43,-149,-41,-85,-84,-90,37,37,-100,-99,-167,-166,37,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'WHILE':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,343,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,249,-250,-39,-42,-38,-40,249,-148,-147,-43,-149,249,-41,-167,-166,-164,249,-150,-163,381,-151,249,-162,-165,-154,249,-152,249,-153,249,249,-158,-157,-155,249,249,-159,-156,249,-161,-160,]),'DIVEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[162,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'EXTERN':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[10,10,-61,-72,-71,-58,-54,-55,-33,-29,-59,10,-34,-53,-68,-63,-52,10,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,10,-67,10,-70,-74,10,-57,-82,-249,-81,-107,-30,10,-97,-96,10,-45,-46,10,-109,-36,10,-47,-83,-250,-110,-111,-113,-112,10,10,-98,-37,-39,-42,-38,-40,10,-148,-147,-43,-149,-41,-85,-84,10,10,-100,-99,-167,-166,10,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'CASE':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,250,-250,-39,-42,-38,-40,250,-148,-147,-43,-149,250,-41,-167,-166,-164,250,-150,-163,-151,250,-162,-165,-154,250,-152,250,-153,250,250,-158,-157,-155,250,250,-159,-156,250,-161,-160,]),'LAND':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,210,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,210,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-213,-221,-222,-207,-228,-229,]),'REGISTER':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[17,17,-61,-72,-71,-58,-54,-55,-33,-29,-59,17,-34,-53,-68,-63,-52,17,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,17,-67,17,-70,-74,17,-57,-82,-249,-81,-107,-30,17,-97,-96,17,-45,-46,17,-109,-36,17,-47,-83,-250,-110,-111,-113,-112,17,17,-98,-37,-39,-42,-38,-40,17,-148,-147,-43,-149,-41,-85,-84,17,17,-100,-99,-167,-166,17,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'MODEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[164,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'NE':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,202,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,202,-194,-192,-196,-200,-195,-191,-198,202,-189,-188,-197,202,-199,202,202,-190,-213,-221,-222,-207,-228,-229,]),'SWITCH':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,252,-250,-39,-42,-38,-40,252,-148,-147,-43,-149,252,-41,-167,-166,-164,252,-150,-163,-151,252,-162,-165,-154,252,-152,252,-153,252,252,-158,-157,-155,252,252,-159,-156,252,-161,-160,]),'INT_CONST_HEX':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,109,-45,-219,109,-217,109,-216,109,-215,109,109,-214,-218,109,109,-250,109,-176,-179,-177,-173,-174,-178,-180,109,-182,-183,-175,-181,109,-215,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,-251,-39,-42,-38,109,-40,109,109,-148,-147,-43,-149,109,-41,109,109,109,-215,109,-12,109,109,-11,-167,-166,109,-164,109,109,-150,109,-163,-151,109,109,109,109,-251,109,-215,-251,-131,-162,-165,109,-154,109,-152,109,109,109,-153,109,109,109,-251,109,-158,-157,-155,109,109,109,-159,-156,109,-161,-160,]),'_COMPLEX':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[27,27,-61,-72,-71,-58,-54,-55,-33,-29,-59,27,-34,-53,-68,-63,-52,27,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,27,-67,27,-70,-74,27,-57,-82,-249,-81,27,-107,-30,27,-97,-96,27,-45,-46,27,-109,27,27,27,27,-88,27,27,-36,27,-47,27,27,-83,-89,-250,27,-110,27,27,-111,-113,-112,27,27,-98,-37,-39,-42,-38,-40,27,-148,-147,-43,-149,-41,-85,-84,-90,27,27,-100,-99,-167,-166,27,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'PLUSEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[167,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'STRUCT':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[34,34,-61,-72,-71,-58,-54,-55,-33,-29,-59,34,-34,-53,-68,-63,-52,34,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,34,-67,34,-70,-74,34,-57,-82,-249,-81,34,-107,-30,34,-97,-96,34,-45,-46,34,-109,34,34,34,34,-88,34,34,-36,34,-47,34,34,-83,-89,-250,34,-110,34,34,-111,-113,-112,34,34,-98,-37,-39,-42,-38,-40,34,-148,-147,-43,-149,-41,-85,-84,-90,34,34,-100,-99,-167,-166,34,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'CONDOP':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,213,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-213,-221,-222,-207,-228,-229,]),'BREAK':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,256,-250,-39,-42,-38,-40,256,-148,-147,-43,-149,256,-41,-167,-166,-164,256,-150,-163,-151,256,-162,-165,-154,256,-152,256,-153,256,256,-158,-157,-155,256,256,-159,-156,256,-161,-160,]),'VOLATILE':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,28,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,66,68,73,75,80,82,83,84,85,86,87,88,89,112,139,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[46,46,-61,-72,-71,-58,-54,-55,-33,-29,-59,46,-34,-53,-68,-63,-52,46,-56,-170,-106,-66,46,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,46,-67,46,-70,-74,46,-57,-82,-249,-81,46,-107,-30,46,-97,-96,-116,46,46,-45,-46,46,-109,46,46,46,46,-88,46,46,-117,-36,46,-47,46,46,-83,-89,-250,46,-110,46,46,-111,-113,-112,46,46,-98,-37,-39,-42,-38,-40,46,-148,-147,-43,-149,-41,-85,-84,-90,46,46,-100,-99,-167,-166,46,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'INLINE':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[49,49,-61,-72,-71,-58,-54,-55,-33,-29,-59,49,-34,-53,-68,-63,-52,49,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,49,-67,49,-70,-74,49,-57,-82,-249,-81,-107,-30,49,-97,-96,49,-45,-46,49,-109,-36,49,-47,-83,-250,-110,-111,-113,-112,49,49,-98,-37,-39,-42,-38,-40,49,-148,-147,-43,-149,-41,-85,-84,49,49,-100,-99,-167,-166,49,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'DO':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,259,-250,-39,-42,-38,-40,259,-148,-147,-43,-149,259,-41,-167,-166,-164,259,-150,-163,-151,259,-162,-165,-154,259,-152,259,-153,259,259,-158,-157,-155,259,259,-159,-156,259,-161,-160,]),'LNOT':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,91,-45,-219,91,-217,91,-216,91,-215,91,91,-214,-218,91,91,-250,91,-176,-179,-177,-173,-174,-178,-180,91,-182,-183,-175,-181,91,-215,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,-251,-39,-42,-38,91,-40,91,91,-148,-147,-43,-149,91,-41,91,91,91,-215,91,-12,91,91,-11,-167,-166,91,-164,91,91,-150,91,-163,-151,91,91,91,91,-251,91,-215,-251,-131,-162,-165,91,-154,91,-152,91,91,91,-153,91,91,91,-251,91,-158,-157,-155,91,91,91,-159,-156,91,-161,-160,]),'CONST':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,28,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,66,68,73,75,80,82,83,84,85,86,87,88,89,112,139,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[3,3,-61,-72,-71,-58,-54,-55,-33,-29,-59,3,-34,-53,-68,-63,-52,3,-56,-170,-106,-66,3,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,3,-67,3,-70,-74,3,-57,-82,-249,-81,3,-107,-30,3,-97,-96,-116,3,3,-45,-46,3,-109,3,3,3,3,-88,3,3,-117,-36,3,-47,3,3,-83,-89,-250,3,-110,3,3,-111,-113,-112,3,3,-98,-37,-39,-42,-38,-40,3,-148,-147,-43,-149,-41,-85,-84,-90,3,3,-100,-99,-167,-166,3,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'LOR':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,198,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-213,-221,-222,-207,-228,-229,]),'CHAR_CONST':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,94,-45,-219,94,-217,94,-216,94,-215,94,94,-214,-218,94,94,-250,94,-176,-179,-177,-173,-174,-178,-180,94,-182,-183,-175,-181,94,-215,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,-251,-39,-42,-38,94,-40,94,94,-148,-147,-43,-149,94,-41,94,94,94,-215,94,-12,94,94,-11,-167,-166,94,-164,94,94,-150,94,-163,-151,94,94,94,94,-251,94,-215,-251,-131,-162,-165,94,-154,94,-152,94,94,94,-153,94,94,94,-251,94,-158,-157,-155,94,94,94,-159,-156,94,-161,-160,]),'LSHIFT':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,199,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,199,-194,-192,199,199,199,-191,199,199,-189,-188,199,199,199,199,199,-190,-213,-221,-222,-207,-228,-229,]),'RBRACE':([55,75,86,88,92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,122,124,135,136,137,145,147,148,150,151,174,176,178,180,184,187,188,190,196,228,229,230,236,238,239,242,244,251,253,254,255,257,258,260,261,267,269,271,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,320,321,328,331,332,335,340,342,344,349,350,351,356,368,369,370,373,374,377,382,385,386,392,396,400,401,402,405,406,408,409,416,417,419,420,],[-249,-45,151,-88,-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,-185,-242,-239,-171,-230,-101,151,-104,-251,151,151,-89,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,151,151,-102,-126,-39,-42,-38,-40,-6,-148,-147,-43,-149,-5,-41,151,-184,-90,-172,-225,-224,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-103,-105,151,-167,-166,-164,-150,-163,-151,-213,-221,-222,-207,-129,151,-127,-162,-165,-154,-152,151,-186,-128,-153,151,-228,-130,-158,-157,-155,-229,-159,-156,-161,-160,]),'_BOOL':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[13,13,-61,-72,-71,-58,-54,-55,-33,-29,-59,13,-34,-53,-68,-63,-52,13,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,13,-67,13,-70,-74,13,-57,-82,-249,-81,13,-107,-30,13,-97,-96,13,-45,-46,13,-109,13,13,13,13,-88,13,13,-36,13,-47,13,13,-83,-89,-250,13,-110,13,13,-111,-113,-112,13,13,-98,-37,-39,-42,-38,-40,13,-148,-147,-43,-149,-41,-85,-84,-90,13,13,-100,-99,-167,-166,13,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'LE':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,201,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,201,-194,-192,-196,201,-195,-191,-198,201,-189,-188,-197,201,201,201,201,-190,-213,-221,-222,-207,-228,-229,]),'SEMI':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,30,31,32,33,35,36,37,38,39,40,41,42,43,44,45,46,49,50,51,52,54,55,56,58,59,60,63,64,70,71,72,73,74,75,76,77,79,83,87,89,90,92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,122,124,143,144,145,149,151,152,153,154,155,157,158,159,160,161,174,176,178,180,184,185,187,188,190,191,194,196,216,217,231,233,234,236,237,238,239,241,242,243,244,246,247,251,253,254,255,256,257,258,259,260,262,264,265,266,267,271,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,318,319,330,331,332,333,334,335,336,339,340,342,344,345,347,348,349,350,351,355,356,370,373,374,375,376,377,379,382,386,392,393,394,395,396,397,399,401,403,405,406,408,409,412,413,415,416,417,418,419,420,],[15,-251,-61,-72,-71,-58,-54,-55,-33,-29,-59,-251,-34,-53,-68,-63,-52,15,-56,-170,-106,-66,-69,-251,-32,-73,-108,-64,-31,-60,-35,-62,-65,75,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-249,-81,-49,-107,-30,-97,-96,-18,-44,-17,-77,-75,-45,-48,-51,-251,-109,-251,-251,-251,-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,-185,-242,-239,-171,-230,-77,-36,-251,-83,-250,-21,-80,-22,-79,-24,269,-91,-23,-93,-248,-212,-246,-226,-227,-110,-206,-211,-209,-111,-168,-210,-113,-112,-98,-76,-78,-126,-37,-39,-42,331,-38,332,-40,335,-14,-251,-148,-147,-43,342,-149,-13,-251,-41,-237,-85,-84,-95,-184,-172,-225,-224,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-100,-99,373,-167,-166,374,-251,-164,-251,-13,-150,-163,-151,-251,-92,-94,-213,-221,-222,-169,-207,-127,-162,-165,393,-251,-154,-251,-152,-186,-128,-251,404,-251,-153,-251,-251,-228,410,-158,-157,-155,-229,416,-251,-251,-159,-156,-251,-161,-160,]),'LT':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,203,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,203,-194,-192,-196,203,-195,-191,-198,203,-189,-188,-197,203,203,203,203,-190,-213,-221,-222,-207,-228,-229,]),'COMMA':([1,2,3,5,6,9,10,13,14,17,18,19,21,23,24,25,27,28,29,32,33,35,37,39,40,42,43,44,45,46,49,50,51,52,54,56,58,59,63,64,66,67,68,69,70,73,74,76,77,83,92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,122,124,128,129,130,131,132,135,136,137,138,139,143,149,151,157,159,161,174,176,178,180,184,185,187,188,190,191,192,194,196,216,217,219,220,222,223,224,225,228,229,230,231,233,234,236,247,262,264,265,266,267,271,273,274,275,276,277,278,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,314,315,317,318,319,320,321,328,333,347,348,349,350,351,355,356,359,360,361,362,368,370,378,380,383,384,385,386,387,388,389,392,401,402,407,409,],[-251,-61,-72,-71,-58,-54,-55,-59,-251,-53,-68,-63,-52,-56,-170,-106,-66,-251,-69,-73,-108,-64,-60,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-81,-49,-107,-97,-96,-116,-114,-26,-25,140,-77,-75,-48,-51,-109,-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,-185,-242,-239,-171,-230,-120,-251,226,227,-124,-101,230,-104,-115,-117,-77,-83,-250,268,-91,-93,-248,-212,-246,-226,-227,-110,-206,-211,-209,-111,282,-168,-210,-113,-112,-123,-2,-122,-139,-137,-1,230,230,-102,-98,-76,-78,-126,282,-237,-85,-84,-95,-184,-172,-225,-224,282,-235,-223,352,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,282,-202,-190,-138,-125,-121,-100,-99,-103,-105,369,282,-92,-94,-213,-221,-222,-169,-207,-146,-140,-142,-144,-129,-127,282,282,282,-236,400,-186,-141,-143,-145,-128,-228,-130,282,-229,]),'TYPEDEF':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[23,23,-61,-72,-71,-58,-54,-55,-33,-29,-59,23,-34,-53,-68,-63,-52,23,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,23,-67,23,-70,-74,23,-57,-82,-249,-81,-107,-30,23,-97,-96,23,-45,-46,23,-109,-36,23,-47,-83,-250,-110,-111,-113,-112,23,23,-98,-37,-39,-42,-38,-40,23,-148,-147,-43,-149,-41,-85,-84,23,23,-100,-99,-167,-166,23,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'XOR':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,206,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,206,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,206,-199,-201,206,-190,-213,-221,-222,-207,-228,-229,]),'AUTO':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[21,21,-61,-72,-71,-58,-54,-55,-33,-29,-59,21,-34,-53,-68,-63,-52,21,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,21,-67,21,-70,-74,21,-57,-82,-249,-81,-107,-30,21,-97,-96,21,-45,-46,21,-109,-36,21,-47,-83,-250,-110,-111,-113,-112,21,21,-98,-37,-39,-42,-38,-40,21,-148,-147,-43,-149,-41,-85,-84,21,21,-100,-99,-167,-166,21,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'TIMES':([0,1,2,3,4,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,27,28,29,30,31,32,35,36,37,38,39,40,42,43,44,45,46,49,50,51,52,54,55,56,58,60,61,63,64,66,67,68,69,75,76,77,79,87,89,90,91,92,93,94,95,96,97,98,99,100,101,102,104,105,106,108,109,110,111,112,113,114,115,116,117,118,119,120,123,124,129,139,140,141,144,145,149,151,152,153,154,155,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,180,182,183,184,186,187,188,189,190,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,218,221,231,232,235,237,238,239,242,243,244,250,251,253,254,255,257,259,260,262,264,265,268,270,273,274,277,281,282,283,285,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,311,312,318,319,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,349,350,351,352,353,356,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[28,-251,-61,-72,28,-71,-58,-54,-55,-33,-29,-59,-251,-34,-53,-68,-63,-52,28,-56,-170,-66,-251,-69,28,-32,-73,-64,-31,-60,-35,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-249,-81,-49,-30,110,-97,-96,-116,28,-26,-25,-45,-48,-51,28,-251,-251,28,-219,-206,-233,-243,-247,-244,-241,-231,177,-217,-232,-208,-187,177,-216,177,-240,-215,-220,177,177,-237,-245,-214,-238,208,-242,-239,-218,-230,28,-117,28,177,-36,177,-83,-250,-21,-80,-22,-79,177,-176,-179,-177,-173,-174,-178,-180,177,-182,-183,-175,-181,-248,177,-212,-215,-246,-226,177,177,-227,177,-206,-211,177,-209,28,-210,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,28,311,-98,177,-251,-37,-39,-42,-38,177,-40,177,177,-148,-147,-43,-149,177,-41,-237,-85,-84,28,177,-225,-224,-223,-234,177,177,28,208,208,208,208,208,208,208,208,208,208,-189,-188,208,208,208,208,208,-190,-215,364,-100,-99,-12,177,177,-11,-167,-166,177,-164,177,177,-150,177,-163,-151,177,177,-213,-221,-222,177,177,-207,-251,177,-215,-251,-131,-162,-165,177,-154,177,-152,177,177,177,-153,177,177,177,-251,-228,177,-158,-157,-155,-229,177,177,177,-159,-156,177,-161,-160,]),'LPAREN':([0,1,2,3,4,5,6,9,10,11,12,13,14,15,16,17,18,19,21,22,23,24,25,27,28,29,30,31,32,33,35,36,37,38,39,40,42,43,44,45,46,49,50,51,52,54,55,56,58,59,60,61,63,64,66,67,68,69,75,76,77,79,83,87,89,90,91,93,94,95,96,97,98,99,100,101,102,105,106,108,109,110,111,112,113,114,115,116,117,119,120,123,124,129,138,139,140,141,144,145,149,151,152,153,154,155,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,177,178,180,182,183,184,185,186,189,191,195,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,221,223,224,231,232,235,237,238,239,242,243,244,245,249,250,251,252,253,254,255,257,259,260,262,263,264,265,268,270,273,274,277,281,282,283,285,286,311,312,314,318,319,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,350,351,352,353,357,358,359,360,361,362,364,369,372,373,374,376,377,379,381,382,387,388,389,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[4,-251,-61,-72,4,-71,-58,-54,-55,-33,-29,-59,-251,-34,4,-53,-68,-63,-52,4,-56,-170,62,-66,-251,-69,4,-32,-73,-108,-64,-31,-60,-35,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-249,-81,-49,62,-30,112,-97,-96,-116,-114,-26,-25,-45,-48,-51,4,-109,-251,-251,4,-219,-233,-243,-247,-244,-241,-231,175,-217,-232,183,186,-216,189,-240,-215,-220,112,189,-237,-245,-214,-238,-242,-239,-218,-230,218,-115,-117,4,112,-36,112,-83,-250,-21,-80,-22,-79,186,-176,-179,-177,-173,-174,-178,-180,112,-182,-183,-175,-181,-248,112,-215,-246,-226,112,112,-227,-110,112,112,-111,285,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,112,186,186,-113,-112,218,112,313,218,-98,186,-251,-37,-39,-42,-38,112,-40,334,337,186,112,341,-148,-147,-43,-149,112,-41,-237,346,-85,-84,4,186,-225,-224,-223,-234,112,186,285,285,-215,112,313,-100,-99,-12,186,112,-11,-167,-166,112,-164,112,112,-150,112,-163,-151,112,112,-221,-222,112,186,-251,186,-146,-140,-142,-144,-215,-251,-131,-162,-165,112,-154,112,398,-152,-141,-143,-145,112,112,112,-153,112,112,112,-251,-228,112,-158,-157,-155,-229,112,112,112,-159,-156,112,-161,-160,]),'MINUSMINUS':([55,61,75,91,93,94,95,96,97,98,99,100,101,102,105,106,108,109,110,111,112,113,114,115,116,117,119,120,123,124,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,177,178,180,182,183,184,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,262,270,273,274,277,281,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,350,351,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[-249,113,-45,-219,-233,-243,-247,-244,-241,-231,113,-217,-232,184,113,-216,113,-240,-215,-220,113,113,-237,-245,-214,-238,-242,-239,-218,-230,113,113,-250,113,-176,-179,-177,-173,-174,-178,-180,113,-182,-183,-175,-181,-248,113,-215,-246,-226,113,113,-227,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,-251,-39,-42,-38,113,-40,113,113,-148,-147,-43,-149,113,-41,-237,113,-225,-224,-223,-234,113,113,-215,113,-12,113,113,-11,-167,-166,113,-164,113,113,-150,113,-163,-151,113,113,-221,-222,113,113,-251,113,-215,-251,-131,-162,-165,113,-154,113,-152,113,113,113,-153,113,113,113,-251,-228,113,-158,-157,-155,-229,113,113,113,-159,-156,113,-161,-160,]),'ID':([0,1,2,3,4,5,6,7,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,39,40,42,43,44,45,46,49,50,51,52,54,55,56,58,60,61,62,63,64,65,66,67,68,69,75,76,77,79,87,89,90,91,99,100,105,106,108,110,112,113,116,123,129,133,134,138,139,140,141,144,145,149,151,152,153,154,155,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,179,181,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,218,221,224,226,230,231,232,235,237,238,239,240,242,243,244,250,251,253,254,255,257,259,260,264,265,268,270,282,283,311,312,318,319,322,324,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[33,-251,-61,-72,33,-71,-58,56,-54,-55,-33,-29,-59,-251,-34,33,-53,-68,-63,-87,-52,33,-56,-170,64,-66,-251,-69,33,-32,-73,-86,-64,-31,-60,-35,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-249,-81,-49,-30,114,114,-97,-96,137,-116,-114,-26,-25,-45,-48,-51,33,-251,-251,33,-219,114,-217,114,-216,114,-215,114,114,-214,-218,33,137,137,-115,-117,33,114,-36,262,-83,-250,-21,-80,-22,-79,114,-176,-179,-177,-173,-174,-178,-180,114,-182,-183,-175,-181,114,-215,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,33,114,33,114,137,-98,114,-251,-37,-39,-42,330,-38,114,-40,114,262,-148,-147,-43,-149,262,-41,-85,-84,33,114,114,114,-215,114,-100,-99,-12,114,114,114,-11,-167,-166,114,-164,262,114,-150,114,-163,-151,262,114,114,114,-251,114,-215,-251,-131,-162,-165,114,-154,262,-152,114,114,262,-153,262,114,262,-251,114,-158,-157,-155,114,262,262,-159,-156,262,-161,-160,]),'IF':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,263,-250,-39,-42,-38,-40,263,-148,-147,-43,-149,263,-41,-167,-166,-164,263,-150,-163,-151,263,-162,-165,-154,263,-152,263,-153,263,263,-158,-157,-155,263,263,-159,-156,263,-161,-160,]),'STRING_LITERAL':([55,61,75,91,99,100,101,105,106,108,110,112,113,115,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,178,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,115,-45,-219,115,-217,178,115,-216,115,-215,115,115,-245,-214,-218,115,115,-250,115,-176,-179,-177,-173,-174,-178,-180,115,-182,-183,-175,-181,115,-215,-246,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,-251,-39,-42,-38,115,-40,115,115,-148,-147,-43,-149,115,-41,115,115,115,-215,115,-12,115,115,-11,-167,-166,115,-164,115,115,-150,115,-163,-151,115,115,115,115,-251,115,-215,-251,-131,-162,-165,115,-154,115,-152,115,115,115,-153,115,115,115,-251,115,-158,-157,-155,115,115,115,-159,-156,115,-161,-160,]),'FLOAT':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[35,35,-61,-72,-71,-58,-54,-55,-33,-29,-59,35,-34,-53,-68,-63,-52,35,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,35,-67,35,-70,-74,35,-57,-82,-249,-81,35,-107,-30,35,-97,-96,35,-45,-46,35,-109,35,35,35,35,-88,35,35,-36,35,-47,35,35,-83,-89,-250,35,-110,35,35,-111,-113,-112,35,35,-98,-37,-39,-42,-38,-40,35,-148,-147,-43,-149,-41,-85,-84,-90,35,35,-100,-99,-167,-166,35,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'XOREQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[166,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'LSHIFTEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[168,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'RBRACKET':([61,92,93,94,95,96,97,98,101,102,103,104,107,109,110,111,114,115,117,118,119,120,121,122,124,151,174,176,178,180,184,187,188,190,194,196,221,267,271,273,274,275,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,310,311,312,349,350,351,355,356,363,364,367,386,401,409,],[-251,-206,-233,-243,-247,-244,-241,-231,-232,-208,185,-187,-4,-240,191,-220,-237,-245,-238,-185,-242,-239,-3,-171,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-168,-210,-251,-184,-172,-225,-224,350,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,361,362,-251,-213,-221,-222,-169,-207,387,388,390,-186,-228,-229,]),} - -_lr_action = { } -for _k, _v in _lr_action_items.items(): - for _x,_y in zip(_v[0],_v[1]): - if not _x in _lr_action: _lr_action[_x] = { } - _lr_action[_x][_k] = _y -del _lr_action_items - -_lr_goto_items = {'storage_class_specifier':([0,1,14,22,42,44,48,62,73,82,145,218,227,251,285,313,334,],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,]),'identifier_list_opt':([62,],[125,]),'selection_statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[260,260,260,260,260,260,260,260,260,260,260,260,]),'constant':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,]),'unary_expression':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[92,176,187,190,92,196,92,92,187,92,92,92,92,92,92,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,92,187,187,92,187,92,187,92,92,187,92,187,92,187,92,92,92,92,92,92,92,92,187,187,92,92,92,92,92,92,92,92,92,92,92,92,92,]),'conditional_expression':([61,112,141,145,156,169,175,182,183,186,189,213,221,232,243,250,251,259,270,282,312,325,326,334,336,337,341,345,346,352,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[122,122,122,122,267,122,122,122,122,122,122,122,122,267,122,267,122,122,267,122,122,267,122,122,122,122,122,122,122,122,386,122,122,122,122,122,122,122,122,122,122,122,122,122,]),'brace_close':([86,136,147,148,228,229,261,328,369,385,400,],[149,231,264,265,318,319,344,370,392,401,409,]),'struct_or_union_specifier':([0,1,14,22,42,44,48,57,62,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,]),'unified_wstring_literal':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,]),'abstract_declarator_opt':([129,195,],[219,284,]),'iteration_statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[239,239,239,239,239,239,239,239,239,239,239,239,]),'init_declarator_list':([30,79,],[70,70,]),'translation_unit_or_empty':([0,],[8,]),'struct_declaration_list':([57,84,85,],[86,147,148,]),'enumerator':([65,133,134,230,],[135,135,135,320,]),'pp_directive':([0,22,],[11,11,]),'declaration_list':([48,73,],[82,82,]),'declaration_specifiers_opt':([1,14,42,44,],[50,58,76,77,]),'abstract_declarator':([129,195,218,285,],[220,220,309,309,]),'external_declaration':([0,22,],[12,60,]),'type_specifier':([0,1,14,22,42,44,48,57,62,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[14,14,14,14,14,14,14,87,14,14,14,87,87,87,87,87,87,14,87,87,87,87,87,14,14,14,14,14,14,]),'designation':([235,357,369,400,],[322,322,322,322,]),'compound_statement':([81,142,145,251,259,336,345,379,395,397,399,413,415,418,],[144,237,244,244,244,244,244,244,244,244,244,244,244,244,]),'pointer':([0,4,22,30,67,79,90,129,140,195,218,268,285,],[16,16,16,16,138,16,16,224,16,286,224,16,286,]),'type_name':([112,175,186,189,],[193,272,279,280,]),'unified_string_literal':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,]),'postfix_expression':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,]),'assignment_expression_opt':([61,221,312,],[103,310,363,]),'designation_opt':([235,357,369,400,],[326,326,391,391,]),'expression_statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[238,238,238,238,238,238,238,238,238,238,238,238,]),'unary_operator':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,]),'cast_expression':([61,105,112,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[104,188,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,356,104,104,104,104,104,104,104,104,104,104,356,104,104,104,104,104,104,104,104,104,104,104,104,104,104,]),'brace_open':([7,26,54,56,63,64,81,141,142,145,251,259,283,326,336,345,349,353,354,379,391,395,397,399,413,415,418,],[57,65,84,85,133,134,145,235,145,145,145,145,357,235,145,145,357,357,357,145,235,145,145,145,145,145,145,]),'init_declarator':([30,79,140,],[74,74,233,]),'translation_unit':([0,],[22,]),'assignment_operator':([92,],[169,]),'struct_or_union':([0,1,14,22,42,44,48,57,62,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,]),'block_item_list_opt':([145,],[261,]),'struct_declaration':([57,84,85,86,147,148,],[88,88,88,150,150,150,]),'assignment_expression':([61,112,141,145,169,175,182,183,186,189,213,221,243,251,259,282,312,326,334,336,337,341,345,346,352,376,379,391,393,395,397,398,399,404,410,413,415,418,],[107,194,236,194,271,194,194,276,194,194,194,107,194,194,194,355,107,236,194,194,194,194,194,194,384,194,194,236,194,194,194,194,194,194,194,194,194,194,]),'parameter_type_list':([62,218,285,313,],[127,307,307,307,]),'type_qualifier_list_opt':([28,],[67,]),'direct_declarator':([0,4,16,22,30,79,90,129,140,218,224,268,],[25,25,59,25,25,25,25,25,25,25,59,25,]),'type_qualifier_list':([28,],[68,]),'designator':([235,329,357,369,400,],[323,371,323,323,323,]),'argument_expression_list':([183,],[278,]),'initializer':([141,326,391,],[234,368,402,]),'direct_abstract_declarator':([129,195,218,224,285,286,],[223,223,223,314,223,314,]),'specifier_qualifier_list_opt':([87,89,],[153,155,]),'constant_expression':([156,232,250,270,325,],[266,321,338,348,367,]),'expression_opt':([145,251,259,334,336,345,376,379,393,395,397,399,404,410,413,415,418,],[241,241,241,375,241,241,394,241,403,241,241,241,411,414,241,241,241,]),'primary_expression':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,]),'declaration_specifiers':([0,1,14,22,42,44,48,62,73,82,145,218,227,251,285,313,334,],[30,52,52,30,52,52,79,129,79,79,79,129,129,79,129,129,79,]),'declaration':([0,22,48,73,82,145,251,334,],[31,31,80,80,146,254,254,376,]),'struct_declarator_list_opt':([90,],[158,]),'identifier_list':([62,],[130,]),'typedef_name':([0,1,14,22,42,44,48,57,62,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,]),'parameter_type_list_opt':([218,285,313,],[308,308,365,]),'jump_statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[255,255,255,255,255,255,255,255,255,255,255,255,]),'declaration_list_opt':([48,73,],[81,142,]),'struct_declarator':([90,268,],[159,347,]),'function_definition':([0,22,],[36,36,]),'binary_expression':([61,112,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,312,325,326,334,336,337,341,345,346,352,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[118,118,118,118,118,118,118,118,118,118,118,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,118,304,305,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,]),'parameter_list':([62,218,285,313,],[131,131,131,131,]),'init_declarator_list_opt':([30,79,],[71,71,]),'enum_specifier':([0,1,14,22,42,44,48,57,62,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,]),'struct_declarator_list':([90,],[157,]),'decl_body':([0,22,48,73,82,145,251,334,],[41,41,41,41,41,41,41,41,]),'type_qualifier':([0,1,14,22,28,42,44,48,57,62,68,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[42,42,42,42,66,42,42,42,89,42,139,42,42,89,89,89,89,89,89,42,89,89,89,89,89,42,42,42,42,42,42,]),'enumerator_list':([65,133,134,],[136,228,229,]),'labeled_statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[242,242,242,242,242,242,242,242,242,242,242,242,]),'function_specifier':([0,1,14,22,42,44,48,62,73,82,145,218,227,251,285,313,334,],[44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,]),'specifier_qualifier_list':([57,84,85,86,87,89,112,147,148,175,186,189,],[90,90,90,90,154,154,195,90,90,195,195,195,]),'block_item':([145,251,],[257,340,]),'block_item_list':([145,],[251,]),'statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[253,253,343,377,382,396,405,406,408,417,419,420,]),'empty':([0,1,14,28,30,42,44,48,61,62,73,79,87,89,90,129,145,195,218,221,235,251,259,285,312,313,334,336,345,357,369,376,379,393,395,397,399,400,404,410,413,415,418,],[47,51,51,69,72,51,51,78,121,126,78,72,152,152,160,225,258,225,306,121,327,339,339,306,121,306,339,339,339,327,327,339,339,339,339,339,339,327,339,339,339,339,339,]),'initializer_list':([235,357,],[328,385,]),'declarator':([0,4,22,30,79,90,129,140,218,268,],[48,53,48,73,143,161,222,143,53,161,]),'parameter_declaration':([62,218,227,285,313,],[128,128,317,128,128,]),'designator_list':([235,357,369,400,],[329,329,329,329,]),'identifier':([61,62,99,105,108,112,113,141,145,156,169,175,179,181,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,226,232,243,250,251,259,270,282,283,312,324,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[124,132,124,124,124,124,124,124,124,124,124,124,273,274,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,315,124,124,124,124,124,124,124,124,124,366,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,]),'expression':([112,145,175,182,186,189,213,243,251,259,334,336,337,341,345,346,376,379,393,395,397,398,399,404,410,413,415,418,],[192,247,192,275,192,192,303,333,247,247,247,247,378,380,247,383,247,247,247,247,247,407,247,247,247,247,247,247,]),} - -_lr_goto = { } -for _k, _v in _lr_goto_items.items(): - for _x,_y in zip(_v[0],_v[1]): - if not _x in _lr_goto: _lr_goto[_x] = { } - _lr_goto[_x][_k] = _y -del _lr_goto_items -_lr_productions = [ - ("S' -> translation_unit_or_empty","S'",1,None,None,None), - ('abstract_declarator_opt -> empty','abstract_declarator_opt',1,'p_abstract_declarator_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('abstract_declarator_opt -> abstract_declarator','abstract_declarator_opt',1,'p_abstract_declarator_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('assignment_expression_opt -> empty','assignment_expression_opt',1,'p_assignment_expression_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('assignment_expression_opt -> assignment_expression','assignment_expression_opt',1,'p_assignment_expression_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('block_item_list_opt -> empty','block_item_list_opt',1,'p_block_item_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('block_item_list_opt -> block_item_list','block_item_list_opt',1,'p_block_item_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('declaration_list_opt -> empty','declaration_list_opt',1,'p_declaration_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('declaration_list_opt -> declaration_list','declaration_list_opt',1,'p_declaration_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('declaration_specifiers_opt -> empty','declaration_specifiers_opt',1,'p_declaration_specifiers_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('declaration_specifiers_opt -> declaration_specifiers','declaration_specifiers_opt',1,'p_declaration_specifiers_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('designation_opt -> empty','designation_opt',1,'p_designation_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('designation_opt -> designation','designation_opt',1,'p_designation_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('expression_opt -> empty','expression_opt',1,'p_expression_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('expression_opt -> expression','expression_opt',1,'p_expression_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('identifier_list_opt -> empty','identifier_list_opt',1,'p_identifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('identifier_list_opt -> identifier_list','identifier_list_opt',1,'p_identifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('init_declarator_list_opt -> empty','init_declarator_list_opt',1,'p_init_declarator_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('init_declarator_list_opt -> init_declarator_list','init_declarator_list_opt',1,'p_init_declarator_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('parameter_type_list_opt -> empty','parameter_type_list_opt',1,'p_parameter_type_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('parameter_type_list_opt -> parameter_type_list','parameter_type_list_opt',1,'p_parameter_type_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('specifier_qualifier_list_opt -> empty','specifier_qualifier_list_opt',1,'p_specifier_qualifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('specifier_qualifier_list_opt -> specifier_qualifier_list','specifier_qualifier_list_opt',1,'p_specifier_qualifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('struct_declarator_list_opt -> empty','struct_declarator_list_opt',1,'p_struct_declarator_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('struct_declarator_list_opt -> struct_declarator_list','struct_declarator_list_opt',1,'p_struct_declarator_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('type_qualifier_list_opt -> empty','type_qualifier_list_opt',1,'p_type_qualifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('type_qualifier_list_opt -> type_qualifier_list','type_qualifier_list_opt',1,'p_type_qualifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('translation_unit_or_empty -> translation_unit','translation_unit_or_empty',1,'p_translation_unit_or_empty','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',355), - ('translation_unit_or_empty -> empty','translation_unit_or_empty',1,'p_translation_unit_or_empty','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',356), - ('translation_unit -> external_declaration','translation_unit',1,'p_translation_unit_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',364), - ('translation_unit -> translation_unit external_declaration','translation_unit',2,'p_translation_unit_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',371), - ('external_declaration -> function_definition','external_declaration',1,'p_external_declaration_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',383), - ('external_declaration -> declaration','external_declaration',1,'p_external_declaration_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',388), - ('external_declaration -> pp_directive','external_declaration',1,'p_external_declaration_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',393), - ('external_declaration -> SEMI','external_declaration',1,'p_external_declaration_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',398), - ('pp_directive -> PPHASH','pp_directive',1,'p_pp_directive','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',403), - ('function_definition -> declarator declaration_list_opt compound_statement','function_definition',3,'p_function_definition_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',412), - ('function_definition -> declaration_specifiers declarator declaration_list_opt compound_statement','function_definition',4,'p_function_definition_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',424), - ('statement -> labeled_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',435), - ('statement -> expression_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',436), - ('statement -> compound_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',437), - ('statement -> selection_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',438), - ('statement -> iteration_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',439), - ('statement -> jump_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',440), - ('decl_body -> declaration_specifiers init_declarator_list_opt','decl_body',2,'p_decl_body','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',454), - ('declaration -> decl_body SEMI','declaration',2,'p_declaration','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',537), - ('declaration_list -> declaration','declaration_list',1,'p_declaration_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',546), - ('declaration_list -> declaration_list declaration','declaration_list',2,'p_declaration_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',547), - ('declaration_specifiers -> type_qualifier declaration_specifiers_opt','declaration_specifiers',2,'p_declaration_specifiers_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',552), - ('declaration_specifiers -> type_specifier declaration_specifiers_opt','declaration_specifiers',2,'p_declaration_specifiers_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',557), - ('declaration_specifiers -> storage_class_specifier declaration_specifiers_opt','declaration_specifiers',2,'p_declaration_specifiers_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',562), - ('declaration_specifiers -> function_specifier declaration_specifiers_opt','declaration_specifiers',2,'p_declaration_specifiers_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',567), - ('storage_class_specifier -> AUTO','storage_class_specifier',1,'p_storage_class_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',572), - ('storage_class_specifier -> REGISTER','storage_class_specifier',1,'p_storage_class_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',573), - ('storage_class_specifier -> STATIC','storage_class_specifier',1,'p_storage_class_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',574), - ('storage_class_specifier -> EXTERN','storage_class_specifier',1,'p_storage_class_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',575), - ('storage_class_specifier -> TYPEDEF','storage_class_specifier',1,'p_storage_class_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',576), - ('function_specifier -> INLINE','function_specifier',1,'p_function_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',581), - ('type_specifier -> VOID','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',586), - ('type_specifier -> _BOOL','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',587), - ('type_specifier -> CHAR','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',588), - ('type_specifier -> SHORT','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',589), - ('type_specifier -> INT','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',590), - ('type_specifier -> LONG','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',591), - ('type_specifier -> FLOAT','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',592), - ('type_specifier -> DOUBLE','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',593), - ('type_specifier -> _COMPLEX','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',594), - ('type_specifier -> SIGNED','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',595), - ('type_specifier -> UNSIGNED','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',596), - ('type_specifier -> typedef_name','type_specifier',1,'p_type_specifier_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',601), - ('type_specifier -> enum_specifier','type_specifier',1,'p_type_specifier_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',602), - ('type_specifier -> struct_or_union_specifier','type_specifier',1,'p_type_specifier_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',603), - ('type_qualifier -> CONST','type_qualifier',1,'p_type_qualifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',608), - ('type_qualifier -> RESTRICT','type_qualifier',1,'p_type_qualifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',609), - ('type_qualifier -> VOLATILE','type_qualifier',1,'p_type_qualifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',610), - ('init_declarator_list -> init_declarator','init_declarator_list',1,'p_init_declarator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',615), - ('init_declarator_list -> init_declarator_list COMMA init_declarator','init_declarator_list',3,'p_init_declarator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',616), - ('init_declarator -> declarator','init_declarator',1,'p_init_declarator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',624), - ('init_declarator -> declarator EQUALS initializer','init_declarator',3,'p_init_declarator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',625), - ('specifier_qualifier_list -> type_qualifier specifier_qualifier_list_opt','specifier_qualifier_list',2,'p_specifier_qualifier_list_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',630), - ('specifier_qualifier_list -> type_specifier specifier_qualifier_list_opt','specifier_qualifier_list',2,'p_specifier_qualifier_list_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',635), - ('struct_or_union_specifier -> struct_or_union ID','struct_or_union_specifier',2,'p_struct_or_union_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',643), - ('struct_or_union_specifier -> struct_or_union TYPEID','struct_or_union_specifier',2,'p_struct_or_union_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',644), - ('struct_or_union_specifier -> struct_or_union brace_open struct_declaration_list brace_close','struct_or_union_specifier',4,'p_struct_or_union_specifier_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',653), - ('struct_or_union_specifier -> struct_or_union ID brace_open struct_declaration_list brace_close','struct_or_union_specifier',5,'p_struct_or_union_specifier_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',662), - ('struct_or_union_specifier -> struct_or_union TYPEID brace_open struct_declaration_list brace_close','struct_or_union_specifier',5,'p_struct_or_union_specifier_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',663), - ('struct_or_union -> STRUCT','struct_or_union',1,'p_struct_or_union','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',672), - ('struct_or_union -> UNION','struct_or_union',1,'p_struct_or_union','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',673), - ('struct_declaration_list -> struct_declaration','struct_declaration_list',1,'p_struct_declaration_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',680), - ('struct_declaration_list -> struct_declaration_list struct_declaration','struct_declaration_list',2,'p_struct_declaration_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',681), - ('struct_declaration -> specifier_qualifier_list struct_declarator_list_opt SEMI','struct_declaration',3,'p_struct_declaration_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',686), - ('struct_declarator_list -> struct_declarator','struct_declarator_list',1,'p_struct_declarator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',737), - ('struct_declarator_list -> struct_declarator_list COMMA struct_declarator','struct_declarator_list',3,'p_struct_declarator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',738), - ('struct_declarator -> declarator','struct_declarator',1,'p_struct_declarator_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',746), - ('struct_declarator -> declarator COLON constant_expression','struct_declarator',3,'p_struct_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',751), - ('struct_declarator -> COLON constant_expression','struct_declarator',2,'p_struct_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',752), - ('enum_specifier -> ENUM ID','enum_specifier',2,'p_enum_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',760), - ('enum_specifier -> ENUM TYPEID','enum_specifier',2,'p_enum_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',761), - ('enum_specifier -> ENUM brace_open enumerator_list brace_close','enum_specifier',4,'p_enum_specifier_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',766), - ('enum_specifier -> ENUM ID brace_open enumerator_list brace_close','enum_specifier',5,'p_enum_specifier_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',771), - ('enum_specifier -> ENUM TYPEID brace_open enumerator_list brace_close','enum_specifier',5,'p_enum_specifier_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',772), - ('enumerator_list -> enumerator','enumerator_list',1,'p_enumerator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',777), - ('enumerator_list -> enumerator_list COMMA','enumerator_list',2,'p_enumerator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',778), - ('enumerator_list -> enumerator_list COMMA enumerator','enumerator_list',3,'p_enumerator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',779), - ('enumerator -> ID','enumerator',1,'p_enumerator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',790), - ('enumerator -> ID EQUALS constant_expression','enumerator',3,'p_enumerator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',791), - ('declarator -> direct_declarator','declarator',1,'p_declarator_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',803), - ('declarator -> pointer direct_declarator','declarator',2,'p_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',808), - ('direct_declarator -> ID','direct_declarator',1,'p_direct_declarator_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',813), - ('direct_declarator -> LPAREN declarator RPAREN','direct_declarator',3,'p_direct_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',822), - ('direct_declarator -> direct_declarator LBRACKET assignment_expression_opt RBRACKET','direct_declarator',4,'p_direct_declarator_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',827), - ('direct_declarator -> direct_declarator LBRACKET TIMES RBRACKET','direct_declarator',4,'p_direct_declarator_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',839), - ('direct_declarator -> direct_declarator LPAREN parameter_type_list RPAREN','direct_declarator',4,'p_direct_declarator_5','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',849), - ('direct_declarator -> direct_declarator LPAREN identifier_list_opt RPAREN','direct_declarator',4,'p_direct_declarator_5','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',850), - ('pointer -> TIMES type_qualifier_list_opt','pointer',2,'p_pointer','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',860), - ('pointer -> TIMES type_qualifier_list_opt pointer','pointer',3,'p_pointer','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',861), - ('type_qualifier_list -> type_qualifier','type_qualifier_list',1,'p_type_qualifier_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',871), - ('type_qualifier_list -> type_qualifier_list type_qualifier','type_qualifier_list',2,'p_type_qualifier_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',872), - ('parameter_type_list -> parameter_list','parameter_type_list',1,'p_parameter_type_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',877), - ('parameter_type_list -> parameter_list COMMA ELLIPSIS','parameter_type_list',3,'p_parameter_type_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',878), - ('parameter_list -> parameter_declaration','parameter_list',1,'p_parameter_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',886), - ('parameter_list -> parameter_list COMMA parameter_declaration','parameter_list',3,'p_parameter_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',887), - ('parameter_declaration -> declaration_specifiers declarator','parameter_declaration',2,'p_parameter_declaration_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',896), - ('parameter_declaration -> declaration_specifiers abstract_declarator_opt','parameter_declaration',2,'p_parameter_declaration_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',915), - ('identifier_list -> identifier','identifier_list',1,'p_identifier_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',927), - ('identifier_list -> identifier_list COMMA identifier','identifier_list',3,'p_identifier_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',928), - ('initializer -> assignment_expression','initializer',1,'p_initializer_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',937), - ('initializer -> brace_open initializer_list brace_close','initializer',3,'p_initializer_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',942), - ('initializer -> brace_open initializer_list COMMA brace_close','initializer',4,'p_initializer_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',943), - ('initializer_list -> designation_opt initializer','initializer_list',2,'p_initializer_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',948), - ('initializer_list -> initializer_list COMMA designation_opt initializer','initializer_list',4,'p_initializer_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',949), - ('designation -> designator_list EQUALS','designation',2,'p_designation','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',960), - ('designator_list -> designator','designator_list',1,'p_designator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',968), - ('designator_list -> designator_list designator','designator_list',2,'p_designator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',969), - ('designator -> LBRACKET constant_expression RBRACKET','designator',3,'p_designator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',974), - ('designator -> PERIOD identifier','designator',2,'p_designator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',975), - ('type_name -> specifier_qualifier_list abstract_declarator_opt','type_name',2,'p_type_name','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',980), - ('abstract_declarator -> pointer','abstract_declarator',1,'p_abstract_declarator_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',996), - ('abstract_declarator -> pointer direct_abstract_declarator','abstract_declarator',2,'p_abstract_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1004), - ('abstract_declarator -> direct_abstract_declarator','abstract_declarator',1,'p_abstract_declarator_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1009), - ('direct_abstract_declarator -> LPAREN abstract_declarator RPAREN','direct_abstract_declarator',3,'p_direct_abstract_declarator_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1019), - ('direct_abstract_declarator -> direct_abstract_declarator LBRACKET assignment_expression_opt RBRACKET','direct_abstract_declarator',4,'p_direct_abstract_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1023), - ('direct_abstract_declarator -> LBRACKET assignment_expression_opt RBRACKET','direct_abstract_declarator',3,'p_direct_abstract_declarator_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1033), - ('direct_abstract_declarator -> direct_abstract_declarator LBRACKET TIMES RBRACKET','direct_abstract_declarator',4,'p_direct_abstract_declarator_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1041), - ('direct_abstract_declarator -> LBRACKET TIMES RBRACKET','direct_abstract_declarator',3,'p_direct_abstract_declarator_5','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1051), - ('direct_abstract_declarator -> direct_abstract_declarator LPAREN parameter_type_list_opt RPAREN','direct_abstract_declarator',4,'p_direct_abstract_declarator_6','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1059), - ('direct_abstract_declarator -> LPAREN parameter_type_list_opt RPAREN','direct_abstract_declarator',3,'p_direct_abstract_declarator_7','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1069), - ('block_item -> declaration','block_item',1,'p_block_item','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1080), - ('block_item -> statement','block_item',1,'p_block_item','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1081), - ('block_item_list -> block_item','block_item_list',1,'p_block_item_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1088), - ('block_item_list -> block_item_list block_item','block_item_list',2,'p_block_item_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1089), - ('compound_statement -> brace_open block_item_list_opt brace_close','compound_statement',3,'p_compound_statement_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1095), - ('labeled_statement -> ID COLON statement','labeled_statement',3,'p_labeled_statement_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1101), - ('labeled_statement -> CASE constant_expression COLON statement','labeled_statement',4,'p_labeled_statement_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1105), - ('labeled_statement -> DEFAULT COLON statement','labeled_statement',3,'p_labeled_statement_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1109), - ('selection_statement -> IF LPAREN expression RPAREN statement','selection_statement',5,'p_selection_statement_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1113), - ('selection_statement -> IF LPAREN expression RPAREN statement ELSE statement','selection_statement',7,'p_selection_statement_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1117), - ('selection_statement -> SWITCH LPAREN expression RPAREN statement','selection_statement',5,'p_selection_statement_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1121), - ('iteration_statement -> WHILE LPAREN expression RPAREN statement','iteration_statement',5,'p_iteration_statement_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1126), - ('iteration_statement -> DO statement WHILE LPAREN expression RPAREN SEMI','iteration_statement',7,'p_iteration_statement_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1130), - ('iteration_statement -> FOR LPAREN expression_opt SEMI expression_opt SEMI expression_opt RPAREN statement','iteration_statement',9,'p_iteration_statement_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1134), - ('iteration_statement -> FOR LPAREN declaration expression_opt SEMI expression_opt RPAREN statement','iteration_statement',8,'p_iteration_statement_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1138), - ('jump_statement -> GOTO ID SEMI','jump_statement',3,'p_jump_statement_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1142), - ('jump_statement -> BREAK SEMI','jump_statement',2,'p_jump_statement_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1146), - ('jump_statement -> CONTINUE SEMI','jump_statement',2,'p_jump_statement_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1150), - ('jump_statement -> RETURN expression SEMI','jump_statement',3,'p_jump_statement_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1154), - ('jump_statement -> RETURN SEMI','jump_statement',2,'p_jump_statement_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1155), - ('expression_statement -> expression_opt SEMI','expression_statement',2,'p_expression_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1160), - ('expression -> assignment_expression','expression',1,'p_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1167), - ('expression -> expression COMMA assignment_expression','expression',3,'p_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1168), - ('typedef_name -> TYPEID','typedef_name',1,'p_typedef_name','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1180), - ('assignment_expression -> conditional_expression','assignment_expression',1,'p_assignment_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1184), - ('assignment_expression -> unary_expression assignment_operator assignment_expression','assignment_expression',3,'p_assignment_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1185), - ('assignment_operator -> EQUALS','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1198), - ('assignment_operator -> XOREQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1199), - ('assignment_operator -> TIMESEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1200), - ('assignment_operator -> DIVEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1201), - ('assignment_operator -> MODEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1202), - ('assignment_operator -> PLUSEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1203), - ('assignment_operator -> MINUSEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1204), - ('assignment_operator -> LSHIFTEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1205), - ('assignment_operator -> RSHIFTEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1206), - ('assignment_operator -> ANDEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1207), - ('assignment_operator -> OREQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1208), - ('constant_expression -> conditional_expression','constant_expression',1,'p_constant_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1213), - ('conditional_expression -> binary_expression','conditional_expression',1,'p_conditional_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1217), - ('conditional_expression -> binary_expression CONDOP expression COLON conditional_expression','conditional_expression',5,'p_conditional_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1218), - ('binary_expression -> cast_expression','binary_expression',1,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1226), - ('binary_expression -> binary_expression TIMES binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1227), - ('binary_expression -> binary_expression DIVIDE binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1228), - ('binary_expression -> binary_expression MOD binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1229), - ('binary_expression -> binary_expression PLUS binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1230), - ('binary_expression -> binary_expression MINUS binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1231), - ('binary_expression -> binary_expression RSHIFT binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1232), - ('binary_expression -> binary_expression LSHIFT binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1233), - ('binary_expression -> binary_expression LT binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1234), - ('binary_expression -> binary_expression LE binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1235), - ('binary_expression -> binary_expression GE binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1236), - ('binary_expression -> binary_expression GT binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1237), - ('binary_expression -> binary_expression EQ binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1238), - ('binary_expression -> binary_expression NE binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1239), - ('binary_expression -> binary_expression AND binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1240), - ('binary_expression -> binary_expression OR binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1241), - ('binary_expression -> binary_expression XOR binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1242), - ('binary_expression -> binary_expression LAND binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1243), - ('binary_expression -> binary_expression LOR binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1244), - ('cast_expression -> unary_expression','cast_expression',1,'p_cast_expression_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1252), - ('cast_expression -> LPAREN type_name RPAREN cast_expression','cast_expression',4,'p_cast_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1256), - ('unary_expression -> postfix_expression','unary_expression',1,'p_unary_expression_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1260), - ('unary_expression -> PLUSPLUS unary_expression','unary_expression',2,'p_unary_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1264), - ('unary_expression -> MINUSMINUS unary_expression','unary_expression',2,'p_unary_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1265), - ('unary_expression -> unary_operator cast_expression','unary_expression',2,'p_unary_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1266), - ('unary_expression -> SIZEOF unary_expression','unary_expression',2,'p_unary_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1271), - ('unary_expression -> SIZEOF LPAREN type_name RPAREN','unary_expression',4,'p_unary_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1272), - ('unary_operator -> AND','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1280), - ('unary_operator -> TIMES','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1281), - ('unary_operator -> PLUS','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1282), - ('unary_operator -> MINUS','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1283), - ('unary_operator -> NOT','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1284), - ('unary_operator -> LNOT','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1285), - ('postfix_expression -> primary_expression','postfix_expression',1,'p_postfix_expression_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1290), - ('postfix_expression -> postfix_expression LBRACKET expression RBRACKET','postfix_expression',4,'p_postfix_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1294), - ('postfix_expression -> postfix_expression LPAREN argument_expression_list RPAREN','postfix_expression',4,'p_postfix_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1298), - ('postfix_expression -> postfix_expression LPAREN RPAREN','postfix_expression',3,'p_postfix_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1299), - ('postfix_expression -> postfix_expression PERIOD identifier','postfix_expression',3,'p_postfix_expression_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1304), - ('postfix_expression -> postfix_expression ARROW identifier','postfix_expression',3,'p_postfix_expression_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1305), - ('postfix_expression -> postfix_expression PLUSPLUS','postfix_expression',2,'p_postfix_expression_5','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1310), - ('postfix_expression -> postfix_expression MINUSMINUS','postfix_expression',2,'p_postfix_expression_5','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1311), - ('postfix_expression -> LPAREN type_name RPAREN brace_open initializer_list brace_close','postfix_expression',6,'p_postfix_expression_6','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1316), - ('postfix_expression -> LPAREN type_name RPAREN brace_open initializer_list COMMA brace_close','postfix_expression',7,'p_postfix_expression_6','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1317), - ('primary_expression -> identifier','primary_expression',1,'p_primary_expression_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1322), - ('primary_expression -> constant','primary_expression',1,'p_primary_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1326), - ('primary_expression -> unified_string_literal','primary_expression',1,'p_primary_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1330), - ('primary_expression -> unified_wstring_literal','primary_expression',1,'p_primary_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1331), - ('primary_expression -> LPAREN expression RPAREN','primary_expression',3,'p_primary_expression_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1336), - ('argument_expression_list -> assignment_expression','argument_expression_list',1,'p_argument_expression_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1340), - ('argument_expression_list -> argument_expression_list COMMA assignment_expression','argument_expression_list',3,'p_argument_expression_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1341), - ('identifier -> ID','identifier',1,'p_identifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1350), - ('constant -> INT_CONST_DEC','constant',1,'p_constant_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1354), - ('constant -> INT_CONST_OCT','constant',1,'p_constant_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1355), - ('constant -> INT_CONST_HEX','constant',1,'p_constant_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1356), - ('constant -> FLOAT_CONST','constant',1,'p_constant_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1362), - ('constant -> HEX_FLOAT_CONST','constant',1,'p_constant_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1363), - ('constant -> CHAR_CONST','constant',1,'p_constant_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1369), - ('constant -> WCHAR_CONST','constant',1,'p_constant_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1370), - ('unified_string_literal -> STRING_LITERAL','unified_string_literal',1,'p_unified_string_literal','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1381), - ('unified_string_literal -> unified_string_literal STRING_LITERAL','unified_string_literal',2,'p_unified_string_literal','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1382), - ('unified_wstring_literal -> WSTRING_LITERAL','unified_wstring_literal',1,'p_unified_wstring_literal','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1392), - ('unified_wstring_literal -> unified_wstring_literal WSTRING_LITERAL','unified_wstring_literal',2,'p_unified_wstring_literal','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1393), - ('brace_open -> LBRACE','brace_open',1,'p_brace_open','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1403), - ('brace_close -> RBRACE','brace_close',1,'p_brace_close','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1409), - ('empty -> ','empty',0,'p_empty','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1415), -] diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/build/lib.linux-x86_64-2.7/snip_basic_verify2/__init__.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/build/lib.linux-x86_64-2.7/snip_basic_verify2/__init__.py deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/build/lib.linux-x86_64-2.7/snip_basic_verify2/__init__.py +++ /dev/null @@ -1,18 +0,0 @@ - -from cffi import FFI -import sys - -ffi = FFI() -ffi.cdef(""" // some declarations from the man page - struct passwd { - char *pw_name; - ...; - }; - struct passwd *getpwuid(int uid); -""") -C = ffi.verify(""" // passed to the real C compiler -#include -#include -""", libraries=[], # or a list of libraries to link with - ext_package='snip_basic_verify2', - force_generic_engine=hasattr(sys, '_force_generic_engine_')) diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/build/lib.linux-x86_64-2.7/snip_basic_verify2/_cffi__gd39ab08bx8432a366.pypy-20.so b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/build/lib.linux-x86_64-2.7/snip_basic_verify2/_cffi__gd39ab08bx8432a366.pypy-20.so deleted file mode 100755 Binary file pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/build/lib.linux-x86_64-2.7/snip_basic_verify2/_cffi__gd39ab08bx8432a366.pypy-20.so has changed diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/build/temp.linux-x86_64-2.7/snip_basic_verify2/__pycache__/_cffi__gd39ab08bx8432a366.o b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/build/temp.linux-x86_64-2.7/snip_basic_verify2/__pycache__/_cffi__gd39ab08bx8432a366.o deleted file mode 100644 Binary file pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/build/temp.linux-x86_64-2.7/snip_basic_verify2/__pycache__/_cffi__gd39ab08bx8432a366.o has changed diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/lextab.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/lextab.py deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/lextab.py +++ /dev/null @@ -1,9 +0,0 @@ -# pycparser.lextab.py. This file automatically created by PLY (version 3.4). Don't edit! -_tabversion = '3.4' -_lextokens = {'VOID': 1, 'LBRACKET': 1, 'WCHAR_CONST': 1, 'FLOAT_CONST': 1, 'MINUS': 1, 'RPAREN': 1, 'LONG': 1, 'PLUS': 1, 'ELLIPSIS': 1, 'GT': 1, 'GOTO': 1, 'ENUM': 1, 'PERIOD': 1, 'GE': 1, 'INT_CONST_DEC': 1, 'ARROW': 1, 'HEX_FLOAT_CONST': 1, 'DOUBLE': 1, 'MINUSEQUAL': 1, 'INT_CONST_OCT': 1, 'TIMESEQUAL': 1, 'OR': 1, 'SHORT': 1, 'RETURN': 1, 'RSHIFTEQUAL': 1, 'RESTRICT': 1, 'STATIC': 1, 'SIZEOF': 1, 'UNSIGNED': 1, 'UNION': 1, 'COLON': 1, 'WSTRING_LITERAL': 1, 'DIVIDE': 1, 'FOR': 1, 'PLUSPLUS': 1, 'EQUALS': 1, 'ELSE': 1, 'INLINE': 1, 'EQ': 1, 'AND': 1, 'TYPEID': 1, 'LBRACE': 1, 'PPHASH': 1, 'INT': 1, 'SIGNED': 1, 'CONTINUE': 1, 'NOT': 1, 'OREQUAL': 1, 'MOD': 1, 'RSHIFT': 1, 'DEFAULT': 1, 'CHAR': 1, 'WHILE': 1, 'DIVEQUAL': 1, 'EXTERN': 1, 'CASE': 1, 'LAND': 1, 'REGISTER': 1, 'MODEQUAL': 1, 'NE': 1, 'SWITCH': 1, 'INT_CONST_HEX': 1, '_COMPLEX': 1, 'PLUSEQUAL': 1, 'STRUCT': 1, 'CONDOP': 1, 'BREAK': 1, 'VOLATILE': 1, 'ANDEQUAL': 1, 'DO': 1, 'LNOT': 1, 'CONST': 1, 'LOR': 1, 'CHAR_CONST': 1, 'LSHIFT': 1, 'RBRACE': 1, '_BOOL': 1, 'LE': 1, 'SEMI': 1, 'LT': 1, 'COMMA': 1, 'TYPEDEF': 1, 'XOR': 1, 'AUTO': 1, 'TIMES': 1, 'LPAREN': 1, 'MINUSMINUS': 1, 'ID': 1, 'IF': 1, 'STRING_LITERAL': 1, 'FLOAT': 1, 'XOREQUAL': 1, 'LSHIFTEQUAL': 1, 'RBRACKET': 1} -_lexreflags = 0 -_lexliterals = '' -_lexstateinfo = {'ppline': 'exclusive', 'pppragma': 'exclusive', 'INITIAL': 'inclusive'} -_lexstatere = {'ppline': [('(?P"([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*")|(?P(0(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?)|([1-9][0-9]*(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?))|(?P\\n)|(?Pline)', [None, ('t_ppline_FILENAME', 'FILENAME'), None, None, None, None, None, None, ('t_ppline_LINE_NUMBER', 'LINE_NUMBER'), None, None, None, None, None, None, None, None, ('t_ppline_NEWLINE', 'NEWLINE'), ('t_ppline_PPLINE', 'PPLINE')])], 'pppragma': [('(?P\\n)|(?Ppragma)|(?P"([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*")|(?P[a-zA-Z_][0-9a-zA-Z_]*)', [None, ('t_pppragma_NEWLINE', 'NEWLINE'), ('t_pppragma_PPPRAGMA', 'PPPRAGMA'), ('t_pppragma_STR', 'STR'), None, None, None, None, None, None, ('t_pppragma_ID', 'ID')])], 'INITIAL': [('(?P[ \\t]*\\#)|(?P\\n+)|(?P((((([0-9]*\\.[0-9]+)|([0-9]+\\.))([eE][-+]?[0-9]+)?)|([0-9]+([eE][-+]?[0-9]+)))[FfLl]?))|(?P(0[xX]([0-9a-fA-F]+|((([0-9a-fA-F]+)?\\.[0-9a-fA-F]+)|([0-9a-fA-F]+\\.)))([pP][+-]?[0-9]+)[FfLl]?))|(?P0[xX][0-9a-fA-F]+(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?)|(?P0[0-7]*[89])|(?P0[0-7]*(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?)', [None, ('t_PPHASH', 'PPHASH'), ('t_NEWLINE', 'NEWLINE'), ('t_FLOAT_CONST', 'FLOAT_CONST'), None, None, None, None, None, None, None, None, None, ('t_HEX_FLOAT_CONST', 'HEX_FLOAT_CONST'), None, None, None, None, None, None, None, ('t_INT_CONST_HEX', 'INT_CONST_HEX'), None, None, None, ('t_BAD_CONST_OCT', 'BAD_CONST_OCT'), ('t_INT_CONST_OCT', 'INT_CONST_OCT')]), ('(?P(0(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?)|([1-9][0-9]*(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?))|(?P\'([^\'\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))\')|(?PL\'([^\'\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))\')|(?P(\'([^\'\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*\\n)|(\'([^\'\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*$))|(?P(\'([^\'\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))[^\'\n]+\')|(\'\')|(\'([\\\\][^a-zA-Z._~^!=&\\^\\-\\\\?\'"x0-7])[^\'\\n]*\'))|(?PL"([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*")|(?P"([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*([\\\\][^a-zA-Z._~^!=&\\^\\-\\\\?\'"x0-7])([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*")|(?P[a-zA-Z_][0-9a-zA-Z_]*)', [None, ('t_INT_CONST_DEC', 'INT_CONST_DEC'), None, None, None, None, None, None, None, None, ('t_CHAR_CONST', 'CHAR_CONST'), None, None, None, None, None, None, ('t_WCHAR_CONST', 'WCHAR_CONST'), None, None, None, None, None, None, ('t_UNMATCHED_QUOTE', 'UNMATCHED_QUOTE'), None, None, None, None, None, None, None, None, None, None, None, None, None, None, ('t_BAD_CHAR_CONST', 'BAD_CHAR_CONST'), None, None, None, None, None, None, None, None, None, None, ('t_WSTRING_LITERAL', 'WSTRING_LITERAL'), None, None, None, None, None, None, ('t_BAD_STRING_LITERAL', 'BAD_STRING_LITERAL'), None, None, None, None, None, None, None, None, None, None, None, None, None, ('t_ID', 'ID')]), ('(?P"([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*")|(?P\\.\\.\\.)|(?P\\+\\+)|(?P\\|\\|)|(?P\\^=)|(?P\\|=)|(?P<<=)|(?P>>=)|(?P\\+=)|(?P\\*=)|(?P\\+)|(?P%=)|(?P\\{)|(?P/=)|(?P\\])|(?P\\?)', [None, (None, 'STRING_LITERAL'), None, None, None, None, None, None, (None, 'ELLIPSIS'), (None, 'PLUSPLUS'), (None, 'LOR'), (None, 'XOREQUAL'), (None, 'OREQUAL'), (None, 'LSHIFTEQUAL'), (None, 'RSHIFTEQUAL'), (None, 'PLUSEQUAL'), (None, 'TIMESEQUAL'), (None, 'PLUS'), (None, 'MODEQUAL'), (None, 'LBRACE'), (None, 'DIVEQUAL'), (None, 'RBRACKET'), (None, 'CONDOP')]), ('(?P\\^)|(?P<<)|(?P<=)|(?P\\()|(?P->)|(?P==)|(?P\\})|(?P!=)|(?P--)|(?P\\|)|(?P\\*)|(?P\\[)|(?P>=)|(?P\\))|(?P&&)|(?P>>)|(?P&=)|(?P-=)|(?P\\.)|(?P=)|(?P<)|(?P,)|(?P/)|(?P&)|(?P%)|(?P;)|(?P-)|(?P>)|(?P:)|(?P~)|(?P!)', [None, (None, 'XOR'), (None, 'LSHIFT'), (None, 'LE'), (None, 'LPAREN'), (None, 'ARROW'), (None, 'EQ'), (None, 'RBRACE'), (None, 'NE'), (None, 'MINUSMINUS'), (None, 'OR'), (None, 'TIMES'), (None, 'LBRACKET'), (None, 'GE'), (None, 'RPAREN'), (None, 'LAND'), (None, 'RSHIFT'), (None, 'ANDEQUAL'), (None, 'MINUSEQUAL'), (None, 'PERIOD'), (None, 'EQUALS'), (None, 'LT'), (None, 'COMMA'), (None, 'DIVIDE'), (None, 'AND'), (None, 'MOD'), (None, 'SEMI'), (None, 'MINUS'), (None, 'GT'), (None, 'COLON'), (None, 'NOT'), (None, 'LNOT')])]} -_lexstateignore = {'ppline': ' \t', 'pppragma': ' \t<>.-{}();+-*/$%@&^~!?:,0123456789', 'INITIAL': ' \t'} -_lexstateerrorf = {'ppline': 't_ppline_error', 'pppragma': 't_pppragma_error', 'INITIAL': 't_error'} diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/setup.py deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/setup.py +++ /dev/null @@ -1,9 +0,0 @@ -# Generated by pypy/tool/import_cffi.py - -from distutils.core import setup -import snip_basic_verify2 - -setup( - packages=['snip_basic_verify2'], - ext_package='snip_basic_verify2', - ext_modules=[snip_basic_verify2.ffi.verifier.get_extension()]) diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/snip_basic_verify2/__init__.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/snip_basic_verify2/__init__.py deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/snip_basic_verify2/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by pypy/tool/import_cffi.py - -from cffi import FFI -import sys - -ffi = FFI() -ffi.cdef(""" // some declarations from the man page - struct passwd { - char *pw_name; - ...; - }; - struct passwd *getpwuid(int uid); -""") -C = ffi.verify(""" // passed to the real C compiler -#include -#include -""", libraries=[], # or a list of libraries to link with - ext_package='snip_basic_verify2', - force_generic_engine=hasattr(sys, '_force_generic_engine_')) diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/snip_basic_verify2/__pycache__/_cffi__gd39ab08bx8432a366.c b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/snip_basic_verify2/__pycache__/_cffi__gd39ab08bx8432a366.c deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/snip_basic_verify2/__pycache__/_cffi__gd39ab08bx8432a366.c +++ /dev/null @@ -1,53 +0,0 @@ - -#include -#include -#include -#include -#include /* XXX for ssize_t on some platforms */ - -#ifdef _WIN32 -# include -# define snprintf _snprintf -typedef __int8 int8_t; -typedef __int16 int16_t; -typedef __int32 int32_t; -typedef __int64 int64_t; -typedef unsigned __int8 uint8_t; -typedef unsigned __int16 uint16_t; -typedef unsigned __int32 uint32_t; -typedef unsigned __int64 uint64_t; -typedef SSIZE_T ssize_t; -typedef unsigned char _Bool; -#else -# include -#endif - - // passed to the real C compiler -#include -#include - -struct passwd * _cffi_f_getpwuid(int x0) -{ - return getpwuid(x0); -} - -static void _cffi_check_struct_passwd(struct passwd *p) -{ - /* only to generate compile-time warnings or errors */ - { char * *tmp = &p->pw_name; (void)tmp; } -} -ssize_t _cffi_layout_struct_passwd(ssize_t i) -{ - struct _cffi_aligncheck { char x; struct passwd y; }; - static ssize_t nums[] = { - sizeof(struct passwd), - offsetof(struct _cffi_aligncheck, y), - offsetof(struct passwd, pw_name), - sizeof(((struct passwd *)0)->pw_name), - -1 - }; - return nums[i]; - /* the next line is not executed, but compiled */ - _cffi_check_struct_passwd(0); -} - diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/snip_basic_verify2/__pycache__/_cffi__gd39ab08bx8432a366.pypy-20.so b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/snip_basic_verify2/__pycache__/_cffi__gd39ab08bx8432a366.pypy-20.so deleted file mode 100755 Binary file pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/snip_basic_verify2/__pycache__/_cffi__gd39ab08bx8432a366.pypy-20.so has changed diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/snip_basic_verify2/__pycache__/snip_basic_verify2/__pycache__/_cffi__gd39ab08bx8432a366.o b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/snip_basic_verify2/__pycache__/snip_basic_verify2/__pycache__/_cffi__gd39ab08bx8432a366.o deleted file mode 100644 Binary file pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/snip_basic_verify2/__pycache__/snip_basic_verify2/__pycache__/_cffi__gd39ab08bx8432a366.o has changed diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/yacctab.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/yacctab.py deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/yacctab.py +++ /dev/null @@ -1,280 +0,0 @@ - -# yacctab.py -# This file is automatically generated. Do not edit. -_tabversion = '3.2' - -_lr_method = 'LALR' - -_lr_signature = '\x9er\xf1|P\xb6\xbb\x13\xed\xf52\xa1\xb1\xc3J\x12' - -_lr_action_items = {'VOID':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[6,6,-61,-72,-71,-58,-54,-55,-33,-29,-59,6,-34,-53,-68,-63,-52,6,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,6,-67,6,-70,-74,6,-57,-82,-249,-81,6,-107,-30,6,-97,-96,6,-45,-46,6,-109,6,6,6,6,-88,6,6,-36,6,-47,6,6,-83,-89,-250,6,-110,6,6,-111,-113,-112,6,6,-98,-37,-39,-42,-38,-40,6,-148,-147,-43,-149,-41,-85,-84,-90,6,6,-100,-99,-167,-166,6,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'LBRACKET':([1,2,3,5,6,9,10,13,14,17,18,19,21,23,24,25,27,28,29,32,33,35,37,39,40,42,43,44,45,46,49,50,51,52,54,55,56,58,59,63,64,66,67,68,69,76,77,83,87,89,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,129,138,139,149,151,152,153,154,155,174,178,180,184,185,191,195,216,217,218,223,224,231,235,262,264,265,273,274,277,281,285,286,314,318,319,323,329,350,351,357,359,360,361,362,366,369,371,387,388,389,390,400,401,409,],[-251,-61,-72,-71,-58,-54,-55,-59,-251,-53,-68,-63,-52,-56,-170,61,-66,-251,-69,-73,-108,-64,-60,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-249,-81,-49,61,-97,-96,-116,-114,-26,-25,-48,-51,-109,-251,-251,-233,-243,-247,-244,-241,-231,-232,182,-240,-220,-237,-245,-238,-242,-239,-230,221,-115,-117,-83,-250,-21,-80,-22,-79,-248,-246,-226,-227,-110,-111,221,-113,-112,221,312,221,-98,325,-237,-85,-84,-225,-224,-223,-234,221,221,312,-100,-99,-132,325,-221,-222,325,-146,-140,-142,-144,-135,325,-133,-141,-143,-145,-134,325,-228,-229,]),'WCHAR_CONST':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,96,-45,-219,96,-217,96,-216,96,-215,96,96,-214,-218,96,96,-250,96,-176,-179,-177,-173,-174,-178,-180,96,-182,-183,-175,-181,96,-215,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,-251,-39,-42,-38,96,-40,96,96,-148,-147,-43,-149,96,-41,96,96,96,-215,96,-12,96,96,-11,-167,-166,96,-164,96,96,-150,96,-163,-151,96,96,96,96,-251,96,-215,-251,-131,-162,-165,96,-154,96,-152,96,96,96,-153,96,96,96,-251,96,-158,-157,-155,96,96,96,-159,-156,96,-161,-160,]),'FLOAT_CONST':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,97,-45,-219,97,-217,97,-216,97,-215,97,97,-214,-218,97,97,-250,97,-176,-179,-177,-173,-174,-178,-180,97,-182,-183,-175,-181,97,-215,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,-251,-39,-42,-38,97,-40,97,97,-148,-147,-43,-149,97,-41,97,97,97,-215,97,-12,97,97,-11,-167,-166,97,-164,97,97,-150,97,-163,-151,97,97,97,97,-251,97,-215,-251,-131,-162,-165,97,-154,97,-152,97,97,97,-153,97,97,97,-251,97,-158,-157,-155,97,97,97,-159,-156,97,-161,-160,]),'MINUS':([55,61,75,91,92,93,94,95,96,97,98,99,100,101,102,104,105,106,108,109,110,111,112,113,114,115,116,117,118,119,120,123,124,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,180,182,183,184,186,187,188,189,190,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,262,270,273,274,277,281,282,283,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,349,350,351,352,353,356,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[-249,100,-45,-219,-206,-233,-243,-247,-244,-241,-231,100,-217,-232,-208,-187,100,-216,100,-240,-215,-220,100,100,-237,-245,-214,-238,200,-242,-239,-218,-230,100,100,-250,100,-176,-179,-177,-173,-174,-178,-180,100,-182,-183,-175,-181,-248,100,-212,-215,-246,-226,100,100,-227,100,-206,-211,100,-209,-210,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,-251,-39,-42,-38,100,-40,100,100,-148,-147,-43,-149,100,-41,-237,100,-225,-224,-223,-234,100,100,200,200,200,-192,200,200,200,-191,200,200,-189,-188,200,200,200,200,200,-190,-215,100,-12,100,100,-11,-167,-166,100,-164,100,100,-150,100,-163,-151,100,100,-213,-221,-222,100,100,-207,-251,100,-215,-251,-131,-162,-165,100,-154,100,-152,100,100,100,-153,100,100,100,-251,-228,100,-158,-157,-155,-229,100,100,100,-159,-156,100,-161,-160,]),'RPAREN':([1,2,3,5,6,9,10,13,14,17,18,19,21,23,24,25,27,28,29,32,33,35,37,39,40,42,43,44,45,46,49,50,51,52,53,54,56,58,59,62,63,64,66,67,68,69,76,77,83,87,89,92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,122,124,125,126,127,128,129,130,131,132,138,139,149,151,152,153,154,155,174,176,178,180,183,184,185,187,188,190,191,192,193,194,195,196,216,217,218,219,220,222,223,224,225,231,247,264,265,271,272,273,274,276,277,278,279,280,281,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,306,307,308,309,313,314,315,316,317,318,319,339,349,350,351,355,356,359,360,361,362,365,378,380,383,384,386,387,388,389,401,404,407,409,410,411,414,],[-251,-61,-72,-71,-58,-54,-55,-59,-251,-53,-68,-63,-52,-56,-170,-106,-66,-251,-69,-73,-108,-64,-60,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,83,-82,-81,-49,-107,-251,-97,-96,-116,-114,-26,-25,-48,-51,-109,-251,-251,-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,-185,-242,-239,-171,-230,216,-15,217,-120,-251,-16,-118,-124,-115,-117,-83,-250,-21,-80,-22,-79,-248,-212,-246,-226,277,-227,-110,-206,-211,-209,-111,281,283,-168,-251,-210,-113,-112,-251,-123,-2,-122,-139,-137,-1,-98,-14,-85,-84,-172,349,-225,-224,-235,-223,351,353,354,-234,-136,-251,-137,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-19,-20,359,360,-251,-138,-125,-119,-121,-100,-99,-13,-213,-221,-222,-169,-207,-146,-140,-142,-144,389,395,397,399,-236,-186,-141,-143,-145,-228,-251,412,-229,-251,415,418,]),'LONG':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[19,19,-61,-72,-71,-58,-54,-55,-33,-29,-59,19,-34,-53,-68,-63,-52,19,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,19,-67,19,-70,-74,19,-57,-82,-249,-81,19,-107,-30,19,-97,-96,19,-45,-46,19,-109,19,19,19,19,-88,19,19,-36,19,-47,19,19,-83,-89,-250,19,-110,19,19,-111,-113,-112,19,19,-98,-37,-39,-42,-38,-40,19,-148,-147,-43,-149,-41,-85,-84,-90,19,19,-100,-99,-167,-166,19,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'PLUS':([55,61,75,91,92,93,94,95,96,97,98,99,100,101,102,104,105,106,108,109,110,111,112,113,114,115,116,117,118,119,120,123,124,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,180,182,183,184,186,187,188,189,190,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,262,270,273,274,277,281,282,283,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,349,350,351,352,353,356,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[-249,106,-45,-219,-206,-233,-243,-247,-244,-241,-231,106,-217,-232,-208,-187,106,-216,106,-240,-215,-220,106,106,-237,-245,-214,-238,204,-242,-239,-218,-230,106,106,-250,106,-176,-179,-177,-173,-174,-178,-180,106,-182,-183,-175,-181,-248,106,-212,-215,-246,-226,106,106,-227,106,-206,-211,106,-209,-210,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,-251,-39,-42,-38,106,-40,106,106,-148,-147,-43,-149,106,-41,-237,106,-225,-224,-223,-234,106,106,204,204,204,-192,204,204,204,-191,204,204,-189,-188,204,204,204,204,204,-190,-215,106,-12,106,106,-11,-167,-166,106,-164,106,106,-150,106,-163,-151,106,106,-213,-221,-222,106,106,-207,-251,106,-215,-251,-131,-162,-165,106,-154,106,-152,106,106,106,-153,106,106,106,-251,-228,106,-158,-157,-155,-229,106,106,106,-159,-156,106,-161,-160,]),'ELLIPSIS':([227,],[316,]),'GT':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,205,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,205,-194,-192,-196,205,-195,-191,-198,205,-189,-188,-197,205,205,205,205,-190,-213,-221,-222,-207,-228,-229,]),'GOTO':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,240,-250,-39,-42,-38,-40,240,-148,-147,-43,-149,240,-41,-167,-166,-164,240,-150,-163,-151,240,-162,-165,-154,240,-152,240,-153,240,240,-158,-157,-155,240,240,-159,-156,240,-161,-160,]),'ENUM':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[26,26,-61,-72,-71,-58,-54,-55,-33,-29,-59,26,-34,-53,-68,-63,-52,26,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,26,-67,26,-70,-74,26,-57,-82,-249,-81,26,-107,-30,26,-97,-96,26,-45,-46,26,-109,26,26,26,26,-88,26,26,-36,26,-47,26,26,-83,-89,-250,26,-110,26,26,-111,-113,-112,26,26,-98,-37,-39,-42,-38,-40,26,-148,-147,-43,-149,-41,-85,-84,-90,26,26,-100,-99,-167,-166,26,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'PERIOD':([55,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,178,180,184,235,262,273,274,277,281,323,329,350,351,357,366,369,371,390,400,401,409,],[-249,-233,-243,-247,-244,-241,-231,-232,181,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-246,-226,-227,324,-237,-225,-224,-223,-234,-132,324,-221,-222,324,-135,324,-133,-134,324,-228,-229,]),'GE':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,209,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,209,-194,-192,-196,209,-195,-191,-198,209,-189,-188,-197,209,209,209,209,-190,-213,-221,-222,-207,-228,-229,]),'INT_CONST_DEC':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,117,-45,-219,117,-217,117,-216,117,-215,117,117,-214,-218,117,117,-250,117,-176,-179,-177,-173,-174,-178,-180,117,-182,-183,-175,-181,117,-215,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,-251,-39,-42,-38,117,-40,117,117,-148,-147,-43,-149,117,-41,117,117,117,-215,117,-12,117,117,-11,-167,-166,117,-164,117,117,-150,117,-163,-151,117,117,117,117,-251,117,-215,-251,-131,-162,-165,117,-154,117,-152,117,117,117,-153,117,117,117,-251,117,-158,-157,-155,117,117,117,-159,-156,117,-161,-160,]),'ARROW':([93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,178,180,184,262,273,274,277,281,350,351,401,409,],[-233,-243,-247,-244,-241,-231,-232,179,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-246,-226,-227,-237,-225,-224,-223,-234,-221,-222,-228,-229,]),'HEX_FLOAT_CONST':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,119,-45,-219,119,-217,119,-216,119,-215,119,119,-214,-218,119,119,-250,119,-176,-179,-177,-173,-174,-178,-180,119,-182,-183,-175,-181,119,-215,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,-251,-39,-42,-38,119,-40,119,119,-148,-147,-43,-149,119,-41,119,119,119,-215,119,-12,119,119,-11,-167,-166,119,-164,119,119,-150,119,-163,-151,119,119,119,119,-251,119,-215,-251,-131,-162,-165,119,-154,119,-152,119,119,119,-153,119,119,119,-251,119,-158,-157,-155,119,119,119,-159,-156,119,-161,-160,]),'DOUBLE':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[40,40,-61,-72,-71,-58,-54,-55,-33,-29,-59,40,-34,-53,-68,-63,-52,40,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,40,-67,40,-70,-74,40,-57,-82,-249,-81,40,-107,-30,40,-97,-96,40,-45,-46,40,-109,40,40,40,40,-88,40,40,-36,40,-47,40,40,-83,-89,-250,40,-110,40,40,-111,-113,-112,40,40,-98,-37,-39,-42,-38,-40,40,-148,-147,-43,-149,-41,-85,-84,-90,40,40,-100,-99,-167,-166,40,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'MINUSEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[163,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'INT_CONST_OCT':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,120,-45,-219,120,-217,120,-216,120,-215,120,120,-214,-218,120,120,-250,120,-176,-179,-177,-173,-174,-178,-180,120,-182,-183,-175,-181,120,-215,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,-251,-39,-42,-38,120,-40,120,120,-148,-147,-43,-149,120,-41,120,120,120,-215,120,-12,120,120,-11,-167,-166,120,-164,120,120,-150,120,-163,-151,120,120,120,120,-251,120,-215,-251,-131,-162,-165,120,-154,120,-152,120,120,120,-153,120,120,120,-251,120,-158,-157,-155,120,120,120,-159,-156,120,-161,-160,]),'TIMESEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[172,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'OR':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,214,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,214,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,214,-199,-201,-202,-190,-213,-221,-222,-207,-228,-229,]),'SHORT':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[2,2,-61,-72,-71,-58,-54,-55,-33,-29,-59,2,-34,-53,-68,-63,-52,2,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,2,-67,2,-70,-74,2,-57,-82,-249,-81,2,-107,-30,2,-97,-96,2,-45,-46,2,-109,2,2,2,2,-88,2,2,-36,2,-47,2,2,-83,-89,-250,2,-110,2,2,-111,-113,-112,2,2,-98,-37,-39,-42,-38,-40,2,-148,-147,-43,-149,-41,-85,-84,-90,2,2,-100,-99,-167,-166,2,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'RETURN':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,243,-250,-39,-42,-38,-40,243,-148,-147,-43,-149,243,-41,-167,-166,-164,243,-150,-163,-151,243,-162,-165,-154,243,-152,243,-153,243,243,-158,-157,-155,243,243,-159,-156,243,-161,-160,]),'RSHIFTEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[173,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'RESTRICT':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,28,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,66,68,73,75,80,82,83,84,85,86,87,88,89,112,139,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[32,32,-61,-72,-71,-58,-54,-55,-33,-29,-59,32,-34,-53,-68,-63,-52,32,-56,-170,-106,-66,32,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,32,-67,32,-70,-74,32,-57,-82,-249,-81,32,-107,-30,32,-97,-96,-116,32,32,-45,-46,32,-109,32,32,32,32,-88,32,32,-117,-36,32,-47,32,32,-83,-89,-250,32,-110,32,32,-111,-113,-112,32,32,-98,-37,-39,-42,-38,-40,32,-148,-147,-43,-149,-41,-85,-84,-90,32,32,-100,-99,-167,-166,32,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'STATIC':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[9,9,-61,-72,-71,-58,-54,-55,-33,-29,-59,9,-34,-53,-68,-63,-52,9,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,9,-67,9,-70,-74,9,-57,-82,-249,-81,-107,-30,9,-97,-96,9,-45,-46,9,-109,-36,9,-47,-83,-250,-110,-111,-113,-112,9,9,-98,-37,-39,-42,-38,-40,9,-148,-147,-43,-149,-41,-85,-84,9,9,-100,-99,-167,-166,9,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'SIZEOF':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,99,-45,-219,99,-217,99,-216,99,-215,99,99,-214,-218,99,99,-250,99,-176,-179,-177,-173,-174,-178,-180,99,-182,-183,-175,-181,99,-215,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,-251,-39,-42,-38,99,-40,99,99,-148,-147,-43,-149,99,-41,99,99,99,-215,99,-12,99,99,-11,-167,-166,99,-164,99,99,-150,99,-163,-151,99,99,99,99,-251,99,-215,-251,-131,-162,-165,99,-154,99,-152,99,99,99,-153,99,99,99,-251,99,-158,-157,-155,99,99,99,-159,-156,99,-161,-160,]),'UNSIGNED':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[18,18,-61,-72,-71,-58,-54,-55,-33,-29,-59,18,-34,-53,-68,-63,-52,18,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,18,-67,18,-70,-74,18,-57,-82,-249,-81,18,-107,-30,18,-97,-96,18,-45,-46,18,-109,18,18,18,18,-88,18,18,-36,18,-47,18,18,-83,-89,-250,18,-110,18,18,-111,-113,-112,18,18,-98,-37,-39,-42,-38,-40,18,-148,-147,-43,-149,-41,-85,-84,-90,18,18,-100,-99,-167,-166,18,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'UNION':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[20,20,-61,-72,-71,-58,-54,-55,-33,-29,-59,20,-34,-53,-68,-63,-52,20,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,20,-67,20,-70,-74,20,-57,-82,-249,-81,20,-107,-30,20,-97,-96,20,-45,-46,20,-109,20,20,20,20,-88,20,20,-36,20,-47,20,20,-83,-89,-250,20,-110,20,20,-111,-113,-112,20,20,-98,-37,-39,-42,-38,-40,20,-148,-147,-43,-149,-41,-85,-84,-90,20,20,-100,-99,-167,-166,20,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'COLON':([2,3,5,6,13,18,19,24,25,27,29,32,33,35,37,39,40,43,45,46,54,56,59,63,64,83,87,89,90,92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,122,124,149,151,152,153,154,155,161,174,176,178,180,184,185,187,188,190,191,194,196,216,217,231,248,262,264,265,267,268,271,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,318,319,338,349,350,351,355,356,386,401,409,],[-61,-72,-71,-58,-59,-68,-63,-170,-106,-66,-69,-73,-108,-64,-60,-62,-65,-67,-70,-74,-82,-81,-107,-97,-96,-109,-251,-251,156,-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,-185,-242,-239,-171,-230,-83,-250,-21,-80,-22,-79,270,-248,-212,-246,-226,-227,-110,-206,-211,-209,-111,-168,-210,-113,-112,-98,336,345,-85,-84,-184,156,-172,-225,-224,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,358,-202,-190,-100,-99,379,-213,-221,-222,-169,-207,-186,-228,-229,]),'$end':([0,8,11,12,15,22,31,36,38,47,60,75,144,151,237,344,],[-251,0,-33,-29,-34,-27,-32,-31,-35,-28,-30,-45,-36,-250,-37,-151,]),'WSTRING_LITERAL':([55,61,75,91,93,95,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,95,-45,-219,174,-247,95,-217,95,-216,95,-215,95,95,-214,-218,95,95,-250,95,-176,-179,-177,-173,-174,-178,-180,95,-182,-183,-175,-181,-248,95,-215,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,-251,-39,-42,-38,95,-40,95,95,-148,-147,-43,-149,95,-41,95,95,95,-215,95,-12,95,95,-11,-167,-166,95,-164,95,95,-150,95,-163,-151,95,95,95,95,-251,95,-215,-251,-131,-162,-165,95,-154,95,-152,95,95,95,-153,95,95,95,-251,95,-158,-157,-155,95,95,95,-159,-156,95,-161,-160,]),'DIVIDE':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,207,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,207,207,207,207,207,207,207,207,207,207,-189,-188,207,207,207,207,207,-190,-213,-221,-222,-207,-228,-229,]),'FOR':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,245,-250,-39,-42,-38,-40,245,-148,-147,-43,-149,245,-41,-167,-166,-164,245,-150,-163,-151,245,-162,-165,-154,245,-152,245,-153,245,245,-158,-157,-155,245,245,-159,-156,245,-161,-160,]),'PLUSPLUS':([55,61,75,91,93,94,95,96,97,98,99,100,101,102,105,106,108,109,110,111,112,113,114,115,116,117,119,120,123,124,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,177,178,180,182,183,184,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,262,270,273,274,277,281,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,350,351,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[-249,108,-45,-219,-233,-243,-247,-244,-241,-231,108,-217,-232,180,108,-216,108,-240,-215,-220,108,108,-237,-245,-214,-238,-242,-239,-218,-230,108,108,-250,108,-176,-179,-177,-173,-174,-178,-180,108,-182,-183,-175,-181,-248,108,-215,-246,-226,108,108,-227,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,-251,-39,-42,-38,108,-40,108,108,-148,-147,-43,-149,108,-41,-237,108,-225,-224,-223,-234,108,108,-215,108,-12,108,108,-11,-167,-166,108,-164,108,108,-150,108,-163,-151,108,108,-221,-222,108,108,-251,108,-215,-251,-131,-162,-165,108,-154,108,-152,108,108,108,-153,108,108,108,-251,-228,108,-158,-157,-155,-229,108,108,108,-159,-156,108,-161,-160,]),'EQUALS':([25,33,59,73,83,92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,137,143,151,174,176,178,180,184,185,187,188,190,191,196,216,217,262,273,274,277,281,323,329,349,350,351,356,366,371,390,401,409,],[-106,-108,-107,141,-109,165,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,232,141,-250,-248,-212,-246,-226,-227,-110,-206,-211,-209,-111,-210,-113,-112,-237,-225,-224,-223,-234,-132,372,-213,-221,-222,-207,-135,-133,-134,-228,-229,]),'ELSE':([151,238,239,242,244,255,260,331,332,335,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[-250,-39,-42,-38,-40,-43,-41,-167,-166,-164,-163,-151,-162,-165,-154,-152,-153,-158,-157,413,-159,-156,-161,-160,]),'ANDEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[170,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'EQ':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,211,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,211,-194,-192,-196,-200,-195,-191,-198,211,-189,-188,-197,211,-199,211,211,-190,-213,-221,-222,-207,-228,-229,]),'AND':([55,61,75,91,92,93,94,95,96,97,98,99,100,101,102,104,105,106,108,109,110,111,112,113,114,115,116,117,118,119,120,123,124,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,180,182,183,184,186,187,188,189,190,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,262,270,273,274,277,281,282,283,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,349,350,351,352,353,356,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[-249,116,-45,-219,-206,-233,-243,-247,-244,-241,-231,116,-217,-232,-208,-187,116,-216,116,-240,-215,-220,116,116,-237,-245,-214,-238,212,-242,-239,-218,-230,116,116,-250,116,-176,-179,-177,-173,-174,-178,-180,116,-182,-183,-175,-181,-248,116,-212,-215,-246,-226,116,116,-227,116,-206,-211,116,-209,-210,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,-251,-39,-42,-38,116,-40,116,116,-148,-147,-43,-149,116,-41,-237,116,-225,-224,-223,-234,116,116,-193,212,-194,-192,-196,-200,-195,-191,-198,212,-189,-188,-197,212,-199,-201,212,-190,-215,116,-12,116,116,-11,-167,-166,116,-164,116,116,-150,116,-163,-151,116,116,-213,-221,-222,116,116,-207,-251,116,-215,-251,-131,-162,-165,116,-154,116,-152,116,116,116,-153,116,116,116,-251,-228,116,-158,-157,-155,-229,116,116,116,-159,-156,116,-161,-160,]),'TYPEID':([0,1,2,3,5,6,7,9,10,11,12,13,14,15,17,18,19,20,21,22,23,24,25,26,27,29,31,32,33,34,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[24,24,-61,-72,-71,-58,54,-54,-55,-33,-29,-59,24,-34,-53,-68,-63,-87,-52,24,-56,-170,-106,63,-66,-69,-32,-73,-108,-86,-64,-31,-60,-35,-62,-65,24,-67,24,-70,-74,24,-57,-82,-249,-81,24,-107,-30,24,-97,-96,24,-45,-46,24,-109,24,24,24,24,-88,24,24,-36,24,-47,24,24,-83,-89,-250,24,-110,24,24,-111,-113,-112,24,24,-98,-37,-39,-42,-38,-40,24,-148,-147,-43,-149,-41,-85,-84,-90,24,24,-100,-99,-167,-166,24,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'LBRACE':([7,20,25,26,33,34,48,54,55,56,59,63,64,73,75,78,80,81,82,83,141,142,145,146,151,185,191,216,217,235,238,239,242,244,251,253,254,255,257,259,260,283,322,326,327,331,332,335,336,340,342,344,345,349,353,354,357,369,372,373,374,377,379,382,391,395,396,397,399,400,405,406,408,413,415,416,417,418,419,420,],[55,-87,-106,55,-108,-86,-251,55,-249,55,-107,55,55,-251,-45,-7,-46,55,-8,-109,55,55,55,-47,-250,-110,-111,-113,-112,-251,-39,-42,-38,-40,55,-148,-147,-43,-149,55,-41,55,-12,55,-11,-167,-166,-164,55,-150,-163,-151,55,55,55,55,-251,-251,-131,-162,-165,-154,55,-152,55,55,-153,55,55,-251,-158,-157,-155,55,55,-159,-156,55,-161,-160,]),'PPHASH':([0,11,12,15,22,31,36,38,60,75,144,151,237,344,],[38,-33,-29,-34,38,-32,-31,-35,-30,-45,-36,-250,-37,-151,]),'INT':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[39,39,-61,-72,-71,-58,-54,-55,-33,-29,-59,39,-34,-53,-68,-63,-52,39,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,39,-67,39,-70,-74,39,-57,-82,-249,-81,39,-107,-30,39,-97,-96,39,-45,-46,39,-109,39,39,39,39,-88,39,39,-36,39,-47,39,39,-83,-89,-250,39,-110,39,39,-111,-113,-112,39,39,-98,-37,-39,-42,-38,-40,39,-148,-147,-43,-149,-41,-85,-84,-90,39,39,-100,-99,-167,-166,39,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'SIGNED':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[43,43,-61,-72,-71,-58,-54,-55,-33,-29,-59,43,-34,-53,-68,-63,-52,43,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,43,-67,43,-70,-74,43,-57,-82,-249,-81,43,-107,-30,43,-97,-96,43,-45,-46,43,-109,43,43,43,43,-88,43,43,-36,43,-47,43,43,-83,-89,-250,43,-110,43,43,-111,-113,-112,43,43,-98,-37,-39,-42,-38,-40,43,-148,-147,-43,-149,-41,-85,-84,-90,43,43,-100,-99,-167,-166,43,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'CONTINUE':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,246,-250,-39,-42,-38,-40,246,-148,-147,-43,-149,246,-41,-167,-166,-164,246,-150,-163,-151,246,-162,-165,-154,246,-152,246,-153,246,246,-158,-157,-155,246,246,-159,-156,246,-161,-160,]),'NOT':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,123,-45,-219,123,-217,123,-216,123,-215,123,123,-214,-218,123,123,-250,123,-176,-179,-177,-173,-174,-178,-180,123,-182,-183,-175,-181,123,-215,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,-251,-39,-42,-38,123,-40,123,123,-148,-147,-43,-149,123,-41,123,123,123,-215,123,-12,123,123,-11,-167,-166,123,-164,123,123,-150,123,-163,-151,123,123,123,123,-251,123,-215,-251,-131,-162,-165,123,-154,123,-152,123,123,123,-153,123,123,123,-251,123,-158,-157,-155,123,123,123,-159,-156,123,-161,-160,]),'OREQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[171,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'MOD':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,215,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,215,215,215,215,215,215,215,215,215,215,-189,-188,215,215,215,215,215,-190,-213,-221,-222,-207,-228,-229,]),'RSHIFT':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,197,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,197,-194,-192,197,197,197,-191,197,197,-189,-188,197,197,197,197,197,-190,-213,-221,-222,-207,-228,-229,]),'DEFAULT':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,248,-250,-39,-42,-38,-40,248,-148,-147,-43,-149,248,-41,-167,-166,-164,248,-150,-163,-151,248,-162,-165,-154,248,-152,248,-153,248,248,-158,-157,-155,248,248,-159,-156,248,-161,-160,]),'CHAR':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[37,37,-61,-72,-71,-58,-54,-55,-33,-29,-59,37,-34,-53,-68,-63,-52,37,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,37,-67,37,-70,-74,37,-57,-82,-249,-81,37,-107,-30,37,-97,-96,37,-45,-46,37,-109,37,37,37,37,-88,37,37,-36,37,-47,37,37,-83,-89,-250,37,-110,37,37,-111,-113,-112,37,37,-98,-37,-39,-42,-38,-40,37,-148,-147,-43,-149,-41,-85,-84,-90,37,37,-100,-99,-167,-166,37,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'WHILE':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,343,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,249,-250,-39,-42,-38,-40,249,-148,-147,-43,-149,249,-41,-167,-166,-164,249,-150,-163,381,-151,249,-162,-165,-154,249,-152,249,-153,249,249,-158,-157,-155,249,249,-159,-156,249,-161,-160,]),'DIVEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[162,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'EXTERN':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[10,10,-61,-72,-71,-58,-54,-55,-33,-29,-59,10,-34,-53,-68,-63,-52,10,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,10,-67,10,-70,-74,10,-57,-82,-249,-81,-107,-30,10,-97,-96,10,-45,-46,10,-109,-36,10,-47,-83,-250,-110,-111,-113,-112,10,10,-98,-37,-39,-42,-38,-40,10,-148,-147,-43,-149,-41,-85,-84,10,10,-100,-99,-167,-166,10,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'CASE':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,250,-250,-39,-42,-38,-40,250,-148,-147,-43,-149,250,-41,-167,-166,-164,250,-150,-163,-151,250,-162,-165,-154,250,-152,250,-153,250,250,-158,-157,-155,250,250,-159,-156,250,-161,-160,]),'LAND':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,210,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,210,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-213,-221,-222,-207,-228,-229,]),'REGISTER':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[17,17,-61,-72,-71,-58,-54,-55,-33,-29,-59,17,-34,-53,-68,-63,-52,17,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,17,-67,17,-70,-74,17,-57,-82,-249,-81,-107,-30,17,-97,-96,17,-45,-46,17,-109,-36,17,-47,-83,-250,-110,-111,-113,-112,17,17,-98,-37,-39,-42,-38,-40,17,-148,-147,-43,-149,-41,-85,-84,17,17,-100,-99,-167,-166,17,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'MODEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[164,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'NE':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,202,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,202,-194,-192,-196,-200,-195,-191,-198,202,-189,-188,-197,202,-199,202,202,-190,-213,-221,-222,-207,-228,-229,]),'SWITCH':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,252,-250,-39,-42,-38,-40,252,-148,-147,-43,-149,252,-41,-167,-166,-164,252,-150,-163,-151,252,-162,-165,-154,252,-152,252,-153,252,252,-158,-157,-155,252,252,-159,-156,252,-161,-160,]),'INT_CONST_HEX':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,109,-45,-219,109,-217,109,-216,109,-215,109,109,-214,-218,109,109,-250,109,-176,-179,-177,-173,-174,-178,-180,109,-182,-183,-175,-181,109,-215,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,-251,-39,-42,-38,109,-40,109,109,-148,-147,-43,-149,109,-41,109,109,109,-215,109,-12,109,109,-11,-167,-166,109,-164,109,109,-150,109,-163,-151,109,109,109,109,-251,109,-215,-251,-131,-162,-165,109,-154,109,-152,109,109,109,-153,109,109,109,-251,109,-158,-157,-155,109,109,109,-159,-156,109,-161,-160,]),'_COMPLEX':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[27,27,-61,-72,-71,-58,-54,-55,-33,-29,-59,27,-34,-53,-68,-63,-52,27,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,27,-67,27,-70,-74,27,-57,-82,-249,-81,27,-107,-30,27,-97,-96,27,-45,-46,27,-109,27,27,27,27,-88,27,27,-36,27,-47,27,27,-83,-89,-250,27,-110,27,27,-111,-113,-112,27,27,-98,-37,-39,-42,-38,-40,27,-148,-147,-43,-149,-41,-85,-84,-90,27,27,-100,-99,-167,-166,27,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'PLUSEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[167,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'STRUCT':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[34,34,-61,-72,-71,-58,-54,-55,-33,-29,-59,34,-34,-53,-68,-63,-52,34,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,34,-67,34,-70,-74,34,-57,-82,-249,-81,34,-107,-30,34,-97,-96,34,-45,-46,34,-109,34,34,34,34,-88,34,34,-36,34,-47,34,34,-83,-89,-250,34,-110,34,34,-111,-113,-112,34,34,-98,-37,-39,-42,-38,-40,34,-148,-147,-43,-149,-41,-85,-84,-90,34,34,-100,-99,-167,-166,34,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'CONDOP':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,213,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-213,-221,-222,-207,-228,-229,]),'BREAK':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,256,-250,-39,-42,-38,-40,256,-148,-147,-43,-149,256,-41,-167,-166,-164,256,-150,-163,-151,256,-162,-165,-154,256,-152,256,-153,256,256,-158,-157,-155,256,256,-159,-156,256,-161,-160,]),'VOLATILE':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,28,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,66,68,73,75,80,82,83,84,85,86,87,88,89,112,139,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[46,46,-61,-72,-71,-58,-54,-55,-33,-29,-59,46,-34,-53,-68,-63,-52,46,-56,-170,-106,-66,46,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,46,-67,46,-70,-74,46,-57,-82,-249,-81,46,-107,-30,46,-97,-96,-116,46,46,-45,-46,46,-109,46,46,46,46,-88,46,46,-117,-36,46,-47,46,46,-83,-89,-250,46,-110,46,46,-111,-113,-112,46,46,-98,-37,-39,-42,-38,-40,46,-148,-147,-43,-149,-41,-85,-84,-90,46,46,-100,-99,-167,-166,46,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'INLINE':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[49,49,-61,-72,-71,-58,-54,-55,-33,-29,-59,49,-34,-53,-68,-63,-52,49,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,49,-67,49,-70,-74,49,-57,-82,-249,-81,-107,-30,49,-97,-96,49,-45,-46,49,-109,-36,49,-47,-83,-250,-110,-111,-113,-112,49,49,-98,-37,-39,-42,-38,-40,49,-148,-147,-43,-149,-41,-85,-84,49,49,-100,-99,-167,-166,49,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'DO':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,259,-250,-39,-42,-38,-40,259,-148,-147,-43,-149,259,-41,-167,-166,-164,259,-150,-163,-151,259,-162,-165,-154,259,-152,259,-153,259,259,-158,-157,-155,259,259,-159,-156,259,-161,-160,]),'LNOT':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,91,-45,-219,91,-217,91,-216,91,-215,91,91,-214,-218,91,91,-250,91,-176,-179,-177,-173,-174,-178,-180,91,-182,-183,-175,-181,91,-215,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,-251,-39,-42,-38,91,-40,91,91,-148,-147,-43,-149,91,-41,91,91,91,-215,91,-12,91,91,-11,-167,-166,91,-164,91,91,-150,91,-163,-151,91,91,91,91,-251,91,-215,-251,-131,-162,-165,91,-154,91,-152,91,91,91,-153,91,91,91,-251,91,-158,-157,-155,91,91,91,-159,-156,91,-161,-160,]),'CONST':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,28,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,66,68,73,75,80,82,83,84,85,86,87,88,89,112,139,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[3,3,-61,-72,-71,-58,-54,-55,-33,-29,-59,3,-34,-53,-68,-63,-52,3,-56,-170,-106,-66,3,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,3,-67,3,-70,-74,3,-57,-82,-249,-81,3,-107,-30,3,-97,-96,-116,3,3,-45,-46,3,-109,3,3,3,3,-88,3,3,-117,-36,3,-47,3,3,-83,-89,-250,3,-110,3,3,-111,-113,-112,3,3,-98,-37,-39,-42,-38,-40,3,-148,-147,-43,-149,-41,-85,-84,-90,3,3,-100,-99,-167,-166,3,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'LOR':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,198,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-213,-221,-222,-207,-228,-229,]),'CHAR_CONST':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,94,-45,-219,94,-217,94,-216,94,-215,94,94,-214,-218,94,94,-250,94,-176,-179,-177,-173,-174,-178,-180,94,-182,-183,-175,-181,94,-215,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,-251,-39,-42,-38,94,-40,94,94,-148,-147,-43,-149,94,-41,94,94,94,-215,94,-12,94,94,-11,-167,-166,94,-164,94,94,-150,94,-163,-151,94,94,94,94,-251,94,-215,-251,-131,-162,-165,94,-154,94,-152,94,94,94,-153,94,94,94,-251,94,-158,-157,-155,94,94,94,-159,-156,94,-161,-160,]),'LSHIFT':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,199,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,199,-194,-192,199,199,199,-191,199,199,-189,-188,199,199,199,199,199,-190,-213,-221,-222,-207,-228,-229,]),'RBRACE':([55,75,86,88,92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,122,124,135,136,137,145,147,148,150,151,174,176,178,180,184,187,188,190,196,228,229,230,236,238,239,242,244,251,253,254,255,257,258,260,261,267,269,271,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,320,321,328,331,332,335,340,342,344,349,350,351,356,368,369,370,373,374,377,382,385,386,392,396,400,401,402,405,406,408,409,416,417,419,420,],[-249,-45,151,-88,-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,-185,-242,-239,-171,-230,-101,151,-104,-251,151,151,-89,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,151,151,-102,-126,-39,-42,-38,-40,-6,-148,-147,-43,-149,-5,-41,151,-184,-90,-172,-225,-224,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-103,-105,151,-167,-166,-164,-150,-163,-151,-213,-221,-222,-207,-129,151,-127,-162,-165,-154,-152,151,-186,-128,-153,151,-228,-130,-158,-157,-155,-229,-159,-156,-161,-160,]),'_BOOL':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[13,13,-61,-72,-71,-58,-54,-55,-33,-29,-59,13,-34,-53,-68,-63,-52,13,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,13,-67,13,-70,-74,13,-57,-82,-249,-81,13,-107,-30,13,-97,-96,13,-45,-46,13,-109,13,13,13,13,-88,13,13,-36,13,-47,13,13,-83,-89,-250,13,-110,13,13,-111,-113,-112,13,13,-98,-37,-39,-42,-38,-40,13,-148,-147,-43,-149,-41,-85,-84,-90,13,13,-100,-99,-167,-166,13,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'LE':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,201,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,201,-194,-192,-196,201,-195,-191,-198,201,-189,-188,-197,201,201,201,201,-190,-213,-221,-222,-207,-228,-229,]),'SEMI':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,30,31,32,33,35,36,37,38,39,40,41,42,43,44,45,46,49,50,51,52,54,55,56,58,59,60,63,64,70,71,72,73,74,75,76,77,79,83,87,89,90,92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,122,124,143,144,145,149,151,152,153,154,155,157,158,159,160,161,174,176,178,180,184,185,187,188,190,191,194,196,216,217,231,233,234,236,237,238,239,241,242,243,244,246,247,251,253,254,255,256,257,258,259,260,262,264,265,266,267,271,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,318,319,330,331,332,333,334,335,336,339,340,342,344,345,347,348,349,350,351,355,356,370,373,374,375,376,377,379,382,386,392,393,394,395,396,397,399,401,403,405,406,408,409,412,413,415,416,417,418,419,420,],[15,-251,-61,-72,-71,-58,-54,-55,-33,-29,-59,-251,-34,-53,-68,-63,-52,15,-56,-170,-106,-66,-69,-251,-32,-73,-108,-64,-31,-60,-35,-62,-65,75,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-249,-81,-49,-107,-30,-97,-96,-18,-44,-17,-77,-75,-45,-48,-51,-251,-109,-251,-251,-251,-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,-185,-242,-239,-171,-230,-77,-36,-251,-83,-250,-21,-80,-22,-79,-24,269,-91,-23,-93,-248,-212,-246,-226,-227,-110,-206,-211,-209,-111,-168,-210,-113,-112,-98,-76,-78,-126,-37,-39,-42,331,-38,332,-40,335,-14,-251,-148,-147,-43,342,-149,-13,-251,-41,-237,-85,-84,-95,-184,-172,-225,-224,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-100,-99,373,-167,-166,374,-251,-164,-251,-13,-150,-163,-151,-251,-92,-94,-213,-221,-222,-169,-207,-127,-162,-165,393,-251,-154,-251,-152,-186,-128,-251,404,-251,-153,-251,-251,-228,410,-158,-157,-155,-229,416,-251,-251,-159,-156,-251,-161,-160,]),'LT':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,203,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,203,-194,-192,-196,203,-195,-191,-198,203,-189,-188,-197,203,203,203,203,-190,-213,-221,-222,-207,-228,-229,]),'COMMA':([1,2,3,5,6,9,10,13,14,17,18,19,21,23,24,25,27,28,29,32,33,35,37,39,40,42,43,44,45,46,49,50,51,52,54,56,58,59,63,64,66,67,68,69,70,73,74,76,77,83,92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,122,124,128,129,130,131,132,135,136,137,138,139,143,149,151,157,159,161,174,176,178,180,184,185,187,188,190,191,192,194,196,216,217,219,220,222,223,224,225,228,229,230,231,233,234,236,247,262,264,265,266,267,271,273,274,275,276,277,278,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,314,315,317,318,319,320,321,328,333,347,348,349,350,351,355,356,359,360,361,362,368,370,378,380,383,384,385,386,387,388,389,392,401,402,407,409,],[-251,-61,-72,-71,-58,-54,-55,-59,-251,-53,-68,-63,-52,-56,-170,-106,-66,-251,-69,-73,-108,-64,-60,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-81,-49,-107,-97,-96,-116,-114,-26,-25,140,-77,-75,-48,-51,-109,-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,-185,-242,-239,-171,-230,-120,-251,226,227,-124,-101,230,-104,-115,-117,-77,-83,-250,268,-91,-93,-248,-212,-246,-226,-227,-110,-206,-211,-209,-111,282,-168,-210,-113,-112,-123,-2,-122,-139,-137,-1,230,230,-102,-98,-76,-78,-126,282,-237,-85,-84,-95,-184,-172,-225,-224,282,-235,-223,352,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,282,-202,-190,-138,-125,-121,-100,-99,-103,-105,369,282,-92,-94,-213,-221,-222,-169,-207,-146,-140,-142,-144,-129,-127,282,282,282,-236,400,-186,-141,-143,-145,-128,-228,-130,282,-229,]),'TYPEDEF':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[23,23,-61,-72,-71,-58,-54,-55,-33,-29,-59,23,-34,-53,-68,-63,-52,23,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,23,-67,23,-70,-74,23,-57,-82,-249,-81,-107,-30,23,-97,-96,23,-45,-46,23,-109,-36,23,-47,-83,-250,-110,-111,-113,-112,23,23,-98,-37,-39,-42,-38,-40,23,-148,-147,-43,-149,-41,-85,-84,23,23,-100,-99,-167,-166,23,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'XOR':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,206,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,206,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,206,-199,-201,206,-190,-213,-221,-222,-207,-228,-229,]),'AUTO':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[21,21,-61,-72,-71,-58,-54,-55,-33,-29,-59,21,-34,-53,-68,-63,-52,21,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,21,-67,21,-70,-74,21,-57,-82,-249,-81,-107,-30,21,-97,-96,21,-45,-46,21,-109,-36,21,-47,-83,-250,-110,-111,-113,-112,21,21,-98,-37,-39,-42,-38,-40,21,-148,-147,-43,-149,-41,-85,-84,21,21,-100,-99,-167,-166,21,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'TIMES':([0,1,2,3,4,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,27,28,29,30,31,32,35,36,37,38,39,40,42,43,44,45,46,49,50,51,52,54,55,56,58,60,61,63,64,66,67,68,69,75,76,77,79,87,89,90,91,92,93,94,95,96,97,98,99,100,101,102,104,105,106,108,109,110,111,112,113,114,115,116,117,118,119,120,123,124,129,139,140,141,144,145,149,151,152,153,154,155,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,180,182,183,184,186,187,188,189,190,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,218,221,231,232,235,237,238,239,242,243,244,250,251,253,254,255,257,259,260,262,264,265,268,270,273,274,277,281,282,283,285,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,311,312,318,319,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,349,350,351,352,353,356,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[28,-251,-61,-72,28,-71,-58,-54,-55,-33,-29,-59,-251,-34,-53,-68,-63,-52,28,-56,-170,-66,-251,-69,28,-32,-73,-64,-31,-60,-35,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-249,-81,-49,-30,110,-97,-96,-116,28,-26,-25,-45,-48,-51,28,-251,-251,28,-219,-206,-233,-243,-247,-244,-241,-231,177,-217,-232,-208,-187,177,-216,177,-240,-215,-220,177,177,-237,-245,-214,-238,208,-242,-239,-218,-230,28,-117,28,177,-36,177,-83,-250,-21,-80,-22,-79,177,-176,-179,-177,-173,-174,-178,-180,177,-182,-183,-175,-181,-248,177,-212,-215,-246,-226,177,177,-227,177,-206,-211,177,-209,28,-210,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,28,311,-98,177,-251,-37,-39,-42,-38,177,-40,177,177,-148,-147,-43,-149,177,-41,-237,-85,-84,28,177,-225,-224,-223,-234,177,177,28,208,208,208,208,208,208,208,208,208,208,-189,-188,208,208,208,208,208,-190,-215,364,-100,-99,-12,177,177,-11,-167,-166,177,-164,177,177,-150,177,-163,-151,177,177,-213,-221,-222,177,177,-207,-251,177,-215,-251,-131,-162,-165,177,-154,177,-152,177,177,177,-153,177,177,177,-251,-228,177,-158,-157,-155,-229,177,177,177,-159,-156,177,-161,-160,]),'LPAREN':([0,1,2,3,4,5,6,9,10,11,12,13,14,15,16,17,18,19,21,22,23,24,25,27,28,29,30,31,32,33,35,36,37,38,39,40,42,43,44,45,46,49,50,51,52,54,55,56,58,59,60,61,63,64,66,67,68,69,75,76,77,79,83,87,89,90,91,93,94,95,96,97,98,99,100,101,102,105,106,108,109,110,111,112,113,114,115,116,117,119,120,123,124,129,138,139,140,141,144,145,149,151,152,153,154,155,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,177,178,180,182,183,184,185,186,189,191,195,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,221,223,224,231,232,235,237,238,239,242,243,244,245,249,250,251,252,253,254,255,257,259,260,262,263,264,265,268,270,273,274,277,281,282,283,285,286,311,312,314,318,319,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,350,351,352,353,357,358,359,360,361,362,364,369,372,373,374,376,377,379,381,382,387,388,389,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[4,-251,-61,-72,4,-71,-58,-54,-55,-33,-29,-59,-251,-34,4,-53,-68,-63,-52,4,-56,-170,62,-66,-251,-69,4,-32,-73,-108,-64,-31,-60,-35,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-249,-81,-49,62,-30,112,-97,-96,-116,-114,-26,-25,-45,-48,-51,4,-109,-251,-251,4,-219,-233,-243,-247,-244,-241,-231,175,-217,-232,183,186,-216,189,-240,-215,-220,112,189,-237,-245,-214,-238,-242,-239,-218,-230,218,-115,-117,4,112,-36,112,-83,-250,-21,-80,-22,-79,186,-176,-179,-177,-173,-174,-178,-180,112,-182,-183,-175,-181,-248,112,-215,-246,-226,112,112,-227,-110,112,112,-111,285,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,112,186,186,-113,-112,218,112,313,218,-98,186,-251,-37,-39,-42,-38,112,-40,334,337,186,112,341,-148,-147,-43,-149,112,-41,-237,346,-85,-84,4,186,-225,-224,-223,-234,112,186,285,285,-215,112,313,-100,-99,-12,186,112,-11,-167,-166,112,-164,112,112,-150,112,-163,-151,112,112,-221,-222,112,186,-251,186,-146,-140,-142,-144,-215,-251,-131,-162,-165,112,-154,112,398,-152,-141,-143,-145,112,112,112,-153,112,112,112,-251,-228,112,-158,-157,-155,-229,112,112,112,-159,-156,112,-161,-160,]),'MINUSMINUS':([55,61,75,91,93,94,95,96,97,98,99,100,101,102,105,106,108,109,110,111,112,113,114,115,116,117,119,120,123,124,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,177,178,180,182,183,184,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,262,270,273,274,277,281,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,350,351,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[-249,113,-45,-219,-233,-243,-247,-244,-241,-231,113,-217,-232,184,113,-216,113,-240,-215,-220,113,113,-237,-245,-214,-238,-242,-239,-218,-230,113,113,-250,113,-176,-179,-177,-173,-174,-178,-180,113,-182,-183,-175,-181,-248,113,-215,-246,-226,113,113,-227,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,-251,-39,-42,-38,113,-40,113,113,-148,-147,-43,-149,113,-41,-237,113,-225,-224,-223,-234,113,113,-215,113,-12,113,113,-11,-167,-166,113,-164,113,113,-150,113,-163,-151,113,113,-221,-222,113,113,-251,113,-215,-251,-131,-162,-165,113,-154,113,-152,113,113,113,-153,113,113,113,-251,-228,113,-158,-157,-155,-229,113,113,113,-159,-156,113,-161,-160,]),'ID':([0,1,2,3,4,5,6,7,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,39,40,42,43,44,45,46,49,50,51,52,54,55,56,58,60,61,62,63,64,65,66,67,68,69,75,76,77,79,87,89,90,91,99,100,105,106,108,110,112,113,116,123,129,133,134,138,139,140,141,144,145,149,151,152,153,154,155,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,179,181,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,218,221,224,226,230,231,232,235,237,238,239,240,242,243,244,250,251,253,254,255,257,259,260,264,265,268,270,282,283,311,312,318,319,322,324,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[33,-251,-61,-72,33,-71,-58,56,-54,-55,-33,-29,-59,-251,-34,33,-53,-68,-63,-87,-52,33,-56,-170,64,-66,-251,-69,33,-32,-73,-86,-64,-31,-60,-35,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-249,-81,-49,-30,114,114,-97,-96,137,-116,-114,-26,-25,-45,-48,-51,33,-251,-251,33,-219,114,-217,114,-216,114,-215,114,114,-214,-218,33,137,137,-115,-117,33,114,-36,262,-83,-250,-21,-80,-22,-79,114,-176,-179,-177,-173,-174,-178,-180,114,-182,-183,-175,-181,114,-215,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,33,114,33,114,137,-98,114,-251,-37,-39,-42,330,-38,114,-40,114,262,-148,-147,-43,-149,262,-41,-85,-84,33,114,114,114,-215,114,-100,-99,-12,114,114,114,-11,-167,-166,114,-164,262,114,-150,114,-163,-151,262,114,114,114,-251,114,-215,-251,-131,-162,-165,114,-154,262,-152,114,114,262,-153,262,114,262,-251,114,-158,-157,-155,114,262,262,-159,-156,262,-161,-160,]),'IF':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,263,-250,-39,-42,-38,-40,263,-148,-147,-43,-149,263,-41,-167,-166,-164,263,-150,-163,-151,263,-162,-165,-154,263,-152,263,-153,263,263,-158,-157,-155,263,263,-159,-156,263,-161,-160,]),'STRING_LITERAL':([55,61,75,91,99,100,101,105,106,108,110,112,113,115,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,178,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,115,-45,-219,115,-217,178,115,-216,115,-215,115,115,-245,-214,-218,115,115,-250,115,-176,-179,-177,-173,-174,-178,-180,115,-182,-183,-175,-181,115,-215,-246,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,-251,-39,-42,-38,115,-40,115,115,-148,-147,-43,-149,115,-41,115,115,115,-215,115,-12,115,115,-11,-167,-166,115,-164,115,115,-150,115,-163,-151,115,115,115,115,-251,115,-215,-251,-131,-162,-165,115,-154,115,-152,115,115,115,-153,115,115,115,-251,115,-158,-157,-155,115,115,115,-159,-156,115,-161,-160,]),'FLOAT':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[35,35,-61,-72,-71,-58,-54,-55,-33,-29,-59,35,-34,-53,-68,-63,-52,35,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,35,-67,35,-70,-74,35,-57,-82,-249,-81,35,-107,-30,35,-97,-96,35,-45,-46,35,-109,35,35,35,35,-88,35,35,-36,35,-47,35,35,-83,-89,-250,35,-110,35,35,-111,-113,-112,35,35,-98,-37,-39,-42,-38,-40,35,-148,-147,-43,-149,-41,-85,-84,-90,35,35,-100,-99,-167,-166,35,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'XOREQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[166,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'LSHIFTEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[168,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'RBRACKET':([61,92,93,94,95,96,97,98,101,102,103,104,107,109,110,111,114,115,117,118,119,120,121,122,124,151,174,176,178,180,184,187,188,190,194,196,221,267,271,273,274,275,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,310,311,312,349,350,351,355,356,363,364,367,386,401,409,],[-251,-206,-233,-243,-247,-244,-241,-231,-232,-208,185,-187,-4,-240,191,-220,-237,-245,-238,-185,-242,-239,-3,-171,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-168,-210,-251,-184,-172,-225,-224,350,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,361,362,-251,-213,-221,-222,-169,-207,387,388,390,-186,-228,-229,]),} - -_lr_action = { } -for _k, _v in _lr_action_items.items(): - for _x,_y in zip(_v[0],_v[1]): - if not _x in _lr_action: _lr_action[_x] = { } - _lr_action[_x][_k] = _y -del _lr_action_items - -_lr_goto_items = {'storage_class_specifier':([0,1,14,22,42,44,48,62,73,82,145,218,227,251,285,313,334,],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,]),'identifier_list_opt':([62,],[125,]),'selection_statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[260,260,260,260,260,260,260,260,260,260,260,260,]),'constant':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,]),'unary_expression':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[92,176,187,190,92,196,92,92,187,92,92,92,92,92,92,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,92,187,187,92,187,92,187,92,92,187,92,187,92,187,92,92,92,92,92,92,92,92,187,187,92,92,92,92,92,92,92,92,92,92,92,92,92,]),'conditional_expression':([61,112,141,145,156,169,175,182,183,186,189,213,221,232,243,250,251,259,270,282,312,325,326,334,336,337,341,345,346,352,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[122,122,122,122,267,122,122,122,122,122,122,122,122,267,122,267,122,122,267,122,122,267,122,122,122,122,122,122,122,122,386,122,122,122,122,122,122,122,122,122,122,122,122,122,]),'brace_close':([86,136,147,148,228,229,261,328,369,385,400,],[149,231,264,265,318,319,344,370,392,401,409,]),'struct_or_union_specifier':([0,1,14,22,42,44,48,57,62,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,]),'unified_wstring_literal':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,]),'abstract_declarator_opt':([129,195,],[219,284,]),'iteration_statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[239,239,239,239,239,239,239,239,239,239,239,239,]),'init_declarator_list':([30,79,],[70,70,]),'translation_unit_or_empty':([0,],[8,]),'struct_declaration_list':([57,84,85,],[86,147,148,]),'enumerator':([65,133,134,230,],[135,135,135,320,]),'pp_directive':([0,22,],[11,11,]),'declaration_list':([48,73,],[82,82,]),'declaration_specifiers_opt':([1,14,42,44,],[50,58,76,77,]),'abstract_declarator':([129,195,218,285,],[220,220,309,309,]),'external_declaration':([0,22,],[12,60,]),'type_specifier':([0,1,14,22,42,44,48,57,62,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[14,14,14,14,14,14,14,87,14,14,14,87,87,87,87,87,87,14,87,87,87,87,87,14,14,14,14,14,14,]),'designation':([235,357,369,400,],[322,322,322,322,]),'compound_statement':([81,142,145,251,259,336,345,379,395,397,399,413,415,418,],[144,237,244,244,244,244,244,244,244,244,244,244,244,244,]),'pointer':([0,4,22,30,67,79,90,129,140,195,218,268,285,],[16,16,16,16,138,16,16,224,16,286,224,16,286,]),'type_name':([112,175,186,189,],[193,272,279,280,]),'unified_string_literal':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,]),'postfix_expression':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,]),'assignment_expression_opt':([61,221,312,],[103,310,363,]),'designation_opt':([235,357,369,400,],[326,326,391,391,]),'expression_statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[238,238,238,238,238,238,238,238,238,238,238,238,]),'unary_operator':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,]),'cast_expression':([61,105,112,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[104,188,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,356,104,104,104,104,104,104,104,104,104,104,356,104,104,104,104,104,104,104,104,104,104,104,104,104,104,]),'brace_open':([7,26,54,56,63,64,81,141,142,145,251,259,283,326,336,345,349,353,354,379,391,395,397,399,413,415,418,],[57,65,84,85,133,134,145,235,145,145,145,145,357,235,145,145,357,357,357,145,235,145,145,145,145,145,145,]),'init_declarator':([30,79,140,],[74,74,233,]),'translation_unit':([0,],[22,]),'assignment_operator':([92,],[169,]),'struct_or_union':([0,1,14,22,42,44,48,57,62,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,]),'block_item_list_opt':([145,],[261,]),'struct_declaration':([57,84,85,86,147,148,],[88,88,88,150,150,150,]),'assignment_expression':([61,112,141,145,169,175,182,183,186,189,213,221,243,251,259,282,312,326,334,336,337,341,345,346,352,376,379,391,393,395,397,398,399,404,410,413,415,418,],[107,194,236,194,271,194,194,276,194,194,194,107,194,194,194,355,107,236,194,194,194,194,194,194,384,194,194,236,194,194,194,194,194,194,194,194,194,194,]),'parameter_type_list':([62,218,285,313,],[127,307,307,307,]),'type_qualifier_list_opt':([28,],[67,]),'direct_declarator':([0,4,16,22,30,79,90,129,140,218,224,268,],[25,25,59,25,25,25,25,25,25,25,59,25,]),'type_qualifier_list':([28,],[68,]),'designator':([235,329,357,369,400,],[323,371,323,323,323,]),'argument_expression_list':([183,],[278,]),'initializer':([141,326,391,],[234,368,402,]),'direct_abstract_declarator':([129,195,218,224,285,286,],[223,223,223,314,223,314,]),'specifier_qualifier_list_opt':([87,89,],[153,155,]),'constant_expression':([156,232,250,270,325,],[266,321,338,348,367,]),'expression_opt':([145,251,259,334,336,345,376,379,393,395,397,399,404,410,413,415,418,],[241,241,241,375,241,241,394,241,403,241,241,241,411,414,241,241,241,]),'primary_expression':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,]),'declaration_specifiers':([0,1,14,22,42,44,48,62,73,82,145,218,227,251,285,313,334,],[30,52,52,30,52,52,79,129,79,79,79,129,129,79,129,129,79,]),'declaration':([0,22,48,73,82,145,251,334,],[31,31,80,80,146,254,254,376,]),'struct_declarator_list_opt':([90,],[158,]),'identifier_list':([62,],[130,]),'typedef_name':([0,1,14,22,42,44,48,57,62,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,]),'parameter_type_list_opt':([218,285,313,],[308,308,365,]),'jump_statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[255,255,255,255,255,255,255,255,255,255,255,255,]),'declaration_list_opt':([48,73,],[81,142,]),'struct_declarator':([90,268,],[159,347,]),'function_definition':([0,22,],[36,36,]),'binary_expression':([61,112,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,312,325,326,334,336,337,341,345,346,352,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[118,118,118,118,118,118,118,118,118,118,118,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,118,304,305,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,]),'parameter_list':([62,218,285,313,],[131,131,131,131,]),'init_declarator_list_opt':([30,79,],[71,71,]),'enum_specifier':([0,1,14,22,42,44,48,57,62,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,]),'struct_declarator_list':([90,],[157,]),'decl_body':([0,22,48,73,82,145,251,334,],[41,41,41,41,41,41,41,41,]),'type_qualifier':([0,1,14,22,28,42,44,48,57,62,68,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[42,42,42,42,66,42,42,42,89,42,139,42,42,89,89,89,89,89,89,42,89,89,89,89,89,42,42,42,42,42,42,]),'enumerator_list':([65,133,134,],[136,228,229,]),'labeled_statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[242,242,242,242,242,242,242,242,242,242,242,242,]),'function_specifier':([0,1,14,22,42,44,48,62,73,82,145,218,227,251,285,313,334,],[44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,]),'specifier_qualifier_list':([57,84,85,86,87,89,112,147,148,175,186,189,],[90,90,90,90,154,154,195,90,90,195,195,195,]),'block_item':([145,251,],[257,340,]),'block_item_list':([145,],[251,]),'statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[253,253,343,377,382,396,405,406,408,417,419,420,]),'empty':([0,1,14,28,30,42,44,48,61,62,73,79,87,89,90,129,145,195,218,221,235,251,259,285,312,313,334,336,345,357,369,376,379,393,395,397,399,400,404,410,413,415,418,],[47,51,51,69,72,51,51,78,121,126,78,72,152,152,160,225,258,225,306,121,327,339,339,306,121,306,339,339,339,327,327,339,339,339,339,339,339,327,339,339,339,339,339,]),'initializer_list':([235,357,],[328,385,]),'declarator':([0,4,22,30,79,90,129,140,218,268,],[48,53,48,73,143,161,222,143,53,161,]),'parameter_declaration':([62,218,227,285,313,],[128,128,317,128,128,]),'designator_list':([235,357,369,400,],[329,329,329,329,]),'identifier':([61,62,99,105,108,112,113,141,145,156,169,175,179,181,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,226,232,243,250,251,259,270,282,283,312,324,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[124,132,124,124,124,124,124,124,124,124,124,124,273,274,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,315,124,124,124,124,124,124,124,124,124,366,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,]),'expression':([112,145,175,182,186,189,213,243,251,259,334,336,337,341,345,346,376,379,393,395,397,398,399,404,410,413,415,418,],[192,247,192,275,192,192,303,333,247,247,247,247,378,380,247,383,247,247,247,247,247,407,247,247,247,247,247,247,]),} - -_lr_goto = { } -for _k, _v in _lr_goto_items.items(): - for _x,_y in zip(_v[0],_v[1]): - if not _x in _lr_goto: _lr_goto[_x] = { } - _lr_goto[_x][_k] = _y -del _lr_goto_items -_lr_productions = [ - ("S' -> translation_unit_or_empty","S'",1,None,None,None), - ('abstract_declarator_opt -> empty','abstract_declarator_opt',1,'p_abstract_declarator_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('abstract_declarator_opt -> abstract_declarator','abstract_declarator_opt',1,'p_abstract_declarator_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('assignment_expression_opt -> empty','assignment_expression_opt',1,'p_assignment_expression_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('assignment_expression_opt -> assignment_expression','assignment_expression_opt',1,'p_assignment_expression_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('block_item_list_opt -> empty','block_item_list_opt',1,'p_block_item_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('block_item_list_opt -> block_item_list','block_item_list_opt',1,'p_block_item_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('declaration_list_opt -> empty','declaration_list_opt',1,'p_declaration_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('declaration_list_opt -> declaration_list','declaration_list_opt',1,'p_declaration_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('declaration_specifiers_opt -> empty','declaration_specifiers_opt',1,'p_declaration_specifiers_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('declaration_specifiers_opt -> declaration_specifiers','declaration_specifiers_opt',1,'p_declaration_specifiers_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('designation_opt -> empty','designation_opt',1,'p_designation_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('designation_opt -> designation','designation_opt',1,'p_designation_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('expression_opt -> empty','expression_opt',1,'p_expression_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('expression_opt -> expression','expression_opt',1,'p_expression_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('identifier_list_opt -> empty','identifier_list_opt',1,'p_identifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('identifier_list_opt -> identifier_list','identifier_list_opt',1,'p_identifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('init_declarator_list_opt -> empty','init_declarator_list_opt',1,'p_init_declarator_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('init_declarator_list_opt -> init_declarator_list','init_declarator_list_opt',1,'p_init_declarator_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('parameter_type_list_opt -> empty','parameter_type_list_opt',1,'p_parameter_type_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('parameter_type_list_opt -> parameter_type_list','parameter_type_list_opt',1,'p_parameter_type_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('specifier_qualifier_list_opt -> empty','specifier_qualifier_list_opt',1,'p_specifier_qualifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('specifier_qualifier_list_opt -> specifier_qualifier_list','specifier_qualifier_list_opt',1,'p_specifier_qualifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('struct_declarator_list_opt -> empty','struct_declarator_list_opt',1,'p_struct_declarator_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('struct_declarator_list_opt -> struct_declarator_list','struct_declarator_list_opt',1,'p_struct_declarator_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('type_qualifier_list_opt -> empty','type_qualifier_list_opt',1,'p_type_qualifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('type_qualifier_list_opt -> type_qualifier_list','type_qualifier_list_opt',1,'p_type_qualifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('translation_unit_or_empty -> translation_unit','translation_unit_or_empty',1,'p_translation_unit_or_empty','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',355), - ('translation_unit_or_empty -> empty','translation_unit_or_empty',1,'p_translation_unit_or_empty','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',356), - ('translation_unit -> external_declaration','translation_unit',1,'p_translation_unit_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',364), - ('translation_unit -> translation_unit external_declaration','translation_unit',2,'p_translation_unit_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',371), - ('external_declaration -> function_definition','external_declaration',1,'p_external_declaration_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',383), - ('external_declaration -> declaration','external_declaration',1,'p_external_declaration_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',388), - ('external_declaration -> pp_directive','external_declaration',1,'p_external_declaration_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',393), - ('external_declaration -> SEMI','external_declaration',1,'p_external_declaration_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',398), - ('pp_directive -> PPHASH','pp_directive',1,'p_pp_directive','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',403), - ('function_definition -> declarator declaration_list_opt compound_statement','function_definition',3,'p_function_definition_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',412), - ('function_definition -> declaration_specifiers declarator declaration_list_opt compound_statement','function_definition',4,'p_function_definition_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',424), - ('statement -> labeled_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',435), - ('statement -> expression_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',436), - ('statement -> compound_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',437), - ('statement -> selection_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',438), - ('statement -> iteration_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',439), - ('statement -> jump_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',440), - ('decl_body -> declaration_specifiers init_declarator_list_opt','decl_body',2,'p_decl_body','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',454), - ('declaration -> decl_body SEMI','declaration',2,'p_declaration','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',537), - ('declaration_list -> declaration','declaration_list',1,'p_declaration_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',546), - ('declaration_list -> declaration_list declaration','declaration_list',2,'p_declaration_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',547), - ('declaration_specifiers -> type_qualifier declaration_specifiers_opt','declaration_specifiers',2,'p_declaration_specifiers_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',552), - ('declaration_specifiers -> type_specifier declaration_specifiers_opt','declaration_specifiers',2,'p_declaration_specifiers_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',557), - ('declaration_specifiers -> storage_class_specifier declaration_specifiers_opt','declaration_specifiers',2,'p_declaration_specifiers_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',562), - ('declaration_specifiers -> function_specifier declaration_specifiers_opt','declaration_specifiers',2,'p_declaration_specifiers_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',567), - ('storage_class_specifier -> AUTO','storage_class_specifier',1,'p_storage_class_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',572), - ('storage_class_specifier -> REGISTER','storage_class_specifier',1,'p_storage_class_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',573), - ('storage_class_specifier -> STATIC','storage_class_specifier',1,'p_storage_class_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',574), - ('storage_class_specifier -> EXTERN','storage_class_specifier',1,'p_storage_class_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',575), - ('storage_class_specifier -> TYPEDEF','storage_class_specifier',1,'p_storage_class_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',576), - ('function_specifier -> INLINE','function_specifier',1,'p_function_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',581), - ('type_specifier -> VOID','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',586), - ('type_specifier -> _BOOL','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',587), - ('type_specifier -> CHAR','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',588), - ('type_specifier -> SHORT','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',589), - ('type_specifier -> INT','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',590), - ('type_specifier -> LONG','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',591), - ('type_specifier -> FLOAT','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',592), - ('type_specifier -> DOUBLE','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',593), - ('type_specifier -> _COMPLEX','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',594), - ('type_specifier -> SIGNED','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',595), - ('type_specifier -> UNSIGNED','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',596), - ('type_specifier -> typedef_name','type_specifier',1,'p_type_specifier_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',601), - ('type_specifier -> enum_specifier','type_specifier',1,'p_type_specifier_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',602), - ('type_specifier -> struct_or_union_specifier','type_specifier',1,'p_type_specifier_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',603), - ('type_qualifier -> CONST','type_qualifier',1,'p_type_qualifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',608), - ('type_qualifier -> RESTRICT','type_qualifier',1,'p_type_qualifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',609), - ('type_qualifier -> VOLATILE','type_qualifier',1,'p_type_qualifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',610), - ('init_declarator_list -> init_declarator','init_declarator_list',1,'p_init_declarator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',615), - ('init_declarator_list -> init_declarator_list COMMA init_declarator','init_declarator_list',3,'p_init_declarator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',616), - ('init_declarator -> declarator','init_declarator',1,'p_init_declarator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',624), - ('init_declarator -> declarator EQUALS initializer','init_declarator',3,'p_init_declarator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',625), - ('specifier_qualifier_list -> type_qualifier specifier_qualifier_list_opt','specifier_qualifier_list',2,'p_specifier_qualifier_list_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',630), - ('specifier_qualifier_list -> type_specifier specifier_qualifier_list_opt','specifier_qualifier_list',2,'p_specifier_qualifier_list_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',635), - ('struct_or_union_specifier -> struct_or_union ID','struct_or_union_specifier',2,'p_struct_or_union_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',643), - ('struct_or_union_specifier -> struct_or_union TYPEID','struct_or_union_specifier',2,'p_struct_or_union_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',644), - ('struct_or_union_specifier -> struct_or_union brace_open struct_declaration_list brace_close','struct_or_union_specifier',4,'p_struct_or_union_specifier_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',653), - ('struct_or_union_specifier -> struct_or_union ID brace_open struct_declaration_list brace_close','struct_or_union_specifier',5,'p_struct_or_union_specifier_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',662), - ('struct_or_union_specifier -> struct_or_union TYPEID brace_open struct_declaration_list brace_close','struct_or_union_specifier',5,'p_struct_or_union_specifier_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',663), - ('struct_or_union -> STRUCT','struct_or_union',1,'p_struct_or_union','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',672), - ('struct_or_union -> UNION','struct_or_union',1,'p_struct_or_union','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',673), - ('struct_declaration_list -> struct_declaration','struct_declaration_list',1,'p_struct_declaration_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',680), - ('struct_declaration_list -> struct_declaration_list struct_declaration','struct_declaration_list',2,'p_struct_declaration_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',681), - ('struct_declaration -> specifier_qualifier_list struct_declarator_list_opt SEMI','struct_declaration',3,'p_struct_declaration_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',686), - ('struct_declarator_list -> struct_declarator','struct_declarator_list',1,'p_struct_declarator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',737), - ('struct_declarator_list -> struct_declarator_list COMMA struct_declarator','struct_declarator_list',3,'p_struct_declarator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',738), - ('struct_declarator -> declarator','struct_declarator',1,'p_struct_declarator_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',746), - ('struct_declarator -> declarator COLON constant_expression','struct_declarator',3,'p_struct_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',751), - ('struct_declarator -> COLON constant_expression','struct_declarator',2,'p_struct_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',752), - ('enum_specifier -> ENUM ID','enum_specifier',2,'p_enum_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',760), - ('enum_specifier -> ENUM TYPEID','enum_specifier',2,'p_enum_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',761), - ('enum_specifier -> ENUM brace_open enumerator_list brace_close','enum_specifier',4,'p_enum_specifier_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',766), - ('enum_specifier -> ENUM ID brace_open enumerator_list brace_close','enum_specifier',5,'p_enum_specifier_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',771), - ('enum_specifier -> ENUM TYPEID brace_open enumerator_list brace_close','enum_specifier',5,'p_enum_specifier_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',772), - ('enumerator_list -> enumerator','enumerator_list',1,'p_enumerator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',777), - ('enumerator_list -> enumerator_list COMMA','enumerator_list',2,'p_enumerator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',778), - ('enumerator_list -> enumerator_list COMMA enumerator','enumerator_list',3,'p_enumerator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',779), - ('enumerator -> ID','enumerator',1,'p_enumerator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',790), - ('enumerator -> ID EQUALS constant_expression','enumerator',3,'p_enumerator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',791), - ('declarator -> direct_declarator','declarator',1,'p_declarator_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',803), - ('declarator -> pointer direct_declarator','declarator',2,'p_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',808), - ('direct_declarator -> ID','direct_declarator',1,'p_direct_declarator_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',813), - ('direct_declarator -> LPAREN declarator RPAREN','direct_declarator',3,'p_direct_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',822), - ('direct_declarator -> direct_declarator LBRACKET assignment_expression_opt RBRACKET','direct_declarator',4,'p_direct_declarator_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',827), - ('direct_declarator -> direct_declarator LBRACKET TIMES RBRACKET','direct_declarator',4,'p_direct_declarator_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',839), - ('direct_declarator -> direct_declarator LPAREN parameter_type_list RPAREN','direct_declarator',4,'p_direct_declarator_5','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',849), - ('direct_declarator -> direct_declarator LPAREN identifier_list_opt RPAREN','direct_declarator',4,'p_direct_declarator_5','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',850), - ('pointer -> TIMES type_qualifier_list_opt','pointer',2,'p_pointer','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',860), - ('pointer -> TIMES type_qualifier_list_opt pointer','pointer',3,'p_pointer','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',861), - ('type_qualifier_list -> type_qualifier','type_qualifier_list',1,'p_type_qualifier_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',871), - ('type_qualifier_list -> type_qualifier_list type_qualifier','type_qualifier_list',2,'p_type_qualifier_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',872), - ('parameter_type_list -> parameter_list','parameter_type_list',1,'p_parameter_type_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',877), - ('parameter_type_list -> parameter_list COMMA ELLIPSIS','parameter_type_list',3,'p_parameter_type_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',878), - ('parameter_list -> parameter_declaration','parameter_list',1,'p_parameter_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',886), - ('parameter_list -> parameter_list COMMA parameter_declaration','parameter_list',3,'p_parameter_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',887), - ('parameter_declaration -> declaration_specifiers declarator','parameter_declaration',2,'p_parameter_declaration_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',896), - ('parameter_declaration -> declaration_specifiers abstract_declarator_opt','parameter_declaration',2,'p_parameter_declaration_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',915), - ('identifier_list -> identifier','identifier_list',1,'p_identifier_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',927), - ('identifier_list -> identifier_list COMMA identifier','identifier_list',3,'p_identifier_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',928), - ('initializer -> assignment_expression','initializer',1,'p_initializer_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',937), - ('initializer -> brace_open initializer_list brace_close','initializer',3,'p_initializer_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',942), - ('initializer -> brace_open initializer_list COMMA brace_close','initializer',4,'p_initializer_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',943), - ('initializer_list -> designation_opt initializer','initializer_list',2,'p_initializer_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',948), - ('initializer_list -> initializer_list COMMA designation_opt initializer','initializer_list',4,'p_initializer_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',949), - ('designation -> designator_list EQUALS','designation',2,'p_designation','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',960), - ('designator_list -> designator','designator_list',1,'p_designator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',968), - ('designator_list -> designator_list designator','designator_list',2,'p_designator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',969), - ('designator -> LBRACKET constant_expression RBRACKET','designator',3,'p_designator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',974), - ('designator -> PERIOD identifier','designator',2,'p_designator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',975), - ('type_name -> specifier_qualifier_list abstract_declarator_opt','type_name',2,'p_type_name','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',980), - ('abstract_declarator -> pointer','abstract_declarator',1,'p_abstract_declarator_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',996), - ('abstract_declarator -> pointer direct_abstract_declarator','abstract_declarator',2,'p_abstract_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1004), - ('abstract_declarator -> direct_abstract_declarator','abstract_declarator',1,'p_abstract_declarator_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1009), - ('direct_abstract_declarator -> LPAREN abstract_declarator RPAREN','direct_abstract_declarator',3,'p_direct_abstract_declarator_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1019), - ('direct_abstract_declarator -> direct_abstract_declarator LBRACKET assignment_expression_opt RBRACKET','direct_abstract_declarator',4,'p_direct_abstract_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1023), - ('direct_abstract_declarator -> LBRACKET assignment_expression_opt RBRACKET','direct_abstract_declarator',3,'p_direct_abstract_declarator_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1033), - ('direct_abstract_declarator -> direct_abstract_declarator LBRACKET TIMES RBRACKET','direct_abstract_declarator',4,'p_direct_abstract_declarator_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1041), - ('direct_abstract_declarator -> LBRACKET TIMES RBRACKET','direct_abstract_declarator',3,'p_direct_abstract_declarator_5','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1051), - ('direct_abstract_declarator -> direct_abstract_declarator LPAREN parameter_type_list_opt RPAREN','direct_abstract_declarator',4,'p_direct_abstract_declarator_6','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1059), - ('direct_abstract_declarator -> LPAREN parameter_type_list_opt RPAREN','direct_abstract_declarator',3,'p_direct_abstract_declarator_7','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1069), - ('block_item -> declaration','block_item',1,'p_block_item','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1080), - ('block_item -> statement','block_item',1,'p_block_item','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1081), - ('block_item_list -> block_item','block_item_list',1,'p_block_item_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1088), - ('block_item_list -> block_item_list block_item','block_item_list',2,'p_block_item_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1089), - ('compound_statement -> brace_open block_item_list_opt brace_close','compound_statement',3,'p_compound_statement_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1095), - ('labeled_statement -> ID COLON statement','labeled_statement',3,'p_labeled_statement_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1101), - ('labeled_statement -> CASE constant_expression COLON statement','labeled_statement',4,'p_labeled_statement_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1105), - ('labeled_statement -> DEFAULT COLON statement','labeled_statement',3,'p_labeled_statement_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1109), - ('selection_statement -> IF LPAREN expression RPAREN statement','selection_statement',5,'p_selection_statement_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1113), - ('selection_statement -> IF LPAREN expression RPAREN statement ELSE statement','selection_statement',7,'p_selection_statement_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1117), - ('selection_statement -> SWITCH LPAREN expression RPAREN statement','selection_statement',5,'p_selection_statement_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1121), - ('iteration_statement -> WHILE LPAREN expression RPAREN statement','iteration_statement',5,'p_iteration_statement_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1126), - ('iteration_statement -> DO statement WHILE LPAREN expression RPAREN SEMI','iteration_statement',7,'p_iteration_statement_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1130), - ('iteration_statement -> FOR LPAREN expression_opt SEMI expression_opt SEMI expression_opt RPAREN statement','iteration_statement',9,'p_iteration_statement_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1134), - ('iteration_statement -> FOR LPAREN declaration expression_opt SEMI expression_opt RPAREN statement','iteration_statement',8,'p_iteration_statement_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1138), - ('jump_statement -> GOTO ID SEMI','jump_statement',3,'p_jump_statement_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1142), - ('jump_statement -> BREAK SEMI','jump_statement',2,'p_jump_statement_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1146), - ('jump_statement -> CONTINUE SEMI','jump_statement',2,'p_jump_statement_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1150), - ('jump_statement -> RETURN expression SEMI','jump_statement',3,'p_jump_statement_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1154), - ('jump_statement -> RETURN SEMI','jump_statement',2,'p_jump_statement_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1155), - ('expression_statement -> expression_opt SEMI','expression_statement',2,'p_expression_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1160), - ('expression -> assignment_expression','expression',1,'p_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1167), - ('expression -> expression COMMA assignment_expression','expression',3,'p_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1168), - ('typedef_name -> TYPEID','typedef_name',1,'p_typedef_name','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1180), - ('assignment_expression -> conditional_expression','assignment_expression',1,'p_assignment_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1184), - ('assignment_expression -> unary_expression assignment_operator assignment_expression','assignment_expression',3,'p_assignment_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1185), - ('assignment_operator -> EQUALS','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1198), - ('assignment_operator -> XOREQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1199), - ('assignment_operator -> TIMESEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1200), - ('assignment_operator -> DIVEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1201), - ('assignment_operator -> MODEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1202), - ('assignment_operator -> PLUSEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1203), - ('assignment_operator -> MINUSEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1204), - ('assignment_operator -> LSHIFTEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1205), - ('assignment_operator -> RSHIFTEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1206), - ('assignment_operator -> ANDEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1207), - ('assignment_operator -> OREQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1208), - ('constant_expression -> conditional_expression','constant_expression',1,'p_constant_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1213), - ('conditional_expression -> binary_expression','conditional_expression',1,'p_conditional_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1217), - ('conditional_expression -> binary_expression CONDOP expression COLON conditional_expression','conditional_expression',5,'p_conditional_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1218), - ('binary_expression -> cast_expression','binary_expression',1,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1226), - ('binary_expression -> binary_expression TIMES binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1227), - ('binary_expression -> binary_expression DIVIDE binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1228), - ('binary_expression -> binary_expression MOD binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1229), - ('binary_expression -> binary_expression PLUS binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1230), - ('binary_expression -> binary_expression MINUS binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1231), - ('binary_expression -> binary_expression RSHIFT binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1232), - ('binary_expression -> binary_expression LSHIFT binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1233), - ('binary_expression -> binary_expression LT binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1234), - ('binary_expression -> binary_expression LE binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1235), - ('binary_expression -> binary_expression GE binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1236), - ('binary_expression -> binary_expression GT binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1237), - ('binary_expression -> binary_expression EQ binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1238), - ('binary_expression -> binary_expression NE binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1239), - ('binary_expression -> binary_expression AND binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1240), - ('binary_expression -> binary_expression OR binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1241), - ('binary_expression -> binary_expression XOR binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1242), - ('binary_expression -> binary_expression LAND binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1243), - ('binary_expression -> binary_expression LOR binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1244), - ('cast_expression -> unary_expression','cast_expression',1,'p_cast_expression_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1252), - ('cast_expression -> LPAREN type_name RPAREN cast_expression','cast_expression',4,'p_cast_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1256), - ('unary_expression -> postfix_expression','unary_expression',1,'p_unary_expression_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1260), - ('unary_expression -> PLUSPLUS unary_expression','unary_expression',2,'p_unary_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1264), - ('unary_expression -> MINUSMINUS unary_expression','unary_expression',2,'p_unary_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1265), - ('unary_expression -> unary_operator cast_expression','unary_expression',2,'p_unary_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1266), - ('unary_expression -> SIZEOF unary_expression','unary_expression',2,'p_unary_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1271), - ('unary_expression -> SIZEOF LPAREN type_name RPAREN','unary_expression',4,'p_unary_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1272), - ('unary_operator -> AND','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1280), - ('unary_operator -> TIMES','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1281), - ('unary_operator -> PLUS','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1282), - ('unary_operator -> MINUS','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1283), - ('unary_operator -> NOT','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1284), - ('unary_operator -> LNOT','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1285), - ('postfix_expression -> primary_expression','postfix_expression',1,'p_postfix_expression_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1290), - ('postfix_expression -> postfix_expression LBRACKET expression RBRACKET','postfix_expression',4,'p_postfix_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1294), - ('postfix_expression -> postfix_expression LPAREN argument_expression_list RPAREN','postfix_expression',4,'p_postfix_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1298), - ('postfix_expression -> postfix_expression LPAREN RPAREN','postfix_expression',3,'p_postfix_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1299), - ('postfix_expression -> postfix_expression PERIOD identifier','postfix_expression',3,'p_postfix_expression_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1304), - ('postfix_expression -> postfix_expression ARROW identifier','postfix_expression',3,'p_postfix_expression_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1305), - ('postfix_expression -> postfix_expression PLUSPLUS','postfix_expression',2,'p_postfix_expression_5','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1310), - ('postfix_expression -> postfix_expression MINUSMINUS','postfix_expression',2,'p_postfix_expression_5','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1311), - ('postfix_expression -> LPAREN type_name RPAREN brace_open initializer_list brace_close','postfix_expression',6,'p_postfix_expression_6','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1316), - ('postfix_expression -> LPAREN type_name RPAREN brace_open initializer_list COMMA brace_close','postfix_expression',7,'p_postfix_expression_6','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1317), - ('primary_expression -> identifier','primary_expression',1,'p_primary_expression_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1322), - ('primary_expression -> constant','primary_expression',1,'p_primary_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1326), - ('primary_expression -> unified_string_literal','primary_expression',1,'p_primary_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1330), - ('primary_expression -> unified_wstring_literal','primary_expression',1,'p_primary_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1331), - ('primary_expression -> LPAREN expression RPAREN','primary_expression',3,'p_primary_expression_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1336), - ('argument_expression_list -> assignment_expression','argument_expression_list',1,'p_argument_expression_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1340), - ('argument_expression_list -> argument_expression_list COMMA assignment_expression','argument_expression_list',3,'p_argument_expression_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1341), - ('identifier -> ID','identifier',1,'p_identifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1350), - ('constant -> INT_CONST_DEC','constant',1,'p_constant_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1354), - ('constant -> INT_CONST_OCT','constant',1,'p_constant_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1355), - ('constant -> INT_CONST_HEX','constant',1,'p_constant_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1356), - ('constant -> FLOAT_CONST','constant',1,'p_constant_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1362), - ('constant -> HEX_FLOAT_CONST','constant',1,'p_constant_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1363), - ('constant -> CHAR_CONST','constant',1,'p_constant_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1369), - ('constant -> WCHAR_CONST','constant',1,'p_constant_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1370), - ('unified_string_literal -> STRING_LITERAL','unified_string_literal',1,'p_unified_string_literal','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1381), - ('unified_string_literal -> unified_string_literal STRING_LITERAL','unified_string_literal',2,'p_unified_string_literal','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1382), - ('unified_wstring_literal -> WSTRING_LITERAL','unified_wstring_literal',1,'p_unified_wstring_literal','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1392), - ('unified_wstring_literal -> unified_wstring_literal WSTRING_LITERAL','unified_wstring_literal',2,'p_unified_wstring_literal','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1393), - ('brace_open -> LBRACE','brace_open',1,'p_brace_open','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1403), - ('brace_close -> RBRACE','brace_close',1,'p_brace_close','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1409), - ('empty -> ','empty',0,'p_empty','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1415), -] diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/build/lib/snip_infrastructure/__init__.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/build/lib/snip_infrastructure/__init__.py deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/build/lib/snip_infrastructure/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# Generated by pypy/tool/import_cffi.py - -def func(): - return 42 diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/setup.py deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/setup.py +++ /dev/null @@ -1,6 +0,0 @@ -# Generated by pypy/tool/import_cffi.py - -from distutils.core import setup - -setup(packages=['snip_infrastructure'], - requires=['cffi']) diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/snip_infrastructure/__init__.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/snip_infrastructure/__init__.py deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/snip_infrastructure/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# Generated by pypy/tool/import_cffi.py - -def func(): - return 42 diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/UNKNOWN.egg-info/PKG-INFO b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/UNKNOWN.egg-info/PKG-INFO deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/UNKNOWN.egg-info/PKG-INFO +++ /dev/null @@ -1,10 +0,0 @@ -Metadata-Version: 1.0 -Name: UNKNOWN -Version: 0.0.0 -Summary: UNKNOWN -Home-page: UNKNOWN -Author: UNKNOWN -Author-email: UNKNOWN -License: UNKNOWN -Description: UNKNOWN -Platform: UNKNOWN diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/UNKNOWN.egg-info/SOURCES.txt b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/UNKNOWN.egg-info/SOURCES.txt deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/UNKNOWN.egg-info/SOURCES.txt +++ /dev/null @@ -1,8 +0,0 @@ -setup.py -snip_setuptools_verify.py -UNKNOWN.egg-info/PKG-INFO -UNKNOWN.egg-info/SOURCES.txt -UNKNOWN.egg-info/dependency_links.txt -UNKNOWN.egg-info/not-zip-safe -UNKNOWN.egg-info/top_level.txt -__pycache__/_cffi__gd39ab08bx8432a366.c \ No newline at end of file diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/UNKNOWN.egg-info/dependency_links.txt b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/UNKNOWN.egg-info/dependency_links.txt deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/UNKNOWN.egg-info/dependency_links.txt +++ /dev/null @@ -1,1 +0,0 @@ - diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/UNKNOWN.egg-info/not-zip-safe b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/UNKNOWN.egg-info/not-zip-safe deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/UNKNOWN.egg-info/not-zip-safe +++ /dev/null @@ -1,1 +0,0 @@ - diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/UNKNOWN.egg-info/top_level.txt b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/UNKNOWN.egg-info/top_level.txt deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/UNKNOWN.egg-info/top_level.txt +++ /dev/null @@ -1,2 +0,0 @@ -snip_setuptools_verify -_cffi__gd39ab08bx8432a366 diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/__pycache__/__pycache__/_cffi__gd39ab08bx8432a366.o b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/__pycache__/__pycache__/_cffi__gd39ab08bx8432a366.o deleted file mode 100644 Binary file pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/__pycache__/__pycache__/_cffi__gd39ab08bx8432a366.o has changed diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/__pycache__/_cffi__gd39ab08bx8432a366.c b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/__pycache__/_cffi__gd39ab08bx8432a366.c deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/__pycache__/_cffi__gd39ab08bx8432a366.c +++ /dev/null @@ -1,53 +0,0 @@ - -#include -#include -#include -#include -#include /* XXX for ssize_t on some platforms */ - -#ifdef _WIN32 -# include -# define snprintf _snprintf -typedef __int8 int8_t; -typedef __int16 int16_t; -typedef __int32 int32_t; -typedef __int64 int64_t; -typedef unsigned __int8 uint8_t; -typedef unsigned __int16 uint16_t; -typedef unsigned __int32 uint32_t; -typedef unsigned __int64 uint64_t; -typedef SSIZE_T ssize_t; -typedef unsigned char _Bool; -#else -# include -#endif - - // passed to the real C compiler -#include -#include - -struct passwd * _cffi_f_getpwuid(int x0) -{ - return getpwuid(x0); -} - -static void _cffi_check_struct_passwd(struct passwd *p) -{ - /* only to generate compile-time warnings or errors */ - { char * *tmp = &p->pw_name; (void)tmp; } -} -ssize_t _cffi_layout_struct_passwd(ssize_t i) -{ - struct _cffi_aligncheck { char x; struct passwd y; }; - static ssize_t nums[] = { - sizeof(struct passwd), - offsetof(struct _cffi_aligncheck, y), - offsetof(struct passwd, pw_name), - sizeof(((struct passwd *)0)->pw_name), - -1 - }; - return nums[i]; - /* the next line is not executed, but compiled */ - _cffi_check_struct_passwd(0); -} - diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/__pycache__/_cffi__gd39ab08bx8432a366.pypy-20.so b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/__pycache__/_cffi__gd39ab08bx8432a366.pypy-20.so deleted file mode 100755 Binary file pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/__pycache__/_cffi__gd39ab08bx8432a366.pypy-20.so has changed diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/build/lib.linux-x86_64-2.7/_cffi__gd39ab08bx8432a366.pypy-20.so b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/build/lib.linux-x86_64-2.7/_cffi__gd39ab08bx8432a366.pypy-20.so deleted file mode 100755 Binary file pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/build/lib.linux-x86_64-2.7/_cffi__gd39ab08bx8432a366.pypy-20.so has changed diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/build/lib.linux-x86_64-2.7/snip_setuptools_verify.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/build/lib.linux-x86_64-2.7/snip_setuptools_verify.py deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/build/lib.linux-x86_64-2.7/snip_setuptools_verify.py +++ /dev/null @@ -1,17 +0,0 @@ - -from cffi import FFI -import sys - -ffi = FFI() -ffi.cdef(""" // some declarations from the man page - struct passwd { - char *pw_name; - ...; - }; - struct passwd *getpwuid(int uid); -""") -C = ffi.verify(""" // passed to the real C compiler -#include -#include -""", libraries=[], # or a list of libraries to link with - force_generic_engine=hasattr(sys, '_force_generic_engine_')) diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/build/temp.linux-x86_64-2.7/__pycache__/_cffi__gd39ab08bx8432a366.o b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/build/temp.linux-x86_64-2.7/__pycache__/_cffi__gd39ab08bx8432a366.o deleted file mode 100644 Binary file pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/build/temp.linux-x86_64-2.7/__pycache__/_cffi__gd39ab08bx8432a366.o has changed diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/dist/UNKNOWN-0.0.0-py2.7-linux-x86_64.egg b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/dist/UNKNOWN-0.0.0-py2.7-linux-x86_64.egg deleted file mode 100644 Binary file pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/dist/UNKNOWN-0.0.0-py2.7-linux-x86_64.egg has changed diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/lextab.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/lextab.py deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/lextab.py +++ /dev/null @@ -1,9 +0,0 @@ -# pycparser.lextab.py. This file automatically created by PLY (version 3.4). Don't edit! -_tabversion = '3.4' -_lextokens = {'VOID': 1, 'LBRACKET': 1, 'WCHAR_CONST': 1, 'FLOAT_CONST': 1, 'MINUS': 1, 'RPAREN': 1, 'LONG': 1, 'PLUS': 1, 'ELLIPSIS': 1, 'GT': 1, 'GOTO': 1, 'ENUM': 1, 'PERIOD': 1, 'GE': 1, 'INT_CONST_DEC': 1, 'ARROW': 1, 'HEX_FLOAT_CONST': 1, 'DOUBLE': 1, 'MINUSEQUAL': 1, 'INT_CONST_OCT': 1, 'TIMESEQUAL': 1, 'OR': 1, 'SHORT': 1, 'RETURN': 1, 'RSHIFTEQUAL': 1, 'RESTRICT': 1, 'STATIC': 1, 'SIZEOF': 1, 'UNSIGNED': 1, 'UNION': 1, 'COLON': 1, 'WSTRING_LITERAL': 1, 'DIVIDE': 1, 'FOR': 1, 'PLUSPLUS': 1, 'EQUALS': 1, 'ELSE': 1, 'INLINE': 1, 'EQ': 1, 'AND': 1, 'TYPEID': 1, 'LBRACE': 1, 'PPHASH': 1, 'INT': 1, 'SIGNED': 1, 'CONTINUE': 1, 'NOT': 1, 'OREQUAL': 1, 'MOD': 1, 'RSHIFT': 1, 'DEFAULT': 1, 'CHAR': 1, 'WHILE': 1, 'DIVEQUAL': 1, 'EXTERN': 1, 'CASE': 1, 'LAND': 1, 'REGISTER': 1, 'MODEQUAL': 1, 'NE': 1, 'SWITCH': 1, 'INT_CONST_HEX': 1, '_COMPLEX': 1, 'PLUSEQUAL': 1, 'STRUCT': 1, 'CONDOP': 1, 'BREAK': 1, 'VOLATILE': 1, 'ANDEQUAL': 1, 'DO': 1, 'LNOT': 1, 'CONST': 1, 'LOR': 1, 'CHAR_CONST': 1, 'LSHIFT': 1, 'RBRACE': 1, '_BOOL': 1, 'LE': 1, 'SEMI': 1, 'LT': 1, 'COMMA': 1, 'TYPEDEF': 1, 'XOR': 1, 'AUTO': 1, 'TIMES': 1, 'LPAREN': 1, 'MINUSMINUS': 1, 'ID': 1, 'IF': 1, 'STRING_LITERAL': 1, 'FLOAT': 1, 'XOREQUAL': 1, 'LSHIFTEQUAL': 1, 'RBRACKET': 1} -_lexreflags = 0 -_lexliterals = '' -_lexstateinfo = {'ppline': 'exclusive', 'pppragma': 'exclusive', 'INITIAL': 'inclusive'} -_lexstatere = {'ppline': [('(?P"([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*")|(?P(0(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?)|([1-9][0-9]*(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?))|(?P\\n)|(?Pline)', [None, ('t_ppline_FILENAME', 'FILENAME'), None, None, None, None, None, None, ('t_ppline_LINE_NUMBER', 'LINE_NUMBER'), None, None, None, None, None, None, None, None, ('t_ppline_NEWLINE', 'NEWLINE'), ('t_ppline_PPLINE', 'PPLINE')])], 'pppragma': [('(?P\\n)|(?Ppragma)|(?P"([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*")|(?P[a-zA-Z_][0-9a-zA-Z_]*)', [None, ('t_pppragma_NEWLINE', 'NEWLINE'), ('t_pppragma_PPPRAGMA', 'PPPRAGMA'), ('t_pppragma_STR', 'STR'), None, None, None, None, None, None, ('t_pppragma_ID', 'ID')])], 'INITIAL': [('(?P[ \\t]*\\#)|(?P\\n+)|(?P((((([0-9]*\\.[0-9]+)|([0-9]+\\.))([eE][-+]?[0-9]+)?)|([0-9]+([eE][-+]?[0-9]+)))[FfLl]?))|(?P(0[xX]([0-9a-fA-F]+|((([0-9a-fA-F]+)?\\.[0-9a-fA-F]+)|([0-9a-fA-F]+\\.)))([pP][+-]?[0-9]+)[FfLl]?))|(?P0[xX][0-9a-fA-F]+(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?)|(?P0[0-7]*[89])|(?P0[0-7]*(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?)', [None, ('t_PPHASH', 'PPHASH'), ('t_NEWLINE', 'NEWLINE'), ('t_FLOAT_CONST', 'FLOAT_CONST'), None, None, None, None, None, None, None, None, None, ('t_HEX_FLOAT_CONST', 'HEX_FLOAT_CONST'), None, None, None, None, None, None, None, ('t_INT_CONST_HEX', 'INT_CONST_HEX'), None, None, None, ('t_BAD_CONST_OCT', 'BAD_CONST_OCT'), ('t_INT_CONST_OCT', 'INT_CONST_OCT')]), ('(?P(0(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?)|([1-9][0-9]*(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?))|(?P\'([^\'\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))\')|(?PL\'([^\'\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))\')|(?P(\'([^\'\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*\\n)|(\'([^\'\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*$))|(?P(\'([^\'\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))[^\'\n]+\')|(\'\')|(\'([\\\\][^a-zA-Z._~^!=&\\^\\-\\\\?\'"x0-7])[^\'\\n]*\'))|(?PL"([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*")|(?P"([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*([\\\\][^a-zA-Z._~^!=&\\^\\-\\\\?\'"x0-7])([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*")|(?P[a-zA-Z_][0-9a-zA-Z_]*)', [None, ('t_INT_CONST_DEC', 'INT_CONST_DEC'), None, None, None, None, None, None, None, None, ('t_CHAR_CONST', 'CHAR_CONST'), None, None, None, None, None, None, ('t_WCHAR_CONST', 'WCHAR_CONST'), None, None, None, None, None, None, ('t_UNMATCHED_QUOTE', 'UNMATCHED_QUOTE'), None, None, None, None, None, None, None, None, None, None, None, None, None, None, ('t_BAD_CHAR_CONST', 'BAD_CHAR_CONST'), None, None, None, None, None, None, None, None, None, None, ('t_WSTRING_LITERAL', 'WSTRING_LITERAL'), None, None, None, None, None, None, ('t_BAD_STRING_LITERAL', 'BAD_STRING_LITERAL'), None, None, None, None, None, None, None, None, None, None, None, None, None, ('t_ID', 'ID')]), ('(?P"([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*")|(?P\\.\\.\\.)|(?P\\+\\+)|(?P\\|\\|)|(?P\\^=)|(?P\\|=)|(?P<<=)|(?P>>=)|(?P\\+=)|(?P\\*=)|(?P\\+)|(?P%=)|(?P\\{)|(?P/=)|(?P\\])|(?P\\?)', [None, (None, 'STRING_LITERAL'), None, None, None, None, None, None, (None, 'ELLIPSIS'), (None, 'PLUSPLUS'), (None, 'LOR'), (None, 'XOREQUAL'), (None, 'OREQUAL'), (None, 'LSHIFTEQUAL'), (None, 'RSHIFTEQUAL'), (None, 'PLUSEQUAL'), (None, 'TIMESEQUAL'), (None, 'PLUS'), (None, 'MODEQUAL'), (None, 'LBRACE'), (None, 'DIVEQUAL'), (None, 'RBRACKET'), (None, 'CONDOP')]), ('(?P\\^)|(?P<<)|(?P<=)|(?P\\()|(?P->)|(?P==)|(?P\\})|(?P!=)|(?P--)|(?P\\|)|(?P\\*)|(?P\\[)|(?P>=)|(?P\\))|(?P&&)|(?P>>)|(?P&=)|(?P-=)|(?P\\.)|(?P=)|(?P<)|(?P,)|(?P/)|(?P&)|(?P%)|(?P;)|(?P-)|(?P>)|(?P:)|(?P~)|(?P!)', [None, (None, 'XOR'), (None, 'LSHIFT'), (None, 'LE'), (None, 'LPAREN'), (None, 'ARROW'), (None, 'EQ'), (None, 'RBRACE'), (None, 'NE'), (None, 'MINUSMINUS'), (None, 'OR'), (None, 'TIMES'), (None, 'LBRACKET'), (None, 'GE'), (None, 'RPAREN'), (None, 'LAND'), (None, 'RSHIFT'), (None, 'ANDEQUAL'), (None, 'MINUSEQUAL'), (None, 'PERIOD'), (None, 'EQUALS'), (None, 'LT'), (None, 'COMMA'), (None, 'DIVIDE'), (None, 'AND'), (None, 'MOD'), (None, 'SEMI'), (None, 'MINUS'), (None, 'GT'), (None, 'COLON'), (None, 'NOT'), (None, 'LNOT')])]} -_lexstateignore = {'ppline': ' \t', 'pppragma': ' \t<>.-{}();+-*/$%@&^~!?:,0123456789', 'INITIAL': ' \t'} -_lexstateerrorf = {'ppline': 't_ppline_error', 'pppragma': 't_pppragma_error', 'INITIAL': 't_error'} diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/setup.py deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/setup.py +++ /dev/null @@ -1,9 +0,0 @@ -# Generated by pypy/tool/import_cffi.py - -from setuptools import setup -import snip_setuptools_verify - -setup( - zip_safe=False, - py_modules=['snip_setuptools_verify'], - ext_modules=[snip_setuptools_verify.ffi.verifier.get_extension()]) diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/snip_setuptools_verify.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/snip_setuptools_verify.py deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/snip_setuptools_verify.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by pypy/tool/import_cffi.py - -from cffi import FFI -import sys - -ffi = FFI() -ffi.cdef(""" // some declarations from the man page - struct passwd { - char *pw_name; - ...; - }; - struct passwd *getpwuid(int uid); -""") -C = ffi.verify(""" // passed to the real C compiler -#include -#include -""", libraries=[], # or a list of libraries to link with - force_generic_engine=hasattr(sys, '_force_generic_engine_')) diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/yacctab.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/yacctab.py deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/yacctab.py +++ /dev/null @@ -1,280 +0,0 @@ - -# yacctab.py -# This file is automatically generated. Do not edit. -_tabversion = '3.2' - -_lr_method = 'LALR' - -_lr_signature = '\x9er\xf1|P\xb6\xbb\x13\xed\xf52\xa1\xb1\xc3J\x12' - -_lr_action_items = {'VOID':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[6,6,-61,-72,-71,-58,-54,-55,-33,-29,-59,6,-34,-53,-68,-63,-52,6,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,6,-67,6,-70,-74,6,-57,-82,-249,-81,6,-107,-30,6,-97,-96,6,-45,-46,6,-109,6,6,6,6,-88,6,6,-36,6,-47,6,6,-83,-89,-250,6,-110,6,6,-111,-113,-112,6,6,-98,-37,-39,-42,-38,-40,6,-148,-147,-43,-149,-41,-85,-84,-90,6,6,-100,-99,-167,-166,6,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'LBRACKET':([1,2,3,5,6,9,10,13,14,17,18,19,21,23,24,25,27,28,29,32,33,35,37,39,40,42,43,44,45,46,49,50,51,52,54,55,56,58,59,63,64,66,67,68,69,76,77,83,87,89,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,129,138,139,149,151,152,153,154,155,174,178,180,184,185,191,195,216,217,218,223,224,231,235,262,264,265,273,274,277,281,285,286,314,318,319,323,329,350,351,357,359,360,361,362,366,369,371,387,388,389,390,400,401,409,],[-251,-61,-72,-71,-58,-54,-55,-59,-251,-53,-68,-63,-52,-56,-170,61,-66,-251,-69,-73,-108,-64,-60,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-249,-81,-49,61,-97,-96,-116,-114,-26,-25,-48,-51,-109,-251,-251,-233,-243,-247,-244,-241,-231,-232,182,-240,-220,-237,-245,-238,-242,-239,-230,221,-115,-117,-83,-250,-21,-80,-22,-79,-248,-246,-226,-227,-110,-111,221,-113,-112,221,312,221,-98,325,-237,-85,-84,-225,-224,-223,-234,221,221,312,-100,-99,-132,325,-221,-222,325,-146,-140,-142,-144,-135,325,-133,-141,-143,-145,-134,325,-228,-229,]),'WCHAR_CONST':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,96,-45,-219,96,-217,96,-216,96,-215,96,96,-214,-218,96,96,-250,96,-176,-179,-177,-173,-174,-178,-180,96,-182,-183,-175,-181,96,-215,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,-251,-39,-42,-38,96,-40,96,96,-148,-147,-43,-149,96,-41,96,96,96,-215,96,-12,96,96,-11,-167,-166,96,-164,96,96,-150,96,-163,-151,96,96,96,96,-251,96,-215,-251,-131,-162,-165,96,-154,96,-152,96,96,96,-153,96,96,96,-251,96,-158,-157,-155,96,96,96,-159,-156,96,-161,-160,]),'FLOAT_CONST':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,97,-45,-219,97,-217,97,-216,97,-215,97,97,-214,-218,97,97,-250,97,-176,-179,-177,-173,-174,-178,-180,97,-182,-183,-175,-181,97,-215,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,-251,-39,-42,-38,97,-40,97,97,-148,-147,-43,-149,97,-41,97,97,97,-215,97,-12,97,97,-11,-167,-166,97,-164,97,97,-150,97,-163,-151,97,97,97,97,-251,97,-215,-251,-131,-162,-165,97,-154,97,-152,97,97,97,-153,97,97,97,-251,97,-158,-157,-155,97,97,97,-159,-156,97,-161,-160,]),'MINUS':([55,61,75,91,92,93,94,95,96,97,98,99,100,101,102,104,105,106,108,109,110,111,112,113,114,115,116,117,118,119,120,123,124,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,180,182,183,184,186,187,188,189,190,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,262,270,273,274,277,281,282,283,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,349,350,351,352,353,356,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[-249,100,-45,-219,-206,-233,-243,-247,-244,-241,-231,100,-217,-232,-208,-187,100,-216,100,-240,-215,-220,100,100,-237,-245,-214,-238,200,-242,-239,-218,-230,100,100,-250,100,-176,-179,-177,-173,-174,-178,-180,100,-182,-183,-175,-181,-248,100,-212,-215,-246,-226,100,100,-227,100,-206,-211,100,-209,-210,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,-251,-39,-42,-38,100,-40,100,100,-148,-147,-43,-149,100,-41,-237,100,-225,-224,-223,-234,100,100,200,200,200,-192,200,200,200,-191,200,200,-189,-188,200,200,200,200,200,-190,-215,100,-12,100,100,-11,-167,-166,100,-164,100,100,-150,100,-163,-151,100,100,-213,-221,-222,100,100,-207,-251,100,-215,-251,-131,-162,-165,100,-154,100,-152,100,100,100,-153,100,100,100,-251,-228,100,-158,-157,-155,-229,100,100,100,-159,-156,100,-161,-160,]),'RPAREN':([1,2,3,5,6,9,10,13,14,17,18,19,21,23,24,25,27,28,29,32,33,35,37,39,40,42,43,44,45,46,49,50,51,52,53,54,56,58,59,62,63,64,66,67,68,69,76,77,83,87,89,92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,122,124,125,126,127,128,129,130,131,132,138,139,149,151,152,153,154,155,174,176,178,180,183,184,185,187,188,190,191,192,193,194,195,196,216,217,218,219,220,222,223,224,225,231,247,264,265,271,272,273,274,276,277,278,279,280,281,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,306,307,308,309,313,314,315,316,317,318,319,339,349,350,351,355,356,359,360,361,362,365,378,380,383,384,386,387,388,389,401,404,407,409,410,411,414,],[-251,-61,-72,-71,-58,-54,-55,-59,-251,-53,-68,-63,-52,-56,-170,-106,-66,-251,-69,-73,-108,-64,-60,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,83,-82,-81,-49,-107,-251,-97,-96,-116,-114,-26,-25,-48,-51,-109,-251,-251,-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,-185,-242,-239,-171,-230,216,-15,217,-120,-251,-16,-118,-124,-115,-117,-83,-250,-21,-80,-22,-79,-248,-212,-246,-226,277,-227,-110,-206,-211,-209,-111,281,283,-168,-251,-210,-113,-112,-251,-123,-2,-122,-139,-137,-1,-98,-14,-85,-84,-172,349,-225,-224,-235,-223,351,353,354,-234,-136,-251,-137,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-19,-20,359,360,-251,-138,-125,-119,-121,-100,-99,-13,-213,-221,-222,-169,-207,-146,-140,-142,-144,389,395,397,399,-236,-186,-141,-143,-145,-228,-251,412,-229,-251,415,418,]),'LONG':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[19,19,-61,-72,-71,-58,-54,-55,-33,-29,-59,19,-34,-53,-68,-63,-52,19,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,19,-67,19,-70,-74,19,-57,-82,-249,-81,19,-107,-30,19,-97,-96,19,-45,-46,19,-109,19,19,19,19,-88,19,19,-36,19,-47,19,19,-83,-89,-250,19,-110,19,19,-111,-113,-112,19,19,-98,-37,-39,-42,-38,-40,19,-148,-147,-43,-149,-41,-85,-84,-90,19,19,-100,-99,-167,-166,19,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'PLUS':([55,61,75,91,92,93,94,95,96,97,98,99,100,101,102,104,105,106,108,109,110,111,112,113,114,115,116,117,118,119,120,123,124,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,180,182,183,184,186,187,188,189,190,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,262,270,273,274,277,281,282,283,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,349,350,351,352,353,356,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[-249,106,-45,-219,-206,-233,-243,-247,-244,-241,-231,106,-217,-232,-208,-187,106,-216,106,-240,-215,-220,106,106,-237,-245,-214,-238,204,-242,-239,-218,-230,106,106,-250,106,-176,-179,-177,-173,-174,-178,-180,106,-182,-183,-175,-181,-248,106,-212,-215,-246,-226,106,106,-227,106,-206,-211,106,-209,-210,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,-251,-39,-42,-38,106,-40,106,106,-148,-147,-43,-149,106,-41,-237,106,-225,-224,-223,-234,106,106,204,204,204,-192,204,204,204,-191,204,204,-189,-188,204,204,204,204,204,-190,-215,106,-12,106,106,-11,-167,-166,106,-164,106,106,-150,106,-163,-151,106,106,-213,-221,-222,106,106,-207,-251,106,-215,-251,-131,-162,-165,106,-154,106,-152,106,106,106,-153,106,106,106,-251,-228,106,-158,-157,-155,-229,106,106,106,-159,-156,106,-161,-160,]),'ELLIPSIS':([227,],[316,]),'GT':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,205,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,205,-194,-192,-196,205,-195,-191,-198,205,-189,-188,-197,205,205,205,205,-190,-213,-221,-222,-207,-228,-229,]),'GOTO':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,240,-250,-39,-42,-38,-40,240,-148,-147,-43,-149,240,-41,-167,-166,-164,240,-150,-163,-151,240,-162,-165,-154,240,-152,240,-153,240,240,-158,-157,-155,240,240,-159,-156,240,-161,-160,]),'ENUM':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[26,26,-61,-72,-71,-58,-54,-55,-33,-29,-59,26,-34,-53,-68,-63,-52,26,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,26,-67,26,-70,-74,26,-57,-82,-249,-81,26,-107,-30,26,-97,-96,26,-45,-46,26,-109,26,26,26,26,-88,26,26,-36,26,-47,26,26,-83,-89,-250,26,-110,26,26,-111,-113,-112,26,26,-98,-37,-39,-42,-38,-40,26,-148,-147,-43,-149,-41,-85,-84,-90,26,26,-100,-99,-167,-166,26,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'PERIOD':([55,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,178,180,184,235,262,273,274,277,281,323,329,350,351,357,366,369,371,390,400,401,409,],[-249,-233,-243,-247,-244,-241,-231,-232,181,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-246,-226,-227,324,-237,-225,-224,-223,-234,-132,324,-221,-222,324,-135,324,-133,-134,324,-228,-229,]),'GE':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,209,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,209,-194,-192,-196,209,-195,-191,-198,209,-189,-188,-197,209,209,209,209,-190,-213,-221,-222,-207,-228,-229,]),'INT_CONST_DEC':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,117,-45,-219,117,-217,117,-216,117,-215,117,117,-214,-218,117,117,-250,117,-176,-179,-177,-173,-174,-178,-180,117,-182,-183,-175,-181,117,-215,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,-251,-39,-42,-38,117,-40,117,117,-148,-147,-43,-149,117,-41,117,117,117,-215,117,-12,117,117,-11,-167,-166,117,-164,117,117,-150,117,-163,-151,117,117,117,117,-251,117,-215,-251,-131,-162,-165,117,-154,117,-152,117,117,117,-153,117,117,117,-251,117,-158,-157,-155,117,117,117,-159,-156,117,-161,-160,]),'ARROW':([93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,178,180,184,262,273,274,277,281,350,351,401,409,],[-233,-243,-247,-244,-241,-231,-232,179,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-246,-226,-227,-237,-225,-224,-223,-234,-221,-222,-228,-229,]),'HEX_FLOAT_CONST':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,119,-45,-219,119,-217,119,-216,119,-215,119,119,-214,-218,119,119,-250,119,-176,-179,-177,-173,-174,-178,-180,119,-182,-183,-175,-181,119,-215,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,-251,-39,-42,-38,119,-40,119,119,-148,-147,-43,-149,119,-41,119,119,119,-215,119,-12,119,119,-11,-167,-166,119,-164,119,119,-150,119,-163,-151,119,119,119,119,-251,119,-215,-251,-131,-162,-165,119,-154,119,-152,119,119,119,-153,119,119,119,-251,119,-158,-157,-155,119,119,119,-159,-156,119,-161,-160,]),'DOUBLE':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[40,40,-61,-72,-71,-58,-54,-55,-33,-29,-59,40,-34,-53,-68,-63,-52,40,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,40,-67,40,-70,-74,40,-57,-82,-249,-81,40,-107,-30,40,-97,-96,40,-45,-46,40,-109,40,40,40,40,-88,40,40,-36,40,-47,40,40,-83,-89,-250,40,-110,40,40,-111,-113,-112,40,40,-98,-37,-39,-42,-38,-40,40,-148,-147,-43,-149,-41,-85,-84,-90,40,40,-100,-99,-167,-166,40,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'MINUSEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[163,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'INT_CONST_OCT':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,120,-45,-219,120,-217,120,-216,120,-215,120,120,-214,-218,120,120,-250,120,-176,-179,-177,-173,-174,-178,-180,120,-182,-183,-175,-181,120,-215,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,-251,-39,-42,-38,120,-40,120,120,-148,-147,-43,-149,120,-41,120,120,120,-215,120,-12,120,120,-11,-167,-166,120,-164,120,120,-150,120,-163,-151,120,120,120,120,-251,120,-215,-251,-131,-162,-165,120,-154,120,-152,120,120,120,-153,120,120,120,-251,120,-158,-157,-155,120,120,120,-159,-156,120,-161,-160,]),'TIMESEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[172,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'OR':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,214,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,214,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,214,-199,-201,-202,-190,-213,-221,-222,-207,-228,-229,]),'SHORT':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[2,2,-61,-72,-71,-58,-54,-55,-33,-29,-59,2,-34,-53,-68,-63,-52,2,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,2,-67,2,-70,-74,2,-57,-82,-249,-81,2,-107,-30,2,-97,-96,2,-45,-46,2,-109,2,2,2,2,-88,2,2,-36,2,-47,2,2,-83,-89,-250,2,-110,2,2,-111,-113,-112,2,2,-98,-37,-39,-42,-38,-40,2,-148,-147,-43,-149,-41,-85,-84,-90,2,2,-100,-99,-167,-166,2,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'RETURN':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,243,-250,-39,-42,-38,-40,243,-148,-147,-43,-149,243,-41,-167,-166,-164,243,-150,-163,-151,243,-162,-165,-154,243,-152,243,-153,243,243,-158,-157,-155,243,243,-159,-156,243,-161,-160,]),'RSHIFTEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[173,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'RESTRICT':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,28,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,66,68,73,75,80,82,83,84,85,86,87,88,89,112,139,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[32,32,-61,-72,-71,-58,-54,-55,-33,-29,-59,32,-34,-53,-68,-63,-52,32,-56,-170,-106,-66,32,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,32,-67,32,-70,-74,32,-57,-82,-249,-81,32,-107,-30,32,-97,-96,-116,32,32,-45,-46,32,-109,32,32,32,32,-88,32,32,-117,-36,32,-47,32,32,-83,-89,-250,32,-110,32,32,-111,-113,-112,32,32,-98,-37,-39,-42,-38,-40,32,-148,-147,-43,-149,-41,-85,-84,-90,32,32,-100,-99,-167,-166,32,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'STATIC':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[9,9,-61,-72,-71,-58,-54,-55,-33,-29,-59,9,-34,-53,-68,-63,-52,9,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,9,-67,9,-70,-74,9,-57,-82,-249,-81,-107,-30,9,-97,-96,9,-45,-46,9,-109,-36,9,-47,-83,-250,-110,-111,-113,-112,9,9,-98,-37,-39,-42,-38,-40,9,-148,-147,-43,-149,-41,-85,-84,9,9,-100,-99,-167,-166,9,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'SIZEOF':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,99,-45,-219,99,-217,99,-216,99,-215,99,99,-214,-218,99,99,-250,99,-176,-179,-177,-173,-174,-178,-180,99,-182,-183,-175,-181,99,-215,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,-251,-39,-42,-38,99,-40,99,99,-148,-147,-43,-149,99,-41,99,99,99,-215,99,-12,99,99,-11,-167,-166,99,-164,99,99,-150,99,-163,-151,99,99,99,99,-251,99,-215,-251,-131,-162,-165,99,-154,99,-152,99,99,99,-153,99,99,99,-251,99,-158,-157,-155,99,99,99,-159,-156,99,-161,-160,]),'UNSIGNED':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[18,18,-61,-72,-71,-58,-54,-55,-33,-29,-59,18,-34,-53,-68,-63,-52,18,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,18,-67,18,-70,-74,18,-57,-82,-249,-81,18,-107,-30,18,-97,-96,18,-45,-46,18,-109,18,18,18,18,-88,18,18,-36,18,-47,18,18,-83,-89,-250,18,-110,18,18,-111,-113,-112,18,18,-98,-37,-39,-42,-38,-40,18,-148,-147,-43,-149,-41,-85,-84,-90,18,18,-100,-99,-167,-166,18,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'UNION':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[20,20,-61,-72,-71,-58,-54,-55,-33,-29,-59,20,-34,-53,-68,-63,-52,20,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,20,-67,20,-70,-74,20,-57,-82,-249,-81,20,-107,-30,20,-97,-96,20,-45,-46,20,-109,20,20,20,20,-88,20,20,-36,20,-47,20,20,-83,-89,-250,20,-110,20,20,-111,-113,-112,20,20,-98,-37,-39,-42,-38,-40,20,-148,-147,-43,-149,-41,-85,-84,-90,20,20,-100,-99,-167,-166,20,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'COLON':([2,3,5,6,13,18,19,24,25,27,29,32,33,35,37,39,40,43,45,46,54,56,59,63,64,83,87,89,90,92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,122,124,149,151,152,153,154,155,161,174,176,178,180,184,185,187,188,190,191,194,196,216,217,231,248,262,264,265,267,268,271,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,318,319,338,349,350,351,355,356,386,401,409,],[-61,-72,-71,-58,-59,-68,-63,-170,-106,-66,-69,-73,-108,-64,-60,-62,-65,-67,-70,-74,-82,-81,-107,-97,-96,-109,-251,-251,156,-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,-185,-242,-239,-171,-230,-83,-250,-21,-80,-22,-79,270,-248,-212,-246,-226,-227,-110,-206,-211,-209,-111,-168,-210,-113,-112,-98,336,345,-85,-84,-184,156,-172,-225,-224,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,358,-202,-190,-100,-99,379,-213,-221,-222,-169,-207,-186,-228,-229,]),'$end':([0,8,11,12,15,22,31,36,38,47,60,75,144,151,237,344,],[-251,0,-33,-29,-34,-27,-32,-31,-35,-28,-30,-45,-36,-250,-37,-151,]),'WSTRING_LITERAL':([55,61,75,91,93,95,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,95,-45,-219,174,-247,95,-217,95,-216,95,-215,95,95,-214,-218,95,95,-250,95,-176,-179,-177,-173,-174,-178,-180,95,-182,-183,-175,-181,-248,95,-215,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,-251,-39,-42,-38,95,-40,95,95,-148,-147,-43,-149,95,-41,95,95,95,-215,95,-12,95,95,-11,-167,-166,95,-164,95,95,-150,95,-163,-151,95,95,95,95,-251,95,-215,-251,-131,-162,-165,95,-154,95,-152,95,95,95,-153,95,95,95,-251,95,-158,-157,-155,95,95,95,-159,-156,95,-161,-160,]),'DIVIDE':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,207,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,207,207,207,207,207,207,207,207,207,207,-189,-188,207,207,207,207,207,-190,-213,-221,-222,-207,-228,-229,]),'FOR':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,245,-250,-39,-42,-38,-40,245,-148,-147,-43,-149,245,-41,-167,-166,-164,245,-150,-163,-151,245,-162,-165,-154,245,-152,245,-153,245,245,-158,-157,-155,245,245,-159,-156,245,-161,-160,]),'PLUSPLUS':([55,61,75,91,93,94,95,96,97,98,99,100,101,102,105,106,108,109,110,111,112,113,114,115,116,117,119,120,123,124,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,177,178,180,182,183,184,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,262,270,273,274,277,281,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,350,351,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[-249,108,-45,-219,-233,-243,-247,-244,-241,-231,108,-217,-232,180,108,-216,108,-240,-215,-220,108,108,-237,-245,-214,-238,-242,-239,-218,-230,108,108,-250,108,-176,-179,-177,-173,-174,-178,-180,108,-182,-183,-175,-181,-248,108,-215,-246,-226,108,108,-227,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,-251,-39,-42,-38,108,-40,108,108,-148,-147,-43,-149,108,-41,-237,108,-225,-224,-223,-234,108,108,-215,108,-12,108,108,-11,-167,-166,108,-164,108,108,-150,108,-163,-151,108,108,-221,-222,108,108,-251,108,-215,-251,-131,-162,-165,108,-154,108,-152,108,108,108,-153,108,108,108,-251,-228,108,-158,-157,-155,-229,108,108,108,-159,-156,108,-161,-160,]),'EQUALS':([25,33,59,73,83,92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,137,143,151,174,176,178,180,184,185,187,188,190,191,196,216,217,262,273,274,277,281,323,329,349,350,351,356,366,371,390,401,409,],[-106,-108,-107,141,-109,165,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,232,141,-250,-248,-212,-246,-226,-227,-110,-206,-211,-209,-111,-210,-113,-112,-237,-225,-224,-223,-234,-132,372,-213,-221,-222,-207,-135,-133,-134,-228,-229,]),'ELSE':([151,238,239,242,244,255,260,331,332,335,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[-250,-39,-42,-38,-40,-43,-41,-167,-166,-164,-163,-151,-162,-165,-154,-152,-153,-158,-157,413,-159,-156,-161,-160,]),'ANDEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[170,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'EQ':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,211,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,211,-194,-192,-196,-200,-195,-191,-198,211,-189,-188,-197,211,-199,211,211,-190,-213,-221,-222,-207,-228,-229,]),'AND':([55,61,75,91,92,93,94,95,96,97,98,99,100,101,102,104,105,106,108,109,110,111,112,113,114,115,116,117,118,119,120,123,124,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,180,182,183,184,186,187,188,189,190,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,262,270,273,274,277,281,282,283,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,349,350,351,352,353,356,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[-249,116,-45,-219,-206,-233,-243,-247,-244,-241,-231,116,-217,-232,-208,-187,116,-216,116,-240,-215,-220,116,116,-237,-245,-214,-238,212,-242,-239,-218,-230,116,116,-250,116,-176,-179,-177,-173,-174,-178,-180,116,-182,-183,-175,-181,-248,116,-212,-215,-246,-226,116,116,-227,116,-206,-211,116,-209,-210,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,-251,-39,-42,-38,116,-40,116,116,-148,-147,-43,-149,116,-41,-237,116,-225,-224,-223,-234,116,116,-193,212,-194,-192,-196,-200,-195,-191,-198,212,-189,-188,-197,212,-199,-201,212,-190,-215,116,-12,116,116,-11,-167,-166,116,-164,116,116,-150,116,-163,-151,116,116,-213,-221,-222,116,116,-207,-251,116,-215,-251,-131,-162,-165,116,-154,116,-152,116,116,116,-153,116,116,116,-251,-228,116,-158,-157,-155,-229,116,116,116,-159,-156,116,-161,-160,]),'TYPEID':([0,1,2,3,5,6,7,9,10,11,12,13,14,15,17,18,19,20,21,22,23,24,25,26,27,29,31,32,33,34,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[24,24,-61,-72,-71,-58,54,-54,-55,-33,-29,-59,24,-34,-53,-68,-63,-87,-52,24,-56,-170,-106,63,-66,-69,-32,-73,-108,-86,-64,-31,-60,-35,-62,-65,24,-67,24,-70,-74,24,-57,-82,-249,-81,24,-107,-30,24,-97,-96,24,-45,-46,24,-109,24,24,24,24,-88,24,24,-36,24,-47,24,24,-83,-89,-250,24,-110,24,24,-111,-113,-112,24,24,-98,-37,-39,-42,-38,-40,24,-148,-147,-43,-149,-41,-85,-84,-90,24,24,-100,-99,-167,-166,24,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'LBRACE':([7,20,25,26,33,34,48,54,55,56,59,63,64,73,75,78,80,81,82,83,141,142,145,146,151,185,191,216,217,235,238,239,242,244,251,253,254,255,257,259,260,283,322,326,327,331,332,335,336,340,342,344,345,349,353,354,357,369,372,373,374,377,379,382,391,395,396,397,399,400,405,406,408,413,415,416,417,418,419,420,],[55,-87,-106,55,-108,-86,-251,55,-249,55,-107,55,55,-251,-45,-7,-46,55,-8,-109,55,55,55,-47,-250,-110,-111,-113,-112,-251,-39,-42,-38,-40,55,-148,-147,-43,-149,55,-41,55,-12,55,-11,-167,-166,-164,55,-150,-163,-151,55,55,55,55,-251,-251,-131,-162,-165,-154,55,-152,55,55,-153,55,55,-251,-158,-157,-155,55,55,-159,-156,55,-161,-160,]),'PPHASH':([0,11,12,15,22,31,36,38,60,75,144,151,237,344,],[38,-33,-29,-34,38,-32,-31,-35,-30,-45,-36,-250,-37,-151,]),'INT':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[39,39,-61,-72,-71,-58,-54,-55,-33,-29,-59,39,-34,-53,-68,-63,-52,39,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,39,-67,39,-70,-74,39,-57,-82,-249,-81,39,-107,-30,39,-97,-96,39,-45,-46,39,-109,39,39,39,39,-88,39,39,-36,39,-47,39,39,-83,-89,-250,39,-110,39,39,-111,-113,-112,39,39,-98,-37,-39,-42,-38,-40,39,-148,-147,-43,-149,-41,-85,-84,-90,39,39,-100,-99,-167,-166,39,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'SIGNED':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[43,43,-61,-72,-71,-58,-54,-55,-33,-29,-59,43,-34,-53,-68,-63,-52,43,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,43,-67,43,-70,-74,43,-57,-82,-249,-81,43,-107,-30,43,-97,-96,43,-45,-46,43,-109,43,43,43,43,-88,43,43,-36,43,-47,43,43,-83,-89,-250,43,-110,43,43,-111,-113,-112,43,43,-98,-37,-39,-42,-38,-40,43,-148,-147,-43,-149,-41,-85,-84,-90,43,43,-100,-99,-167,-166,43,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'CONTINUE':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,246,-250,-39,-42,-38,-40,246,-148,-147,-43,-149,246,-41,-167,-166,-164,246,-150,-163,-151,246,-162,-165,-154,246,-152,246,-153,246,246,-158,-157,-155,246,246,-159,-156,246,-161,-160,]),'NOT':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,123,-45,-219,123,-217,123,-216,123,-215,123,123,-214,-218,123,123,-250,123,-176,-179,-177,-173,-174,-178,-180,123,-182,-183,-175,-181,123,-215,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,-251,-39,-42,-38,123,-40,123,123,-148,-147,-43,-149,123,-41,123,123,123,-215,123,-12,123,123,-11,-167,-166,123,-164,123,123,-150,123,-163,-151,123,123,123,123,-251,123,-215,-251,-131,-162,-165,123,-154,123,-152,123,123,123,-153,123,123,123,-251,123,-158,-157,-155,123,123,123,-159,-156,123,-161,-160,]),'OREQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[171,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'MOD':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,215,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,215,215,215,215,215,215,215,215,215,215,-189,-188,215,215,215,215,215,-190,-213,-221,-222,-207,-228,-229,]),'RSHIFT':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,197,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,197,-194,-192,197,197,197,-191,197,197,-189,-188,197,197,197,197,197,-190,-213,-221,-222,-207,-228,-229,]),'DEFAULT':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,248,-250,-39,-42,-38,-40,248,-148,-147,-43,-149,248,-41,-167,-166,-164,248,-150,-163,-151,248,-162,-165,-154,248,-152,248,-153,248,248,-158,-157,-155,248,248,-159,-156,248,-161,-160,]),'CHAR':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[37,37,-61,-72,-71,-58,-54,-55,-33,-29,-59,37,-34,-53,-68,-63,-52,37,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,37,-67,37,-70,-74,37,-57,-82,-249,-81,37,-107,-30,37,-97,-96,37,-45,-46,37,-109,37,37,37,37,-88,37,37,-36,37,-47,37,37,-83,-89,-250,37,-110,37,37,-111,-113,-112,37,37,-98,-37,-39,-42,-38,-40,37,-148,-147,-43,-149,-41,-85,-84,-90,37,37,-100,-99,-167,-166,37,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'WHILE':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,343,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,249,-250,-39,-42,-38,-40,249,-148,-147,-43,-149,249,-41,-167,-166,-164,249,-150,-163,381,-151,249,-162,-165,-154,249,-152,249,-153,249,249,-158,-157,-155,249,249,-159,-156,249,-161,-160,]),'DIVEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[162,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'EXTERN':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[10,10,-61,-72,-71,-58,-54,-55,-33,-29,-59,10,-34,-53,-68,-63,-52,10,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,10,-67,10,-70,-74,10,-57,-82,-249,-81,-107,-30,10,-97,-96,10,-45,-46,10,-109,-36,10,-47,-83,-250,-110,-111,-113,-112,10,10,-98,-37,-39,-42,-38,-40,10,-148,-147,-43,-149,-41,-85,-84,10,10,-100,-99,-167,-166,10,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'CASE':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,250,-250,-39,-42,-38,-40,250,-148,-147,-43,-149,250,-41,-167,-166,-164,250,-150,-163,-151,250,-162,-165,-154,250,-152,250,-153,250,250,-158,-157,-155,250,250,-159,-156,250,-161,-160,]),'LAND':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,210,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,210,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-213,-221,-222,-207,-228,-229,]),'REGISTER':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[17,17,-61,-72,-71,-58,-54,-55,-33,-29,-59,17,-34,-53,-68,-63,-52,17,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,17,-67,17,-70,-74,17,-57,-82,-249,-81,-107,-30,17,-97,-96,17,-45,-46,17,-109,-36,17,-47,-83,-250,-110,-111,-113,-112,17,17,-98,-37,-39,-42,-38,-40,17,-148,-147,-43,-149,-41,-85,-84,17,17,-100,-99,-167,-166,17,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'MODEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[164,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'NE':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,202,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,202,-194,-192,-196,-200,-195,-191,-198,202,-189,-188,-197,202,-199,202,202,-190,-213,-221,-222,-207,-228,-229,]),'SWITCH':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,252,-250,-39,-42,-38,-40,252,-148,-147,-43,-149,252,-41,-167,-166,-164,252,-150,-163,-151,252,-162,-165,-154,252,-152,252,-153,252,252,-158,-157,-155,252,252,-159,-156,252,-161,-160,]),'INT_CONST_HEX':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,109,-45,-219,109,-217,109,-216,109,-215,109,109,-214,-218,109,109,-250,109,-176,-179,-177,-173,-174,-178,-180,109,-182,-183,-175,-181,109,-215,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,-251,-39,-42,-38,109,-40,109,109,-148,-147,-43,-149,109,-41,109,109,109,-215,109,-12,109,109,-11,-167,-166,109,-164,109,109,-150,109,-163,-151,109,109,109,109,-251,109,-215,-251,-131,-162,-165,109,-154,109,-152,109,109,109,-153,109,109,109,-251,109,-158,-157,-155,109,109,109,-159,-156,109,-161,-160,]),'_COMPLEX':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[27,27,-61,-72,-71,-58,-54,-55,-33,-29,-59,27,-34,-53,-68,-63,-52,27,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,27,-67,27,-70,-74,27,-57,-82,-249,-81,27,-107,-30,27,-97,-96,27,-45,-46,27,-109,27,27,27,27,-88,27,27,-36,27,-47,27,27,-83,-89,-250,27,-110,27,27,-111,-113,-112,27,27,-98,-37,-39,-42,-38,-40,27,-148,-147,-43,-149,-41,-85,-84,-90,27,27,-100,-99,-167,-166,27,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'PLUSEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[167,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'STRUCT':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[34,34,-61,-72,-71,-58,-54,-55,-33,-29,-59,34,-34,-53,-68,-63,-52,34,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,34,-67,34,-70,-74,34,-57,-82,-249,-81,34,-107,-30,34,-97,-96,34,-45,-46,34,-109,34,34,34,34,-88,34,34,-36,34,-47,34,34,-83,-89,-250,34,-110,34,34,-111,-113,-112,34,34,-98,-37,-39,-42,-38,-40,34,-148,-147,-43,-149,-41,-85,-84,-90,34,34,-100,-99,-167,-166,34,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'CONDOP':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,213,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-213,-221,-222,-207,-228,-229,]),'BREAK':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,256,-250,-39,-42,-38,-40,256,-148,-147,-43,-149,256,-41,-167,-166,-164,256,-150,-163,-151,256,-162,-165,-154,256,-152,256,-153,256,256,-158,-157,-155,256,256,-159,-156,256,-161,-160,]),'VOLATILE':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,28,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,66,68,73,75,80,82,83,84,85,86,87,88,89,112,139,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[46,46,-61,-72,-71,-58,-54,-55,-33,-29,-59,46,-34,-53,-68,-63,-52,46,-56,-170,-106,-66,46,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,46,-67,46,-70,-74,46,-57,-82,-249,-81,46,-107,-30,46,-97,-96,-116,46,46,-45,-46,46,-109,46,46,46,46,-88,46,46,-117,-36,46,-47,46,46,-83,-89,-250,46,-110,46,46,-111,-113,-112,46,46,-98,-37,-39,-42,-38,-40,46,-148,-147,-43,-149,-41,-85,-84,-90,46,46,-100,-99,-167,-166,46,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'INLINE':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[49,49,-61,-72,-71,-58,-54,-55,-33,-29,-59,49,-34,-53,-68,-63,-52,49,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,49,-67,49,-70,-74,49,-57,-82,-249,-81,-107,-30,49,-97,-96,49,-45,-46,49,-109,-36,49,-47,-83,-250,-110,-111,-113,-112,49,49,-98,-37,-39,-42,-38,-40,49,-148,-147,-43,-149,-41,-85,-84,49,49,-100,-99,-167,-166,49,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'DO':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,259,-250,-39,-42,-38,-40,259,-148,-147,-43,-149,259,-41,-167,-166,-164,259,-150,-163,-151,259,-162,-165,-154,259,-152,259,-153,259,259,-158,-157,-155,259,259,-159,-156,259,-161,-160,]),'LNOT':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,91,-45,-219,91,-217,91,-216,91,-215,91,91,-214,-218,91,91,-250,91,-176,-179,-177,-173,-174,-178,-180,91,-182,-183,-175,-181,91,-215,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,-251,-39,-42,-38,91,-40,91,91,-148,-147,-43,-149,91,-41,91,91,91,-215,91,-12,91,91,-11,-167,-166,91,-164,91,91,-150,91,-163,-151,91,91,91,91,-251,91,-215,-251,-131,-162,-165,91,-154,91,-152,91,91,91,-153,91,91,91,-251,91,-158,-157,-155,91,91,91,-159,-156,91,-161,-160,]),'CONST':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,28,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,66,68,73,75,80,82,83,84,85,86,87,88,89,112,139,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[3,3,-61,-72,-71,-58,-54,-55,-33,-29,-59,3,-34,-53,-68,-63,-52,3,-56,-170,-106,-66,3,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,3,-67,3,-70,-74,3,-57,-82,-249,-81,3,-107,-30,3,-97,-96,-116,3,3,-45,-46,3,-109,3,3,3,3,-88,3,3,-117,-36,3,-47,3,3,-83,-89,-250,3,-110,3,3,-111,-113,-112,3,3,-98,-37,-39,-42,-38,-40,3,-148,-147,-43,-149,-41,-85,-84,-90,3,3,-100,-99,-167,-166,3,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'LOR':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,198,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-213,-221,-222,-207,-228,-229,]),'CHAR_CONST':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,94,-45,-219,94,-217,94,-216,94,-215,94,94,-214,-218,94,94,-250,94,-176,-179,-177,-173,-174,-178,-180,94,-182,-183,-175,-181,94,-215,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,-251,-39,-42,-38,94,-40,94,94,-148,-147,-43,-149,94,-41,94,94,94,-215,94,-12,94,94,-11,-167,-166,94,-164,94,94,-150,94,-163,-151,94,94,94,94,-251,94,-215,-251,-131,-162,-165,94,-154,94,-152,94,94,94,-153,94,94,94,-251,94,-158,-157,-155,94,94,94,-159,-156,94,-161,-160,]),'LSHIFT':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,199,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,199,-194,-192,199,199,199,-191,199,199,-189,-188,199,199,199,199,199,-190,-213,-221,-222,-207,-228,-229,]),'RBRACE':([55,75,86,88,92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,122,124,135,136,137,145,147,148,150,151,174,176,178,180,184,187,188,190,196,228,229,230,236,238,239,242,244,251,253,254,255,257,258,260,261,267,269,271,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,320,321,328,331,332,335,340,342,344,349,350,351,356,368,369,370,373,374,377,382,385,386,392,396,400,401,402,405,406,408,409,416,417,419,420,],[-249,-45,151,-88,-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,-185,-242,-239,-171,-230,-101,151,-104,-251,151,151,-89,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,151,151,-102,-126,-39,-42,-38,-40,-6,-148,-147,-43,-149,-5,-41,151,-184,-90,-172,-225,-224,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-103,-105,151,-167,-166,-164,-150,-163,-151,-213,-221,-222,-207,-129,151,-127,-162,-165,-154,-152,151,-186,-128,-153,151,-228,-130,-158,-157,-155,-229,-159,-156,-161,-160,]),'_BOOL':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[13,13,-61,-72,-71,-58,-54,-55,-33,-29,-59,13,-34,-53,-68,-63,-52,13,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,13,-67,13,-70,-74,13,-57,-82,-249,-81,13,-107,-30,13,-97,-96,13,-45,-46,13,-109,13,13,13,13,-88,13,13,-36,13,-47,13,13,-83,-89,-250,13,-110,13,13,-111,-113,-112,13,13,-98,-37,-39,-42,-38,-40,13,-148,-147,-43,-149,-41,-85,-84,-90,13,13,-100,-99,-167,-166,13,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'LE':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,201,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,201,-194,-192,-196,201,-195,-191,-198,201,-189,-188,-197,201,201,201,201,-190,-213,-221,-222,-207,-228,-229,]),'SEMI':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,30,31,32,33,35,36,37,38,39,40,41,42,43,44,45,46,49,50,51,52,54,55,56,58,59,60,63,64,70,71,72,73,74,75,76,77,79,83,87,89,90,92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,122,124,143,144,145,149,151,152,153,154,155,157,158,159,160,161,174,176,178,180,184,185,187,188,190,191,194,196,216,217,231,233,234,236,237,238,239,241,242,243,244,246,247,251,253,254,255,256,257,258,259,260,262,264,265,266,267,271,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,318,319,330,331,332,333,334,335,336,339,340,342,344,345,347,348,349,350,351,355,356,370,373,374,375,376,377,379,382,386,392,393,394,395,396,397,399,401,403,405,406,408,409,412,413,415,416,417,418,419,420,],[15,-251,-61,-72,-71,-58,-54,-55,-33,-29,-59,-251,-34,-53,-68,-63,-52,15,-56,-170,-106,-66,-69,-251,-32,-73,-108,-64,-31,-60,-35,-62,-65,75,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-249,-81,-49,-107,-30,-97,-96,-18,-44,-17,-77,-75,-45,-48,-51,-251,-109,-251,-251,-251,-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,-185,-242,-239,-171,-230,-77,-36,-251,-83,-250,-21,-80,-22,-79,-24,269,-91,-23,-93,-248,-212,-246,-226,-227,-110,-206,-211,-209,-111,-168,-210,-113,-112,-98,-76,-78,-126,-37,-39,-42,331,-38,332,-40,335,-14,-251,-148,-147,-43,342,-149,-13,-251,-41,-237,-85,-84,-95,-184,-172,-225,-224,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-100,-99,373,-167,-166,374,-251,-164,-251,-13,-150,-163,-151,-251,-92,-94,-213,-221,-222,-169,-207,-127,-162,-165,393,-251,-154,-251,-152,-186,-128,-251,404,-251,-153,-251,-251,-228,410,-158,-157,-155,-229,416,-251,-251,-159,-156,-251,-161,-160,]),'LT':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,203,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,203,-194,-192,-196,203,-195,-191,-198,203,-189,-188,-197,203,203,203,203,-190,-213,-221,-222,-207,-228,-229,]),'COMMA':([1,2,3,5,6,9,10,13,14,17,18,19,21,23,24,25,27,28,29,32,33,35,37,39,40,42,43,44,45,46,49,50,51,52,54,56,58,59,63,64,66,67,68,69,70,73,74,76,77,83,92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,122,124,128,129,130,131,132,135,136,137,138,139,143,149,151,157,159,161,174,176,178,180,184,185,187,188,190,191,192,194,196,216,217,219,220,222,223,224,225,228,229,230,231,233,234,236,247,262,264,265,266,267,271,273,274,275,276,277,278,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,314,315,317,318,319,320,321,328,333,347,348,349,350,351,355,356,359,360,361,362,368,370,378,380,383,384,385,386,387,388,389,392,401,402,407,409,],[-251,-61,-72,-71,-58,-54,-55,-59,-251,-53,-68,-63,-52,-56,-170,-106,-66,-251,-69,-73,-108,-64,-60,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-81,-49,-107,-97,-96,-116,-114,-26,-25,140,-77,-75,-48,-51,-109,-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,-185,-242,-239,-171,-230,-120,-251,226,227,-124,-101,230,-104,-115,-117,-77,-83,-250,268,-91,-93,-248,-212,-246,-226,-227,-110,-206,-211,-209,-111,282,-168,-210,-113,-112,-123,-2,-122,-139,-137,-1,230,230,-102,-98,-76,-78,-126,282,-237,-85,-84,-95,-184,-172,-225,-224,282,-235,-223,352,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,282,-202,-190,-138,-125,-121,-100,-99,-103,-105,369,282,-92,-94,-213,-221,-222,-169,-207,-146,-140,-142,-144,-129,-127,282,282,282,-236,400,-186,-141,-143,-145,-128,-228,-130,282,-229,]),'TYPEDEF':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[23,23,-61,-72,-71,-58,-54,-55,-33,-29,-59,23,-34,-53,-68,-63,-52,23,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,23,-67,23,-70,-74,23,-57,-82,-249,-81,-107,-30,23,-97,-96,23,-45,-46,23,-109,-36,23,-47,-83,-250,-110,-111,-113,-112,23,23,-98,-37,-39,-42,-38,-40,23,-148,-147,-43,-149,-41,-85,-84,23,23,-100,-99,-167,-166,23,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'XOR':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,206,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,206,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,206,-199,-201,206,-190,-213,-221,-222,-207,-228,-229,]),'AUTO':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[21,21,-61,-72,-71,-58,-54,-55,-33,-29,-59,21,-34,-53,-68,-63,-52,21,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,21,-67,21,-70,-74,21,-57,-82,-249,-81,-107,-30,21,-97,-96,21,-45,-46,21,-109,-36,21,-47,-83,-250,-110,-111,-113,-112,21,21,-98,-37,-39,-42,-38,-40,21,-148,-147,-43,-149,-41,-85,-84,21,21,-100,-99,-167,-166,21,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'TIMES':([0,1,2,3,4,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,27,28,29,30,31,32,35,36,37,38,39,40,42,43,44,45,46,49,50,51,52,54,55,56,58,60,61,63,64,66,67,68,69,75,76,77,79,87,89,90,91,92,93,94,95,96,97,98,99,100,101,102,104,105,106,108,109,110,111,112,113,114,115,116,117,118,119,120,123,124,129,139,140,141,144,145,149,151,152,153,154,155,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,180,182,183,184,186,187,188,189,190,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,218,221,231,232,235,237,238,239,242,243,244,250,251,253,254,255,257,259,260,262,264,265,268,270,273,274,277,281,282,283,285,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,311,312,318,319,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,349,350,351,352,353,356,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[28,-251,-61,-72,28,-71,-58,-54,-55,-33,-29,-59,-251,-34,-53,-68,-63,-52,28,-56,-170,-66,-251,-69,28,-32,-73,-64,-31,-60,-35,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-249,-81,-49,-30,110,-97,-96,-116,28,-26,-25,-45,-48,-51,28,-251,-251,28,-219,-206,-233,-243,-247,-244,-241,-231,177,-217,-232,-208,-187,177,-216,177,-240,-215,-220,177,177,-237,-245,-214,-238,208,-242,-239,-218,-230,28,-117,28,177,-36,177,-83,-250,-21,-80,-22,-79,177,-176,-179,-177,-173,-174,-178,-180,177,-182,-183,-175,-181,-248,177,-212,-215,-246,-226,177,177,-227,177,-206,-211,177,-209,28,-210,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,28,311,-98,177,-251,-37,-39,-42,-38,177,-40,177,177,-148,-147,-43,-149,177,-41,-237,-85,-84,28,177,-225,-224,-223,-234,177,177,28,208,208,208,208,208,208,208,208,208,208,-189,-188,208,208,208,208,208,-190,-215,364,-100,-99,-12,177,177,-11,-167,-166,177,-164,177,177,-150,177,-163,-151,177,177,-213,-221,-222,177,177,-207,-251,177,-215,-251,-131,-162,-165,177,-154,177,-152,177,177,177,-153,177,177,177,-251,-228,177,-158,-157,-155,-229,177,177,177,-159,-156,177,-161,-160,]),'LPAREN':([0,1,2,3,4,5,6,9,10,11,12,13,14,15,16,17,18,19,21,22,23,24,25,27,28,29,30,31,32,33,35,36,37,38,39,40,42,43,44,45,46,49,50,51,52,54,55,56,58,59,60,61,63,64,66,67,68,69,75,76,77,79,83,87,89,90,91,93,94,95,96,97,98,99,100,101,102,105,106,108,109,110,111,112,113,114,115,116,117,119,120,123,124,129,138,139,140,141,144,145,149,151,152,153,154,155,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,177,178,180,182,183,184,185,186,189,191,195,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,221,223,224,231,232,235,237,238,239,242,243,244,245,249,250,251,252,253,254,255,257,259,260,262,263,264,265,268,270,273,274,277,281,282,283,285,286,311,312,314,318,319,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,350,351,352,353,357,358,359,360,361,362,364,369,372,373,374,376,377,379,381,382,387,388,389,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[4,-251,-61,-72,4,-71,-58,-54,-55,-33,-29,-59,-251,-34,4,-53,-68,-63,-52,4,-56,-170,62,-66,-251,-69,4,-32,-73,-108,-64,-31,-60,-35,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-249,-81,-49,62,-30,112,-97,-96,-116,-114,-26,-25,-45,-48,-51,4,-109,-251,-251,4,-219,-233,-243,-247,-244,-241,-231,175,-217,-232,183,186,-216,189,-240,-215,-220,112,189,-237,-245,-214,-238,-242,-239,-218,-230,218,-115,-117,4,112,-36,112,-83,-250,-21,-80,-22,-79,186,-176,-179,-177,-173,-174,-178,-180,112,-182,-183,-175,-181,-248,112,-215,-246,-226,112,112,-227,-110,112,112,-111,285,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,112,186,186,-113,-112,218,112,313,218,-98,186,-251,-37,-39,-42,-38,112,-40,334,337,186,112,341,-148,-147,-43,-149,112,-41,-237,346,-85,-84,4,186,-225,-224,-223,-234,112,186,285,285,-215,112,313,-100,-99,-12,186,112,-11,-167,-166,112,-164,112,112,-150,112,-163,-151,112,112,-221,-222,112,186,-251,186,-146,-140,-142,-144,-215,-251,-131,-162,-165,112,-154,112,398,-152,-141,-143,-145,112,112,112,-153,112,112,112,-251,-228,112,-158,-157,-155,-229,112,112,112,-159,-156,112,-161,-160,]),'MINUSMINUS':([55,61,75,91,93,94,95,96,97,98,99,100,101,102,105,106,108,109,110,111,112,113,114,115,116,117,119,120,123,124,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,177,178,180,182,183,184,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,262,270,273,274,277,281,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,350,351,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[-249,113,-45,-219,-233,-243,-247,-244,-241,-231,113,-217,-232,184,113,-216,113,-240,-215,-220,113,113,-237,-245,-214,-238,-242,-239,-218,-230,113,113,-250,113,-176,-179,-177,-173,-174,-178,-180,113,-182,-183,-175,-181,-248,113,-215,-246,-226,113,113,-227,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,-251,-39,-42,-38,113,-40,113,113,-148,-147,-43,-149,113,-41,-237,113,-225,-224,-223,-234,113,113,-215,113,-12,113,113,-11,-167,-166,113,-164,113,113,-150,113,-163,-151,113,113,-221,-222,113,113,-251,113,-215,-251,-131,-162,-165,113,-154,113,-152,113,113,113,-153,113,113,113,-251,-228,113,-158,-157,-155,-229,113,113,113,-159,-156,113,-161,-160,]),'ID':([0,1,2,3,4,5,6,7,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,39,40,42,43,44,45,46,49,50,51,52,54,55,56,58,60,61,62,63,64,65,66,67,68,69,75,76,77,79,87,89,90,91,99,100,105,106,108,110,112,113,116,123,129,133,134,138,139,140,141,144,145,149,151,152,153,154,155,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,179,181,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,218,221,224,226,230,231,232,235,237,238,239,240,242,243,244,250,251,253,254,255,257,259,260,264,265,268,270,282,283,311,312,318,319,322,324,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[33,-251,-61,-72,33,-71,-58,56,-54,-55,-33,-29,-59,-251,-34,33,-53,-68,-63,-87,-52,33,-56,-170,64,-66,-251,-69,33,-32,-73,-86,-64,-31,-60,-35,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-249,-81,-49,-30,114,114,-97,-96,137,-116,-114,-26,-25,-45,-48,-51,33,-251,-251,33,-219,114,-217,114,-216,114,-215,114,114,-214,-218,33,137,137,-115,-117,33,114,-36,262,-83,-250,-21,-80,-22,-79,114,-176,-179,-177,-173,-174,-178,-180,114,-182,-183,-175,-181,114,-215,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,33,114,33,114,137,-98,114,-251,-37,-39,-42,330,-38,114,-40,114,262,-148,-147,-43,-149,262,-41,-85,-84,33,114,114,114,-215,114,-100,-99,-12,114,114,114,-11,-167,-166,114,-164,262,114,-150,114,-163,-151,262,114,114,114,-251,114,-215,-251,-131,-162,-165,114,-154,262,-152,114,114,262,-153,262,114,262,-251,114,-158,-157,-155,114,262,262,-159,-156,262,-161,-160,]),'IF':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,263,-250,-39,-42,-38,-40,263,-148,-147,-43,-149,263,-41,-167,-166,-164,263,-150,-163,-151,263,-162,-165,-154,263,-152,263,-153,263,263,-158,-157,-155,263,263,-159,-156,263,-161,-160,]),'STRING_LITERAL':([55,61,75,91,99,100,101,105,106,108,110,112,113,115,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,178,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,115,-45,-219,115,-217,178,115,-216,115,-215,115,115,-245,-214,-218,115,115,-250,115,-176,-179,-177,-173,-174,-178,-180,115,-182,-183,-175,-181,115,-215,-246,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,-251,-39,-42,-38,115,-40,115,115,-148,-147,-43,-149,115,-41,115,115,115,-215,115,-12,115,115,-11,-167,-166,115,-164,115,115,-150,115,-163,-151,115,115,115,115,-251,115,-215,-251,-131,-162,-165,115,-154,115,-152,115,115,115,-153,115,115,115,-251,115,-158,-157,-155,115,115,115,-159,-156,115,-161,-160,]),'FLOAT':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[35,35,-61,-72,-71,-58,-54,-55,-33,-29,-59,35,-34,-53,-68,-63,-52,35,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,35,-67,35,-70,-74,35,-57,-82,-249,-81,35,-107,-30,35,-97,-96,35,-45,-46,35,-109,35,35,35,35,-88,35,35,-36,35,-47,35,35,-83,-89,-250,35,-110,35,35,-111,-113,-112,35,35,-98,-37,-39,-42,-38,-40,35,-148,-147,-43,-149,-41,-85,-84,-90,35,35,-100,-99,-167,-166,35,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'XOREQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[166,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'LSHIFTEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[168,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'RBRACKET':([61,92,93,94,95,96,97,98,101,102,103,104,107,109,110,111,114,115,117,118,119,120,121,122,124,151,174,176,178,180,184,187,188,190,194,196,221,267,271,273,274,275,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,310,311,312,349,350,351,355,356,363,364,367,386,401,409,],[-251,-206,-233,-243,-247,-244,-241,-231,-232,-208,185,-187,-4,-240,191,-220,-237,-245,-238,-185,-242,-239,-3,-171,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-168,-210,-251,-184,-172,-225,-224,350,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,361,362,-251,-213,-221,-222,-169,-207,387,388,390,-186,-228,-229,]),} - -_lr_action = { } -for _k, _v in _lr_action_items.items(): - for _x,_y in zip(_v[0],_v[1]): - if not _x in _lr_action: _lr_action[_x] = { } - _lr_action[_x][_k] = _y -del _lr_action_items - -_lr_goto_items = {'storage_class_specifier':([0,1,14,22,42,44,48,62,73,82,145,218,227,251,285,313,334,],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,]),'identifier_list_opt':([62,],[125,]),'selection_statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[260,260,260,260,260,260,260,260,260,260,260,260,]),'constant':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,]),'unary_expression':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[92,176,187,190,92,196,92,92,187,92,92,92,92,92,92,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,92,187,187,92,187,92,187,92,92,187,92,187,92,187,92,92,92,92,92,92,92,92,187,187,92,92,92,92,92,92,92,92,92,92,92,92,92,]),'conditional_expression':([61,112,141,145,156,169,175,182,183,186,189,213,221,232,243,250,251,259,270,282,312,325,326,334,336,337,341,345,346,352,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[122,122,122,122,267,122,122,122,122,122,122,122,122,267,122,267,122,122,267,122,122,267,122,122,122,122,122,122,122,122,386,122,122,122,122,122,122,122,122,122,122,122,122,122,]),'brace_close':([86,136,147,148,228,229,261,328,369,385,400,],[149,231,264,265,318,319,344,370,392,401,409,]),'struct_or_union_specifier':([0,1,14,22,42,44,48,57,62,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,]),'unified_wstring_literal':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,]),'abstract_declarator_opt':([129,195,],[219,284,]),'iteration_statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[239,239,239,239,239,239,239,239,239,239,239,239,]),'init_declarator_list':([30,79,],[70,70,]),'translation_unit_or_empty':([0,],[8,]),'struct_declaration_list':([57,84,85,],[86,147,148,]),'enumerator':([65,133,134,230,],[135,135,135,320,]),'pp_directive':([0,22,],[11,11,]),'declaration_list':([48,73,],[82,82,]),'declaration_specifiers_opt':([1,14,42,44,],[50,58,76,77,]),'abstract_declarator':([129,195,218,285,],[220,220,309,309,]),'external_declaration':([0,22,],[12,60,]),'type_specifier':([0,1,14,22,42,44,48,57,62,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[14,14,14,14,14,14,14,87,14,14,14,87,87,87,87,87,87,14,87,87,87,87,87,14,14,14,14,14,14,]),'designation':([235,357,369,400,],[322,322,322,322,]),'compound_statement':([81,142,145,251,259,336,345,379,395,397,399,413,415,418,],[144,237,244,244,244,244,244,244,244,244,244,244,244,244,]),'pointer':([0,4,22,30,67,79,90,129,140,195,218,268,285,],[16,16,16,16,138,16,16,224,16,286,224,16,286,]),'type_name':([112,175,186,189,],[193,272,279,280,]),'unified_string_literal':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,]),'postfix_expression':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,]),'assignment_expression_opt':([61,221,312,],[103,310,363,]),'designation_opt':([235,357,369,400,],[326,326,391,391,]),'expression_statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[238,238,238,238,238,238,238,238,238,238,238,238,]),'unary_operator':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,]),'cast_expression':([61,105,112,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[104,188,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,356,104,104,104,104,104,104,104,104,104,104,356,104,104,104,104,104,104,104,104,104,104,104,104,104,104,]),'brace_open':([7,26,54,56,63,64,81,141,142,145,251,259,283,326,336,345,349,353,354,379,391,395,397,399,413,415,418,],[57,65,84,85,133,134,145,235,145,145,145,145,357,235,145,145,357,357,357,145,235,145,145,145,145,145,145,]),'init_declarator':([30,79,140,],[74,74,233,]),'translation_unit':([0,],[22,]),'assignment_operator':([92,],[169,]),'struct_or_union':([0,1,14,22,42,44,48,57,62,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,]),'block_item_list_opt':([145,],[261,]),'struct_declaration':([57,84,85,86,147,148,],[88,88,88,150,150,150,]),'assignment_expression':([61,112,141,145,169,175,182,183,186,189,213,221,243,251,259,282,312,326,334,336,337,341,345,346,352,376,379,391,393,395,397,398,399,404,410,413,415,418,],[107,194,236,194,271,194,194,276,194,194,194,107,194,194,194,355,107,236,194,194,194,194,194,194,384,194,194,236,194,194,194,194,194,194,194,194,194,194,]),'parameter_type_list':([62,218,285,313,],[127,307,307,307,]),'type_qualifier_list_opt':([28,],[67,]),'direct_declarator':([0,4,16,22,30,79,90,129,140,218,224,268,],[25,25,59,25,25,25,25,25,25,25,59,25,]),'type_qualifier_list':([28,],[68,]),'designator':([235,329,357,369,400,],[323,371,323,323,323,]),'argument_expression_list':([183,],[278,]),'initializer':([141,326,391,],[234,368,402,]),'direct_abstract_declarator':([129,195,218,224,285,286,],[223,223,223,314,223,314,]),'specifier_qualifier_list_opt':([87,89,],[153,155,]),'constant_expression':([156,232,250,270,325,],[266,321,338,348,367,]),'expression_opt':([145,251,259,334,336,345,376,379,393,395,397,399,404,410,413,415,418,],[241,241,241,375,241,241,394,241,403,241,241,241,411,414,241,241,241,]),'primary_expression':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,]),'declaration_specifiers':([0,1,14,22,42,44,48,62,73,82,145,218,227,251,285,313,334,],[30,52,52,30,52,52,79,129,79,79,79,129,129,79,129,129,79,]),'declaration':([0,22,48,73,82,145,251,334,],[31,31,80,80,146,254,254,376,]),'struct_declarator_list_opt':([90,],[158,]),'identifier_list':([62,],[130,]),'typedef_name':([0,1,14,22,42,44,48,57,62,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,]),'parameter_type_list_opt':([218,285,313,],[308,308,365,]),'jump_statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[255,255,255,255,255,255,255,255,255,255,255,255,]),'declaration_list_opt':([48,73,],[81,142,]),'struct_declarator':([90,268,],[159,347,]),'function_definition':([0,22,],[36,36,]),'binary_expression':([61,112,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,312,325,326,334,336,337,341,345,346,352,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[118,118,118,118,118,118,118,118,118,118,118,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,118,304,305,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,]),'parameter_list':([62,218,285,313,],[131,131,131,131,]),'init_declarator_list_opt':([30,79,],[71,71,]),'enum_specifier':([0,1,14,22,42,44,48,57,62,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,]),'struct_declarator_list':([90,],[157,]),'decl_body':([0,22,48,73,82,145,251,334,],[41,41,41,41,41,41,41,41,]),'type_qualifier':([0,1,14,22,28,42,44,48,57,62,68,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[42,42,42,42,66,42,42,42,89,42,139,42,42,89,89,89,89,89,89,42,89,89,89,89,89,42,42,42,42,42,42,]),'enumerator_list':([65,133,134,],[136,228,229,]),'labeled_statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[242,242,242,242,242,242,242,242,242,242,242,242,]),'function_specifier':([0,1,14,22,42,44,48,62,73,82,145,218,227,251,285,313,334,],[44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,]),'specifier_qualifier_list':([57,84,85,86,87,89,112,147,148,175,186,189,],[90,90,90,90,154,154,195,90,90,195,195,195,]),'block_item':([145,251,],[257,340,]),'block_item_list':([145,],[251,]),'statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[253,253,343,377,382,396,405,406,408,417,419,420,]),'empty':([0,1,14,28,30,42,44,48,61,62,73,79,87,89,90,129,145,195,218,221,235,251,259,285,312,313,334,336,345,357,369,376,379,393,395,397,399,400,404,410,413,415,418,],[47,51,51,69,72,51,51,78,121,126,78,72,152,152,160,225,258,225,306,121,327,339,339,306,121,306,339,339,339,327,327,339,339,339,339,339,339,327,339,339,339,339,339,]),'initializer_list':([235,357,],[328,385,]),'declarator':([0,4,22,30,79,90,129,140,218,268,],[48,53,48,73,143,161,222,143,53,161,]),'parameter_declaration':([62,218,227,285,313,],[128,128,317,128,128,]),'designator_list':([235,357,369,400,],[329,329,329,329,]),'identifier':([61,62,99,105,108,112,113,141,145,156,169,175,179,181,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,226,232,243,250,251,259,270,282,283,312,324,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[124,132,124,124,124,124,124,124,124,124,124,124,273,274,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,315,124,124,124,124,124,124,124,124,124,366,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,]),'expression':([112,145,175,182,186,189,213,243,251,259,334,336,337,341,345,346,376,379,393,395,397,398,399,404,410,413,415,418,],[192,247,192,275,192,192,303,333,247,247,247,247,378,380,247,383,247,247,247,247,247,407,247,247,247,247,247,247,]),} - -_lr_goto = { } -for _k, _v in _lr_goto_items.items(): - for _x,_y in zip(_v[0],_v[1]): - if not _x in _lr_goto: _lr_goto[_x] = { } - _lr_goto[_x][_k] = _y -del _lr_goto_items -_lr_productions = [ - ("S' -> translation_unit_or_empty","S'",1,None,None,None), - ('abstract_declarator_opt -> empty','abstract_declarator_opt',1,'p_abstract_declarator_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('abstract_declarator_opt -> abstract_declarator','abstract_declarator_opt',1,'p_abstract_declarator_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('assignment_expression_opt -> empty','assignment_expression_opt',1,'p_assignment_expression_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('assignment_expression_opt -> assignment_expression','assignment_expression_opt',1,'p_assignment_expression_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('block_item_list_opt -> empty','block_item_list_opt',1,'p_block_item_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('block_item_list_opt -> block_item_list','block_item_list_opt',1,'p_block_item_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('declaration_list_opt -> empty','declaration_list_opt',1,'p_declaration_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('declaration_list_opt -> declaration_list','declaration_list_opt',1,'p_declaration_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('declaration_specifiers_opt -> empty','declaration_specifiers_opt',1,'p_declaration_specifiers_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('declaration_specifiers_opt -> declaration_specifiers','declaration_specifiers_opt',1,'p_declaration_specifiers_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('designation_opt -> empty','designation_opt',1,'p_designation_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('designation_opt -> designation','designation_opt',1,'p_designation_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('expression_opt -> empty','expression_opt',1,'p_expression_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('expression_opt -> expression','expression_opt',1,'p_expression_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('identifier_list_opt -> empty','identifier_list_opt',1,'p_identifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('identifier_list_opt -> identifier_list','identifier_list_opt',1,'p_identifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('init_declarator_list_opt -> empty','init_declarator_list_opt',1,'p_init_declarator_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('init_declarator_list_opt -> init_declarator_list','init_declarator_list_opt',1,'p_init_declarator_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('parameter_type_list_opt -> empty','parameter_type_list_opt',1,'p_parameter_type_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('parameter_type_list_opt -> parameter_type_list','parameter_type_list_opt',1,'p_parameter_type_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('specifier_qualifier_list_opt -> empty','specifier_qualifier_list_opt',1,'p_specifier_qualifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('specifier_qualifier_list_opt -> specifier_qualifier_list','specifier_qualifier_list_opt',1,'p_specifier_qualifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('struct_declarator_list_opt -> empty','struct_declarator_list_opt',1,'p_struct_declarator_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('struct_declarator_list_opt -> struct_declarator_list','struct_declarator_list_opt',1,'p_struct_declarator_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('type_qualifier_list_opt -> empty','type_qualifier_list_opt',1,'p_type_qualifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('type_qualifier_list_opt -> type_qualifier_list','type_qualifier_list_opt',1,'p_type_qualifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('translation_unit_or_empty -> translation_unit','translation_unit_or_empty',1,'p_translation_unit_or_empty','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',355), - ('translation_unit_or_empty -> empty','translation_unit_or_empty',1,'p_translation_unit_or_empty','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',356), - ('translation_unit -> external_declaration','translation_unit',1,'p_translation_unit_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',364), - ('translation_unit -> translation_unit external_declaration','translation_unit',2,'p_translation_unit_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',371), - ('external_declaration -> function_definition','external_declaration',1,'p_external_declaration_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',383), - ('external_declaration -> declaration','external_declaration',1,'p_external_declaration_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',388), - ('external_declaration -> pp_directive','external_declaration',1,'p_external_declaration_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',393), - ('external_declaration -> SEMI','external_declaration',1,'p_external_declaration_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',398), - ('pp_directive -> PPHASH','pp_directive',1,'p_pp_directive','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',403), - ('function_definition -> declarator declaration_list_opt compound_statement','function_definition',3,'p_function_definition_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',412), - ('function_definition -> declaration_specifiers declarator declaration_list_opt compound_statement','function_definition',4,'p_function_definition_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',424), - ('statement -> labeled_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',435), - ('statement -> expression_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',436), - ('statement -> compound_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',437), - ('statement -> selection_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',438), - ('statement -> iteration_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',439), - ('statement -> jump_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',440), - ('decl_body -> declaration_specifiers init_declarator_list_opt','decl_body',2,'p_decl_body','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',454), - ('declaration -> decl_body SEMI','declaration',2,'p_declaration','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',537), - ('declaration_list -> declaration','declaration_list',1,'p_declaration_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',546), - ('declaration_list -> declaration_list declaration','declaration_list',2,'p_declaration_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',547), - ('declaration_specifiers -> type_qualifier declaration_specifiers_opt','declaration_specifiers',2,'p_declaration_specifiers_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',552), - ('declaration_specifiers -> type_specifier declaration_specifiers_opt','declaration_specifiers',2,'p_declaration_specifiers_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',557), - ('declaration_specifiers -> storage_class_specifier declaration_specifiers_opt','declaration_specifiers',2,'p_declaration_specifiers_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',562), - ('declaration_specifiers -> function_specifier declaration_specifiers_opt','declaration_specifiers',2,'p_declaration_specifiers_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',567), - ('storage_class_specifier -> AUTO','storage_class_specifier',1,'p_storage_class_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',572), - ('storage_class_specifier -> REGISTER','storage_class_specifier',1,'p_storage_class_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',573), - ('storage_class_specifier -> STATIC','storage_class_specifier',1,'p_storage_class_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',574), - ('storage_class_specifier -> EXTERN','storage_class_specifier',1,'p_storage_class_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',575), - ('storage_class_specifier -> TYPEDEF','storage_class_specifier',1,'p_storage_class_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',576), - ('function_specifier -> INLINE','function_specifier',1,'p_function_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',581), - ('type_specifier -> VOID','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',586), - ('type_specifier -> _BOOL','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',587), - ('type_specifier -> CHAR','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',588), - ('type_specifier -> SHORT','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',589), - ('type_specifier -> INT','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',590), - ('type_specifier -> LONG','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',591), - ('type_specifier -> FLOAT','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',592), - ('type_specifier -> DOUBLE','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',593), - ('type_specifier -> _COMPLEX','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',594), - ('type_specifier -> SIGNED','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',595), - ('type_specifier -> UNSIGNED','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',596), - ('type_specifier -> typedef_name','type_specifier',1,'p_type_specifier_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',601), - ('type_specifier -> enum_specifier','type_specifier',1,'p_type_specifier_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',602), - ('type_specifier -> struct_or_union_specifier','type_specifier',1,'p_type_specifier_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',603), - ('type_qualifier -> CONST','type_qualifier',1,'p_type_qualifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',608), - ('type_qualifier -> RESTRICT','type_qualifier',1,'p_type_qualifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',609), - ('type_qualifier -> VOLATILE','type_qualifier',1,'p_type_qualifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',610), - ('init_declarator_list -> init_declarator','init_declarator_list',1,'p_init_declarator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',615), - ('init_declarator_list -> init_declarator_list COMMA init_declarator','init_declarator_list',3,'p_init_declarator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',616), - ('init_declarator -> declarator','init_declarator',1,'p_init_declarator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',624), - ('init_declarator -> declarator EQUALS initializer','init_declarator',3,'p_init_declarator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',625), - ('specifier_qualifier_list -> type_qualifier specifier_qualifier_list_opt','specifier_qualifier_list',2,'p_specifier_qualifier_list_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',630), - ('specifier_qualifier_list -> type_specifier specifier_qualifier_list_opt','specifier_qualifier_list',2,'p_specifier_qualifier_list_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',635), - ('struct_or_union_specifier -> struct_or_union ID','struct_or_union_specifier',2,'p_struct_or_union_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',643), - ('struct_or_union_specifier -> struct_or_union TYPEID','struct_or_union_specifier',2,'p_struct_or_union_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',644), - ('struct_or_union_specifier -> struct_or_union brace_open struct_declaration_list brace_close','struct_or_union_specifier',4,'p_struct_or_union_specifier_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',653), - ('struct_or_union_specifier -> struct_or_union ID brace_open struct_declaration_list brace_close','struct_or_union_specifier',5,'p_struct_or_union_specifier_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',662), - ('struct_or_union_specifier -> struct_or_union TYPEID brace_open struct_declaration_list brace_close','struct_or_union_specifier',5,'p_struct_or_union_specifier_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',663), - ('struct_or_union -> STRUCT','struct_or_union',1,'p_struct_or_union','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',672), - ('struct_or_union -> UNION','struct_or_union',1,'p_struct_or_union','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',673), - ('struct_declaration_list -> struct_declaration','struct_declaration_list',1,'p_struct_declaration_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',680), - ('struct_declaration_list -> struct_declaration_list struct_declaration','struct_declaration_list',2,'p_struct_declaration_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',681), - ('struct_declaration -> specifier_qualifier_list struct_declarator_list_opt SEMI','struct_declaration',3,'p_struct_declaration_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',686), - ('struct_declarator_list -> struct_declarator','struct_declarator_list',1,'p_struct_declarator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',737), - ('struct_declarator_list -> struct_declarator_list COMMA struct_declarator','struct_declarator_list',3,'p_struct_declarator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',738), - ('struct_declarator -> declarator','struct_declarator',1,'p_struct_declarator_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',746), - ('struct_declarator -> declarator COLON constant_expression','struct_declarator',3,'p_struct_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',751), - ('struct_declarator -> COLON constant_expression','struct_declarator',2,'p_struct_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',752), - ('enum_specifier -> ENUM ID','enum_specifier',2,'p_enum_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',760), - ('enum_specifier -> ENUM TYPEID','enum_specifier',2,'p_enum_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',761), - ('enum_specifier -> ENUM brace_open enumerator_list brace_close','enum_specifier',4,'p_enum_specifier_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',766), - ('enum_specifier -> ENUM ID brace_open enumerator_list brace_close','enum_specifier',5,'p_enum_specifier_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',771), - ('enum_specifier -> ENUM TYPEID brace_open enumerator_list brace_close','enum_specifier',5,'p_enum_specifier_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',772), - ('enumerator_list -> enumerator','enumerator_list',1,'p_enumerator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',777), - ('enumerator_list -> enumerator_list COMMA','enumerator_list',2,'p_enumerator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',778), - ('enumerator_list -> enumerator_list COMMA enumerator','enumerator_list',3,'p_enumerator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',779), - ('enumerator -> ID','enumerator',1,'p_enumerator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',790), - ('enumerator -> ID EQUALS constant_expression','enumerator',3,'p_enumerator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',791), - ('declarator -> direct_declarator','declarator',1,'p_declarator_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',803), - ('declarator -> pointer direct_declarator','declarator',2,'p_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',808), - ('direct_declarator -> ID','direct_declarator',1,'p_direct_declarator_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',813), - ('direct_declarator -> LPAREN declarator RPAREN','direct_declarator',3,'p_direct_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',822), - ('direct_declarator -> direct_declarator LBRACKET assignment_expression_opt RBRACKET','direct_declarator',4,'p_direct_declarator_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',827), - ('direct_declarator -> direct_declarator LBRACKET TIMES RBRACKET','direct_declarator',4,'p_direct_declarator_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',839), - ('direct_declarator -> direct_declarator LPAREN parameter_type_list RPAREN','direct_declarator',4,'p_direct_declarator_5','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',849), - ('direct_declarator -> direct_declarator LPAREN identifier_list_opt RPAREN','direct_declarator',4,'p_direct_declarator_5','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',850), - ('pointer -> TIMES type_qualifier_list_opt','pointer',2,'p_pointer','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',860), - ('pointer -> TIMES type_qualifier_list_opt pointer','pointer',3,'p_pointer','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',861), - ('type_qualifier_list -> type_qualifier','type_qualifier_list',1,'p_type_qualifier_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',871), - ('type_qualifier_list -> type_qualifier_list type_qualifier','type_qualifier_list',2,'p_type_qualifier_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',872), - ('parameter_type_list -> parameter_list','parameter_type_list',1,'p_parameter_type_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',877), - ('parameter_type_list -> parameter_list COMMA ELLIPSIS','parameter_type_list',3,'p_parameter_type_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',878), - ('parameter_list -> parameter_declaration','parameter_list',1,'p_parameter_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',886), - ('parameter_list -> parameter_list COMMA parameter_declaration','parameter_list',3,'p_parameter_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',887), - ('parameter_declaration -> declaration_specifiers declarator','parameter_declaration',2,'p_parameter_declaration_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',896), - ('parameter_declaration -> declaration_specifiers abstract_declarator_opt','parameter_declaration',2,'p_parameter_declaration_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',915), - ('identifier_list -> identifier','identifier_list',1,'p_identifier_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',927), - ('identifier_list -> identifier_list COMMA identifier','identifier_list',3,'p_identifier_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',928), - ('initializer -> assignment_expression','initializer',1,'p_initializer_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',937), - ('initializer -> brace_open initializer_list brace_close','initializer',3,'p_initializer_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',942), - ('initializer -> brace_open initializer_list COMMA brace_close','initializer',4,'p_initializer_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',943), - ('initializer_list -> designation_opt initializer','initializer_list',2,'p_initializer_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',948), - ('initializer_list -> initializer_list COMMA designation_opt initializer','initializer_list',4,'p_initializer_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',949), - ('designation -> designator_list EQUALS','designation',2,'p_designation','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',960), - ('designator_list -> designator','designator_list',1,'p_designator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',968), - ('designator_list -> designator_list designator','designator_list',2,'p_designator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',969), - ('designator -> LBRACKET constant_expression RBRACKET','designator',3,'p_designator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',974), - ('designator -> PERIOD identifier','designator',2,'p_designator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',975), - ('type_name -> specifier_qualifier_list abstract_declarator_opt','type_name',2,'p_type_name','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',980), - ('abstract_declarator -> pointer','abstract_declarator',1,'p_abstract_declarator_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',996), - ('abstract_declarator -> pointer direct_abstract_declarator','abstract_declarator',2,'p_abstract_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1004), - ('abstract_declarator -> direct_abstract_declarator','abstract_declarator',1,'p_abstract_declarator_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1009), - ('direct_abstract_declarator -> LPAREN abstract_declarator RPAREN','direct_abstract_declarator',3,'p_direct_abstract_declarator_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1019), - ('direct_abstract_declarator -> direct_abstract_declarator LBRACKET assignment_expression_opt RBRACKET','direct_abstract_declarator',4,'p_direct_abstract_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1023), - ('direct_abstract_declarator -> LBRACKET assignment_expression_opt RBRACKET','direct_abstract_declarator',3,'p_direct_abstract_declarator_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1033), - ('direct_abstract_declarator -> direct_abstract_declarator LBRACKET TIMES RBRACKET','direct_abstract_declarator',4,'p_direct_abstract_declarator_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1041), - ('direct_abstract_declarator -> LBRACKET TIMES RBRACKET','direct_abstract_declarator',3,'p_direct_abstract_declarator_5','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1051), - ('direct_abstract_declarator -> direct_abstract_declarator LPAREN parameter_type_list_opt RPAREN','direct_abstract_declarator',4,'p_direct_abstract_declarator_6','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1059), - ('direct_abstract_declarator -> LPAREN parameter_type_list_opt RPAREN','direct_abstract_declarator',3,'p_direct_abstract_declarator_7','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1069), - ('block_item -> declaration','block_item',1,'p_block_item','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1080), - ('block_item -> statement','block_item',1,'p_block_item','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1081), - ('block_item_list -> block_item','block_item_list',1,'p_block_item_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1088), - ('block_item_list -> block_item_list block_item','block_item_list',2,'p_block_item_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1089), - ('compound_statement -> brace_open block_item_list_opt brace_close','compound_statement',3,'p_compound_statement_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1095), - ('labeled_statement -> ID COLON statement','labeled_statement',3,'p_labeled_statement_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1101), - ('labeled_statement -> CASE constant_expression COLON statement','labeled_statement',4,'p_labeled_statement_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1105), - ('labeled_statement -> DEFAULT COLON statement','labeled_statement',3,'p_labeled_statement_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1109), - ('selection_statement -> IF LPAREN expression RPAREN statement','selection_statement',5,'p_selection_statement_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1113), - ('selection_statement -> IF LPAREN expression RPAREN statement ELSE statement','selection_statement',7,'p_selection_statement_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1117), - ('selection_statement -> SWITCH LPAREN expression RPAREN statement','selection_statement',5,'p_selection_statement_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1121), - ('iteration_statement -> WHILE LPAREN expression RPAREN statement','iteration_statement',5,'p_iteration_statement_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1126), - ('iteration_statement -> DO statement WHILE LPAREN expression RPAREN SEMI','iteration_statement',7,'p_iteration_statement_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1130), - ('iteration_statement -> FOR LPAREN expression_opt SEMI expression_opt SEMI expression_opt RPAREN statement','iteration_statement',9,'p_iteration_statement_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1134), - ('iteration_statement -> FOR LPAREN declaration expression_opt SEMI expression_opt RPAREN statement','iteration_statement',8,'p_iteration_statement_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1138), - ('jump_statement -> GOTO ID SEMI','jump_statement',3,'p_jump_statement_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1142), - ('jump_statement -> BREAK SEMI','jump_statement',2,'p_jump_statement_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1146), - ('jump_statement -> CONTINUE SEMI','jump_statement',2,'p_jump_statement_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1150), - ('jump_statement -> RETURN expression SEMI','jump_statement',3,'p_jump_statement_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1154), - ('jump_statement -> RETURN SEMI','jump_statement',2,'p_jump_statement_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1155), - ('expression_statement -> expression_opt SEMI','expression_statement',2,'p_expression_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1160), - ('expression -> assignment_expression','expression',1,'p_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1167), - ('expression -> expression COMMA assignment_expression','expression',3,'p_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1168), - ('typedef_name -> TYPEID','typedef_name',1,'p_typedef_name','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1180), - ('assignment_expression -> conditional_expression','assignment_expression',1,'p_assignment_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1184), - ('assignment_expression -> unary_expression assignment_operator assignment_expression','assignment_expression',3,'p_assignment_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1185), - ('assignment_operator -> EQUALS','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1198), - ('assignment_operator -> XOREQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1199), - ('assignment_operator -> TIMESEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1200), - ('assignment_operator -> DIVEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1201), - ('assignment_operator -> MODEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1202), - ('assignment_operator -> PLUSEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1203), - ('assignment_operator -> MINUSEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1204), - ('assignment_operator -> LSHIFTEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1205), - ('assignment_operator -> RSHIFTEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1206), - ('assignment_operator -> ANDEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1207), - ('assignment_operator -> OREQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1208), - ('constant_expression -> conditional_expression','constant_expression',1,'p_constant_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1213), - ('conditional_expression -> binary_expression','conditional_expression',1,'p_conditional_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1217), - ('conditional_expression -> binary_expression CONDOP expression COLON conditional_expression','conditional_expression',5,'p_conditional_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1218), - ('binary_expression -> cast_expression','binary_expression',1,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1226), - ('binary_expression -> binary_expression TIMES binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1227), - ('binary_expression -> binary_expression DIVIDE binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1228), - ('binary_expression -> binary_expression MOD binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1229), - ('binary_expression -> binary_expression PLUS binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1230), - ('binary_expression -> binary_expression MINUS binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1231), - ('binary_expression -> binary_expression RSHIFT binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1232), - ('binary_expression -> binary_expression LSHIFT binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1233), - ('binary_expression -> binary_expression LT binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1234), - ('binary_expression -> binary_expression LE binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1235), - ('binary_expression -> binary_expression GE binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1236), - ('binary_expression -> binary_expression GT binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1237), - ('binary_expression -> binary_expression EQ binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1238), - ('binary_expression -> binary_expression NE binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1239), - ('binary_expression -> binary_expression AND binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1240), - ('binary_expression -> binary_expression OR binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1241), - ('binary_expression -> binary_expression XOR binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1242), - ('binary_expression -> binary_expression LAND binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1243), - ('binary_expression -> binary_expression LOR binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1244), - ('cast_expression -> unary_expression','cast_expression',1,'p_cast_expression_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1252), - ('cast_expression -> LPAREN type_name RPAREN cast_expression','cast_expression',4,'p_cast_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1256), - ('unary_expression -> postfix_expression','unary_expression',1,'p_unary_expression_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1260), - ('unary_expression -> PLUSPLUS unary_expression','unary_expression',2,'p_unary_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1264), - ('unary_expression -> MINUSMINUS unary_expression','unary_expression',2,'p_unary_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1265), - ('unary_expression -> unary_operator cast_expression','unary_expression',2,'p_unary_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1266), - ('unary_expression -> SIZEOF unary_expression','unary_expression',2,'p_unary_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1271), - ('unary_expression -> SIZEOF LPAREN type_name RPAREN','unary_expression',4,'p_unary_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1272), - ('unary_operator -> AND','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1280), - ('unary_operator -> TIMES','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1281), - ('unary_operator -> PLUS','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1282), - ('unary_operator -> MINUS','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1283), - ('unary_operator -> NOT','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1284), - ('unary_operator -> LNOT','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1285), - ('postfix_expression -> primary_expression','postfix_expression',1,'p_postfix_expression_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1290), - ('postfix_expression -> postfix_expression LBRACKET expression RBRACKET','postfix_expression',4,'p_postfix_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1294), - ('postfix_expression -> postfix_expression LPAREN argument_expression_list RPAREN','postfix_expression',4,'p_postfix_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1298), - ('postfix_expression -> postfix_expression LPAREN RPAREN','postfix_expression',3,'p_postfix_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1299), - ('postfix_expression -> postfix_expression PERIOD identifier','postfix_expression',3,'p_postfix_expression_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1304), - ('postfix_expression -> postfix_expression ARROW identifier','postfix_expression',3,'p_postfix_expression_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1305), - ('postfix_expression -> postfix_expression PLUSPLUS','postfix_expression',2,'p_postfix_expression_5','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1310), - ('postfix_expression -> postfix_expression MINUSMINUS','postfix_expression',2,'p_postfix_expression_5','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1311), - ('postfix_expression -> LPAREN type_name RPAREN brace_open initializer_list brace_close','postfix_expression',6,'p_postfix_expression_6','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1316), - ('postfix_expression -> LPAREN type_name RPAREN brace_open initializer_list COMMA brace_close','postfix_expression',7,'p_postfix_expression_6','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1317), - ('primary_expression -> identifier','primary_expression',1,'p_primary_expression_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1322), - ('primary_expression -> constant','primary_expression',1,'p_primary_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1326), - ('primary_expression -> unified_string_literal','primary_expression',1,'p_primary_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1330), - ('primary_expression -> unified_wstring_literal','primary_expression',1,'p_primary_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1331), - ('primary_expression -> LPAREN expression RPAREN','primary_expression',3,'p_primary_expression_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1336), - ('argument_expression_list -> assignment_expression','argument_expression_list',1,'p_argument_expression_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1340), - ('argument_expression_list -> argument_expression_list COMMA assignment_expression','argument_expression_list',3,'p_argument_expression_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1341), - ('identifier -> ID','identifier',1,'p_identifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1350), - ('constant -> INT_CONST_DEC','constant',1,'p_constant_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1354), - ('constant -> INT_CONST_OCT','constant',1,'p_constant_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1355), - ('constant -> INT_CONST_HEX','constant',1,'p_constant_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1356), - ('constant -> FLOAT_CONST','constant',1,'p_constant_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1362), - ('constant -> HEX_FLOAT_CONST','constant',1,'p_constant_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1363), - ('constant -> CHAR_CONST','constant',1,'p_constant_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1369), - ('constant -> WCHAR_CONST','constant',1,'p_constant_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1370), - ('unified_string_literal -> STRING_LITERAL','unified_string_literal',1,'p_unified_string_literal','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1381), - ('unified_string_literal -> unified_string_literal STRING_LITERAL','unified_string_literal',2,'p_unified_string_literal','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1382), - ('unified_wstring_literal -> WSTRING_LITERAL','unified_wstring_literal',1,'p_unified_wstring_literal','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1392), - ('unified_wstring_literal -> unified_wstring_literal WSTRING_LITERAL','unified_wstring_literal',2,'p_unified_wstring_literal','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1393), - ('brace_open -> LBRACE','brace_open',1,'p_brace_open','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1403), - ('brace_close -> RBRACE','brace_close',1,'p_brace_close','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1409), - ('empty -> ','empty',0,'p_empty','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1415), -] diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/UNKNOWN.egg-info/PKG-INFO b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/UNKNOWN.egg-info/PKG-INFO deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/UNKNOWN.egg-info/PKG-INFO +++ /dev/null @@ -1,10 +0,0 @@ -Metadata-Version: 1.0 -Name: UNKNOWN -Version: 0.0.0 -Summary: UNKNOWN -Home-page: UNKNOWN -Author: UNKNOWN -Author-email: UNKNOWN -License: UNKNOWN -Description: UNKNOWN -Platform: UNKNOWN diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/UNKNOWN.egg-info/SOURCES.txt b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/UNKNOWN.egg-info/SOURCES.txt deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/UNKNOWN.egg-info/SOURCES.txt +++ /dev/null @@ -1,8 +0,0 @@ -setup.py -UNKNOWN.egg-info/PKG-INFO -UNKNOWN.egg-info/SOURCES.txt -UNKNOWN.egg-info/dependency_links.txt -UNKNOWN.egg-info/not-zip-safe -UNKNOWN.egg-info/top_level.txt -snip_setuptools_verify1/__init__.py -snip_setuptools_verify1/__pycache__/_cffi__gd39ab08bx8432a366.c \ No newline at end of file diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/UNKNOWN.egg-info/dependency_links.txt b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/UNKNOWN.egg-info/dependency_links.txt deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/UNKNOWN.egg-info/dependency_links.txt +++ /dev/null @@ -1,1 +0,0 @@ - diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/UNKNOWN.egg-info/not-zip-safe b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/UNKNOWN.egg-info/not-zip-safe deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/UNKNOWN.egg-info/not-zip-safe +++ /dev/null @@ -1,1 +0,0 @@ - diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/UNKNOWN.egg-info/top_level.txt b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/UNKNOWN.egg-info/top_level.txt deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/UNKNOWN.egg-info/top_level.txt +++ /dev/null @@ -1,2 +0,0 @@ -snip_setuptools_verify1 -_cffi__gd39ab08bx8432a366 diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/build/lib.linux-x86_64-2.7/_cffi__gd39ab08bx8432a366.pypy-20.so b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/build/lib.linux-x86_64-2.7/_cffi__gd39ab08bx8432a366.pypy-20.so deleted file mode 100755 Binary file pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/build/lib.linux-x86_64-2.7/_cffi__gd39ab08bx8432a366.pypy-20.so has changed diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/build/lib.linux-x86_64-2.7/snip_setuptools_verify1/__init__.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/build/lib.linux-x86_64-2.7/snip_setuptools_verify1/__init__.py deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/build/lib.linux-x86_64-2.7/snip_setuptools_verify1/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ - -from cffi import FFI -import sys - -ffi = FFI() -ffi.cdef(""" // some declarations from the man page - struct passwd { - char *pw_name; - ...; - }; - struct passwd *getpwuid(int uid); -""") -C = ffi.verify(""" // passed to the real C compiler -#include -#include -""", libraries=[], # or a list of libraries to link with - force_generic_engine=hasattr(sys, '_force_generic_engine_')) diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/build/temp.linux-x86_64-2.7/snip_setuptools_verify1/__pycache__/_cffi__gd39ab08bx8432a366.o b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/build/temp.linux-x86_64-2.7/snip_setuptools_verify1/__pycache__/_cffi__gd39ab08bx8432a366.o deleted file mode 100644 Binary file pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/build/temp.linux-x86_64-2.7/snip_setuptools_verify1/__pycache__/_cffi__gd39ab08bx8432a366.o has changed diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/dist/UNKNOWN-0.0.0-py2.7-linux-x86_64.egg b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/dist/UNKNOWN-0.0.0-py2.7-linux-x86_64.egg deleted file mode 100644 Binary file pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/dist/UNKNOWN-0.0.0-py2.7-linux-x86_64.egg has changed diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/lextab.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/lextab.py deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/lextab.py +++ /dev/null @@ -1,9 +0,0 @@ -# pycparser.lextab.py. This file automatically created by PLY (version 3.4). Don't edit! -_tabversion = '3.4' -_lextokens = {'VOID': 1, 'LBRACKET': 1, 'WCHAR_CONST': 1, 'FLOAT_CONST': 1, 'MINUS': 1, 'RPAREN': 1, 'LONG': 1, 'PLUS': 1, 'ELLIPSIS': 1, 'GT': 1, 'GOTO': 1, 'ENUM': 1, 'PERIOD': 1, 'GE': 1, 'INT_CONST_DEC': 1, 'ARROW': 1, 'HEX_FLOAT_CONST': 1, 'DOUBLE': 1, 'MINUSEQUAL': 1, 'INT_CONST_OCT': 1, 'TIMESEQUAL': 1, 'OR': 1, 'SHORT': 1, 'RETURN': 1, 'RSHIFTEQUAL': 1, 'RESTRICT': 1, 'STATIC': 1, 'SIZEOF': 1, 'UNSIGNED': 1, 'UNION': 1, 'COLON': 1, 'WSTRING_LITERAL': 1, 'DIVIDE': 1, 'FOR': 1, 'PLUSPLUS': 1, 'EQUALS': 1, 'ELSE': 1, 'INLINE': 1, 'EQ': 1, 'AND': 1, 'TYPEID': 1, 'LBRACE': 1, 'PPHASH': 1, 'INT': 1, 'SIGNED': 1, 'CONTINUE': 1, 'NOT': 1, 'OREQUAL': 1, 'MOD': 1, 'RSHIFT': 1, 'DEFAULT': 1, 'CHAR': 1, 'WHILE': 1, 'DIVEQUAL': 1, 'EXTERN': 1, 'CASE': 1, 'LAND': 1, 'REGISTER': 1, 'MODEQUAL': 1, 'NE': 1, 'SWITCH': 1, 'INT_CONST_HEX': 1, '_COMPLEX': 1, 'PLUSEQUAL': 1, 'STRUCT': 1, 'CONDOP': 1, 'BREAK': 1, 'VOLATILE': 1, 'ANDEQUAL': 1, 'DO': 1, 'LNOT': 1, 'CONST': 1, 'LOR': 1, 'CHAR_CONST': 1, 'LSHIFT': 1, 'RBRACE': 1, '_BOOL': 1, 'LE': 1, 'SEMI': 1, 'LT': 1, 'COMMA': 1, 'TYPEDEF': 1, 'XOR': 1, 'AUTO': 1, 'TIMES': 1, 'LPAREN': 1, 'MINUSMINUS': 1, 'ID': 1, 'IF': 1, 'STRING_LITERAL': 1, 'FLOAT': 1, 'XOREQUAL': 1, 'LSHIFTEQUAL': 1, 'RBRACKET': 1} -_lexreflags = 0 -_lexliterals = '' -_lexstateinfo = {'ppline': 'exclusive', 'pppragma': 'exclusive', 'INITIAL': 'inclusive'} -_lexstatere = {'ppline': [('(?P"([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*")|(?P(0(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?)|([1-9][0-9]*(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?))|(?P\\n)|(?Pline)', [None, ('t_ppline_FILENAME', 'FILENAME'), None, None, None, None, None, None, ('t_ppline_LINE_NUMBER', 'LINE_NUMBER'), None, None, None, None, None, None, None, None, ('t_ppline_NEWLINE', 'NEWLINE'), ('t_ppline_PPLINE', 'PPLINE')])], 'pppragma': [('(?P\\n)|(?Ppragma)|(?P"([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*")|(?P[a-zA-Z_][0-9a-zA-Z_]*)', [None, ('t_pppragma_NEWLINE', 'NEWLINE'), ('t_pppragma_PPPRAGMA', 'PPPRAGMA'), ('t_pppragma_STR', 'STR'), None, None, None, None, None, None, ('t_pppragma_ID', 'ID')])], 'INITIAL': [('(?P[ \\t]*\\#)|(?P\\n+)|(?P((((([0-9]*\\.[0-9]+)|([0-9]+\\.))([eE][-+]?[0-9]+)?)|([0-9]+([eE][-+]?[0-9]+)))[FfLl]?))|(?P(0[xX]([0-9a-fA-F]+|((([0-9a-fA-F]+)?\\.[0-9a-fA-F]+)|([0-9a-fA-F]+\\.)))([pP][+-]?[0-9]+)[FfLl]?))|(?P0[xX][0-9a-fA-F]+(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?)|(?P0[0-7]*[89])|(?P0[0-7]*(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?)', [None, ('t_PPHASH', 'PPHASH'), ('t_NEWLINE', 'NEWLINE'), ('t_FLOAT_CONST', 'FLOAT_CONST'), None, None, None, None, None, None, None, None, None, ('t_HEX_FLOAT_CONST', 'HEX_FLOAT_CONST'), None, None, None, None, None, None, None, ('t_INT_CONST_HEX', 'INT_CONST_HEX'), None, None, None, ('t_BAD_CONST_OCT', 'BAD_CONST_OCT'), ('t_INT_CONST_OCT', 'INT_CONST_OCT')]), ('(?P(0(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?)|([1-9][0-9]*(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?))|(?P\'([^\'\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))\')|(?PL\'([^\'\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))\')|(?P(\'([^\'\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*\\n)|(\'([^\'\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*$))|(?P(\'([^\'\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))[^\'\n]+\')|(\'\')|(\'([\\\\][^a-zA-Z._~^!=&\\^\\-\\\\?\'"x0-7])[^\'\\n]*\'))|(?PL"([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*")|(?P"([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*([\\\\][^a-zA-Z._~^!=&\\^\\-\\\\?\'"x0-7])([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*")|(?P[a-zA-Z_][0-9a-zA-Z_]*)', [None, ('t_INT_CONST_DEC', 'INT_CONST_DEC'), None, None, None, None, None, None, None, None, ('t_CHAR_CONST', 'CHAR_CONST'), None, None, None, None, None, None, ('t_WCHAR_CONST', 'WCHAR_CONST'), None, None, None, None, None, None, ('t_UNMATCHED_QUOTE', 'UNMATCHED_QUOTE'), None, None, None, None, None, None, None, None, None, None, None, None, None, None, ('t_BAD_CHAR_CONST', 'BAD_CHAR_CONST'), None, None, None, None, None, None, None, None, None, None, ('t_WSTRING_LITERAL', 'WSTRING_LITERAL'), None, None, None, None, None, None, ('t_BAD_STRING_LITERAL', 'BAD_STRING_LITERAL'), None, None, None, None, None, None, None, None, None, None, None, None, None, ('t_ID', 'ID')]), ('(?P"([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*")|(?P\\.\\.\\.)|(?P\\+\\+)|(?P\\|\\|)|(?P\\^=)|(?P\\|=)|(?P<<=)|(?P>>=)|(?P\\+=)|(?P\\*=)|(?P\\+)|(?P%=)|(?P\\{)|(?P/=)|(?P\\])|(?P\\?)', [None, (None, 'STRING_LITERAL'), None, None, None, None, None, None, (None, 'ELLIPSIS'), (None, 'PLUSPLUS'), (None, 'LOR'), (None, 'XOREQUAL'), (None, 'OREQUAL'), (None, 'LSHIFTEQUAL'), (None, 'RSHIFTEQUAL'), (None, 'PLUSEQUAL'), (None, 'TIMESEQUAL'), (None, 'PLUS'), (None, 'MODEQUAL'), (None, 'LBRACE'), (None, 'DIVEQUAL'), (None, 'RBRACKET'), (None, 'CONDOP')]), ('(?P\\^)|(?P<<)|(?P<=)|(?P\\()|(?P->)|(?P==)|(?P\\})|(?P!=)|(?P--)|(?P\\|)|(?P\\*)|(?P\\[)|(?P>=)|(?P\\))|(?P&&)|(?P>>)|(?P&=)|(?P-=)|(?P\\.)|(?P=)|(?P<)|(?P,)|(?P/)|(?P&)|(?P%)|(?P;)|(?P-)|(?P>)|(?P:)|(?P~)|(?P!)', [None, (None, 'XOR'), (None, 'LSHIFT'), (None, 'LE'), (None, 'LPAREN'), (None, 'ARROW'), (None, 'EQ'), (None, 'RBRACE'), (None, 'NE'), (None, 'MINUSMINUS'), (None, 'OR'), (None, 'TIMES'), (None, 'LBRACKET'), (None, 'GE'), (None, 'RPAREN'), (None, 'LAND'), (None, 'RSHIFT'), (None, 'ANDEQUAL'), (None, 'MINUSEQUAL'), (None, 'PERIOD'), (None, 'EQUALS'), (None, 'LT'), (None, 'COMMA'), (None, 'DIVIDE'), (None, 'AND'), (None, 'MOD'), (None, 'SEMI'), (None, 'MINUS'), (None, 'GT'), (None, 'COLON'), (None, 'NOT'), (None, 'LNOT')])]} -_lexstateignore = {'ppline': ' \t', 'pppragma': ' \t<>.-{}();+-*/$%@&^~!?:,0123456789', 'INITIAL': ' \t'} -_lexstateerrorf = {'ppline': 't_ppline_error', 'pppragma': 't_pppragma_error', 'INITIAL': 't_error'} diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/setup.py deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/setup.py +++ /dev/null @@ -1,9 +0,0 @@ -# Generated by pypy/tool/import_cffi.py - -from setuptools import setup -import snip_setuptools_verify1 - -setup( - zip_safe=False, - packages=['snip_setuptools_verify1'], - ext_modules=[snip_setuptools_verify1.ffi.verifier.get_extension()]) diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/snip_setuptools_verify1/__init__.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/snip_setuptools_verify1/__init__.py deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/snip_setuptools_verify1/__init__.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by pypy/tool/import_cffi.py - -from cffi import FFI -import sys - -ffi = FFI() -ffi.cdef(""" // some declarations from the man page - struct passwd { - char *pw_name; - ...; - }; - struct passwd *getpwuid(int uid); -""") -C = ffi.verify(""" // passed to the real C compiler -#include -#include -""", libraries=[], # or a list of libraries to link with - force_generic_engine=hasattr(sys, '_force_generic_engine_')) diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/snip_setuptools_verify1/__pycache__/_cffi__gd39ab08bx8432a366.c b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/snip_setuptools_verify1/__pycache__/_cffi__gd39ab08bx8432a366.c deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/snip_setuptools_verify1/__pycache__/_cffi__gd39ab08bx8432a366.c +++ /dev/null @@ -1,53 +0,0 @@ - -#include -#include -#include -#include -#include /* XXX for ssize_t on some platforms */ - -#ifdef _WIN32 -# include -# define snprintf _snprintf -typedef __int8 int8_t; -typedef __int16 int16_t; -typedef __int32 int32_t; -typedef __int64 int64_t; -typedef unsigned __int8 uint8_t; -typedef unsigned __int16 uint16_t; -typedef unsigned __int32 uint32_t; -typedef unsigned __int64 uint64_t; -typedef SSIZE_T ssize_t; -typedef unsigned char _Bool; -#else -# include -#endif - - // passed to the real C compiler -#include -#include - -struct passwd * _cffi_f_getpwuid(int x0) -{ - return getpwuid(x0); -} - -static void _cffi_check_struct_passwd(struct passwd *p) -{ - /* only to generate compile-time warnings or errors */ - { char * *tmp = &p->pw_name; (void)tmp; } -} -ssize_t _cffi_layout_struct_passwd(ssize_t i) -{ - struct _cffi_aligncheck { char x; struct passwd y; }; - static ssize_t nums[] = { - sizeof(struct passwd), - offsetof(struct _cffi_aligncheck, y), - offsetof(struct passwd, pw_name), - sizeof(((struct passwd *)0)->pw_name), - -1 - }; - return nums[i]; - /* the next line is not executed, but compiled */ - _cffi_check_struct_passwd(0); -} - diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/snip_setuptools_verify1/__pycache__/_cffi__gd39ab08bx8432a366.pypy-20.so b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/snip_setuptools_verify1/__pycache__/_cffi__gd39ab08bx8432a366.pypy-20.so deleted file mode 100755 Binary file pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/snip_setuptools_verify1/__pycache__/_cffi__gd39ab08bx8432a366.pypy-20.so has changed diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/snip_setuptools_verify1/__pycache__/snip_setuptools_verify1/__pycache__/_cffi__gd39ab08bx8432a366.o b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/snip_setuptools_verify1/__pycache__/snip_setuptools_verify1/__pycache__/_cffi__gd39ab08bx8432a366.o deleted file mode 100644 Binary file pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/snip_setuptools_verify1/__pycache__/snip_setuptools_verify1/__pycache__/_cffi__gd39ab08bx8432a366.o has changed diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/yacctab.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/yacctab.py deleted file mode 100644 --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/yacctab.py From noreply at buildbot.pypy.org Wed Apr 3 13:10:07 2013 From: noreply at buildbot.pypy.org (arigo) Date: Wed, 3 Apr 2013 13:10:07 +0200 (CEST) Subject: [pypy-commit] pypy default: Copy from conftest.py from ../ctypes/test/. Message-ID: <20130403111007.1BB901C030B@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r62969:cf959bd6387f Date: 2013-04-03 13:08 +0200 http://bitbucket.org/pypy/pypy/changeset/cf959bd6387f/ Log: Copy from conftest.py from ../ctypes/test/. diff --git a/pypy/module/test_lib_pypy/ctypes_tests/conftest.py b/pypy/module/test_lib_pypy/cffi_tests/conftest.py copy from pypy/module/test_lib_pypy/ctypes_tests/conftest.py copy to pypy/module/test_lib_pypy/cffi_tests/conftest.py --- a/pypy/module/test_lib_pypy/ctypes_tests/conftest.py +++ b/pypy/module/test_lib_pypy/cffi_tests/conftest.py @@ -1,27 +1,5 @@ -import py, pytest import sys def pytest_ignore_collect(path): if '__pypy__' not in sys.builtin_module_names: return True - -def compile_so_file(): - from rpython.translator.platform import platform - from rpython.translator.tool.cbuild import ExternalCompilationInfo - udir = pytest.ensuretemp('_ctypes_test') - cfile = py.path.local(__file__).dirpath().join("_ctypes_test.c") - - if sys.platform == 'win32': - libraries = ['oleaut32'] - else: - libraries = [] - eci = ExternalCompilationInfo(libraries=libraries) - - return platform.compile([cfile], eci, str(udir.join('_ctypes_test')), - standalone=False) - -# we need to run after the "tmpdir" plugin which installs pytest.ensuretemp - at pytest.mark.trylast -def pytest_configure(config): - global sofile - sofile = compile_so_file() From noreply at buildbot.pypy.org Wed Apr 3 13:12:51 2013 From: noreply at buildbot.pypy.org (arigo) Date: Wed, 3 Apr 2013 13:12:51 +0200 (CEST) Subject: [pypy-commit] pypy default: Re-add the "snippets" subdirectory, removed by mistake Message-ID: <20130403111251.754151C0228@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r62970:da117f9dbcc5 Date: 2013-04-03 13:12 +0200 http://bitbucket.org/pypy/pypy/changeset/da117f9dbcc5/ Log: Re-add the "snippets" subdirectory, removed by mistake diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/setup.py new file mode 100644 --- /dev/null +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/setup.py @@ -0,0 +1,7 @@ + +from distutils.core import setup +import snip_basic_verify + +setup( + py_modules=['snip_basic_verify'], + ext_modules=[snip_basic_verify.ffi.verifier.get_extension()]) diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/snip_basic_verify.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/snip_basic_verify.py new file mode 100644 --- /dev/null +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/snip_basic_verify.py @@ -0,0 +1,17 @@ + +from cffi import FFI +import sys + +ffi = FFI() +ffi.cdef(""" // some declarations from the man page + struct passwd { + char *pw_name; + ...; + }; + struct passwd *getpwuid(int uid); +""") +C = ffi.verify(""" // passed to the real C compiler +#include +#include +""", libraries=[], # or a list of libraries to link with + force_generic_engine=hasattr(sys, '_force_generic_engine_')) diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/setup.py new file mode 100644 --- /dev/null +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/setup.py @@ -0,0 +1,7 @@ + +from distutils.core import setup +import snip_basic_verify1 + +setup( + packages=['snip_basic_verify1'], + ext_modules=[snip_basic_verify1.ffi.verifier.get_extension()]) diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/snip_basic_verify1/__init__.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/snip_basic_verify1/__init__.py new file mode 100644 --- /dev/null +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/snip_basic_verify1/__init__.py @@ -0,0 +1,17 @@ + +from cffi import FFI +import sys + +ffi = FFI() +ffi.cdef(""" // some declarations from the man page + struct passwd { + char *pw_name; + ...; + }; + struct passwd *getpwuid(int uid); +""") +C = ffi.verify(""" // passed to the real C compiler +#include +#include +""", libraries=[], # or a list of libraries to link with + force_generic_engine=hasattr(sys, '_force_generic_engine_')) diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/setup.py new file mode 100644 --- /dev/null +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/setup.py @@ -0,0 +1,8 @@ + +from distutils.core import setup +import snip_basic_verify2 + +setup( + packages=['snip_basic_verify2'], + ext_package='snip_basic_verify2', + ext_modules=[snip_basic_verify2.ffi.verifier.get_extension()]) diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/snip_basic_verify2/__init__.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/snip_basic_verify2/__init__.py new file mode 100644 --- /dev/null +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/snip_basic_verify2/__init__.py @@ -0,0 +1,18 @@ + +from cffi import FFI +import sys + +ffi = FFI() +ffi.cdef(""" // some declarations from the man page + struct passwd { + char *pw_name; + ...; + }; + struct passwd *getpwuid(int uid); +""") +C = ffi.verify(""" // passed to the real C compiler +#include +#include +""", libraries=[], # or a list of libraries to link with + ext_package='snip_basic_verify2', + force_generic_engine=hasattr(sys, '_force_generic_engine_')) diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/setup.py new file mode 100644 --- /dev/null +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/setup.py @@ -0,0 +1,5 @@ + +from distutils.core import setup + +setup(packages=['snip_infrastructure'], + requires=['cffi']) diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/snip_infrastructure/__init__.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/snip_infrastructure/__init__.py new file mode 100644 --- /dev/null +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/snip_infrastructure/__init__.py @@ -0,0 +1,3 @@ + +def func(): + return 42 diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/setup.py new file mode 100644 --- /dev/null +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/setup.py @@ -0,0 +1,8 @@ + +from setuptools import setup +import snip_setuptools_verify + +setup( + zip_safe=False, + py_modules=['snip_setuptools_verify'], + ext_modules=[snip_setuptools_verify.ffi.verifier.get_extension()]) diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/snip_setuptools_verify.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/snip_setuptools_verify.py new file mode 100644 --- /dev/null +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/snip_setuptools_verify.py @@ -0,0 +1,17 @@ + +from cffi import FFI +import sys + +ffi = FFI() +ffi.cdef(""" // some declarations from the man page + struct passwd { + char *pw_name; + ...; + }; + struct passwd *getpwuid(int uid); +""") +C = ffi.verify(""" // passed to the real C compiler +#include +#include +""", libraries=[], # or a list of libraries to link with + force_generic_engine=hasattr(sys, '_force_generic_engine_')) diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/setup.py new file mode 100644 --- /dev/null +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/setup.py @@ -0,0 +1,8 @@ + +from setuptools import setup +import snip_setuptools_verify1 + +setup( + zip_safe=False, + packages=['snip_setuptools_verify1'], + ext_modules=[snip_setuptools_verify1.ffi.verifier.get_extension()]) diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/snip_setuptools_verify1/__init__.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/snip_setuptools_verify1/__init__.py new file mode 100644 --- /dev/null +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/snip_setuptools_verify1/__init__.py @@ -0,0 +1,17 @@ + +from cffi import FFI +import sys + +ffi = FFI() +ffi.cdef(""" // some declarations from the man page + struct passwd { + char *pw_name; + ...; + }; + struct passwd *getpwuid(int uid); +""") +C = ffi.verify(""" // passed to the real C compiler +#include +#include +""", libraries=[], # or a list of libraries to link with + force_generic_engine=hasattr(sys, '_force_generic_engine_')) diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/setup.py new file mode 100644 --- /dev/null +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/setup.py @@ -0,0 +1,9 @@ + +from setuptools import setup +import snip_setuptools_verify2 + +setup( + zip_safe=False, + packages=['snip_setuptools_verify2'], + ext_package='snip_setuptools_verify2', + ext_modules=[snip_setuptools_verify2.ffi.verifier.get_extension()]) diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/snip_setuptools_verify2/__init__.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/snip_setuptools_verify2/__init__.py new file mode 100644 --- /dev/null +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/snip_setuptools_verify2/__init__.py @@ -0,0 +1,18 @@ + +from cffi import FFI +import sys + +ffi = FFI() +ffi.cdef(""" // some declarations from the man page + struct passwd { + char *pw_name; + ...; + }; + struct passwd *getpwuid(int uid); +""") +C = ffi.verify(""" // passed to the real C compiler +#include +#include +""", libraries=[], # or a list of libraries to link with + ext_package='snip_setuptools_verify2', + force_generic_engine=hasattr(sys, '_force_generic_engine_')) From noreply at buildbot.pypy.org Wed Apr 3 13:24:34 2013 From: noreply at buildbot.pypy.org (arigo) Date: Wed, 3 Apr 2013 13:24:34 +0200 (CEST) Subject: [pypy-commit] cffi default: Check that pycparser was correctly installed, by checking that Message-ID: <20130403112434.1EE1F1C0228@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r1228:c8d9d1907505 Date: 2013-04-03 13:24 +0200 http://bitbucket.org/cffi/cffi/changeset/c8d9d1907505/ Log: Check that pycparser was correctly installed, by checking that lextab.py and yacctab.py are not regenerated at run-time. diff --git a/testing/test_zintegration.py b/testing/test_zintegration.py --- a/testing/test_zintegration.py +++ b/testing/test_zintegration.py @@ -61,6 +61,10 @@ really_run_setup_and_program(dirname, venv_dir, python_snippet) finally: del sys._force_generic_engine_ + # the two files lextab.py and yacctab.py are created by not-correctly- + # installed versions of pycparser. + assert not os.path.exists(str(SNIPPET_DIR.join(dirname, 'lextab.py'))) + assert not os.path.exists(str(SNIPPET_DIR.join(dirname, 'yacctab.py'))) def test_infrastructure(): run_setup_and_program('infrastructure', ''' From noreply at buildbot.pypy.org Wed Apr 3 13:25:10 2013 From: noreply at buildbot.pypy.org (arigo) Date: Wed, 3 Apr 2013 13:25:10 +0200 (CEST) Subject: [pypy-commit] pypy default: Update to cffi/c8d9d1907505 Message-ID: <20130403112510.517A91C0228@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r62971:70527adbffa8 Date: 2013-04-03 13:27 +0200 http://bitbucket.org/pypy/pypy/changeset/70527adbffa8/ Log: Update to cffi/c8d9d1907505 diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_zintegration.py b/pypy/module/test_lib_pypy/cffi_tests/test_zintegration.py --- a/pypy/module/test_lib_pypy/cffi_tests/test_zintegration.py +++ b/pypy/module/test_lib_pypy/cffi_tests/test_zintegration.py @@ -62,6 +62,10 @@ really_run_setup_and_program(dirname, venv_dir, python_snippet) finally: del sys._force_generic_engine_ + # the two files lextab.py and yacctab.py are created by not-correctly- + # installed versions of pycparser. + assert not os.path.exists(str(SNIPPET_DIR.join(dirname, 'lextab.py'))) + assert not os.path.exists(str(SNIPPET_DIR.join(dirname, 'yacctab.py'))) def test_infrastructure(): run_setup_and_program('infrastructure', ''' From noreply at buildbot.pypy.org Wed Apr 3 13:32:57 2013 From: noreply at buildbot.pypy.org (arigo) Date: Wed, 3 Apr 2013 13:32:57 +0200 (CEST) Subject: [pypy-commit] pypy default: Fix the path here too. Without this, lextab.py and yacctab.py are Message-ID: <20130403113257.EBDD61C0228@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r62972:1177ea45623b Date: 2013-04-03 13:34 +0200 http://bitbucket.org/pypy/pypy/changeset/1177ea45623b/ Log: Fix the path here too. Without this, lextab.py and yacctab.py are regenerated, which is a waste of time. Now test_zintegration passes. diff --git a/lib_pypy/cffi/_pycparser/c_parser.py b/lib_pypy/cffi/_pycparser/c_parser.py --- a/lib_pypy/cffi/_pycparser/c_parser.py +++ b/lib_pypy/cffi/_pycparser/c_parser.py @@ -20,9 +20,9 @@ def __init__( self, lex_optimize=True, - lextab='pycparser.lextab', + lextab='cffi._pycparser.lextab', yacc_optimize=True, - yacctab='pycparser.yacctab', + yacctab='cffi._pycparser.yacctab', yacc_debug=False): """ Create a new CParser. From noreply at buildbot.pypy.org Wed Apr 3 13:48:52 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Wed, 3 Apr 2013 13:48:52 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: removed a mistake within format strings Message-ID: <20130403114852.B3F681C06BD@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r234:bb72ffd1eb04 Date: 2013-03-25 18:21 +0100 http://bitbucket.org/pypy/lang-smalltalk/changeset/bb72ffd1eb04/ Log: removed a mistake within format strings diff --git a/spyvm/shadow.py b/spyvm/shadow.py --- a/spyvm/shadow.py +++ b/spyvm/shadow.py @@ -798,7 +798,7 @@ return 0 def short_str(self): - return 'BlockContext of %s (%s) [%i]' % ( + return 'BlockContext of %s (%s) [%d]' % ( self.w_method().get_identifier_string(), self.w_receiver(), self.pc() + 1 @@ -942,13 +942,13 @@ def __str__(self): retval = '\nMethodContext of:' retval += self.w_method().as_string(markBytecode=self.pc() + 1) - retval += "Stackptr: %i (this is an empty ascending stack)" % (self._stack_ptr - self.tempsize()) + retval += "Stackptr: %d (this is an empty ascending stack)" % (self._stack_ptr - self.tempsize()) retval += "\nStack : " + str(self.stack()) return retval def short_str(self): block = '[] of' if self.is_closure_context() else '' - return '%s %s (%s) [%i]' % ( + return '%s %s (rcvr: %s) [pc: %d]' % ( block, self.w_method().get_identifier_string(), self.w_receiver(), From noreply at buildbot.pypy.org Wed Apr 3 13:48:51 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Wed, 3 Apr 2013 13:48:51 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: patched getname, because in the newer images, not the class but an association is the last literal. Message-ID: <20130403114851.836681C00BD@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r233:9545bbb0ad07 Date: 2013-03-25 18:20 +0100 http://bitbucket.org/pypy/lang-smalltalk/changeset/9545bbb0ad07/ Log: patched getname, because in the newer images, not the class but an association is the last literal. diff --git a/spyvm/model.py b/spyvm/model.py --- a/spyvm/model.py +++ b/spyvm/model.py @@ -758,7 +758,14 @@ def get_identifier_string(self): try: - classname = self.literals[-1]._shadow.getname() + w_class = self.literals[-1] + if isinstance(w_class, W_PointersObject): + if w_class._shadow is None: + classname = w_class._fetch(1)._shadow.getname() + else: + classname = w_class._shadow.getname() + else: + classname = "" except (IndexError, AttributeError): classname = "" return "%s>>#%s" % (classname, self._likely_methodname) From noreply at buildbot.pypy.org Wed Apr 3 13:48:53 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Wed, 3 Apr 2013 13:48:53 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: patched module setup of test_miniimage to be able to reuse space and interp variables within other tests Message-ID: <20130403114853.CA1CE1C00BD@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r235:104fb3ec72ad Date: 2013-03-25 18:23 +0100 http://bitbucket.org/pypy/lang-smalltalk/changeset/104fb3ec72ad/ Log: patched module setup of test_miniimage to be able to reuse space and interp variables within other tests diff --git a/spyvm/test/test_miniimage.py b/spyvm/test/test_miniimage.py --- a/spyvm/test/test_miniimage.py +++ b/spyvm/test/test_miniimage.py @@ -20,6 +20,7 @@ module.image.from_reader(space, reader) module.space = space module.interp = interpreter.Interpreter(space, image) + return space, module.interp def find_symbol(name): if name == "asSymbol": From noreply at buildbot.pypy.org Wed Apr 3 13:48:54 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Wed, 3 Apr 2013 13:48:54 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: added some tracing code Message-ID: <20130403114854.E25301C00BD@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r236:c47050335e18 Date: 2013-03-25 18:26 +0100 http://bitbucket.org/pypy/lang-smalltalk/changeset/c47050335e18/ Log: added some tracing code for compiling, they need to be commented out because there are still some typing issues. That is the reason I commit them commented out. diff --git a/spyvm/interpreter.py b/spyvm/interpreter.py --- a/spyvm/interpreter.py +++ b/spyvm/interpreter.py @@ -43,6 +43,7 @@ self._loop = False self.next_wakeup_tick = 0 self.interrupt_check_counter = constants.INTERRUPT_COUNTER_SIZE + # self.trace = False def interpret_with_w_frame(self, w_frame): try: @@ -77,8 +78,9 @@ s_new_context = p.s_new_context def c_loop(self, s_context): - # padding = ' ' * (self.max_stack_depth - self.remaining_stack_depth) - # print padding + s_context.short_str() + # if self.trace: + # padding = ' ' * (self.max_stack_depth - self.remaining_stack_depth) + # print padding + s_context.short_str() old_pc = 0 if not jit.we_are_jitted(): self.quick_check_for_interrupt(s_context) @@ -338,10 +340,15 @@ if interp.should_trace(): print "%sActually calling primitive %d" % (interp._last_indent, code,) func = primitives.prim_holder.prim_table[code] + # if interp.trace: + # print "%s calling primitive %d \t(%s)" % (' ' * (interp.max_stack_depth - interp.remaining_stack_depth), + # code, func.func_name) try: # note: argcount does not include rcvr return func(interp, self, argcount) except primitives.PrimitiveFailedError: + # if interp.trace: + # import pdb; pdb.set_trace() if interp.should_trace(True): print "PRIMITIVE FAILED: %d %s" % (s_method.primitive, w_selector.as_string(),) pass # ignore this error and fall back to the Smalltalk version From noreply at buildbot.pypy.org Wed Apr 3 13:48:56 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Wed, 3 Apr 2013 13:48:56 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: extending the tracing code Message-ID: <20130403114856.00F771C00BD@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r237:843613d2ad89 Date: 2013-03-26 10:51 +0100 http://bitbucket.org/pypy/lang-smalltalk/changeset/843613d2ad89/ Log: extending the tracing code diff --git a/spyvm/interpreter.py b/spyvm/interpreter.py --- a/spyvm/interpreter.py +++ b/spyvm/interpreter.py @@ -43,7 +43,8 @@ self._loop = False self.next_wakeup_tick = 0 self.interrupt_check_counter = constants.INTERRUPT_COUNTER_SIZE - # self.trace = False + # ###################################################################### + # self.trace = True def interpret_with_w_frame(self, w_frame): try: @@ -78,6 +79,7 @@ s_new_context = p.s_new_context def c_loop(self, s_context): + # ###################################################################### # if self.trace: # padding = ' ' * (self.max_stack_depth - self.remaining_stack_depth) # print padding + s_context.short_str() @@ -340,6 +342,7 @@ if interp.should_trace(): print "%sActually calling primitive %d" % (interp._last_indent, code,) func = primitives.prim_holder.prim_table[code] + # ################################################################## # if interp.trace: # print "%s calling primitive %d \t(%s)" % (' ' * (interp.max_stack_depth - interp.remaining_stack_depth), # code, func.func_name) @@ -347,8 +350,14 @@ # note: argcount does not include rcvr return func(interp, self, argcount) except primitives.PrimitiveFailedError: - # if interp.trace: + # ############################################################## + # if interp.trace and func.func_name != 'raise_failing_default' and code != 83: # import pdb; pdb.set_trace() + # try: + # func(interp, self, argcount) # will fail again + # except primitives.PrimitiveFailedError: + # pass + if interp.should_trace(True): print "PRIMITIVE FAILED: %d %s" % (s_method.primitive, w_selector.as_string(),) pass # ignore this error and fall back to the Smalltalk version From noreply at buildbot.pypy.org Wed Apr 3 13:48:57 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Wed, 3 Apr 2013 13:48:57 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: fixed a bug in perform_with_args and added some comments Message-ID: <20130403114857.212051C00BD@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r238:c79d9f581fe7 Date: 2013-03-26 11:26 +0100 http://bitbucket.org/pypy/lang-smalltalk/changeset/c79d9f581fe7/ Log: fixed a bug in perform_with_args and added some comments diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -1100,13 +1100,16 @@ def func(interp, s_frame, w_rcvr, w_selector, args_w): stackvalues = s_frame.pop_and_return_n(3) argcount = len(args_w) + # pushing the receiver and args to be popped by _sendSelector s_frame.push(w_rcvr) s_frame.push_all(args_w) - try: - s_frame._sendSelector(w_selector, argcount, interp, + s_frame._sendSelector(w_selector, argcount, interp, w_rcvr, w_rcvr.shadow_of_my_class(interp.space)) - finally: - s_frame.push_all(stackvalues) + # If we return in a regular way, we need to rebuild the former + # stack-contents to be collected by the primitive wrapper, i.a. if + # w_selector points to a primitive method. But if we have an exception, the + # wrapper will not clean. Therefore we should not put this into a finally. + s_frame.push_all(stackvalues) @expose_primitive(SIGNAL, unwrap_spec=[object]) diff --git a/spyvm/test/test_bootstrappedimage.py b/spyvm/test/test_bootstrappedimage.py --- a/spyvm/test/test_bootstrappedimage.py +++ b/spyvm/test/test_bootstrappedimage.py @@ -52,6 +52,7 @@ tools.test_lookup_abs_in_integer() def test_tinyBenchmarks(): + py.test.skip("Waste of time, because it doesn't assert anything.") # we can't find PCSystem, because Smalltalkdict is nil... import time t0 = time.time() From noreply at buildbot.pypy.org Wed Apr 3 13:48:58 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Wed, 3 Apr 2013 13:48:58 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: added positive_32bit_integer wrapping functions to space Message-ID: <20130403114858.65B9D1C00BD@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r239:d1a240901b6d Date: 2013-03-26 13:41 +0100 http://bitbucket.org/pypy/lang-smalltalk/changeset/d1a240901b6d/ Log: added positive_32bit_integer wrapping functions to space the result is that we can now do primitive bitAnd:, bitOr: and bitXor: with LargePositive1WordIntegers also, wrap_int cant wrap to PositiveLargeInts anymore, because in wrap_int, we cant be sure that the result needs be positive. diff --git a/spyvm/objspace.py b/spyvm/objspace.py --- a/spyvm/objspace.py +++ b/spyvm/objspace.py @@ -167,10 +167,11 @@ def wrap_int(self, val): from spyvm import constants - if int_between(constants.TAGGED_MININT, val, constants.TAGGED_MAXINT + 1): + if int_between(constants.TAGGED_MININT, val, + constants.TAGGED_MAXINT + 1): return model.W_SmallInteger(val) - elif val > 0: - return model.W_LargePositiveInteger1Word(val) + # We can't build large integers here, because we don't know what to do + # with negativ vals: raise an error or interpret them as 4-byte positive? raise WrappingError("integer too large to fit into a tagged pointer") def wrap_uint(self, val): @@ -178,7 +179,7 @@ raise WrappingError("negative integer") if intmask(val) >= 0: try: - return self.wrap_int(intmask(val)) + return self.wrap_positive_32bit_int(intmask(val)) except WrappingError: pass # XXX this code sucks @@ -190,6 +191,15 @@ w_result.setchar(i, chr(intmask((val >> i*8) & 255))) return w_result + def wrap_positive_32bit_int(self, val): + # This will always return a positive value. + # XXX: For now, we assume that val is at most 32bit, i.e. overflows are + # checked for before wrapping. + if int_between(0, val, constants.TAGGED_MAXINT + 1): + return model.W_SmallInteger(val) + else: + return model.W_LargePositiveInteger1Word(val) + def wrap_float(self, i): return model.W_Float(i) @@ -225,6 +235,8 @@ elif isinstance(w_value, model.W_LargePositiveInteger1Word): if w_value.value > 0: return w_value.value + else: + raise UnwrappingError("The value is negative when interpreted as 32bit value.") raise UnwrappingError("expected a W_SmallInteger or W_LargePositiveInteger1Word, got %s" % (w_value,)) def unwrap_uint(self, w_value): @@ -247,6 +259,14 @@ else: raise UnwrappingError("Got unexpected class in unwrap_uint") + def unwrap_positive_32bit_int(self, w_value): + if isinstance(w_value, model.W_SmallInteger): + if w_value.value >= 0: + return w_value.value + elif isinstance(w_value, model.W_LargePositiveInteger1Word): + return w_value.value + raise UnwrappingError("Wrong types or negative SmallInteger.") + def unwrap_char(self, w_char): from spyvm import constants w_class = w_char.getclass(self) diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -50,6 +50,7 @@ # converted to an index0 index1_0 = object() char = object() +pos_32bit_int = object() def expose_primitive(code, unwrap_spec=None, no_result=False, result_is_new_frame=False): # some serious magic, don't look @@ -96,6 +97,8 @@ w_arg = s_frame.peek(index) if spec is int: args += (interp.space.unwrap_int(w_arg), ) + elif spec is pos_32bit_int: + args += (interp.space.unwrap_positive_32bit_int(w_arg),) elif spec is index1_0: args += (interp.space.unwrap_int(w_arg)-1, ) elif spec is float: @@ -174,10 +177,11 @@ } for (code,op) in bitwise_binary_ops.items(): def make_func(op): - @expose_primitive(code, unwrap_spec=[int, int]) + @expose_primitive(code, unwrap_spec=[pos_32bit_int, pos_32bit_int]) def func(interp, s_frame, receiver, argument): + from spyvm.model import W_LargePositiveInteger1Word res = op(receiver, argument) - return interp.space.wrap_int(res) + return interp.space.wrap_positive_32bit_int(res) make_func(op) # #/ -- return the result of a division, only succeed if the division is exact diff --git a/spyvm/test/test_primitives.py b/spyvm/test/test_primitives.py --- a/spyvm/test/test_primitives.py +++ b/spyvm/test/test_primitives.py @@ -67,10 +67,10 @@ assert prim(primitives.ADD, [3,4]).value == 7 def test_small_int_add_fail(): - w_result = prim(primitives.ADD, [constants.TAGGED_MAXINT, 2]) - assert isinstance(w_result, model.W_LargePositiveInteger1Word) - assert w_result.value == constants.TAGGED_MAXINT + 2 - prim_fails(primitives.ADD, [constants.TAGGED_MAXINT, constants.TAGGED_MAXINT * 2]) + w_result = prim_fails(primitives.ADD, [constants.TAGGED_MAXINT, 2]) + # assert isinstance(w_result, model.W_LargePositiveInteger1Word) + # assert w_result.value == constants.TAGGED_MAXINT + 2 + # prim_fails(primitives.ADD, [constants.TAGGED_MAXINT, constants.TAGGED_MAXINT * 2]) def test_small_int_minus(): assert prim(primitives.SUBTRACT, [5,9]).value == -4 @@ -84,9 +84,9 @@ assert prim(primitives.MULTIPLY, [6,3]).value == 18 def test_small_int_multiply_overflow(): - w_result = prim(primitives.MULTIPLY, [constants.TAGGED_MAXINT, 2]) - assert isinstance(w_result, model.W_LargePositiveInteger1Word) - assert w_result.value == constants.TAGGED_MAXINT * 2 + w_result = prim_fails(primitives.MULTIPLY, [constants.TAGGED_MAXINT, 2]) + #assert isinstance(w_result, model.W_LargePositiveInteger1Word) + #assert w_result.value == constants.TAGGED_MAXINT * 2 prim_fails(primitives.MULTIPLY, [constants.TAGGED_MAXINT, constants.TAGGED_MAXINT]) prim_fails(primitives.MULTIPLY, [constants.TAGGED_MAXINT, -4]) prim_fails(primitives.MULTIPLY, [constants.TAGGED_MININT, constants.TAGGED_MAXINT]) @@ -171,9 +171,9 @@ prim_fails(primitives.BIT_SHIFT, [4, 31]) prim_fails(primitives.BIT_SHIFT, [4, 30]) prim_fails(primitives.BIT_SHIFT, [4, 29]) - w_result = prim(primitives.BIT_SHIFT, [4, 28]) - assert isinstance(w_result, model.W_LargePositiveInteger1Word) - assert w_result.value == 4 << 28 + w_result = prim_fails(primitives.BIT_SHIFT, [4, 28]) + # assert isinstance(w_result, model.W_LargePositiveInteger1Word) + # assert w_result.value == 4 << 28 def test_smallint_as_float(): assert prim(primitives.SMALLINT_AS_FLOAT, [12]).value == 12.0 From noreply at buildbot.pypy.org Wed Apr 3 13:48:59 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Wed, 3 Apr 2013 13:48:59 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: merge with tip Message-ID: <20130403114859.760B81C00BD@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r240:8301476cf55c Date: 2013-03-26 21:30 +0100 http://bitbucket.org/pypy/lang-smalltalk/changeset/8301476cf55c/ Log: merge with tip and... (because merges can not be partially committed and I forgot to commit directly) added tracing parameter and code to interpreter fixed tracing for compiling fixed problems with stack management in bitblt primitive and perform_with_args by adding another parameter to expose_primitive added capabilities to shift within 32bit range fixed the according tests diff --git a/spyvm/interpreter.py b/spyvm/interpreter.py --- a/spyvm/interpreter.py +++ b/spyvm/interpreter.py @@ -33,7 +33,7 @@ get_printable_location=get_printable_location ) - def __init__(self, space, image=None, image_name="", + def __init__(self, space, image=None, image_name="", trace=False, max_stack_depth=constants.MAX_LOOP_DEPTH): self.space = space self.image = image @@ -44,7 +44,7 @@ self.next_wakeup_tick = 0 self.interrupt_check_counter = constants.INTERRUPT_COUNTER_SIZE # ###################################################################### - # self.trace = True + self.trace = trace def interpret_with_w_frame(self, w_frame): try: @@ -80,9 +80,9 @@ def c_loop(self, s_context): # ###################################################################### - # if self.trace: - # padding = ' ' * (self.max_stack_depth - self.remaining_stack_depth) - # print padding + s_context.short_str() + if self.trace: + padding = ' ' * (self.max_stack_depth - self.remaining_stack_depth) + print padding + s_context.short_str() old_pc = 0 if not jit.we_are_jitted(): self.quick_check_for_interrupt(s_context) @@ -343,27 +343,31 @@ print "%sActually calling primitive %d" % (interp._last_indent, code,) func = primitives.prim_holder.prim_table[code] # ################################################################## - # if interp.trace: - # print "%s calling primitive %d \t(%s)" % (' ' * (interp.max_stack_depth - interp.remaining_stack_depth), - # code, func.func_name) + if interp.trace: + print "%s calling primitive %d \t(in #%s)" % ( + ' ' * (interp.max_stack_depth - interp.remaining_stack_depth), + code, self.w_method()._likely_methodname) try: # note: argcount does not include rcvr return func(interp, self, argcount) except primitives.PrimitiveFailedError: # ############################################################## # if interp.trace and func.func_name != 'raise_failing_default' and code != 83: - # import pdb; pdb.set_trace() + # # import pdb; pdb.set_trace() # try: # func(interp, self, argcount) # will fail again # except primitives.PrimitiveFailedError: # pass + if interp.trace: + print "%s primitive FAILED" % ( + ' ' * (interp.max_stack_depth - interp.remaining_stack_depth),) if interp.should_trace(True): print "PRIMITIVE FAILED: %d %s" % (s_method.primitive, w_selector.as_string(),) pass # ignore this error and fall back to the Smalltalk version arguments = self.pop_and_return_n(argcount) s_frame = s_method.create_frame(self.space, receiver, arguments, self) - self.pop() + self.pop() # receiver return interp.stack_frame(s_frame) def _doesNotUnderstand(self, w_selector, argcount, interp, receiver): diff --git a/spyvm/model.py b/spyvm/model.py --- a/spyvm/model.py +++ b/spyvm/model.py @@ -757,19 +757,23 @@ return retval + "---------------------\n" def get_identifier_string(self): - try: - w_class = self.literals[-1] - if isinstance(w_class, W_PointersObject): - if w_class._shadow is None: - classname = w_class._fetch(1)._shadow.getname() - else: - classname = w_class._shadow.getname() - else: - classname = "" - except (IndexError, AttributeError): - classname = "" + from spyvm import shadow + classname = '' + if len(self.literals) > 0: + w_candidate = self.literals[-1] + if isinstance(w_candidate, W_PointersObject): + c_shadow = w_candidate._shadow + if c_shadow is None: + w_class = w_candidate._fetch(1) + if isinstance(w_class, W_PointersObject): + d_shadow = w_class._shadow + if isinstance(d_shadow, shadow.ClassShadow): + classname = d_shadow.getname() + elif isinstance(shadow, shadow.ClassShadow): + classname = c_shadow.getname() return "%s>>#%s" % (classname, self._likely_methodname) + def invariant(self): return (W_Object.invariant(self) and hasattr(self, 'literals') and diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -52,7 +52,7 @@ char = object() pos_32bit_int = object() -def expose_primitive(code, unwrap_spec=None, no_result=False, result_is_new_frame=False): +def expose_primitive(code, unwrap_spec=None, no_result=False, result_is_new_frame=False, clean_stack=True): # some serious magic, don't look from rpython.rlib.unroll import unrolling_iterable # heuristics to give it a nice name @@ -121,13 +121,17 @@ s_new_frame = func(interp, s_frame, *args) # After calling primitive, reload context-shadow in case it # needs to be updated - s_frame.pop_n(len_unwrap_spec) # only if no exception occurs! + if clean_stack: + # happens only if no exception occurs! + s_frame.pop_n(len_unwrap_spec) return interp.stack_frame(s_new_frame) else: w_result = func(interp, s_frame, *args) # After calling primitive, reload context-shadow in case it # needs to be updated - s_frame.pop_n(len_unwrap_spec) # only if no exception occurs! + if clean_stack: + # happens only if no exception occurs! + s_frame.pop_n(len_unwrap_spec) if not no_result: assert w_result is not None assert isinstance(w_result, model.W_Object) @@ -223,12 +227,20 @@ # (http://codespeak.net/pypy/dist/pypy/doc/coding-guide.html#integer-types) # left shift, must fail if we lose bits beyond 32 + from rpython.rlib.rarithmetic import intmask, r_uint, ovfcheck, int_between if argument > 0: - try: - shifted = rarithmetic.ovfcheck(receiver << argument) - except OverflowError: - raise PrimitiveFailedError() - return interp.space.wrap_int(shifted) + # argument > 0, therefore the highest bit of upperbound is not set, + # i.e. upperbound is positive + upperbound = intmask(r_uint(-1) >> argument) + if 0 <= receiver <= upperbound: + shifted = intmask(receiver << argument) + return interp.space.wrap_positive_32bit_int(shifted) + else: + try: + shifted = ovfcheck(receiver << argument) + except OverflowError: + raise PrimitiveFailedError() + return interp.space.wrap_int(shifted) # right shift, ok to lose bits else: @@ -556,13 +568,12 @@ def func(interp, s_frame, w_rcvr): raise PrimitiveNotYetWrittenError() - at expose_primitive(BITBLT_COPY_BITS, unwrap_spec=[object]) + at expose_primitive(BITBLT_COPY_BITS, unwrap_spec=[object], clean_stack=False) def func(interp, s_frame, w_rcvr): if not isinstance(w_rcvr, model.W_PointersObject) or w_rcvr.size() < 15: raise PrimitiveFailedError space = interp.space - s_frame.push(w_rcvr) s_frame._sendSelfSelector(interp.image.w_simulateCopyBits, 0, interp) w_dest_form = w_rcvr.fetch(space, 0) @@ -571,6 +582,7 @@ assert isinstance(w_bitmap, model.W_DisplayBitmap) w_bitmap.flush_to_screen() + # in case we return normally, we have to restore the removed w_rcvr return w_rcvr @expose_primitive(BE_CURSOR, unwrap_spec=[object]) @@ -1100,21 +1112,14 @@ @expose_primitive(PERFORM_WITH_ARGS, unwrap_spec=[object, object, list], - no_result=True) + no_result=True, clean_stack=False) def func(interp, s_frame, w_rcvr, w_selector, args_w): - stackvalues = s_frame.pop_and_return_n(3) argcount = len(args_w) # pushing the receiver and args to be popped by _sendSelector s_frame.push(w_rcvr) s_frame.push_all(args_w) s_frame._sendSelector(w_selector, argcount, interp, w_rcvr, w_rcvr.shadow_of_my_class(interp.space)) - # If we return in a regular way, we need to rebuild the former - # stack-contents to be collected by the primitive wrapper, i.a. if - # w_selector points to a primitive method. But if we have an exception, the - # wrapper will not clean. Therefore we should not put this into a finally. - s_frame.push_all(stackvalues) - @expose_primitive(SIGNAL, unwrap_spec=[object]) def func(interp, s_frame, w_rcvr): diff --git a/spyvm/test/test_primitives.py b/spyvm/test/test_primitives.py --- a/spyvm/test/test_primitives.py +++ b/spyvm/test/test_primitives.py @@ -167,13 +167,16 @@ assert prim(primitives.BIT_SHIFT, [-4, 27]).value == -536870912 def test_small_int_bit_shift_fail(): + from rpython.rlib.rarithmetic import intmask prim_fails(primitives.BIT_SHIFT, [4, 32]) prim_fails(primitives.BIT_SHIFT, [4, 31]) prim_fails(primitives.BIT_SHIFT, [4, 30]) - prim_fails(primitives.BIT_SHIFT, [4, 29]) - w_result = prim_fails(primitives.BIT_SHIFT, [4, 28]) - # assert isinstance(w_result, model.W_LargePositiveInteger1Word) - # assert w_result.value == 4 << 28 + w_result = prim(primitives.BIT_SHIFT, [4, 29]) + assert isinstance(w_result, model.W_LargePositiveInteger1Word) + assert w_result.value == intmask(4 << 29) + w_result = prim(primitives.BIT_SHIFT, [4, 28]) + assert isinstance(w_result, model.W_LargePositiveInteger1Word) + assert w_result.value == 4 << 28 def test_smallint_as_float(): assert prim(primitives.SMALLINT_AS_FLOAT, [12]).value == 12.0 @@ -709,8 +712,7 @@ prim_table[primitives.BITBLT_COPY_BITS](interp, w_frame.as_context_get_shadow(space), argument_count-1) finally: monkeypatch.undo() - assert w_frame._shadow.pop() is mock_bitblt # the new receiver - assert w_frame._shadow.pop() is mock_bitblt # previous state is still there + assert w_frame._shadow.pop() is mock_bitblt # the receiver # Note: # primitives.NEXT is unimplemented as it is a performance optimization diff --git a/targetimageloadingsmalltalk.py b/targetimageloadingsmalltalk.py --- a/targetimageloadingsmalltalk.py +++ b/targetimageloadingsmalltalk.py @@ -57,6 +57,7 @@ path = None number = 0 benchmark = None + trace = False while idx < len(argv): arg = argv[idx] @@ -76,6 +77,8 @@ _arg_missing(argv, idx, arg) benchmark = argv[idx + 1] idx += 1 + elif arg in ["-t", "--trace"]: + trace = True elif path is None: path = argv[idx] else: @@ -87,7 +90,7 @@ path = "Squeak.image" try: - f = open_file_as_stream(path) + f = open_file_as_stream(path, buffering=0) except OSError as e: os.write(2, "%s -- %s (LoadError)\n" % (os.strerror(e.errno), path)) return 1 @@ -98,7 +101,7 @@ image_reader = squeakimage.reader_for_image(space, squeakimage.Stream(data=imagedata)) image = create_image(space, image_reader) - interp = interpreter.Interpreter(space, image, image_name=os.path.abspath(path)) + interp = interpreter.Interpreter(space, image, image_name=path, trace=trace) if benchmark is not None: return _run_benchmark(interp, number, benchmark) else: From noreply at buildbot.pypy.org Wed Apr 3 13:49:00 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Wed, 3 Apr 2013 13:49:00 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: tests for the changed primitive behavior Message-ID: <20130403114900.83DD11C00BD@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r241:a1b3c3b15d75 Date: 2013-03-26 21:31 +0100 http://bitbucket.org/pypy/lang-smalltalk/changeset/a1b3c3b15d75/ Log: tests for the changed primitive behavior diff --git a/spyvm/test/test_largeinteger.py b/spyvm/test/test_largeinteger.py new file mode 100644 --- /dev/null +++ b/spyvm/test/test_largeinteger.py @@ -0,0 +1,100 @@ +import py +import operator +from spyvm import squeakimage, model, constants, error +from spyvm import interpreter, shadow, objspace, primitives +from spyvm.test import test_miniimage as tools +from spyvm.test.test_miniimage import perform, w +from spyvm.test.test_primitives import MockFrame + +from rpython.rlib.rarithmetic import intmask, r_uint + +space, interp = tools.setup_module(tools, filename='bootstrapped.image') + + +def find_symbol_in_methoddict_of(string, s_class): + s_methoddict = s_class.s_methoddict() + s_methoddict.sync_cache() + methoddict_w = s_methoddict.methoddict + for each in methoddict_w.keys(): + if each.as_string() == string: + return each + +def initialize_class(w_class): + initialize_symbol = find_symbol_in_methoddict_of("initialize", + w_class.shadow_of_my_class(tools.space)) + perform(w_class, initialize_symbol) + +def test_initialize_string_class(): + interp.trace = False + #initialize String class, because equality testing requires a class var set. + initialize_class(w("string").getclass(tools.space)) + +def perform_primitive(rcvr, w_selector, *args): + + code = rcvr.getclass(space)._shadow.lookup(w_selector).primitive() + assert code + func = primitives.prim_holder.prim_table[code] + s_frame = MockFrame([rcvr] + list(args)).as_context_get_shadow(space) + func(interp, s_frame, len(args)) + return s_frame.pop() + +def w_l(largeInteger): + if largeInteger >= 0 and largeInteger <= constants.TAGGED_MAXINT: + return space.wrap_int(intmask(largeInteger)) + else: + return model.W_LargePositiveInteger1Word(intmask(largeInteger)) + +# test that using W_LargePositiveInteger1Word yields the correct results. +# we use this way of testing to have multiple different test which may fail +def do_primitive(selector, operation, i=None, j=None, trace=False): + candidates = i if i is not None else [0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF] + + try: + w_selector = space.get_special_selector(selector) + except Exception: + w_selector = find_symbol_in_methoddict_of(selector, w(intmask(candidates[0])).getclass(space)._shadow) + + interp.trace=trace + for i, v in enumerate(candidates): + x = w_l(v) + if j is None: + y = x + else: + if isinstance(j, list): + y = w_l(j[i]) + else: + y = w_l(j) + z = perform_primitive(x, w_selector, y) + assert r_uint(z.value) == r_uint(operation(v, y.value)) + interp.trace=False + +def test_bitAnd(): + do_primitive("bitAnd:", operator.and_) + do_primitive("bitAnd:", operator.and_, i=[0xFFFFFFFF, 5, 0], j=[5, 0xFFFFFFFF, 0xFFFFFFFF]) + +def test_bitOr(): + do_primitive("bitOr:", operator.or_) + do_primitive("bitOr:", operator.or_, i=[2424328192], j=[34]) + +def test_bitXor(): + do_primitive("bitXor:", operator.xor) + do_primitive("bitXor:", operator.xor, i=[0xFFFFFFFF, 0x0F0F0F0F, 0xFFFFFF], + j=[0xF0F0F0F0, 0xFFFEFCF8, 4294967295]) + +def test_bitShift(): + def shift(a, b): + if b < 0: + return a >> -b + else: + return a << b +# do_primitive("bitShift:", shift, j=-5) + do_primitive("bitShift:", shift, i=[9470032], j=[6]) # 8 + +# def test_primitiveAdd(): +# do_primitive("+", operator.add) + +# def test_primitiveSub(): +# do_primitive("-", operator.sub, j=[0xFF, 0xFFFF, 0xF0E0D0C0], i=[-1, -1, -1]) +# do_primitive("-", operator.sub) + # do_primitive("-", operator.sub, i=[0xFF], j=0x3FFFFFFF) + From noreply at buildbot.pypy.org Wed Apr 3 13:49:01 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Wed, 3 Apr 2013 13:49:01 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: fixed wrap_uint to never create w_LargePositiveInteger instances of size <= 4 Message-ID: <20130403114901.8A77C1C00BD@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r242:868fcedf2f58 Date: 2013-03-28 12:46 +0100 http://bitbucket.org/pypy/lang-smalltalk/changeset/868fcedf2f58/ Log: fixed wrap_uint to never create w_LargePositiveInteger instances of size <= 4 diff --git a/spyvm/objspace.py b/spyvm/objspace.py --- a/spyvm/objspace.py +++ b/spyvm/objspace.py @@ -185,11 +185,13 @@ # XXX this code sucks import math bytes_len = int(math.log(val) / math.log(0xff)) + 1 - bytes_len = 4 if 4 > bytes_len else bytes_len - w_result = model.W_BytesObject(self.classtable['w_LargePositiveInteger'], bytes_len) - for i in range(bytes_len): - w_result.setchar(i, chr(intmask((val >> i*8) & 255))) - return w_result + if bytes_len <= 4: + return self.wrap_positive_32bit_int(intmask(val)) + else: + w_result = model.W_BytesObject(self.classtable['w_LargePositiveInteger'], bytes_len) + for i in range(bytes_len): + w_result.setchar(i, chr(intmask((val >> i*8) & 255))) + return w_result def wrap_positive_32bit_int(self, val): # This will always return a positive value. diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -1115,8 +1115,8 @@ no_result=True, clean_stack=False) def func(interp, s_frame, w_rcvr, w_selector, args_w): argcount = len(args_w) - # pushing the receiver and args to be popped by _sendSelector - s_frame.push(w_rcvr) + s_frame.pop_n(2) # removing our arguments to be substituted with args_w + # pushing the args to be popped by _sendSelector s_frame.push_all(args_w) s_frame._sendSelector(w_selector, argcount, interp, w_rcvr, w_rcvr.shadow_of_my_class(interp.space)) From noreply at buildbot.pypy.org Wed Apr 3 13:49:02 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Wed, 3 Apr 2013 13:49:02 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: (cfbolz, lwassermann): refactored the step function to have an unfolding loop instead of creating the methods source as string and compiling it. Message-ID: <20130403114902.91B881C00BD@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r243:626d7d57e4ab Date: 2013-03-28 14:28 +0100 http://bitbucket.org/pypy/lang-smalltalk/changeset/626d7d57e4ab/ Log: (cfbolz, lwassermann): refactored the step function to have an unfolding loop instead of creating the methods source as string and compiling it. diff --git a/spyvm/interpreter.py b/spyvm/interpreter.py --- a/spyvm/interpreter.py +++ b/spyvm/interpreter.py @@ -781,38 +781,23 @@ assert None not in result return result - +# this table is only used for creating named bytecodes in tests and printing BYTECODE_TABLE = initialize_bytecode_table() +from rpython.rlib.unroll import unrolling_iterable +unrolling_ranges = unrolling_iterable(BYTECODE_RANGES) +def bytecode_step_translated(self, context): + bytecode = context.getbytecode() + for entry in unrolling_ranges: + if len(entry) == 2: + bc, methname = entry + if bytecode == bc: + return getattr(context, methname)(self, bytecode) + else: + start, stop, methname = entry + if start <= bytecode <= stop: + return getattr(context, methname)(self, bytecode) + assert 0, "unreachable" -def make_bytecode_dispatch_translated(): - # this is a performance optimization: when translating the - # interpreter, the bytecode dispatching is not implemented as a - # list lookup and an indirect call but as a switch. - - code = ["def bytecode_step_translated(self, context):"] - code.append(" bytecode = context.getbytecode()") - prefix = "" - for entry in BYTECODE_RANGES: - if len(entry) == 2: - numbers = [entry[0]] - else: - numbers = range(entry[0], entry[1]+1) - cond = " or ".join(["bytecode == %s" % (i, ) - for i in numbers]) - code.append(" %sif %s:" % (prefix, cond, )) - code.append(" return context.%s(self, bytecode)" % (entry[-1], )) - prefix = "el" - source = py.code.Source("\n".join(code)) - #print source - miniglob = {} - exec source.compile() in miniglob - return miniglob["bytecode_step_translated"] - -bytecode_step_translated = make_bytecode_dispatch_translated() - -# we_are_translated returns false on top of CPython and true when -# translating the interpreter -# if objectmodel.we_are_translated(): Interpreter.step = bytecode_step_translated diff --git a/spyvm/objspace.py b/spyvm/objspace.py --- a/spyvm/objspace.py +++ b/spyvm/objspace.py @@ -235,7 +235,7 @@ if isinstance(w_value, model.W_SmallInteger): return w_value.value elif isinstance(w_value, model.W_LargePositiveInteger1Word): - if w_value.value > 0: + if w_value.value >= 0: return w_value.value else: raise UnwrappingError("The value is negative when interpreted as 32bit value.") From noreply at buildbot.pypy.org Wed Apr 3 13:49:03 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Wed, 3 Apr 2013 13:49:03 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: fixed at0 of LargePositive1Word Integer: results can not be negative !!!!!!!!!!!!!!!!!!!! Message-ID: <20130403114903.A2E811C00BD@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r244:eb49c3494141 Date: 2013-04-03 13:32 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/eb49c3494141/ Log: fixed at0 of LargePositive1Word Integer: results can not be negative !!!!!!!!!!!!!!!!!!!! diff --git a/spyvm/model.py b/spyvm/model.py --- a/spyvm/model.py +++ b/spyvm/model.py @@ -215,9 +215,9 @@ def at0(self, space, index0): if index0 >= self.size(): raise IndexError() - skew = index0 * 8 - mask = 0xff << skew - return space.wrap_int(intmask((self.value & mask) >> skew)) + shift = index0 * 8 + result = (self.value >> shift) & 0xff + return space.wrap_int(intmask(result)) def atput0(self, space, index0, w_byte): if index0 >= self.size(): From noreply at buildbot.pypy.org Wed Apr 3 13:49:04 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Wed, 3 Apr 2013 13:49:04 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: changed object printing capabilities in order to enable diffing on traces of c and python (i.e. remove addresses from trace) Message-ID: <20130403114904.B1F2D1C00BD@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r245:92053dadadea Date: 2013-04-03 13:41 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/92053dadadea/ Log: changed object printing capabilities in order to enable diffing on traces of c and python (i.e. remove addresses from trace) diff --git a/spyvm/model.py b/spyvm/model.py --- a/spyvm/model.py +++ b/spyvm/model.py @@ -114,6 +114,12 @@ true for some W_PointersObjects""" return True + def __repr__(self): + return self.as_repr_string() + + def as_repr_string(self): + return "%r" % self + class W_SmallInteger(W_Object): """Boxed integer value""" # TODO can we tell pypy that its never larger then 31-bit? @@ -133,7 +139,7 @@ def invariant(self): return isinstance(self.value, int) and self.value < 0x8000 - def __repr__(self): + def as_repr_string(self): return "W_SmallInteger(%d)" % self.value def is_same_object(self, other): @@ -338,9 +344,6 @@ assert self.w_class is not None return self.w_class - def __repr__(self): - return "<%s %s>" % (self.__class__.__name__, self) - def __str__(self): if isinstance(self, W_PointersObject) and self.has_shadow(): return self._shadow.getname() @@ -350,6 +353,16 @@ name = self.w_class._shadow.name return "a %s" % (name or '?',) + def as_repr_string(self): + return self.as_embellished_string("W_O /w Class", "") + + def as_embellished_string(self, className, additionalInformation): + from rpython.rlib.objectmodel import current_object_addr_as_int + name = self.shadow_of_my_class(self.space).name or "?" + return "<%s (a %s) %s>" % (className, name, + #hex(current_object_addr_as_int(self)), + additionalInformation) + def invariant(self): return (W_AbstractObjectWithIdentityHash.invariant(self) and isinstance(self.w_class, W_PointersObject)) @@ -512,6 +525,11 @@ w_result._vars = [self.fetch(space, i) for i in range(len(self._vars))] return w_result + def as_repr_string(self): + return W_AbstractObjectWithClassReference.as_embellished_string(self, + className='W_PointersObject', + additionalInformation='len(%d)' % self.size()) + class W_BytesObject(W_AbstractObjectWithClassReference): _attrs_ = ['bytes'] @@ -544,8 +562,9 @@ def __str__(self): return self.as_string() - def __repr__(self): - return "" % (self.as_string(),) + def as_repr_string(self): + return W_AbstractObjectWithClassReference.as_embellished_string(self, + className='W_BytesObject', additionalInformation=self.as_string()) def as_string(self): return "".join(self.bytes) @@ -745,6 +764,9 @@ def __str__(self): return self.as_string() + def as_repr_string(self): + return "" % self.get_identifier_string() + def as_string(self, markBytecode=0): from spyvm.interpreter import BYTECODE_TABLE j = 1 @@ -763,7 +785,7 @@ w_candidate = self.literals[-1] if isinstance(w_candidate, W_PointersObject): c_shadow = w_candidate._shadow - if c_shadow is None: + if c_shadow is None and w_candidate.size() >= 2: w_class = w_candidate._fetch(1) if isinstance(w_class, W_PointersObject): d_shadow = w_class._shadow diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -3,8 +3,7 @@ import math import operator from spyvm import model, shadow -from spyvm import constants -from spyvm import display +from spyvm import constants, display from spyvm.error import PrimitiveFailedError, \ PrimitiveNotYetWrittenError from spyvm import wrapper @@ -183,7 +182,6 @@ def make_func(op): @expose_primitive(code, unwrap_spec=[pos_32bit_int, pos_32bit_int]) def func(interp, s_frame, receiver, argument): - from spyvm.model import W_LargePositiveInteger1Word res = op(receiver, argument) return interp.space.wrap_positive_32bit_int(res) make_func(op) @@ -570,6 +568,7 @@ @expose_primitive(BITBLT_COPY_BITS, unwrap_spec=[object], clean_stack=False) def func(interp, s_frame, w_rcvr): + from spyvm.interpreter import Return if not isinstance(w_rcvr, model.W_PointersObject) or w_rcvr.size() < 15: raise PrimitiveFailedError @@ -868,6 +867,7 @@ def func(interp, s_frame, w_arg): import time sec_since_epoch = rarithmetic.r_uint(time.time()) + # XXX: overflow check necessary? sec_since_1901 = sec_since_epoch + secs_between_1901_and_1970 return interp.space.wrap_uint(sec_since_1901) diff --git a/spyvm/shadow.py b/spyvm/shadow.py --- a/spyvm/shadow.py +++ b/spyvm/shadow.py @@ -800,7 +800,7 @@ def short_str(self): return 'BlockContext of %s (%s) [%d]' % ( self.w_method().get_identifier_string(), - self.w_receiver(), + self.w_receiver().as_repr_string(), self.pc() + 1 ) @@ -947,11 +947,11 @@ return retval def short_str(self): - block = '[] of' if self.is_closure_context() else '' - return '%s %s (rcvr: %s) [pc: %d]' % ( + block = '[] of ' if self.is_closure_context() else '' + return '%s%s (rcvr: %s) [pc: %d]' % ( block, self.w_method().get_identifier_string(), - self.w_receiver(), + self.w_receiver().as_repr_string(), self.pc() + 1 ) From noreply at buildbot.pypy.org Wed Apr 3 13:49:05 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Wed, 3 Apr 2013 13:49:05 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: added a space field to all w_objects with class reference, to enable removing the w_class link in favor of s_class links Message-ID: <20130403114905.D39A11C00BD@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r246:dbcaed2eedea Date: 2013-04-03 13:47 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/dbcaed2eedea/ Log: added a space field to all w_objects with class reference, to enable removing the w_class link in favor of s_class links removed negative arguments from bit_shift primitive to support largepositiveintegers and in agreement with original specification diff --git a/spyvm/model.py b/spyvm/model.py --- a/spyvm/model.py +++ b/spyvm/model.py @@ -330,15 +330,16 @@ class W_AbstractObjectWithClassReference(W_AbstractObjectWithIdentityHash): """Objects with arbitrary class (ie not CompiledMethod, SmallInteger or Float).""" - _attrs_ = ['w_class', 's_class'] + _attrs_ = ['w_class', 's_class', 'space'] s_class = None - def __init__(self, w_class): + def __init__(self, space, w_class): if w_class is not None: # it's None only for testing and space generation assert isinstance(w_class, W_PointersObject) if w_class.has_shadow(): self.s_class = w_class.as_class_get_shadow(w_class._shadow.space) self.w_class = w_class + self.space = space def getclass(self, space): assert self.w_class is not None @@ -387,9 +388,9 @@ _shadow = None # Default value @jit.unroll_safe - def __init__(self, w_class, size): + def __init__(self, space, w_class, size): """Create new object with size = fixed + variable size.""" - W_AbstractObjectWithClassReference.__init__(self, w_class) + W_AbstractObjectWithClassReference.__init__(self, space, w_class) vars = self._vars = [None] * size for i in range(size): # do it by hand for the JIT's sake vars[i] = w_nil @@ -400,6 +401,7 @@ self.w_class = g_self.get_class() self.s_class = None self.hash = g_self.get_hash() + self.space = space def at0(self, space, index0): # To test, at0 = in varsize part @@ -476,6 +478,12 @@ from spyvm.shadow import ClassShadow return jit.promote(self.as_special_get_shadow(space, ClassShadow)) + # Should only be used during squeak-image loading. + def as_class_get_penumbra(self, space): + from spyvm.shadow import ClassShadow + self.store_shadow(ClassShadow(space, self)) + return self._shadow + def as_blockcontext_get_shadow(self, space): from spyvm.shadow import BlockContextShadow return self.as_special_get_shadow(space, BlockContextShadow) @@ -521,7 +529,7 @@ return True def clone(self, space): - w_result = W_PointersObject(self.w_class, len(self._vars)) + w_result = W_PointersObject(self.space, self.w_class, len(self._vars)) w_result._vars = [self.fetch(space, i) for i in range(len(self._vars))] return w_result @@ -533,8 +541,8 @@ class W_BytesObject(W_AbstractObjectWithClassReference): _attrs_ = ['bytes'] - def __init__(self, w_class, size): - W_AbstractObjectWithClassReference.__init__(self, w_class) + def __init__(self, space, w_class, size): + W_AbstractObjectWithClassReference.__init__(self, space, w_class) assert isinstance(size, int) self.bytes = ['\x00'] * size @@ -542,6 +550,7 @@ self.w_class = g_self.get_class() self.bytes = g_self.get_bytes() self.hash = g_self.get_hash() + self.space = space def at0(self, space, index0): return space.wrap_int(ord(self.getchar(index0))) @@ -584,21 +593,22 @@ return self.bytes == other.bytes def clone(self, space): - w_result = W_BytesObject(self.w_class, len(self.bytes)) + w_result = W_BytesObject(self.space, self.w_class, len(self.bytes)) w_result.bytes = list(self.bytes) return w_result class W_WordsObject(W_AbstractObjectWithClassReference): _attrs_ = ['words'] - def __init__(self, w_class, size): - W_AbstractObjectWithClassReference.__init__(self, w_class) + def __init__(self, space, w_class, size): + W_AbstractObjectWithClassReference.__init__(self, space, w_class) self.words = [r_uint(0)] * size def fillin(self, space, g_self): self.words = g_self.get_ruints() self.w_class = g_self.get_class() self.hash = g_self.get_hash() + self.space = space def at0(self, space, index0): val = self.getword(index0) @@ -622,7 +632,7 @@ isinstance(self.words, list)) def clone(self, space): - w_result = W_WordsObject(self.w_class, len(self.words)) + w_result = W_WordsObject(self.space, self.w_class, len(self.words)) w_result.words = list(self.words) return w_result @@ -633,14 +643,14 @@ _immutable_fields_ = ['_realsize', 'display'] @staticmethod - def create(w_class, size, depth, display): + def create(space, w_class, size, depth, display): if depth == 1: - return W_DisplayBitmap1Bit(w_class, size, depth, display) + return W_DisplayBitmap1Bit(space, w_class, size, depth, display) else: raise NotImplementedError("non B/W squeak") - def __init__(self, w_class, size, depth, display): - W_AbstractObjectWithClassReference.__init__(self, w_class) + def __init__(self, space, w_class, size, depth, display): + W_AbstractObjectWithClassReference.__init__(self, space, w_class) bytelen = NATIVE_DEPTH / depth * size self.pixelbuffer = lltype.malloc(rffi.ULONGP.TO, bytelen, flavor='raw') self._realsize = size @@ -667,7 +677,7 @@ return False def clone(self, space): - w_result = W_WordsObject(self.w_class, self._realsize) + w_result = W_WordsObject(self.space, self.w_class, self._realsize) n = 0 while n < self._realsize: w_result.words[n] = self.getword(n) diff --git a/spyvm/objspace.py b/spyvm/objspace.py --- a/spyvm/objspace.py +++ b/spyvm/objspace.py @@ -124,7 +124,7 @@ w_cinst.store(self, constants.CHARACTER_VALUE_INDEX, model.W_SmallInteger(i)) return w_cinst - w_charactertable = model.W_PointersObject( + w_charactertable = model.W_PointersObject(self, self.classtable['w_Array'], 256) self.w_charactertable = w_charactertable for i in range(256): @@ -135,6 +135,7 @@ # 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.space = self w_nil.w_class = self.classtable['w_UndefinedObject'] w_true = self.classtable['w_True'].as_class_get_shadow(self).new() @@ -145,7 +146,7 @@ self.w_zero = model.W_SmallInteger(0) self.w_one = model.W_SmallInteger(1) self.w_two = model.W_SmallInteger(2) - w_special_selectors = model.W_PointersObject( + w_special_selectors = model.W_PointersObject(self, self.classtable['w_Array'], len(constants.SPECIAL_SELECTORS) * 2) self.w_special_selectors = w_special_selectors @@ -175,9 +176,12 @@ raise WrappingError("integer too large to fit into a tagged pointer") def wrap_uint(self, val): + from rpython.rlib.objectmodel import we_are_translated + if not we_are_translated(): + assert val <= 0xFFFFFFFF if val < 0: raise WrappingError("negative integer") - if intmask(val) >= 0: + if val >= 0: try: return self.wrap_positive_32bit_int(intmask(val)) except WrappingError: @@ -188,7 +192,8 @@ if bytes_len <= 4: return self.wrap_positive_32bit_int(intmask(val)) else: - w_result = model.W_BytesObject(self.classtable['w_LargePositiveInteger'], bytes_len) + w_result = model.W_BytesObject(self, + self.classtable['w_LargePositiveInteger'], bytes_len) for i in range(bytes_len): w_result.setchar(i, chr(intmask((val >> i*8) & 255))) return w_result @@ -327,7 +332,7 @@ def bootstrap_class(space, instsize, w_superclass=None, w_metaclass=None, name='?', format=shadow.POINTERS, varsized=False): from spyvm import model - w_class = model.W_PointersObject(w_metaclass, 0) + w_class = model.W_PointersObject(space, w_metaclass, 0) # a dummy placeholder for testing # XXX s = instantiate(shadow.ClassShadow) diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -217,7 +217,7 @@ return interp.space.wrap_int(receiver // argument) # #bitShift: -- return the shifted value - at expose_primitive(BIT_SHIFT, unwrap_spec=[int, int]) + at expose_primitive(BIT_SHIFT, unwrap_spec=[pos_32bit_int, int]) def func(interp, s_frame, receiver, argument): # TODO: 1 << 100 will overflow to 0. Catch this gracefully by Primitive @@ -557,7 +557,7 @@ @expose_primitive(MOUSE_POINT, unwrap_spec=[object]) def func(interp, s_frame, w_rcvr): x, y = interp.space.get_display().mouse_point() - w_point = model.W_PointersObject(interp.space.w_Point, 2) + w_point = model.W_PointersObject(interp.space, interp.space.w_Point, 2) w_point.store(interp.space, 0, interp.space.wrap_int(x)) w_point.store(interp.space, 1, interp.space.wrap_int(y)) return w_point @@ -620,6 +620,7 @@ if not sdldisplay: sdldisplay = display.SDLDisplay(interp.image_name) w_display_bitmap = model.W_DisplayBitmap.create( + interp.space, w_bitmap.getclass(interp.space), w_bitmap.size(), depth, diff --git a/spyvm/shadow.py b/spyvm/shadow.py --- a/spyvm/shadow.py +++ b/spyvm/shadow.py @@ -201,11 +201,11 @@ def new(self, extrasize=0): w_cls = self.w_self() if self.instance_kind == POINTERS: - w_new = model.W_PointersObject(w_cls, self.instsize()+extrasize) + w_new = model.W_PointersObject(self.space, w_cls, self.instsize()+extrasize) elif self.instance_kind == WORDS: - w_new = model.W_WordsObject(w_cls, extrasize) + w_new = model.W_WordsObject(self.space, w_cls, extrasize) elif self.instance_kind == BYTES: - w_new = model.W_BytesObject(w_cls, extrasize) + w_new = model.W_BytesObject(self.space, w_cls, extrasize) elif self.instance_kind == COMPILED_METHOD: w_new = model.W_CompiledMethod(extrasize) elif self.instance_kind == FLOAT: @@ -214,7 +214,7 @@ if extrasize <= 4: w_new = model.W_LargePositiveInteger1Word(0, extrasize) else: - w_new = model.W_BytesObject(w_cls, extrasize) + w_new = model.W_BytesObject(self.space, w_cls, extrasize) else: raise NotImplementedError(self.instance_kind) return w_new @@ -321,8 +321,8 @@ def initialize_methoddict(self): "NOT_RPYTHON" # this is only for testing. if self._s_methoddict is None: - w_methoddict = model.W_PointersObject(None, 2) - w_methoddict._store(1, model.W_PointersObject(None, 0)) + w_methoddict = model.W_PointersObject(self.space, None, 2) + w_methoddict._store(1, model.W_PointersObject(self.space, None, 0)) self._s_methoddict = w_methoddict.as_methoddict_get_shadow(self.space) self.s_methoddict().sync_cache() self.s_methoddict().invalid = False @@ -710,7 +710,7 @@ # 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(space).myblocksize() - w_result = model.W_PointersObject(space.w_BlockContext, contextsize) + w_result = model.W_PointersObject(space, space.w_BlockContext, contextsize) s_result = BlockContextShadow(space, w_result) s_result_non_fresh = s_result # XXX: find a better solution to translation err s_result = jit.hint(s_result, access_directly=True, fresh_virtualizable=True) diff --git a/spyvm/test/test_interpreter.py b/spyvm/test/test_interpreter.py --- a/spyvm/test/test_interpreter.py +++ b/spyvm/test/test_interpreter.py @@ -94,7 +94,7 @@ w_method.bytes = bytes w_method.argsize=2 w_method.tempsize=8 - w_method.setliterals([model.W_PointersObject(None, 2)]) + w_method.setliterals([model.W_PointersObject(space, None, 2)]) s_frame = w_method.as_compiledmethod_get_shadow(space).create_frame(space, receiver, ["foo", "bar"]) return s_frame.w_self(), s_frame diff --git a/spyvm/test/test_model.py b/spyvm/test/test_model.py --- a/spyvm/test/test_model.py +++ b/spyvm/test/test_model.py @@ -147,13 +147,13 @@ with py.test.raises(error.PrimitiveFailedError): w_method.atput0(space, 9, space.wrap_int(5)) -def test_is_same_object(w_o1=model.W_PointersObject(None,0), w_o2=None): +def test_is_same_object(w_o1=model.W_PointersObject(space, None,0), w_o2=None): if w_o2 is None: w_o2 = w_o1 assert w_o1.is_same_object(w_o2) assert w_o2.is_same_object(w_o1) -def test_not_is_same_object(w_o1=model.W_PointersObject(None,0),w_o2=model.W_PointersObject(None,0)): +def test_not_is_same_object(w_o1=model.W_PointersObject(space, None,0),w_o2=model.W_PointersObject(space, 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) @@ -221,7 +221,7 @@ def test_word_atput(): i = model.W_SmallInteger(100) - b = model.W_WordsObject(None, 1) + b = model.W_WordsObject(space, None, 1) b.atput0(space, 0, i) assert 100 == b.getword(0) i = space.classtable['w_LargePositiveInteger'].as_class_get_shadow(space).new(4) @@ -230,7 +230,7 @@ assert b.getword(0) == 3221225472 def test_word_at(): - b = model.W_WordsObject(None, 1) + b = model.W_WordsObject(space, None, 1) b.setword(0, 100) r = b.at0(space, 0) assert isinstance(r, model.W_SmallInteger) @@ -238,7 +238,7 @@ b.setword(0, 3221225472) r = b.at0(space, 0) - assert isinstance(r, model.W_BytesObject) + assert isinstance(r, (model.W_BytesObject, model.W_LargePositiveInteger1Word)) assert r.size() == 4 def test_float_at(): @@ -288,7 +288,7 @@ assert hex(r_uint(target.value)) == hex(r_uint(source.value)) def test_display_bitmap(): - target = model.W_DisplayBitmap.create(space.w_Array, 100, 1, None) + target = model.W_DisplayBitmap.create(space, space.w_Array, 100, 1, None) target.setword(0, 0xFF00) assert bin(target.getword(0)) == bin(0xFF00) target.setword(0, 0x00FF00FF) diff --git a/spyvm/test/test_objectspace.py b/spyvm/test/test_objectspace.py --- a/spyvm/test/test_objectspace.py +++ b/spyvm/test/test_objectspace.py @@ -28,6 +28,7 @@ assert w_Metaclass.w_class.w_class is w_Metaclass def test_ruint(): + from spyvm import model """ | a b | a := (9223372036854775808). @@ -40,7 +41,7 @@ """ from rpython.rlib.rarithmetic import r_uint - for num in [0, 1, 41, 100, 2**31, sys.maxint + 1]: + for num in [0, 1, 41, 100, 2**31, sys.maxint + 1, -1]: num = r_uint(num) assert space.unwrap_uint(space.wrap_uint(num)) == num for num in [-1, -100, -sys.maxint]: @@ -49,9 +50,10 @@ for obj in [space.wrap_char('a'), space.wrap_int(-1)]: with py.test.raises(objspace.UnwrappingError): space.unwrap_uint(obj) - byteobj = space.wrap_uint(sys.maxint + 1) - byteobj.bytes.append('\x01') - num = space.unwrap_uint(byteobj) + # byteobj = space.wrap_uint(0x100000000) + # assert isinstance(byteobj, model.W_BytesObject) + # byteobj.bytes.append('\x01') + # num = space.unwrap_uint(byteobj) # should not raise. see docstring. diff --git a/spyvm/test/test_primitives.py b/spyvm/test/test_primitives.py --- a/spyvm/test/test_primitives.py +++ b/spyvm/test/test_primitives.py @@ -157,6 +157,7 @@ assert prim(primitives.BIT_SHIFT, [4, 27]).value == 536870912 def test_small_int_bit_shift_negative(): + py.test.skip("While this would make sense, because of the specification, we dont shift negative numbers") assert prim(primitives.BIT_SHIFT, [-4, -3]).value == -1 assert prim(primitives.BIT_SHIFT, [-4, -2]).value == -1 assert prim(primitives.BIT_SHIFT, [-4, -1]).value == -2 @@ -444,12 +445,15 @@ import time now = int(time.time()) w_smalltalk_now1 = prim(primitives.SECONDS_CLOCK, [42]) - assert (now % 256 - ord(w_smalltalk_now1.bytes[0])) % 256 <= 2 w_smalltalk_now2 = prim(primitives.SECONDS_CLOCK, [42]) - # the high-order byte should only change by one (and even that is - # extreeemely unlikely) - assert (ord(w_smalltalk_now2.bytes[-1]) - ord(w_smalltalk_now1.bytes[-1])) <= 1 - + # the test now is flaky, because we assume both have the same type + if isinstance(w_smalltalk_now1, model.W_BytesObject): + assert (now % 256 - ord(w_smalltalk_now1.bytes[0])) % 256 <= 2 + # the high-order byte should only change by one (and even that is + # extreeemely unlikely) + assert (ord(w_smalltalk_now2.bytes[-1]) - ord(w_smalltalk_now1.bytes[-1])) <= 1 + else: + assert w_smalltalk_now2.value - w_smalltalk_now1.value <= 1 def test_load_inst_var(): " try to test the LoadInstVar primitives a little " @@ -635,8 +639,8 @@ def test_primitive_be_display(): assert space.objtable["w_display"] is None - mock_display = model.W_PointersObject(space.w_Point, 4) - w_wordbmp = model.W_WordsObject(space.w_Array, 100) + mock_display = model.W_PointersObject(space, space.w_Point, 4) + w_wordbmp = model.W_WordsObject(space, space.w_Array, 100) mock_display.store(space, 0, w_wordbmp) # bitmap mock_display.store(space, 1, space.wrap_int(32)) # width mock_display.store(space, 2, space.wrap_int(10)) # height @@ -649,8 +653,8 @@ sdldisplay = w_bitmap.display assert isinstance(sdldisplay, display.SDLDisplay) - mock_display2 = model.W_PointersObject(space.w_Point, 4) - mock_display2.store(space, 0, model.W_WordsObject(space.w_Array, 100)) # bitmap + mock_display2 = model.W_PointersObject(space, space.w_Point, 4) + mock_display2.store(space, 0, model.W_WordsObject(space, space.w_Array, 100)) # bitmap mock_display2.store(space, 1, space.wrap_int(32)) # width mock_display2.store(space, 2, space.wrap_int(10)) # height mock_display2.store(space, 3, space.wrap_int(1)) # depth @@ -667,8 +671,8 @@ assert mock_display.fetch(space, 0) is w_bitmap def test_primitive_force_display_update(monkeypatch): - mock_display = model.W_PointersObject(space.w_Point, 4) - w_wordbmp = model.W_WordsObject(space.w_Array, 100) + mock_display = model.W_PointersObject(space, space.w_Point, 4) + w_wordbmp = model.W_WordsObject(space, space.w_Array, 100) mock_display.store(space, 0, w_wordbmp) # bitmap mock_display.store(space, 1, space.wrap_int(32)) # width mock_display.store(space, 2, space.wrap_int(10)) # height @@ -695,7 +699,7 @@ def __init__(self): self.w_simulateCopyBits = "simulateCopyBits" - mock_bitblt = model.W_PointersObject(space.w_Point, 15) + mock_bitblt = model.W_PointersObject(space, space.w_Point, 15) def perform_mock(w_selector, argcount, interp): if w_selector == "simulateCopyBits" or w_selector.as_string() == "simulateCopyBits": diff --git a/spyvm/test/test_shadow.py b/spyvm/test/test_shadow.py --- a/spyvm/test/test_shadow.py +++ b/spyvm/test/test_shadow.py @@ -36,7 +36,7 @@ w_Metaclass) w_methoddict = build_methoddict(methods) size = constants.CLASS_NAME_INDEX + 1 - w_class = model.W_PointersObject(w_classofclass, size) + w_class = model.W_PointersObject(space, w_classofclass, size) 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)) @@ -85,7 +85,7 @@ 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 = model.W_PointersObject(space, space.w_MethodContext, constants.MTHDCTX_TEMP_FRAME_START+method.tempsize+stacksize) 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)) @@ -99,7 +99,7 @@ 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 = model.W_PointersObject(space, space.w_MethodContext, constants.MTHDCTX_TEMP_FRAME_START+stacksize) 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)) diff --git a/spyvm/test/test_wrapper.py b/spyvm/test/test_wrapper.py --- a/spyvm/test/test_wrapper.py +++ b/spyvm/test/test_wrapper.py @@ -10,7 +10,7 @@ return new_frame_tuple("")[0] def test_simpleread(): - w_o = model.W_PointersObject(None, 2) + w_o = model.W_PointersObject(space, None, 2) w = wrapper.Wrapper(space, w_o) w_o._vars[0] = "hello" assert w.read(0) == "hello" @@ -20,7 +20,7 @@ py.test.raises(WrapperException, "w.write(2, \"test\")") def test_accessor_generators(): - w_o = model.W_PointersObject(None, 1) + w_o = model.W_PointersObject(space, None, 1) w = wrapper.LinkWrapper(space, w_o) w_o._vars[0] = "hello" assert w.next_link() == "hello" @@ -28,12 +28,12 @@ assert w.next_link() == "boe" def link(w_next='foo'): - w_object = model.W_PointersObject(None, 1) + w_object = model.W_PointersObject(space, None, 1) 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_object = model.W_PointersObject(space, None,2) w_last = link(space.w_nil) w_lb1 = link(w_last) w_lb2 = link(w_lb1) @@ -72,7 +72,7 @@ w_suspended_context=space.w_nil, priority=0): w_priority = space.wrap_int(priority) - w_process = model.W_PointersObject(None, 4) + w_process = model.W_PointersObject(space, None, 4) process = wrapper.ProcessWrapper(space, w_process) process.store_next_link(w_next) process.store_my_list(w_my_list) @@ -81,7 +81,7 @@ return process def new_processlist(processes_w=[]): - w_processlist = model.W_PointersObject(None, 2) + w_processlist = model.W_PointersObject(space, None, 2) w_first = space.w_nil w_last = space.w_nil for w_process in processes_w[::-1]: @@ -99,7 +99,7 @@ else: maxpriority = 5 prioritydict = {} - w_prioritylist = model.W_PointersObject(None, maxpriority) + w_prioritylist = model.W_PointersObject(space, None, maxpriority) prioritylist = wrapper.Wrapper(space, w_prioritylist) for i in range(maxpriority): prioritylist.write(i, new_processlist(prioritydict.get(i, []))._w_self) @@ -108,14 +108,14 @@ def new_scheduler(w_process=space.w_nil, prioritydict=None): priority_list = new_prioritylist(prioritydict) - w_scheduler = model.W_PointersObject(None, 2) + w_scheduler = model.W_PointersObject(space, None, 2) 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) + w_semaphore = model.W_PointersObject(space, None, 3) semaphore = wrapper.SemaphoreWrapper(space, w_semaphore) semaphore.store_excess_signals(excess_signals) return semaphore From noreply at buildbot.pypy.org Wed Apr 3 13:49:06 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Wed, 3 Apr 2013 13:49:06 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: maybe fixed BIT_BLT primitive repainting on return Message-ID: <20130403114906.D5D9D1C00BD@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r247:bd6f9429a58c Date: 2013-04-03 13:48 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/bd6f9429a58c/ Log: maybe fixed BIT_BLT primitive repainting on return diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -573,13 +573,15 @@ raise PrimitiveFailedError space = interp.space - s_frame._sendSelfSelector(interp.image.w_simulateCopyBits, 0, interp) - - w_dest_form = w_rcvr.fetch(space, 0) - if w_dest_form.is_same_object(space.objtable['w_display']): - w_bitmap = w_dest_form.fetch(space, 0) - assert isinstance(w_bitmap, model.W_DisplayBitmap) - w_bitmap.flush_to_screen() + try: + s_frame._sendSelfSelector(interp.image.w_simulateCopyBits, 0, interp) + except Return: + w_dest_form = w_rcvr.fetch(space, 0) + if w_dest_form.is_same_object(space.objtable['w_display']): + #import pdb; pdb.set_trace() + w_bitmap = w_dest_form.fetch(space, 0) + assert isinstance(w_bitmap, model.W_DisplayBitmap) + w_bitmap.flush_to_screen() # in case we return normally, we have to restore the removed w_rcvr return w_rcvr From noreply at buildbot.pypy.org Wed Apr 3 16:20:29 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 3 Apr 2013 16:20:29 +0200 (CEST) Subject: [pypy-commit] pypy sqlite-cffi: close merged branch Message-ID: <20130403142029.121761C06BD@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: sqlite-cffi Changeset: r62973:463fc6c41f8f Date: 2013-04-03 16:14 +0200 http://bitbucket.org/pypy/pypy/changeset/463fc6c41f8f/ Log: close merged branch From noreply at buildbot.pypy.org Wed Apr 3 16:20:30 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 3 Apr 2013 16:20:30 +0200 (CEST) Subject: [pypy-commit] pypy default: merge sqlite-cffi. Note that this one removes the cleanups done on ctypes Message-ID: <20130403142030.6428E1C0EFF@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r62974:e9ca8b5de3d6 Date: 2013-04-03 16:16 +0200 http://bitbucket.org/pypy/pypy/changeset/e9ca8b5de3d6/ Log: merge sqlite-cffi. Note that this one removes the cleanups done on ctypes version, but I don't think they're salvagable. hg is so dumb diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -23,9 +23,6 @@ # # Note: This software has been modified for use in PyPy. -from ctypes import c_void_p, c_int, c_double, c_int64, c_char_p, c_char, cdll -from ctypes import POINTER, byref, string_at, CFUNCTYPE, cast -from ctypes import sizeof, c_ssize_t from collections import OrderedDict from functools import wraps import datetime @@ -44,210 +41,266 @@ else: _BLOB_TYPE = buffer +from cffi import FFI -def load_library(names): - for name in names: - try: - return cdll.LoadLibrary(name) - except OSError: - pass - else: - raise ImportError("Could not load C-library, tried: %s" % (names,)) +ffi = FFI() -_lib = load_library( - "sqlite3.dll libsqlite3.so.0 libsqlite3.so libsqlite3.dylib".split()) -del load_library +ffi.cdef(""" +#define SQLITE_OK ... +#define SQLITE_ERROR ... +#define SQLITE_INTERNAL ... +#define SQLITE_PERM ... +#define SQLITE_ABORT ... +#define SQLITE_BUSY ... +#define SQLITE_LOCKED ... +#define SQLITE_NOMEM ... +#define SQLITE_READONLY ... +#define SQLITE_INTERRUPT ... +#define SQLITE_IOERR ... +#define SQLITE_CORRUPT ... +#define SQLITE_NOTFOUND ... +#define SQLITE_FULL ... +#define SQLITE_CANTOPEN ... +#define SQLITE_PROTOCOL ... +#define SQLITE_EMPTY ... +#define SQLITE_SCHEMA ... +#define SQLITE_TOOBIG ... +#define SQLITE_CONSTRAINT ... +#define SQLITE_MISMATCH ... +#define SQLITE_MISUSE ... +#define SQLITE_NOLFS ... +#define SQLITE_AUTH ... +#define SQLITE_FORMAT ... +#define SQLITE_RANGE ... +#define SQLITE_NOTADB ... +#define SQLITE_ROW ... +#define SQLITE_DONE ... +#define SQLITE_INTEGER ... +#define SQLITE_FLOAT ... +#define SQLITE_BLOB ... +#define SQLITE_NULL ... +#define SQLITE_TEXT ... +#define SQLITE3_TEXT ... -########################################## -# BEGIN Wrapped SQLite C API and constants -########################################## +#define SQLITE_TRANSIENT ... +#define SQLITE_UTF8 ... -_lib.SQLITE_OK = 0 -_lib.SQLITE_ERROR = 1 -_lib.SQLITE_INTERNAL = 2 -_lib.SQLITE_PERM = 3 -_lib.SQLITE_ABORT = 4 -_lib.SQLITE_BUSY = 5 -_lib.SQLITE_LOCKED = 6 -_lib.SQLITE_NOMEM = 7 -_lib.SQLITE_READONLY = 8 -_lib.SQLITE_INTERRUPT = 9 -_lib.SQLITE_IOERR = 10 -_lib.SQLITE_CORRUPT = 11 -_lib.SQLITE_NOTFOUND = 12 -_lib.SQLITE_FULL = 13 -_lib.SQLITE_CANTOPEN = 14 -_lib.SQLITE_PROTOCOL = 15 -_lib.SQLITE_EMPTY = 16 -_lib.SQLITE_SCHEMA = 17 -_lib.SQLITE_TOOBIG = 18 -_lib.SQLITE_CONSTRAINT = 19 -_lib.SQLITE_MISMATCH = 20 -_lib.SQLITE_MISUSE = 21 -_lib.SQLITE_NOLFS = 22 -_lib.SQLITE_AUTH = 23 -_lib.SQLITE_FORMAT = 24 -_lib.SQLITE_RANGE = 25 -_lib.SQLITE_NOTADB = 26 -_lib.SQLITE_ROW = 100 -_lib.SQLITE_DONE = 101 +#define SQLITE_DENY ... +#define SQLITE_IGNORE ... -_lib.SQLITE_INTEGER = 1 -_lib.SQLITE_FLOAT = 2 -_lib.SQLITE_TEXT = 3 -_lib.SQLITE_BLOB = 4 -_lib.SQLITE_NULL = 5 +#define SQLITE_CREATE_INDEX ... +#define SQLITE_CREATE_TABLE ... +#define SQLITE_CREATE_TEMP_INDEX ... +#define SQLITE_CREATE_TEMP_TABLE ... +#define SQLITE_CREATE_TEMP_TRIGGER ... +#define SQLITE_CREATE_TEMP_VIEW ... +#define SQLITE_CREATE_TRIGGER ... +#define SQLITE_CREATE_VIEW ... +#define SQLITE_DELETE ... +#define SQLITE_DROP_INDEX ... +#define SQLITE_DROP_TABLE ... +#define SQLITE_DROP_TEMP_INDEX ... +#define SQLITE_DROP_TEMP_TABLE ... +#define SQLITE_DROP_TEMP_TRIGGER ... +#define SQLITE_DROP_TEMP_VIEW ... +#define SQLITE_DROP_TRIGGER ... +#define SQLITE_DROP_VIEW ... +#define SQLITE_INSERT ... +#define SQLITE_PRAGMA ... +#define SQLITE_READ ... +#define SQLITE_SELECT ... +#define SQLITE_TRANSACTION ... +#define SQLITE_UPDATE ... +#define SQLITE_ATTACH ... +#define SQLITE_DETACH ... +#define SQLITE_ALTER_TABLE ... +#define SQLITE_REINDEX ... +#define SQLITE_ANALYZE ... +#define SQLITE_CREATE_VTABLE ... +#define SQLITE_DROP_VTABLE ... +#define SQLITE_FUNCTION ... -_lib.SQLITE_UTF8 = 1 +const char *sqlite3_libversion(void); -_lib.SQLITE_TRANSIENT = cast(-1, c_void_p) +typedef ... sqlite3; +typedef ... sqlite3_stmt; +typedef ... sqlite3_context; +typedef ... sqlite3_value; +typedef int64_t sqlite3_int64; +typedef uint64_t sqlite3_uint64; -SQLITE_OK = _lib.SQLITE_OK +int sqlite3_open( + const char *filename, /* Database filename (UTF-8) */ + sqlite3 **ppDb /* OUT: SQLite db handle */ +); -SQLITE_DENY = 1 -SQLITE_IGNORE = 2 +int sqlite3_close(sqlite3 *); -SQLITE_CREATE_INDEX = 1 -SQLITE_CREATE_TABLE = 2 -SQLITE_CREATE_TEMP_INDEX = 3 -SQLITE_CREATE_TEMP_TABLE = 4 -SQLITE_CREATE_TEMP_TRIGGER = 5 -SQLITE_CREATE_TEMP_VIEW = 6 -SQLITE_CREATE_TRIGGER = 7 -SQLITE_CREATE_VIEW = 8 -SQLITE_DELETE = 9 -SQLITE_DROP_INDEX = 10 -SQLITE_DROP_TABLE = 11 -SQLITE_DROP_TEMP_INDEX = 12 -SQLITE_DROP_TEMP_TABLE = 13 -SQLITE_DROP_TEMP_TRIGGER = 14 -SQLITE_DROP_TEMP_VIEW = 15 -SQLITE_DROP_TRIGGER = 16 -SQLITE_DROP_VIEW = 17 -SQLITE_INSERT = 18 -SQLITE_PRAGMA = 19 -SQLITE_READ = 20 -SQLITE_SELECT = 21 -SQLITE_TRANSACTION = 22 -SQLITE_UPDATE = 23 -SQLITE_ATTACH = 24 -SQLITE_DETACH = 25 -SQLITE_ALTER_TABLE = 26 -SQLITE_REINDEX = 27 -SQLITE_ANALYZE = 28 +int sqlite3_busy_timeout(sqlite3*, int ms); +int sqlite3_prepare_v2( + sqlite3 *db, /* Database handle */ + const char *zSql, /* SQL statement, UTF-8 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const char **pzTail /* OUT: Pointer to unused portion of zSql */ +); +int sqlite3_finalize(sqlite3_stmt *pStmt); +int sqlite3_column_count(sqlite3_stmt *pStmt); +const char *sqlite3_column_name(sqlite3_stmt*, int N); +int sqlite3_get_autocommit(sqlite3*); +int sqlite3_reset(sqlite3_stmt *pStmt); +int sqlite3_step(sqlite3_stmt*); +int sqlite3_errcode(sqlite3 *db); +const char *sqlite3_errmsg(sqlite3*); +int sqlite3_changes(sqlite3*); -# SQLite C API +int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); +int sqlite3_bind_double(sqlite3_stmt*, int, double); +int sqlite3_bind_int(sqlite3_stmt*, int, int); +int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); +int sqlite3_bind_null(sqlite3_stmt*, int); +int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*)); +int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); +int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); +int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); -_lib.sqlite3_value_int.argtypes = [c_void_p] -_lib.sqlite3_value_int.restype = c_int +const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); +int sqlite3_column_bytes(sqlite3_stmt*, int iCol); +double sqlite3_column_double(sqlite3_stmt*, int iCol); +int sqlite3_column_int(sqlite3_stmt*, int iCol); +sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol); +const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); +const void *sqlite3_column_text16(sqlite3_stmt*, int iCol); +int sqlite3_column_type(sqlite3_stmt*, int iCol); +const char *sqlite3_column_decltype(sqlite3_stmt*,int); -_lib.sqlite3_value_int64.argtypes = [c_void_p] -_lib.sqlite3_value_int64.restype = c_int64 +void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); +int sqlite3_create_collation( + sqlite3*, + const char *zName, + int eTextRep, + void*, + int(*xCompare)(void*,int,const void*,int,const void*) +); +int sqlite3_set_authorizer( + sqlite3*, + int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), + void *pUserData +); +int sqlite3_create_function( + sqlite3 *db, + const char *zFunctionName, + int nArg, + int eTextRep, + void *pApp, + void (*xFunc)(sqlite3_context*,int,sqlite3_value**), + void (*xStep)(sqlite3_context*,int,sqlite3_value**), + void (*xFinal)(sqlite3_context*) +); +void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); -_lib.sqlite3_value_blob.argtypes = [c_void_p] -_lib.sqlite3_value_blob.restype = c_void_p +sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); +int sqlite3_bind_parameter_count(sqlite3_stmt*); +const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); +int sqlite3_total_changes(sqlite3*); -_lib.sqlite3_value_bytes.argtypes = [c_void_p] -_lib.sqlite3_value_bytes.restype = c_int +int sqlite3_prepare( + sqlite3 *db, /* Database handle */ + const char *zSql, /* SQL statement, UTF-8 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const char **pzTail /* OUT: Pointer to unused portion of zSql */ +); -_lib.sqlite3_value_double.argtypes = [c_void_p] -_lib.sqlite3_value_double.restype = c_double +void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); +void sqlite3_result_double(sqlite3_context*, double); +void sqlite3_result_error(sqlite3_context*, const char*, int); +void sqlite3_result_error16(sqlite3_context*, const void*, int); +void sqlite3_result_error_toobig(sqlite3_context*); +void sqlite3_result_error_nomem(sqlite3_context*); +void sqlite3_result_error_code(sqlite3_context*, int); +void sqlite3_result_int(sqlite3_context*, int); +void sqlite3_result_int64(sqlite3_context*, sqlite3_int64); +void sqlite3_result_null(sqlite3_context*); +void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); +void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); +void sqlite3_result_text16le(sqlite3_context*,const void*, int,void(*)(void*)); +void sqlite3_result_text16be(sqlite3_context*,const void*, int,void(*)(void*)); +void sqlite3_result_value(sqlite3_context*, sqlite3_value*); +void sqlite3_result_zeroblob(sqlite3_context*, int n); -_lib.sqlite3_value_text.argtypes = [c_void_p] -_lib.sqlite3_value_text.restype = c_char_p +const void *sqlite3_value_blob(sqlite3_value*); +int sqlite3_value_bytes(sqlite3_value*); +int sqlite3_value_bytes16(sqlite3_value*); +double sqlite3_value_double(sqlite3_value*); +int sqlite3_value_int(sqlite3_value*); +sqlite3_int64 sqlite3_value_int64(sqlite3_value*); +const unsigned char *sqlite3_value_text(sqlite3_value*); +const void *sqlite3_value_text16(sqlite3_value*); +const void *sqlite3_value_text16le(sqlite3_value*); +const void *sqlite3_value_text16be(sqlite3_value*); +int sqlite3_value_type(sqlite3_value*); +int sqlite3_value_numeric_type(sqlite3_value*); +""") -_lib.sqlite3_value_type.argtypes = [c_void_p] -_lib.sqlite3_value_type.restype = c_int -_lib.sqlite3_bind_blob.argtypes = [c_void_p, c_int, c_void_p, c_int, c_void_p] -_lib.sqlite3_bind_blob.restype = c_int -_lib.sqlite3_bind_double.argtypes = [c_void_p, c_int, c_double] -_lib.sqlite3_bind_double.restype = c_int -_lib.sqlite3_bind_int.argtypes = [c_void_p, c_int, c_int] -_lib.sqlite3_bind_int.restype = c_int -_lib.sqlite3_bind_int64.argtypes = [c_void_p, c_int, c_int64] -_lib.sqlite3_bind_int64.restype = c_int -_lib.sqlite3_bind_null.argtypes = [c_void_p, c_int] -_lib.sqlite3_bind_null.restype = c_int -_lib.sqlite3_bind_parameter_count.argtypes = [c_void_p] -_lib.sqlite3_bind_parameter_count.restype = c_int -_lib.sqlite3_bind_parameter_index.argtypes = [c_void_p, c_char_p] -_lib.sqlite3_bind_parameter_index.restype = c_int -_lib.sqlite3_bind_parameter_name.argtypes = [c_void_p, c_int] -_lib.sqlite3_bind_parameter_name.restype = c_char_p -_lib.sqlite3_bind_text.argtypes = [c_void_p, c_int, c_char_p, c_int, c_void_p] -_lib.sqlite3_bind_text.restype = c_int -_lib.sqlite3_busy_timeout.argtypes = [c_void_p, c_int] -_lib.sqlite3_busy_timeout.restype = c_int -_lib.sqlite3_changes.argtypes = [c_void_p] -_lib.sqlite3_changes.restype = c_int -_lib.sqlite3_close.argtypes = [c_void_p] -_lib.sqlite3_close.restype = c_int -_lib.sqlite3_column_blob.argtypes = [c_void_p, c_int] -_lib.sqlite3_column_blob.restype = c_void_p -_lib.sqlite3_column_bytes.argtypes = [c_void_p, c_int] -_lib.sqlite3_column_bytes.restype = c_int -_lib.sqlite3_column_count.argtypes = [c_void_p] -_lib.sqlite3_column_count.restype = c_int -_lib.sqlite3_column_decltype.argtypes = [c_void_p, c_int] -_lib.sqlite3_column_decltype.restype = c_char_p -_lib.sqlite3_column_double.argtypes = [c_void_p, c_int] -_lib.sqlite3_column_double.restype = c_double -_lib.sqlite3_column_int64.argtypes = [c_void_p, c_int] -_lib.sqlite3_column_int64.restype = c_int64 -_lib.sqlite3_column_name.argtypes = [c_void_p, c_int] -_lib.sqlite3_column_name.restype = c_char_p -_lib.sqlite3_column_text.argtypes = [c_void_p, c_int] -_lib.sqlite3_column_text.restype = POINTER(c_char) -_lib.sqlite3_column_type.argtypes = [c_void_p, c_int] -_lib.sqlite3_column_type.restype = c_int -_lib.sqlite3_complete.argtypes = [c_char_p] -_lib.sqlite3_complete.restype = c_int -_lib.sqlite3_errcode.restype = c_int -_lib.sqlite3_errmsg.argtypes = [c_void_p] -_lib.sqlite3_errmsg.restype = c_char_p -_lib.sqlite3_finalize.argtypes = [c_void_p] -_lib.sqlite3_finalize.restype = c_int -_lib.sqlite3_get_autocommit.argtypes = [c_void_p] -_lib.sqlite3_get_autocommit.restype = c_int -_lib.sqlite3_last_insert_rowid.argtypes = [c_void_p] -_lib.sqlite3_last_insert_rowid.restype = c_int64 -_lib.sqlite3_libversion.argtypes = [] -_lib.sqlite3_libversion.restype = c_char_p -_lib.sqlite3_open.argtypes = [c_char_p, c_void_p] -_lib.sqlite3_open.restype = c_int -_lib.sqlite3_prepare.argtypes = [c_void_p, c_char_p, c_int, c_void_p, POINTER(c_char_p)] -_lib.sqlite3_prepare.restype = c_int -_lib.sqlite3_prepare_v2.argtypes = [c_void_p, c_char_p, c_int, c_void_p, POINTER(c_char_p)] -_lib.sqlite3_prepare_v2.restype = c_int -_lib.sqlite3_step.argtypes = [c_void_p] -_lib.sqlite3_step.restype = c_int -_lib.sqlite3_reset.argtypes = [c_void_p] -_lib.sqlite3_reset.restype = c_int -_lib.sqlite3_total_changes.argtypes = [c_void_p] -_lib.sqlite3_total_changes.restype = c_int +def _has_load_extension(): + """Only available since 3.3.6""" + unverified_ffi = FFI() + unverified_ffi.cdef(""" + typedef ... sqlite3; + int sqlite3_enable_load_extension(sqlite3 *db, int onoff); + """) + unverified_lib = unverified_ffi.dlopen('sqlite3') + return hasattr(unverified_lib, 'sqlite3_enable_load_extension') -_lib.sqlite3_result_blob.argtypes = [c_void_p, c_void_p, c_int, c_void_p] -_lib.sqlite3_result_blob.restype = None -_lib.sqlite3_result_int64.argtypes = [c_void_p, c_int64] -_lib.sqlite3_result_int64.restype = None -_lib.sqlite3_result_null.argtypes = [c_void_p] -_lib.sqlite3_result_null.restype = None -_lib.sqlite3_result_double.argtypes = [c_void_p, c_double] -_lib.sqlite3_result_double.restype = None -_lib.sqlite3_result_error.argtypes = [c_void_p, c_char_p, c_int] -_lib.sqlite3_result_error.restype = None -_lib.sqlite3_result_text.argtypes = [c_void_p, c_char_p, c_int, c_void_p] -_lib.sqlite3_result_text.restype = None -_HAS_LOAD_EXTENSION = hasattr(_lib, "sqlite3_enable_load_extension") -if _HAS_LOAD_EXTENSION: - _lib.sqlite3_enable_load_extension.argtypes = [c_void_p, c_int] - _lib.sqlite3_enable_load_extension.restype = c_int +if _has_load_extension(): + ffi.cdef("int sqlite3_enable_load_extension(sqlite3 *db, int onoff);") -########################################## -# END Wrapped SQLite C API and constants -########################################## +lib = ffi.verify(""" +#include +""", libraries=['sqlite3']) + +exported_sqlite_symbols = [ + 'SQLITE_ALTER_TABLE', + 'SQLITE_ANALYZE', + 'SQLITE_ATTACH', + 'SQLITE_CREATE_INDEX', + 'SQLITE_CREATE_TABLE', + 'SQLITE_CREATE_TEMP_INDEX', + 'SQLITE_CREATE_TEMP_TABLE', + 'SQLITE_CREATE_TEMP_TRIGGER', + 'SQLITE_CREATE_TEMP_VIEW', + 'SQLITE_CREATE_TRIGGER', + 'SQLITE_CREATE_VIEW', + 'SQLITE_DELETE', + 'SQLITE_DENY', + 'SQLITE_DETACH', + 'SQLITE_DROP_INDEX', + 'SQLITE_DROP_TABLE', + 'SQLITE_DROP_TEMP_INDEX', + 'SQLITE_DROP_TEMP_TABLE', + 'SQLITE_DROP_TEMP_TRIGGER', + 'SQLITE_DROP_TEMP_VIEW', + 'SQLITE_DROP_TRIGGER', + 'SQLITE_DROP_VIEW', + 'SQLITE_IGNORE', + 'SQLITE_INSERT', + 'SQLITE_OK', + 'SQLITE_PRAGMA', + 'SQLITE_READ', + 'SQLITE_REINDEX', + 'SQLITE_SELECT', + 'SQLITE_TRANSACTION', + 'SQLITE_UPDATE', +] + +for symbol in exported_sqlite_symbols: + globals()[symbol] = getattr(lib, symbol) + +_SQLITE_TRANSIENT = ffi.cast('void *', lib.SQLITE_TRANSIENT) + # pysqlite version information version = "2.6.0" @@ -257,7 +310,7 @@ PARSE_DECLTYPES = 2 # SQLite version information -sqlite_version = str(_lib.sqlite3_libversion().decode('ascii')) +sqlite_version = ffi.string(lib.sqlite3_libversion()) class Error(StandardError): @@ -334,48 +387,36 @@ if len(self.cache) > self.maxcount: self.cache.popitem(0) - if stat._in_use: + if stat.in_use: stat = Statement(self.connection, sql) - stat._row_factory = row_factory + stat.set_row_factory(row_factory) return stat class Connection(object): - __initialized = False - _db = None - - def __init__(self, database, timeout=5.0, detect_types=0, isolation_level="", - check_same_thread=True, factory=None, cached_statements=100): - self.__initialized = True - self._db = c_void_p() - + def __init__(self, database, timeout=5.0, detect_types=0, + isolation_level="", check_same_thread=True, factory=None, + cached_statements=100): + db_star = ffi.new('sqlite3 **') if isinstance(database, unicode): database = database.encode('utf-8') - if _lib.sqlite3_open(database, byref(self._db)) != _lib.SQLITE_OK: + if lib.sqlite3_open(database, db_star) != lib.SQLITE_OK: raise OperationalError("Could not open database") + self.db = db_star[0] if timeout is not None: timeout = int(timeout * 1000) # pysqlite2 uses timeout in seconds - _lib.sqlite3_busy_timeout(self._db, timeout) + lib.sqlite3_busy_timeout(self.db, timeout) + self.text_factory = _unicode_text_factory + self.closed = False + self.statements = [] + self.statement_counter = 0 self.row_factory = None - self.text_factory = _unicode_text_factory + self._isolation_level = isolation_level + self.detect_types = detect_types + self.statement_cache = _StatementCache(self, cached_statements) - self._detect_types = detect_types - self._in_transaction = False - self.isolation_level = isolation_level - - self.__cursors = [] - self.__cursors_counter = 0 - self.__statements = [] - self.__statements_counter = 0 - self._statement_cache = _StatementCache(self, cached_statements) - - self.__func_cache = {} - self.__aggregates = {} - self.__aggregate_instances = {} - self.__collations = {} - if check_same_thread: - self.__thread_ident = _thread_get_ident() + self.cursors = [] self.Error = Error self.Warning = Warning @@ -388,25 +429,30 @@ self.DataError = DataError self.NotSupportedError = NotSupportedError - def __del__(self): - if self._db: - _lib.sqlite3_close(self._db) + self.func_cache = {} + self._aggregates = {} + self.aggregate_instances = {} + self._collations = {} + if check_same_thread: + self.thread_ident = _thread_get_ident() def close(self): self._check_thread() + if self.closed: + return + for statement in self.statements: + obj = statement() + if obj is not None: + obj.finalize() - self.__do_all_statements(Statement._finalize, True) - - if self._db: - ret = _lib.sqlite3_close(self._db) - if ret != _lib.SQLITE_OK: - raise self._get_exception(ret) - self._db = None + self.closed = True + ret = lib.sqlite3_close(self.db) + self._reset_cursors() + if ret != lib.SQLITE_OK: + raise self._get_exception(ret) def _check_closed(self): - if not self.__initialized: - raise ProgrammingError("Base Connection.__init__ not called.") - if not self._db: + if getattr(self, 'closed', True): raise ProgrammingError("Cannot operate on a closed database.") def _check_closed_wrap(func): @@ -417,16 +463,13 @@ return wrapper def _check_thread(self): - try: - if self.__thread_ident == _thread_get_ident(): - return - except AttributeError: - pass - else: + if not hasattr(self, 'thread_ident'): + return + if self.thread_ident != _thread_get_ident(): raise ProgrammingError( "SQLite objects created in a thread can only be used in that " "same thread. The object was created in thread id %d and this " - "is thread id %d", self.__thread_ident, _thread_get_ident()) + "is thread id %d", self.thread_ident, _thread_get_ident()) def _check_thread_wrap(func): @wraps(func) @@ -437,29 +480,29 @@ def _get_exception(self, error_code=None): if error_code is None: - error_code = _lib.sqlite3_errcode(self._db) - error_message = _lib.sqlite3_errmsg(self._db).decode('utf-8') + error_code = lib.sqlite3_errcode(self.db) + error_message = ffi.string(lib.sqlite3_errmsg(self.db)) - if error_code == _lib.SQLITE_OK: - raise ValueError("error signalled but got SQLITE_OK") - elif error_code in (_lib.SQLITE_INTERNAL, _lib.SQLITE_NOTFOUND): + if error_code == lib.SQLITE_OK: + raise ValueError("error signalled but got lib.SQLITE_OK") + elif error_code in (lib.SQLITE_INTERNAL, lib.SQLITE_NOTFOUND): exc = InternalError - elif error_code == _lib.SQLITE_NOMEM: + elif error_code == lib.SQLITE_NOMEM: exc = MemoryError elif error_code in ( - _lib.SQLITE_ERROR, _lib.SQLITE_PERM, _lib.SQLITE_ABORT, - _lib.SQLITE_BUSY, _lib.SQLITE_LOCKED, _lib.SQLITE_READONLY, - _lib.SQLITE_INTERRUPT, _lib.SQLITE_IOERR, _lib.SQLITE_FULL, - _lib.SQLITE_CANTOPEN, _lib.SQLITE_PROTOCOL, _lib.SQLITE_EMPTY, - _lib.SQLITE_SCHEMA): + lib.SQLITE_ERROR, lib.SQLITE_PERM, lib.SQLITE_ABORT, + lib.SQLITE_BUSY, lib.SQLITE_LOCKED, lib.SQLITE_READONLY, + lib.SQLITE_INTERRUPT, lib.SQLITE_IOERR, lib.SQLITE_FULL, + lib.SQLITE_CANTOPEN, lib.SQLITE_PROTOCOL, lib.SQLITE_EMPTY, + lib.SQLITE_SCHEMA): exc = OperationalError - elif error_code == _lib.SQLITE_CORRUPT: + elif error_code == lib.SQLITE_CORRUPT: exc = DatabaseError - elif error_code == _lib.SQLITE_TOOBIG: + elif error_code == lib.SQLITE_TOOBIG: exc = DataError - elif error_code in (_lib.SQLITE_CONSTRAINT, _lib.SQLITE_MISMATCH): + elif error_code in (lib.SQLITE_CONSTRAINT, lib.SQLITE_MISMATCH): exc = IntegrityError - elif error_code == _lib.SQLITE_MISUSE: + elif error_code == lib.SQLITE_MISUSE: exc = ProgrammingError else: exc = DatabaseError @@ -467,38 +510,26 @@ exc.error_code = error_code return exc - def _remember_cursor(self, cursor): - self.__cursors.append(weakref.ref(cursor)) - self.__cursors_counter += 1 - if self.__cursors_counter < 200: - return - self.__cursors_counter = 0 - self.__cursors = [r for r in self.__cursors if r() is not None] + def _remember_statement(self, statement): + self.statements.append(weakref.ref(statement)) + self.statement_counter += 1 - def _remember_statement(self, statement): - self.__statements.append(weakref.ref(statement)) - self.__statements_counter += 1 - if self.__statements_counter < 200: - return - self.__statements_counter = 0 - self.__statements = [r for r in self.__statements if r() is not None] + if self.statement_counter % 100 == 0: + self.statements = [ref for ref in self.statements + if ref() is not None] - def __do_all_statements(self, action, reset_cursors): - for weakref in self.__statements: - statement = weakref() - if statement is not None: - action(statement) - - if reset_cursors: - for weakref in self.__cursors: - cursor = weakref() - if cursor is not None: - cursor._reset = True + def _reset_cursors(self): + for cursor_ref in self.cursors: + cursor = cursor_ref() + if cursor: + cursor.reset = True @_check_thread_wrap @_check_closed_wrap def __call__(self, sql): - return self._statement_cache.get(sql, self.row_factory) + if not isinstance(sql, basestring): + raise Warning("SQL is of wrong type. Must be string or unicode.") + return self.statement_cache.get(sql, self.row_factory) def cursor(self, factory=None): self._check_thread() @@ -527,60 +558,73 @@ return _iterdump(self) def _begin(self): - statement = c_void_p() - ret = _lib.sqlite3_prepare_v2(self._db, self.__begin_statement, -1, - byref(statement), None) + self._check_closed() + if self._isolation_level is None: + return + if not lib.sqlite3_get_autocommit(self.db): + return + sql = "BEGIN " + self._isolation_level + statement_star = ffi.new('sqlite3_stmt **') + next_char = ffi.new('char **') + ret = lib.sqlite3_prepare_v2(self.db, sql, -1, statement_star, + next_char) try: - if ret != _lib.SQLITE_OK: + if ret != lib.SQLITE_OK: raise self._get_exception(ret) - ret = _lib.sqlite3_step(statement) - if ret != _lib.SQLITE_DONE: + ret = lib.sqlite3_step(statement_star[0]) + if ret != lib.SQLITE_DONE: raise self._get_exception(ret) - self._in_transaction = True finally: - _lib.sqlite3_finalize(statement) + lib.sqlite3_finalize(statement_star[0]) def commit(self): self._check_thread() self._check_closed() - if not self._in_transaction: + if lib.sqlite3_get_autocommit(self.db): return - self.__do_all_statements(Statement._reset, False) + for statement in self.statements: + obj = statement() + if obj is not None: + obj.reset() - statement = c_void_p() - ret = _lib.sqlite3_prepare_v2(self._db, b"COMMIT", -1, - byref(statement), None) + statement_star = ffi.new('sqlite3_stmt **') + next_char = ffi.new('char **') + ret = lib.sqlite3_prepare_v2(self.db, b"COMMIT", -1, statement_star, + next_char) try: - if ret != _lib.SQLITE_OK: + if ret != lib.SQLITE_OK: raise self._get_exception(ret) - ret = _lib.sqlite3_step(statement) - if ret != _lib.SQLITE_DONE: + ret = lib.sqlite3_step(statement_star[0]) + if ret != lib.SQLITE_DONE: raise self._get_exception(ret) - self._in_transaction = False finally: - _lib.sqlite3_finalize(statement) + lib.sqlite3_finalize(statement_star[0]) def rollback(self): self._check_thread() self._check_closed() - if not self._in_transaction: + if lib.sqlite3_get_autocommit(self.db): return - self.__do_all_statements(Statement._reset, True) + for statement in self.statements: + obj = statement() + if obj is not None: + obj.reset() - statement = c_void_p() - ret = _lib.sqlite3_prepare_v2(self._db, b"ROLLBACK", -1, - byref(statement), None) + statement_star = ffi.new('sqlite3_stmt **') + next_char = ffi.new('char **') + ret = lib.sqlite3_prepare_v2(self.db, b"ROLLBACK", -1, statement_star, + next_char) try: - if ret != _lib.SQLITE_OK: + if ret != lib.SQLITE_OK: raise self._get_exception(ret) - ret = _lib.sqlite3_step(statement) - if ret != _lib.SQLITE_DONE: + ret = lib.sqlite3_step(statement_star[0]) + if ret != lib.SQLITE_DONE: raise self._get_exception(ret) - self._in_transaction = False finally: - _lib.sqlite3_finalize(statement) + lib.sqlite3_finalize(statement_star[0]) + self._reset_cursors() def __enter__(self): return self @@ -595,34 +639,29 @@ @_check_closed_wrap def create_function(self, name, num_args, callback): try: - c_closure, _ = self.__func_cache[callback] + closure = self.func_cache[callback] except KeyError: + @ffi.callback("void(sqlite3_context*, int, sqlite3_value**)") def closure(context, nargs, c_params): _function_callback(callback, context, nargs, c_params) - c_closure = _FUNC(closure) - self.__func_cache[callback] = c_closure, closure - - if isinstance(name, unicode): - name = name.encode('utf-8') - ret = _lib.sqlite3_create_function(self._db, name, num_args, - _lib.SQLITE_UTF8, None, - c_closure, - cast(None, _STEP), - cast(None, _FINAL)) - if ret != _lib.SQLITE_OK: + self.func_cache[callback] = closure + ret = lib.sqlite3_create_function(self.db, name, num_args, + lib.SQLITE_UTF8, ffi.NULL, + closure, ffi.NULL, ffi.NULL) + if ret != lib.SQLITE_OK: raise self.OperationalError("Error creating function") @_check_thread_wrap @_check_closed_wrap def create_aggregate(self, name, num_args, cls): try: - c_step_callback, c_final_callback, _, _ = self.__aggregates[cls] + step_callback, final_callback = self._aggregates[cls] except KeyError: + @ffi.callback("void(sqlite3_context*, int, sqlite3_value**)") def step_callback(context, argc, c_params): - aggregate_ptr = cast( - _lib.sqlite3_aggregate_context( - context, sizeof(c_ssize_t)), - POINTER(c_ssize_t)) + res = lib.sqlite3_aggregate_context(context, + ffi.sizeof("size_t")) + aggregate_ptr = ffi.cast("size_t[1]", res) if not aggregate_ptr[0]: try: @@ -630,13 +669,13 @@ except Exception: msg = (b"user-defined aggregate's '__init__' " b"method raised error") - _lib.sqlite3_result_error(context, msg, len(msg)) + lib.sqlite3_result_error(context, msg, len(msg)) return aggregate_id = id(aggregate) - self.__aggregate_instances[aggregate_id] = aggregate + self.aggregate_instances[aggregate_id] = aggregate aggregate_ptr[0] = aggregate_id else: - aggregate = self.__aggregate_instances[aggregate_ptr[0]] + aggregate = self.aggregate_instances[aggregate_ptr[0]] params = _convert_params(context, argc, c_params) try: @@ -644,41 +683,33 @@ except Exception: msg = (b"user-defined aggregate's 'step' " b"method raised error") - _lib.sqlite3_result_error(context, msg, len(msg)) + lib.sqlite3_result_error(context, msg, len(msg)) + @ffi.callback("void(sqlite3_context*)") def final_callback(context): - aggregate_ptr = cast( - _lib.sqlite3_aggregate_context( - context, sizeof(c_ssize_t)), - POINTER(c_ssize_t)) + res = lib.sqlite3_aggregate_context(context, + ffi.sizeof("size_t")) + aggregate_ptr = ffi.cast("size_t[1]", res) if aggregate_ptr[0]: - aggregate = self.__aggregate_instances[aggregate_ptr[0]] + aggregate = self.aggregate_instances[aggregate_ptr[0]] try: val = aggregate.finalize() except Exception: msg = (b"user-defined aggregate's 'finalize' " b"method raised error") - _lib.sqlite3_result_error(context, msg, len(msg)) + lib.sqlite3_result_error(context, msg, len(msg)) else: _convert_result(context, val) finally: - del self.__aggregate_instances[aggregate_ptr[0]] + del self.aggregate_instances[aggregate_ptr[0]] - c_step_callback = _STEP(step_callback) - c_final_callback = _FINAL(final_callback) + self._aggregates[cls] = step_callback, final_callback - self.__aggregates[cls] = (c_step_callback, c_final_callback, - step_callback, final_callback) - - if isinstance(name, unicode): - name = name.encode('utf-8') - ret = _lib.sqlite3_create_function(self._db, name, num_args, - _lib.SQLITE_UTF8, None, - cast(None, _FUNC), - c_step_callback, - c_final_callback) - if ret != _lib.SQLITE_OK: + ret = lib.sqlite3_create_function(self.db, name, num_args, + lib.SQLITE_UTF8, ffi.NULL, ffi.NULL, + step_callback, final_callback) + if ret != lib.SQLITE_OK: raise self._get_exception(ret) @_check_thread_wrap @@ -689,60 +720,55 @@ raise ProgrammingError("invalid character in collation name") if callback is None: - del self.__collations[name] - c_collation_callback = cast(None, _COLLATION) + del self._collations[name] + collation_callback = ffi.NULL else: if not callable(callback): raise TypeError("parameter must be callable") + @ffi.callback("int(void*, int, const void*, int, const void*)") def collation_callback(context, len1, str1, len2, str2): - text1 = string_at(str1, len1).decode('utf-8') - text2 = string_at(str2, len2).decode('utf-8') + text1 = ffi.buffer(str1, len1)[:] + text2 = ffi.buffer(str2, len2)[:] return callback(text1, text2) - c_collation_callback = _COLLATION(collation_callback) - self.__collations[name] = c_collation_callback + self._collations[name] = collation_callback - if isinstance(name, unicode): - name = name.encode('utf-8') - ret = _lib.sqlite3_create_collation(self._db, name, - _lib.SQLITE_UTF8, - None, - c_collation_callback) - if ret != _lib.SQLITE_OK: + ret = lib.sqlite3_create_collation(self.db, name, lib.SQLITE_UTF8, + ffi.NULL, collation_callback) + if ret != lib.SQLITE_OK: raise self._get_exception(ret) @_check_thread_wrap @_check_closed_wrap def set_authorizer(self, callback): try: - c_authorizer, _ = self.__func_cache[callback] + authorizer = self.func_cache[callback] except KeyError: + @ffi.callback("int(void*, int, const char*, const char*, " + "const char*, const char*)") def authorizer(userdata, action, arg1, arg2, dbname, source): try: return int(callback(action, arg1, arg2, dbname, source)) except Exception: - return SQLITE_DENY - c_authorizer = _AUTHORIZER(authorizer) + return lib.SQLITE_DENY + self.func_cache[callback] = authorizer - self.__func_cache[callback] = c_authorizer, authorizer - - ret = _lib.sqlite3_set_authorizer(self._db, - c_authorizer, - None) - if ret != _lib.SQLITE_OK: + ret = lib.sqlite3_set_authorizer(self.db, authorizer, ffi.NULL) + if ret != lib.SQLITE_OK: raise self._get_exception(ret) @_check_thread_wrap @_check_closed_wrap def set_progress_handler(self, callable, nsteps): if callable is None: - c_progress_handler = cast(None, _PROGRESS) + progress_handler = ffi.NULL else: try: - c_progress_handler, _ = self.__func_cache[callable] + progress_handler = self.func_cache[callable] except KeyError: + @ffi.callback("int(void*)") def progress_handler(userdata): try: ret = callable() @@ -750,23 +776,14 @@ except Exception: # abort query if error occurred return 1 - c_progress_handler = _PROGRESS(progress_handler) - self.__func_cache[callable] = c_progress_handler, progress_handler - ret = _lib.sqlite3_progress_handler(self._db, nsteps, - c_progress_handler, - None) - if ret != _lib.SQLITE_OK: - raise self._get_exception(ret) - - if sys.version_info[0] >= 3: - def __get_in_transaction(self): - return self._in_transaction - in_transaction = property(__get_in_transaction) + self.func_cache[callable] = progress_handler + lib.sqlite3_progress_handler(self.db, nsteps, progress_handler, + ffi.NULL) def __get_total_changes(self): self._check_closed() - return _lib.sqlite3_total_changes(self._db) + return lib.sqlite3_total_changes(self.db) total_changes = property(__get_total_changes) def __get_isolation_level(self): @@ -775,190 +792,193 @@ def __set_isolation_level(self, val): if val is None: self.commit() - else: - self.__begin_statement = str("BEGIN " + val).encode('utf-8') + if isinstance(val, unicode): + val = str(val) self._isolation_level = val isolation_level = property(__get_isolation_level, __set_isolation_level) - if _HAS_LOAD_EXTENSION: + if hasattr(lib, 'sqlite3_enable_load_extension'): @_check_thread_wrap @_check_closed_wrap def enable_load_extension(self, enabled): - rc = _lib.sqlite3_enable_load_extension(self._db, int(enabled)) - if rc != _lib.SQLITE_OK: + rc = lib.sqlite3_enable_load_extension(self.db, int(enabled)) + if rc != lib.SQLITE_OK: raise OperationalError("Error enabling load extension") +DML, DQL, DDL = range(3) + + +class CursorLock(object): + def __init__(self, cursor): + self.cursor = cursor + + def __enter__(self): + if self.cursor.locked: + raise ProgrammingError("Recursive use of cursors not allowed.") + self.cursor.locked = True + + def __exit__(self, *args): + self.cursor.locked = False + + class Cursor(object): - __initialized = False - __statement = None - def __init__(self, con): if not isinstance(con, Connection): raise TypeError - self.__connection = con - + con._check_thread() + con._check_closed() + con.cursors.append(weakref.ref(self)) + self.connection = con + self._description = None self.arraysize = 1 self.row_factory = None - self._reset = False - self.__locked = False - self.__closed = False - self.__description = None - self.__rowcount = -1 + self.rowcount = -1 + self.statement = None + self.reset = False + self.locked = False - con._check_thread() - con._remember_cursor(self) + def _check_closed(self): + if not getattr(self, 'connection', None): + raise ProgrammingError("Cannot operate on a closed cursor.") + self.connection._check_thread() + self.connection._check_closed() - self.__initialized = True + def _check_and_lock(self): + self._check_closed() + return CursorLock(self) - def __del__(self): - if self.__statement: - self.__statement._reset() + def execute(self, sql, params=None): + if type(sql) is unicode: + sql = sql.encode("utf-8") - def close(self): - self.__connection._check_thread() - self.__connection._check_closed() - if self.__statement: - self.__statement._reset() - self.__statement = None - self.__closed = True - - def __check_cursor(self): - if not self.__initialized: - raise ProgrammingError("Base Cursor.__init__ not called.") - if self.__closed: - raise ProgrammingError("Cannot operate on a closed cursor.") - if self.__locked: - raise ProgrammingError("Recursive use of cursors not allowed.") - self.__connection._check_thread() - self.__connection._check_closed() - - def __check_cursor_wrap(func): - @wraps(func) - def wrapper(self, *args, **kwargs): - self.__check_cursor() - return func(self, *args, **kwargs) - return wrapper - - def __execute(self, multiple, sql, many_params): - self.__locked = True - try: - self._reset = False - if not isinstance(sql, basestring): - raise ValueError("operation parameter must be str or unicode") - self.__description = None - self.__rowcount = -1 - self.__statement = self.__connection._statement_cache.get( + with self._check_and_lock(): + self._description = None + self.reset = False + self.statement = self.connection.statement_cache.get( sql, self.row_factory) - if self.__connection._isolation_level is not None: - if self.__statement._kind == Statement._DDL: - if self.__connection._in_transaction: - self.__connection.commit() - elif self.__statement._kind == Statement._DML: - if not self.__connection._in_transaction: - self.__connection._begin() + if self.connection._isolation_level is not None: + if self.statement.kind == DDL: + self.connection.commit() + elif self.statement.kind == DML: + self.connection._begin() - if multiple and self.__statement._kind != Statement._DML: - raise ProgrammingError("executemany is only for DML statements") + self.statement.set_params(params) - for params in many_params: - self.__statement._set_params(params) + # Actually execute the SQL statement + ret = lib.sqlite3_step(self.statement.statement) + if ret not in (lib.SQLITE_DONE, lib.SQLITE_ROW): + self.statement.reset() + raise self.connection._get_exception(ret) - # Actually execute the SQL statement - ret = _lib.sqlite3_step(self.__statement._statement) - if ret not in (_lib.SQLITE_DONE, _lib.SQLITE_ROW): - self.__statement._reset() - self.__connection._in_transaction = \ - not _lib.sqlite3_get_autocommit(self.__connection._db) - raise self.__connection._get_exception(ret) + if self.statement.kind == DML: + self.statement.reset() - if self.__statement._kind == Statement._DML: - self.__statement._reset() + if self.statement.kind == DQL and ret == lib.SQLITE_ROW: + self.statement._build_row_cast_map() + self.statement._readahead(self) + else: + self.statement.item = None + self.statement.exhausted = True - if self.__statement._kind == Statement._DQL and ret == _lib.SQLITE_ROW: - self.__statement._build_row_cast_map() - self.__statement._readahead(self) + self.rowcount = -1 + if self.statement.kind == DML: + self.rowcount = lib.sqlite3_changes(self.connection.db) - if self.__statement._kind == Statement._DML: - if self.__rowcount == -1: - self.__rowcount = 0 - self.__rowcount += _lib.sqlite3_changes(self.__connection._db) - finally: - self.__locked = False return self - @__check_cursor_wrap - def execute(self, sql, params=[]): - return self.__execute(False, sql, [params]) + def executemany(self, sql, many_params): + if type(sql) is unicode: + sql = sql.encode("utf-8") - @__check_cursor_wrap - def executemany(self, sql, many_params): - return self.__execute(True, sql, many_params) + with self._check_and_lock(): + self._description = None + self.reset = False + self.statement = self.connection.statement_cache.get( + sql, self.row_factory) + + if self.statement.kind == DML: + self.connection._begin() + else: + raise ProgrammingError( + "executemany is only for DML statements") + + self.rowcount = 0 + for params in many_params: + self.statement.set_params(params) + ret = lib.sqlite3_step(self.statement.statement) + if ret != lib.SQLITE_DONE: + raise self.connection._get_exception(ret) + self.rowcount += lib.sqlite3_changes(self.connection.db) + + return self def executescript(self, sql): - self.__check_cursor() - self._reset = False - if isinstance(sql, unicode): - sql = sql.encode('utf-8') - elif not isinstance(sql, str): - raise ValueError("script argument must be unicode or string.") - sql = c_char_p(sql) - statement = c_void_p() + self._description = None + self.reset = False + if type(sql) is unicode: + sql = sql.encode("utf-8") + self._check_closed() + statement_star = ffi.new('sqlite3_stmt **') + tail = ffi.new('char **') - self.__connection.commit() + self.connection.commit() while True: - rc = _lib.sqlite3_prepare(self.__connection._db, sql, -1, - byref(statement), byref(sql)) - if rc != _lib.SQLITE_OK: - raise self.__connection._get_exception(rc) + rc = lib.sqlite3_prepare(self.connection.db, sql, -1, + statement_star, tail) + sql = ffi.string(tail[0]) + if rc != lib.SQLITE_OK: + raise self.connection._get_exception(rc) - rc = _lib.SQLITE_ROW - while rc == _lib.SQLITE_ROW: - if not statement: - rc = _lib.SQLITE_OK + rc = lib.SQLITE_ROW + while rc == lib.SQLITE_ROW: + if not statement_star[0]: + rc = lib.SQLITE_OK else: - rc = _lib.sqlite3_step(statement) + rc = lib.sqlite3_step(statement_star[0]) - if rc != _lib.SQLITE_DONE: - _lib.sqlite3_finalize(statement) - if rc == _lib.SQLITE_OK: - break + if rc != lib.SQLITE_DONE: + lib.sqlite3_finalize(statement_star[0]) + if rc == lib.SQLITE_OK: + return self else: - raise self.__connection._get_exception(rc) + raise self.connection._get_exception(rc) + rc = lib.sqlite3_finalize(statement_star[0]) + if rc != lib.SQLITE_OK: + raise self.connection._get_exception(rc) - rc = _lib.sqlite3_finalize(statement) - if rc != _lib.SQLITE_OK: - raise self.__connection._get_exception(rc) - - if not sql.value: + if not sql: break return self - def __check_reset(self): - if self._reset: - raise self.__connection.InterfaceError( - "Cursor needed to be reset because of commit/rollback " - "and can no longer be fetched from.") + def __iter__(self): + return iter(self.fetchone, None) - def __iter__(self): - return self + def _check_reset(self): + if self.reset: + raise self.connection.InterfaceError( + "Cursor needed to be reset because of commit/rollback and can " + "no longer be fetched from.") - def __next__(self): - self.__check_cursor() - self.__check_reset() - if not self.__statement: - raise StopIteration - return self.__statement._next(self) + # do all statements + def fetchone(self): + self._check_closed() + self._check_reset() - if sys.version_info[0] < 3: - next = __next__ - del __next__ + if self.statement is None: + return None - def fetchone(self): - return next(self, None) + try: + return self.statement.next(self) + except StopIteration: + return None def fetchmany(self, size=None): + self._check_closed() + self._check_reset() + if self.statement is None: + return [] if size is None: size = self.arraysize lst = [] @@ -969,25 +989,29 @@ return lst def fetchall(self): + self._check_closed() + self._check_reset() + if self.statement is None: + return [] return list(self) - def __get_connection(self): - return self.__connection - connection = property(__get_connection) + def _getdescription(self): + if self._description is None: + self._description = self.statement._get_description() + return self._description - def __get_rowcount(self): - return self.__rowcount - rowcount = property(__get_rowcount) + def _getlastrowid(self): + return lib.sqlite3_last_insert_rowid(self.connection.db) - def __get_description(self): - if self.__description is None: - self.__description = self.__statement._get_description() - return self.__description - description = property(__get_description) - - def __get_lastrowid(self): - return _lib.sqlite3_last_insert_rowid(self.__connection._db) - lastrowid = property(__get_lastrowid) + def close(self): + if not self.connection: + return + self._check_closed() + if self.statement: + self.statement.reset() + self.statement = None + self.connection.cursors.remove(weakref.ref(self)) + self.connection = None def setinputsizes(self, *args): pass @@ -995,71 +1019,92 @@ def setoutputsize(self, *args): pass + description = property(_getdescription) + lastrowid = property(_getlastrowid) + class Statement(object): - _DML, _DQL, _DDL = range(3) - - _statement = None - def __init__(self, connection, sql): - self.__con = connection - self.__con._remember_statement(self) - - if not isinstance(sql, basestring): - raise Warning("SQL is of wrong type. Must be string or unicode.") + self.statement = ffi.NULL + if not isinstance(sql, str): + raise ValueError("sql must be a string") + self.con = connection + self.sql = sql # DEBUG ONLY first_word = self._statement_kind = sql.lstrip().split(" ")[0].upper() if first_word in ("INSERT", "UPDATE", "DELETE", "REPLACE"): - self._kind = Statement._DML + self.kind = DML elif first_word in ("SELECT", "PRAGMA"): - self._kind = Statement._DQL + self.kind = DQL else: - self._kind = Statement._DDL + self.kind = DDL + self.exhausted = False + self.in_use = False + # + # set by set_row_factory + self.row_factory = None - self._in_use = False - self._row_factory = None + statement_star = ffi.new('sqlite3_stmt **') + next_char = ffi.new('char **') + ret = lib.sqlite3_prepare_v2(self.con.db, sql, -1, + statement_star, next_char) + self.statement = statement_star[0] + if ret == lib.SQLITE_OK and not self.statement: + # an empty statement, we work around that as it's the least trouble + ret = lib.sqlite3_prepare_v2(self.con.db, "select 42", -1, + statement_star, next_char) + self.statement = statement_star[0] + self.kind = DQL - if isinstance(sql, unicode): - sql = sql.encode('utf-8') - sql = c_char_p(sql) - self._statement = c_void_p() + if ret != lib.SQLITE_OK: + raise self.con._get_exception(ret) + self.con._remember_statement(self) + if _check_remaining_sql(ffi.string(next_char[0])): + raise Warning("One and only one statement required: %r" % ( + next_char[0],)) + # sql_char should remain alive until here - ret = _lib.sqlite3_prepare_v2(self.__con._db, sql, -1, - byref(self._statement), byref(sql)) - if ret == _lib.SQLITE_OK and self._statement.value is None: - # an empty statement, work around that, as it's the least trouble - sql = c_char_p(b"select 42") - ret = _lib.sqlite3_prepare_v2(self.__con._db, sql, -1, - byref(self._statement), byref(sql)) - self._kind = Statement._DQL - if ret != _lib.SQLITE_OK: - raise self.__con._get_exception(ret) + self._build_row_cast_map() - sql = sql.value.decode('utf-8') - if _check_remaining_sql(sql): - raise Warning("You can only execute one statement at a time.") + def set_row_factory(self, row_factory): + self.row_factory = row_factory - def __del__(self): - if self._statement: - _lib.sqlite3_finalize(self._statement) + def _build_row_cast_map(self): + self.row_cast_map = [] + for i in xrange(lib.sqlite3_column_count(self.statement)): + converter = None - def _finalize(self): - if self._statement: - _lib.sqlite3_finalize(self._statement) - self._statement = None - self._in_use = False + if self.con.detect_types & PARSE_COLNAMES: + colname = lib.sqlite3_column_name(self.statement, i) + if colname != ffi.NULL: + colname = ffi.string(colname) + type_start = -1 + key = None + for pos in range(len(colname)): + if colname[pos] == '[': + type_start = pos + 1 + elif colname[pos] == ']' and type_start != -1: + key = colname[type_start:pos] + converter = converters[key.upper()] - def _reset(self): - if self._in_use and self._statement: - _lib.sqlite3_reset(self._statement) - self._in_use = False + if converter is None and self.con.detect_types & PARSE_DECLTYPES: + decltype = lib.sqlite3_column_decltype(self.statement, i) + if decltype is not ffi.NULL: + # if multiple words, use first, + # eg. "INTEGER NOT NULL" => "INTEGER" + decltype = ffi.string(decltype).split()[0] + if '(' in decltype: + decltype = decltype[:decltype.index('(')] + converter = converters.get(decltype.upper(), None) + + self.row_cast_map.append(converter) if sys.version_info[0] < 3: def __check_decodable(self, param): - if self.__con.text_factory in (unicode, OptimizedUnicode, - _unicode_text_factory): + if self.con.text_factory in (unicode, OptimizedUnicode, + _unicode_text_factory): for c in param: if ord(c) & 0x80 != 0: - raise self.__con.ProgrammingError( + raise self.con.ProgrammingError( "You must not use 8-bit bytestrings unless " "you use a text_factory that can interpret " "8-bit bytestrings (like text_factory = str). " @@ -1074,171 +1119,149 @@ param = adapt(param) if param is None: - rc = _lib.sqlite3_bind_null(self._statement, idx) + lib.sqlite3_bind_null(self.statement, idx) elif isinstance(param, (bool, int, long)): if -2147483648 <= param <= 2147483647: - rc = _lib.sqlite3_bind_int(self._statement, idx, param) + lib.sqlite3_bind_int(self.statement, idx, param) else: - rc = _lib.sqlite3_bind_int64(self._statement, idx, param) + lib.sqlite3_bind_int64(self.statement, idx, param) elif isinstance(param, float): - rc = _lib.sqlite3_bind_double(self._statement, idx, param) + lib.sqlite3_bind_double(self.statement, idx, param) elif isinstance(param, unicode): param = param.encode("utf-8") - rc = _lib.sqlite3_bind_text(self._statement, idx, param, - len(param), _lib.SQLITE_TRANSIENT) + lib.sqlite3_bind_text(self.statement, idx, param, len(param), + _SQLITE_TRANSIENT) elif isinstance(param, str): self.__check_decodable(param) - rc = _lib.sqlite3_bind_text(self._statement, idx, param, - len(param), _lib.SQLITE_TRANSIENT) + lib.sqlite3_bind_text(self.statement, idx, param, len(param), + _SQLITE_TRANSIENT) elif isinstance(param, (buffer, bytes)): - param = bytes(param) - rc = _lib.sqlite3_bind_blob(self._statement, idx, param, - len(param), _lib.SQLITE_TRANSIENT) + lib.sqlite3_bind_blob(self.statement, idx, str(param), len(param), + _SQLITE_TRANSIENT) else: - rc = -1 - return rc + raise InterfaceError( + "parameter type %s is not supported" % str(type(param))) - def _set_params(self, params): - self._in_use = True + def set_params(self, params): + ret = lib.sqlite3_reset(self.statement) + if ret != lib.SQLITE_OK: + raise self.con._get_exception(ret) + self.mark_dirty() - num_params_needed = _lib.sqlite3_bind_parameter_count(self._statement) - if isinstance(params, (tuple, list)) or \ - not isinstance(params, dict) and \ - hasattr(params, '__getitem__'): - try: - num_params = len(params) - except TypeError: - num_params = -1 - if num_params != num_params_needed: - raise ProgrammingError("Incorrect number of bindings supplied. " - "The current statement uses %d, and " - "there are %d supplied." % - (num_params_needed, num_params)) - for i in range(num_params): - rc = self.__set_param(i + 1, params[i]) - if rc != _lib.SQLITE_OK: - raise InterfaceError("Error binding parameter %d - " - "probably unsupported type." % i) - elif isinstance(params, dict): - for i in range(1, num_params_needed + 1): - param_name = _lib.sqlite3_bind_parameter_name(self._statement, i) - if param_name is None: - raise ProgrammingError("Binding %d has no name, but you " - "supplied a dictionary (which has " - "only names)." % i) - param_name = param_name.decode('utf-8')[1:] + if params is None: + if lib.sqlite3_bind_parameter_count(self.statement) != 0: + raise ProgrammingError("wrong number of arguments") + return + + params_type = None + if isinstance(params, dict): + params_type = dict + else: + params_type = list + + if params_type == list: + if len(params) != lib.sqlite3_bind_parameter_count(self.statement): + raise ProgrammingError("wrong number of arguments") + + for i in range(len(params)): + self.__set_param(i + 1, params[i]) + else: + param_count = lib.sqlite3_bind_parameter_count(self.statement) + for idx in range(1, param_count + 1): + param_name = lib.sqlite3_bind_parameter_name(self.statement, + idx) + if param_name == ffi.NULL: + raise ProgrammingError("need named parameters") + param_name = ffi.string(param_name)[1:] try: param = params[param_name] except KeyError: - raise ProgrammingError("You did not supply a value for " - "binding %d." % i) - rc = self.__set_param(i, param) - if rc != _lib.SQLITE_OK: - raise InterfaceError("Error binding parameter :%s - " - "probably unsupported type." % - param_name) - else: - raise ValueError("parameters are of unsupported type") + raise ProgrammingError("missing parameter '%s'" % param) + self.__set_param(idx, param) - def _build_row_cast_map(self): - if not self.__con._detect_types: - return - self.__row_cast_map = [] - for i in xrange(_lib.sqlite3_column_count(self._statement)): - converter = None + def next(self, cursor): + self.con._check_closed() + self.con._check_thread() + if self.exhausted: + raise StopIteration + item = self.item - if self.__con._detect_types & PARSE_COLNAMES: - colname = _lib.sqlite3_column_name(self._statement, i) - if colname is not None: - colname = colname.decode('utf-8') - type_start = -1 - key = None - for pos in range(len(colname)): - if colname[pos] == '[': - type_start = pos + 1 - elif colname[pos] == ']' and type_start != -1: - key = colname[type_start:pos] - converter = converters[key.upper()] + ret = lib.sqlite3_step(self.statement) + if ret == lib.SQLITE_DONE: + self.exhausted = True + self.item = None + elif ret != lib.SQLITE_ROW: + exc = self.con._get_exception(ret) + lib.sqlite3_reset(self.statement) + raise exc - if converter is None and self.__con._detect_types & PARSE_DECLTYPES: - decltype = _lib.sqlite3_column_decltype(self._statement, i) - if decltype is not None: - decltype = decltype.decode('utf-8') - # if multiple words, use first, eg. - # "INTEGER NOT NULL" => "INTEGER" - decltype = decltype.split()[0] - if '(' in decltype: - decltype = decltype[:decltype.index('(')] - converter = converters.get(decltype.upper(), None) - - self.__row_cast_map.append(converter) + self._readahead(cursor) + return item def _readahead(self, cursor): + self.column_count = lib.sqlite3_column_count(self.statement) row = [] - num_cols = _lib.sqlite3_column_count(self._statement) - for i in xrange(num_cols): - if self.__con._detect_types: - converter = self.__row_cast_map[i] + for i in xrange(self.column_count): + typ = lib.sqlite3_column_type(self.statement, i) + + converter = self.row_cast_map[i] + if converter is None: + if typ == lib.SQLITE_NULL: + val = None + elif typ == lib.SQLITE_INTEGER: + val = lib.sqlite3_column_int64(self.statement, i) + elif typ == lib.SQLITE_FLOAT: + val = lib.sqlite3_column_double(self.statement, i) + elif typ == lib.SQLITE_TEXT: + text = lib.sqlite3_column_text(self.statement, i) + text_len = lib.sqlite3_column_bytes(self.statement, i) + val = ffi.buffer(text, text_len)[:] + val = self.con.text_factory(val) + elif typ == lib.SQLITE_BLOB: + blob = lib.sqlite3_column_blob(self.statement, i) + blob_len = lib.sqlite3_column_bytes(self.statement, i) + val = _BLOB_TYPE(ffi.buffer(blob, blob_len)) else: - converter = None - - if converter is not None: - blob = _lib.sqlite3_column_blob(self._statement, i) + blob = lib.sqlite3_column_blob(self.statement, i) if not blob: val = None else: - blob_len = _lib.sqlite3_column_bytes(self._statement, i) - val = bytes(string_at(blob, blob_len)) + blob_len = lib.sqlite3_column_bytes(self.statement, i) + val = ffi.buffer(blob, blob_len)[:] val = converter(val) - else: - typ = _lib.sqlite3_column_type(self._statement, i) - if typ == _lib.SQLITE_NULL: - val = None - elif typ == _lib.SQLITE_INTEGER: - val = _lib.sqlite3_column_int64(self._statement, i) - val = int(val) - elif typ == _lib.SQLITE_FLOAT: - val = _lib.sqlite3_column_double(self._statement, i) - elif typ == _lib.SQLITE_TEXT: - text = _lib.sqlite3_column_text(self._statement, i) - text_len = _lib.sqlite3_column_bytes(self._statement, i) - val = string_at(text, text_len) - val = self.__con.text_factory(val) - elif typ == _lib.SQLITE_BLOB: - blob = _lib.sqlite3_column_blob(self._statement, i) - blob_len = _lib.sqlite3_column_bytes(self._statement, i) - val = _BLOB_TYPE(string_at(blob, blob_len)) row.append(val) row = tuple(row) - if self._row_factory is not None: - row = self._row_factory(cursor, row) - self._item = row + if self.row_factory is not None: + row = self.row_factory(cursor, row) + self.item = row - def _next(self, cursor): - try: - item = self._item - except AttributeError: - raise StopIteration - del self._item + def reset(self): + self.row_cast_map = None + ret = lib.sqlite3_reset(self.statement) + self.in_use = False + self.exhausted = False + return ret - ret = _lib.sqlite3_step(self._statement) - if ret not in (_lib.SQLITE_DONE, _lib.SQLITE_ROW): - _lib.sqlite3_reset(self._statement) - raise self.__con._get_exception(ret) - elif ret == _lib.SQLITE_ROW: - self._readahead(cursor) + def finalize(self): + lib.sqlite3_finalize(self.statement) + self.statement = ffi.NULL + self.in_use = False - return item + def mark_dirty(self): + self.in_use = True + + def __del__(self): + lib.sqlite3_finalize(self.statement) + self.statement = ffi.NULL def _get_description(self): - if self._kind == Statement._DML: + if self.kind == DML: return None desc = [] - for i in xrange(_lib.sqlite3_column_count(self._statement)): - name = _lib.sqlite3_column_name(self._statement, i) - if name is not None: - name = name.decode('utf-8').split("[")[0].strip() + for i in xrange(lib.sqlite3_column_count(self.statement)): + name = lib.sqlite3_column_name(self.statement, i) + name = ffi.string(name).split("[")[0].strip() desc.append((name, None, None, None, None, None, None)) return desc @@ -1323,21 +1346,20 @@ def _convert_params(con, nargs, params): _params = [] for i in range(nargs): - typ = _lib.sqlite3_value_type(params[i]) - if typ == _lib.SQLITE_NULL: + typ = lib.sqlite3_value_type(params[i]) + if typ == lib.SQLITE_NULL: val = None - elif typ == _lib.SQLITE_INTEGER: - val = _lib.sqlite3_value_int64(params[i]) - val = int(val) - elif typ == _lib.SQLITE_FLOAT: - val = _lib.sqlite3_value_double(params[i]) - elif typ == _lib.SQLITE_TEXT: - val = _lib.sqlite3_value_text(params[i]) - val = val.decode('utf-8') - elif typ == _lib.SQLITE_BLOB: - blob = _lib.sqlite3_value_blob(params[i]) - blob_len = _lib.sqlite3_value_bytes(params[i]) - val = _BLOB_TYPE(string_at(blob, blob_len)) + elif typ == lib.SQLITE_INTEGER: + val = lib.sqlite3_value_int64(params[i]) + elif typ == lib.SQLITE_FLOAT: + val = lib.sqlite3_value_double(params[i]) + elif typ == lib.SQLITE_TEXT: + val = lib.sqlite3_value_text(params[i]) + val = unicode(ffi.string(val), 'utf-8') + elif typ == lib.SQLITE_BLOB: + blob = lib.sqlite3_value_blob(params[i]) + blob_len = lib.sqlite3_value_bytes(params[i]) + val = _BLOB_TYPE(ffi.buffer(blob, blob_len)) else: raise NotImplementedError _params.append(val) @@ -1346,18 +1368,18 @@ def _convert_result(con, val): if val is None: - _lib.sqlite3_result_null(con) + lib.sqlite3_result_null(con) elif isinstance(val, (bool, int, long)): - _lib.sqlite3_result_int64(con, int(val)) + lib.sqlite3_result_int64(con, int(val)) elif isinstance(val, float): - _lib.sqlite3_result_double(con, val) + lib.sqlite3_result_double(con, val) elif isinstance(val, unicode): val = val.encode('utf-8') - _lib.sqlite3_result_text(con, val, len(val), _lib.SQLITE_TRANSIENT) + lib.sqlite3_result_text(con, val, len(val), _SQLITE_TRANSIENT) elif isinstance(val, str): - _lib.sqlite3_result_text(con, val, len(val), _lib.SQLITE_TRANSIENT) + lib.sqlite3_result_text(con, val, len(val), _SQLITE_TRANSIENT) elif isinstance(val, (buffer, bytes)): - _lib.sqlite3_result_blob(con, bytes(val), len(val), _lib.SQLITE_TRANSIENT) + lib.sqlite3_result_blob(con, str(val), len(val), _SQLITE_TRANSIENT) else: raise NotImplementedError @@ -1368,30 +1390,10 @@ val = real_cb(*params) except Exception: msg = b"user-defined function raised exception" - _lib.sqlite3_result_error(context, msg, len(msg)) + lib.sqlite3_result_error(context, msg, len(msg)) else: _convert_result(context, val) -_FUNC = CFUNCTYPE(None, c_void_p, c_int, POINTER(c_void_p)) -_STEP = CFUNCTYPE(None, c_void_p, c_int, POINTER(c_void_p)) -_FINAL = CFUNCTYPE(None, c_void_p) -_lib.sqlite3_create_function.argtypes = [c_void_p, c_char_p, c_int, c_int, c_void_p, _FUNC, _STEP, _FINAL] -_lib.sqlite3_create_function.restype = c_int - -_lib.sqlite3_aggregate_context.argtypes = [c_void_p, c_int] -_lib.sqlite3_aggregate_context.restype = c_void_p - -_COLLATION = CFUNCTYPE(c_int, c_void_p, c_int, c_void_p, c_int, c_void_p) -_lib.sqlite3_create_collation.argtypes = [c_void_p, c_char_p, c_int, c_void_p, _COLLATION] -_lib.sqlite3_create_collation.restype = c_int - -_PROGRESS = CFUNCTYPE(c_int, c_void_p) -_lib.sqlite3_progress_handler.argtypes = [c_void_p, c_int, _PROGRESS, c_void_p] -_lib.sqlite3_progress_handler.restype = c_int - -_AUTHORIZER = CFUNCTYPE(c_int, c_void_p, c_int, c_char_p, c_char_p, c_char_p, c_char_p) -_lib.sqlite3_set_authorizer.argtypes = [c_void_p, _AUTHORIZER, c_void_p] -_lib.sqlite3_set_authorizer.restype = c_int converters = {} adapters = {} From noreply at buildbot.pypy.org Wed Apr 3 16:27:57 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 3 Apr 2013 16:27:57 +0200 (CEST) Subject: [pypy-commit] pypy release-2.0-beta2: fix whatsnew Message-ID: <20130403142757.D061E1C06BD@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: release-2.0-beta2 Changeset: r62976:d56e3fdab529 Date: 2013-04-03 16:27 +0200 http://bitbucket.org/pypy/pypy/changeset/d56e3fdab529/ Log: fix whatsnew diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -117,3 +117,7 @@ .. branch: curses_cffi cffi implementation of _curses + +.. branch: sqlite-cffi + +cffi implementation of sqlite3 From noreply at buildbot.pypy.org Wed Apr 3 17:17:41 2013 From: noreply at buildbot.pypy.org (arigo) Date: Wed, 3 Apr 2013 17:17:41 +0200 (CEST) Subject: [pypy-commit] pypy default: Skip these two tests if we're running on a Mac, where they seem to hang Message-ID: <20130403151741.9AD631C0F0E@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r62977:7f69a708a9bf Date: 2013-04-03 17:17 +0200 http://bitbucket.org/pypy/pypy/changeset/7f69a708a9bf/ Log: Skip these two tests if we're running on a Mac, where they seem to hang forever. diff --git a/pypy/module/test_lib_pypy/pyrepl/test_bugs.py b/pypy/module/test_lib_pypy/pyrepl/test_bugs.py --- a/pypy/module/test_lib_pypy/pyrepl/test_bugs.py +++ b/pypy/module/test_lib_pypy/pyrepl/test_bugs.py @@ -24,6 +24,7 @@ # (applicable) bug reports import pytest +import os, sys class HistoricalTestReader(HistoricalReader, BaseTestReader): @@ -46,7 +47,7 @@ read_spec(spec, HistoricalTestReader) - at pytest.mark.skipif("os.name != 'posix'") + at pytest.mark.skipif("os.name != 'posix' or 'darwin' in sys.platform") def test_signal_failure(monkeypatch): import os import pty diff --git a/pypy/module/test_lib_pypy/pyrepl/test_readline.py b/pypy/module/test_lib_pypy/pyrepl/test_readline.py --- a/pypy/module/test_lib_pypy/pyrepl/test_readline.py +++ b/pypy/module/test_lib_pypy/pyrepl/test_readline.py @@ -1,7 +1,8 @@ import pytest +import os, sys - at pytest.mark.skipif("os.name != 'posix'") + at pytest.mark.skipif("os.name != 'posix' or 'darwin' in sys.platform") def test_raw_input(): import os import pty From noreply at buildbot.pypy.org Wed Apr 3 19:37:52 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 3 Apr 2013 19:37:52 +0200 (CEST) Subject: [pypy-commit] pypy default: backout the sqlite-cffi merge, will redo it differently Message-ID: <20130403173752.8A23B1C06BD@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r62978:084972330ddd Date: 2013-04-03 19:37 +0200 http://bitbucket.org/pypy/pypy/changeset/084972330ddd/ Log: backout the sqlite-cffi merge, will redo it differently diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -23,6 +23,9 @@ # # Note: This software has been modified for use in PyPy. +from ctypes import c_void_p, c_int, c_double, c_int64, c_char_p, c_char, cdll +from ctypes import POINTER, byref, string_at, CFUNCTYPE, cast +from ctypes import sizeof, c_ssize_t from collections import OrderedDict from functools import wraps import datetime @@ -41,266 +44,210 @@ else: _BLOB_TYPE = buffer -from cffi import FFI -ffi = FFI() +def load_library(names): + for name in names: + try: + return cdll.LoadLibrary(name) + except OSError: + pass + else: + raise ImportError("Could not load C-library, tried: %s" % (names,)) -ffi.cdef(""" -#define SQLITE_OK ... -#define SQLITE_ERROR ... -#define SQLITE_INTERNAL ... -#define SQLITE_PERM ... -#define SQLITE_ABORT ... -#define SQLITE_BUSY ... -#define SQLITE_LOCKED ... -#define SQLITE_NOMEM ... -#define SQLITE_READONLY ... -#define SQLITE_INTERRUPT ... -#define SQLITE_IOERR ... -#define SQLITE_CORRUPT ... -#define SQLITE_NOTFOUND ... -#define SQLITE_FULL ... -#define SQLITE_CANTOPEN ... -#define SQLITE_PROTOCOL ... -#define SQLITE_EMPTY ... -#define SQLITE_SCHEMA ... -#define SQLITE_TOOBIG ... -#define SQLITE_CONSTRAINT ... -#define SQLITE_MISMATCH ... -#define SQLITE_MISUSE ... -#define SQLITE_NOLFS ... -#define SQLITE_AUTH ... -#define SQLITE_FORMAT ... -#define SQLITE_RANGE ... -#define SQLITE_NOTADB ... -#define SQLITE_ROW ... -#define SQLITE_DONE ... -#define SQLITE_INTEGER ... -#define SQLITE_FLOAT ... -#define SQLITE_BLOB ... -#define SQLITE_NULL ... -#define SQLITE_TEXT ... -#define SQLITE3_TEXT ... +_lib = load_library( + "sqlite3.dll libsqlite3.so.0 libsqlite3.so libsqlite3.dylib".split()) +del load_library -#define SQLITE_TRANSIENT ... -#define SQLITE_UTF8 ... +########################################## +# BEGIN Wrapped SQLite C API and constants +########################################## -#define SQLITE_DENY ... -#define SQLITE_IGNORE ... +_lib.SQLITE_OK = 0 +_lib.SQLITE_ERROR = 1 +_lib.SQLITE_INTERNAL = 2 +_lib.SQLITE_PERM = 3 +_lib.SQLITE_ABORT = 4 +_lib.SQLITE_BUSY = 5 +_lib.SQLITE_LOCKED = 6 +_lib.SQLITE_NOMEM = 7 +_lib.SQLITE_READONLY = 8 +_lib.SQLITE_INTERRUPT = 9 +_lib.SQLITE_IOERR = 10 +_lib.SQLITE_CORRUPT = 11 +_lib.SQLITE_NOTFOUND = 12 +_lib.SQLITE_FULL = 13 +_lib.SQLITE_CANTOPEN = 14 +_lib.SQLITE_PROTOCOL = 15 +_lib.SQLITE_EMPTY = 16 +_lib.SQLITE_SCHEMA = 17 +_lib.SQLITE_TOOBIG = 18 +_lib.SQLITE_CONSTRAINT = 19 +_lib.SQLITE_MISMATCH = 20 +_lib.SQLITE_MISUSE = 21 +_lib.SQLITE_NOLFS = 22 +_lib.SQLITE_AUTH = 23 +_lib.SQLITE_FORMAT = 24 +_lib.SQLITE_RANGE = 25 +_lib.SQLITE_NOTADB = 26 +_lib.SQLITE_ROW = 100 +_lib.SQLITE_DONE = 101 -#define SQLITE_CREATE_INDEX ... -#define SQLITE_CREATE_TABLE ... -#define SQLITE_CREATE_TEMP_INDEX ... -#define SQLITE_CREATE_TEMP_TABLE ... -#define SQLITE_CREATE_TEMP_TRIGGER ... -#define SQLITE_CREATE_TEMP_VIEW ... -#define SQLITE_CREATE_TRIGGER ... -#define SQLITE_CREATE_VIEW ... -#define SQLITE_DELETE ... -#define SQLITE_DROP_INDEX ... -#define SQLITE_DROP_TABLE ... -#define SQLITE_DROP_TEMP_INDEX ... -#define SQLITE_DROP_TEMP_TABLE ... -#define SQLITE_DROP_TEMP_TRIGGER ... -#define SQLITE_DROP_TEMP_VIEW ... -#define SQLITE_DROP_TRIGGER ... -#define SQLITE_DROP_VIEW ... -#define SQLITE_INSERT ... -#define SQLITE_PRAGMA ... -#define SQLITE_READ ... -#define SQLITE_SELECT ... -#define SQLITE_TRANSACTION ... -#define SQLITE_UPDATE ... -#define SQLITE_ATTACH ... -#define SQLITE_DETACH ... -#define SQLITE_ALTER_TABLE ... -#define SQLITE_REINDEX ... -#define SQLITE_ANALYZE ... -#define SQLITE_CREATE_VTABLE ... -#define SQLITE_DROP_VTABLE ... -#define SQLITE_FUNCTION ... +_lib.SQLITE_INTEGER = 1 +_lib.SQLITE_FLOAT = 2 +_lib.SQLITE_TEXT = 3 +_lib.SQLITE_BLOB = 4 +_lib.SQLITE_NULL = 5 -const char *sqlite3_libversion(void); +_lib.SQLITE_UTF8 = 1 -typedef ... sqlite3; -typedef ... sqlite3_stmt; -typedef ... sqlite3_context; -typedef ... sqlite3_value; -typedef int64_t sqlite3_int64; -typedef uint64_t sqlite3_uint64; +_lib.SQLITE_TRANSIENT = cast(-1, c_void_p) -int sqlite3_open( - const char *filename, /* Database filename (UTF-8) */ - sqlite3 **ppDb /* OUT: SQLite db handle */ -); +SQLITE_OK = _lib.SQLITE_OK -int sqlite3_close(sqlite3 *); +SQLITE_DENY = 1 +SQLITE_IGNORE = 2 -int sqlite3_busy_timeout(sqlite3*, int ms); -int sqlite3_prepare_v2( - sqlite3 *db, /* Database handle */ - const char *zSql, /* SQL statement, UTF-8 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const char **pzTail /* OUT: Pointer to unused portion of zSql */ -); -int sqlite3_finalize(sqlite3_stmt *pStmt); -int sqlite3_column_count(sqlite3_stmt *pStmt); -const char *sqlite3_column_name(sqlite3_stmt*, int N); -int sqlite3_get_autocommit(sqlite3*); -int sqlite3_reset(sqlite3_stmt *pStmt); -int sqlite3_step(sqlite3_stmt*); -int sqlite3_errcode(sqlite3 *db); -const char *sqlite3_errmsg(sqlite3*); -int sqlite3_changes(sqlite3*); +SQLITE_CREATE_INDEX = 1 +SQLITE_CREATE_TABLE = 2 +SQLITE_CREATE_TEMP_INDEX = 3 +SQLITE_CREATE_TEMP_TABLE = 4 +SQLITE_CREATE_TEMP_TRIGGER = 5 +SQLITE_CREATE_TEMP_VIEW = 6 +SQLITE_CREATE_TRIGGER = 7 +SQLITE_CREATE_VIEW = 8 +SQLITE_DELETE = 9 +SQLITE_DROP_INDEX = 10 +SQLITE_DROP_TABLE = 11 +SQLITE_DROP_TEMP_INDEX = 12 +SQLITE_DROP_TEMP_TABLE = 13 +SQLITE_DROP_TEMP_TRIGGER = 14 +SQLITE_DROP_TEMP_VIEW = 15 +SQLITE_DROP_TRIGGER = 16 +SQLITE_DROP_VIEW = 17 +SQLITE_INSERT = 18 +SQLITE_PRAGMA = 19 +SQLITE_READ = 20 +SQLITE_SELECT = 21 +SQLITE_TRANSACTION = 22 +SQLITE_UPDATE = 23 +SQLITE_ATTACH = 24 +SQLITE_DETACH = 25 +SQLITE_ALTER_TABLE = 26 +SQLITE_REINDEX = 27 +SQLITE_ANALYZE = 28 -int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); -int sqlite3_bind_double(sqlite3_stmt*, int, double); -int sqlite3_bind_int(sqlite3_stmt*, int, int); -int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); -int sqlite3_bind_null(sqlite3_stmt*, int); -int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*)); -int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); -int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); -int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); +# SQLite C API -const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); -int sqlite3_column_bytes(sqlite3_stmt*, int iCol); -double sqlite3_column_double(sqlite3_stmt*, int iCol); -int sqlite3_column_int(sqlite3_stmt*, int iCol); -sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol); -const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); -const void *sqlite3_column_text16(sqlite3_stmt*, int iCol); -int sqlite3_column_type(sqlite3_stmt*, int iCol); -const char *sqlite3_column_decltype(sqlite3_stmt*,int); +_lib.sqlite3_value_int.argtypes = [c_void_p] +_lib.sqlite3_value_int.restype = c_int -void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); -int sqlite3_create_collation( - sqlite3*, - const char *zName, - int eTextRep, - void*, - int(*xCompare)(void*,int,const void*,int,const void*) -); -int sqlite3_set_authorizer( - sqlite3*, - int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), - void *pUserData -); -int sqlite3_create_function( - sqlite3 *db, - const char *zFunctionName, - int nArg, - int eTextRep, - void *pApp, - void (*xFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*) -); -void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); +_lib.sqlite3_value_int64.argtypes = [c_void_p] +_lib.sqlite3_value_int64.restype = c_int64 -sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); -int sqlite3_bind_parameter_count(sqlite3_stmt*); -const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); -int sqlite3_total_changes(sqlite3*); +_lib.sqlite3_value_blob.argtypes = [c_void_p] +_lib.sqlite3_value_blob.restype = c_void_p -int sqlite3_prepare( - sqlite3 *db, /* Database handle */ - const char *zSql, /* SQL statement, UTF-8 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const char **pzTail /* OUT: Pointer to unused portion of zSql */ -); +_lib.sqlite3_value_bytes.argtypes = [c_void_p] +_lib.sqlite3_value_bytes.restype = c_int -void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); -void sqlite3_result_double(sqlite3_context*, double); -void sqlite3_result_error(sqlite3_context*, const char*, int); -void sqlite3_result_error16(sqlite3_context*, const void*, int); -void sqlite3_result_error_toobig(sqlite3_context*); -void sqlite3_result_error_nomem(sqlite3_context*); -void sqlite3_result_error_code(sqlite3_context*, int); -void sqlite3_result_int(sqlite3_context*, int); -void sqlite3_result_int64(sqlite3_context*, sqlite3_int64); -void sqlite3_result_null(sqlite3_context*); -void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); -void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); -void sqlite3_result_text16le(sqlite3_context*,const void*, int,void(*)(void*)); -void sqlite3_result_text16be(sqlite3_context*,const void*, int,void(*)(void*)); -void sqlite3_result_value(sqlite3_context*, sqlite3_value*); -void sqlite3_result_zeroblob(sqlite3_context*, int n); +_lib.sqlite3_value_double.argtypes = [c_void_p] +_lib.sqlite3_value_double.restype = c_double -const void *sqlite3_value_blob(sqlite3_value*); -int sqlite3_value_bytes(sqlite3_value*); -int sqlite3_value_bytes16(sqlite3_value*); -double sqlite3_value_double(sqlite3_value*); -int sqlite3_value_int(sqlite3_value*); -sqlite3_int64 sqlite3_value_int64(sqlite3_value*); -const unsigned char *sqlite3_value_text(sqlite3_value*); -const void *sqlite3_value_text16(sqlite3_value*); -const void *sqlite3_value_text16le(sqlite3_value*); -const void *sqlite3_value_text16be(sqlite3_value*); -int sqlite3_value_type(sqlite3_value*); -int sqlite3_value_numeric_type(sqlite3_value*); -""") +_lib.sqlite3_value_text.argtypes = [c_void_p] +_lib.sqlite3_value_text.restype = c_char_p +_lib.sqlite3_value_type.argtypes = [c_void_p] +_lib.sqlite3_value_type.restype = c_int -def _has_load_extension(): - """Only available since 3.3.6""" - unverified_ffi = FFI() - unverified_ffi.cdef(""" - typedef ... sqlite3; - int sqlite3_enable_load_extension(sqlite3 *db, int onoff); - """) - unverified_lib = unverified_ffi.dlopen('sqlite3') - return hasattr(unverified_lib, 'sqlite3_enable_load_extension') +_lib.sqlite3_bind_blob.argtypes = [c_void_p, c_int, c_void_p, c_int, c_void_p] +_lib.sqlite3_bind_blob.restype = c_int +_lib.sqlite3_bind_double.argtypes = [c_void_p, c_int, c_double] +_lib.sqlite3_bind_double.restype = c_int +_lib.sqlite3_bind_int.argtypes = [c_void_p, c_int, c_int] +_lib.sqlite3_bind_int.restype = c_int +_lib.sqlite3_bind_int64.argtypes = [c_void_p, c_int, c_int64] +_lib.sqlite3_bind_int64.restype = c_int +_lib.sqlite3_bind_null.argtypes = [c_void_p, c_int] +_lib.sqlite3_bind_null.restype = c_int +_lib.sqlite3_bind_parameter_count.argtypes = [c_void_p] +_lib.sqlite3_bind_parameter_count.restype = c_int +_lib.sqlite3_bind_parameter_index.argtypes = [c_void_p, c_char_p] +_lib.sqlite3_bind_parameter_index.restype = c_int +_lib.sqlite3_bind_parameter_name.argtypes = [c_void_p, c_int] +_lib.sqlite3_bind_parameter_name.restype = c_char_p +_lib.sqlite3_bind_text.argtypes = [c_void_p, c_int, c_char_p, c_int, c_void_p] +_lib.sqlite3_bind_text.restype = c_int +_lib.sqlite3_busy_timeout.argtypes = [c_void_p, c_int] +_lib.sqlite3_busy_timeout.restype = c_int +_lib.sqlite3_changes.argtypes = [c_void_p] +_lib.sqlite3_changes.restype = c_int +_lib.sqlite3_close.argtypes = [c_void_p] +_lib.sqlite3_close.restype = c_int +_lib.sqlite3_column_blob.argtypes = [c_void_p, c_int] +_lib.sqlite3_column_blob.restype = c_void_p +_lib.sqlite3_column_bytes.argtypes = [c_void_p, c_int] +_lib.sqlite3_column_bytes.restype = c_int +_lib.sqlite3_column_count.argtypes = [c_void_p] +_lib.sqlite3_column_count.restype = c_int +_lib.sqlite3_column_decltype.argtypes = [c_void_p, c_int] +_lib.sqlite3_column_decltype.restype = c_char_p +_lib.sqlite3_column_double.argtypes = [c_void_p, c_int] +_lib.sqlite3_column_double.restype = c_double +_lib.sqlite3_column_int64.argtypes = [c_void_p, c_int] +_lib.sqlite3_column_int64.restype = c_int64 +_lib.sqlite3_column_name.argtypes = [c_void_p, c_int] +_lib.sqlite3_column_name.restype = c_char_p +_lib.sqlite3_column_text.argtypes = [c_void_p, c_int] +_lib.sqlite3_column_text.restype = POINTER(c_char) +_lib.sqlite3_column_type.argtypes = [c_void_p, c_int] +_lib.sqlite3_column_type.restype = c_int +_lib.sqlite3_complete.argtypes = [c_char_p] +_lib.sqlite3_complete.restype = c_int +_lib.sqlite3_errcode.restype = c_int +_lib.sqlite3_errmsg.argtypes = [c_void_p] +_lib.sqlite3_errmsg.restype = c_char_p +_lib.sqlite3_finalize.argtypes = [c_void_p] +_lib.sqlite3_finalize.restype = c_int +_lib.sqlite3_get_autocommit.argtypes = [c_void_p] +_lib.sqlite3_get_autocommit.restype = c_int +_lib.sqlite3_last_insert_rowid.argtypes = [c_void_p] +_lib.sqlite3_last_insert_rowid.restype = c_int64 +_lib.sqlite3_libversion.argtypes = [] +_lib.sqlite3_libversion.restype = c_char_p +_lib.sqlite3_open.argtypes = [c_char_p, c_void_p] +_lib.sqlite3_open.restype = c_int +_lib.sqlite3_prepare.argtypes = [c_void_p, c_char_p, c_int, c_void_p, POINTER(c_char_p)] +_lib.sqlite3_prepare.restype = c_int +_lib.sqlite3_prepare_v2.argtypes = [c_void_p, c_char_p, c_int, c_void_p, POINTER(c_char_p)] +_lib.sqlite3_prepare_v2.restype = c_int +_lib.sqlite3_step.argtypes = [c_void_p] +_lib.sqlite3_step.restype = c_int +_lib.sqlite3_reset.argtypes = [c_void_p] +_lib.sqlite3_reset.restype = c_int +_lib.sqlite3_total_changes.argtypes = [c_void_p] +_lib.sqlite3_total_changes.restype = c_int +_lib.sqlite3_result_blob.argtypes = [c_void_p, c_void_p, c_int, c_void_p] +_lib.sqlite3_result_blob.restype = None +_lib.sqlite3_result_int64.argtypes = [c_void_p, c_int64] +_lib.sqlite3_result_int64.restype = None +_lib.sqlite3_result_null.argtypes = [c_void_p] +_lib.sqlite3_result_null.restype = None +_lib.sqlite3_result_double.argtypes = [c_void_p, c_double] +_lib.sqlite3_result_double.restype = None +_lib.sqlite3_result_error.argtypes = [c_void_p, c_char_p, c_int] +_lib.sqlite3_result_error.restype = None +_lib.sqlite3_result_text.argtypes = [c_void_p, c_char_p, c_int, c_void_p] +_lib.sqlite3_result_text.restype = None -if _has_load_extension(): - ffi.cdef("int sqlite3_enable_load_extension(sqlite3 *db, int onoff);") +_HAS_LOAD_EXTENSION = hasattr(_lib, "sqlite3_enable_load_extension") +if _HAS_LOAD_EXTENSION: + _lib.sqlite3_enable_load_extension.argtypes = [c_void_p, c_int] + _lib.sqlite3_enable_load_extension.restype = c_int -lib = ffi.verify(""" -#include -""", libraries=['sqlite3']) - -exported_sqlite_symbols = [ - 'SQLITE_ALTER_TABLE', - 'SQLITE_ANALYZE', - 'SQLITE_ATTACH', - 'SQLITE_CREATE_INDEX', - 'SQLITE_CREATE_TABLE', - 'SQLITE_CREATE_TEMP_INDEX', - 'SQLITE_CREATE_TEMP_TABLE', - 'SQLITE_CREATE_TEMP_TRIGGER', - 'SQLITE_CREATE_TEMP_VIEW', - 'SQLITE_CREATE_TRIGGER', - 'SQLITE_CREATE_VIEW', - 'SQLITE_DELETE', - 'SQLITE_DENY', - 'SQLITE_DETACH', - 'SQLITE_DROP_INDEX', - 'SQLITE_DROP_TABLE', - 'SQLITE_DROP_TEMP_INDEX', - 'SQLITE_DROP_TEMP_TABLE', - 'SQLITE_DROP_TEMP_TRIGGER', - 'SQLITE_DROP_TEMP_VIEW', - 'SQLITE_DROP_TRIGGER', - 'SQLITE_DROP_VIEW', - 'SQLITE_IGNORE', - 'SQLITE_INSERT', - 'SQLITE_OK', - 'SQLITE_PRAGMA', - 'SQLITE_READ', - 'SQLITE_REINDEX', - 'SQLITE_SELECT', - 'SQLITE_TRANSACTION', - 'SQLITE_UPDATE', -] - -for symbol in exported_sqlite_symbols: - globals()[symbol] = getattr(lib, symbol) - -_SQLITE_TRANSIENT = ffi.cast('void *', lib.SQLITE_TRANSIENT) - +########################################## +# END Wrapped SQLite C API and constants +########################################## # pysqlite version information version = "2.6.0" @@ -310,7 +257,7 @@ PARSE_DECLTYPES = 2 # SQLite version information -sqlite_version = ffi.string(lib.sqlite3_libversion()) +sqlite_version = str(_lib.sqlite3_libversion().decode('ascii')) class Error(StandardError): @@ -387,36 +334,48 @@ if len(self.cache) > self.maxcount: self.cache.popitem(0) - if stat.in_use: + if stat._in_use: stat = Statement(self.connection, sql) - stat.set_row_factory(row_factory) + stat._row_factory = row_factory return stat class Connection(object): - def __init__(self, database, timeout=5.0, detect_types=0, - isolation_level="", check_same_thread=True, factory=None, - cached_statements=100): - db_star = ffi.new('sqlite3 **') + __initialized = False + _db = None + + def __init__(self, database, timeout=5.0, detect_types=0, isolation_level="", + check_same_thread=True, factory=None, cached_statements=100): + self.__initialized = True + self._db = c_void_p() + if isinstance(database, unicode): database = database.encode('utf-8') - if lib.sqlite3_open(database, db_star) != lib.SQLITE_OK: + if _lib.sqlite3_open(database, byref(self._db)) != _lib.SQLITE_OK: raise OperationalError("Could not open database") - self.db = db_star[0] if timeout is not None: timeout = int(timeout * 1000) # pysqlite2 uses timeout in seconds - lib.sqlite3_busy_timeout(self.db, timeout) + _lib.sqlite3_busy_timeout(self._db, timeout) + self.row_factory = None self.text_factory = _unicode_text_factory - self.closed = False - self.statements = [] - self.statement_counter = 0 - self.row_factory = None - self._isolation_level = isolation_level - self.detect_types = detect_types - self.statement_cache = _StatementCache(self, cached_statements) - self.cursors = [] + self._detect_types = detect_types + self._in_transaction = False + self.isolation_level = isolation_level + + self.__cursors = [] + self.__cursors_counter = 0 + self.__statements = [] + self.__statements_counter = 0 + self._statement_cache = _StatementCache(self, cached_statements) + + self.__func_cache = {} + self.__aggregates = {} + self.__aggregate_instances = {} + self.__collations = {} + if check_same_thread: + self.__thread_ident = _thread_get_ident() self.Error = Error self.Warning = Warning @@ -429,30 +388,25 @@ self.DataError = DataError self.NotSupportedError = NotSupportedError - self.func_cache = {} - self._aggregates = {} - self.aggregate_instances = {} - self._collations = {} - if check_same_thread: - self.thread_ident = _thread_get_ident() + def __del__(self): + if self._db: + _lib.sqlite3_close(self._db) def close(self): self._check_thread() - if self.closed: - return - for statement in self.statements: - obj = statement() - if obj is not None: - obj.finalize() - self.closed = True - ret = lib.sqlite3_close(self.db) - self._reset_cursors() - if ret != lib.SQLITE_OK: - raise self._get_exception(ret) + self.__do_all_statements(Statement._finalize, True) + + if self._db: + ret = _lib.sqlite3_close(self._db) + if ret != _lib.SQLITE_OK: + raise self._get_exception(ret) + self._db = None def _check_closed(self): - if getattr(self, 'closed', True): + if not self.__initialized: + raise ProgrammingError("Base Connection.__init__ not called.") + if not self._db: raise ProgrammingError("Cannot operate on a closed database.") def _check_closed_wrap(func): @@ -463,13 +417,16 @@ return wrapper def _check_thread(self): - if not hasattr(self, 'thread_ident'): - return - if self.thread_ident != _thread_get_ident(): + try: + if self.__thread_ident == _thread_get_ident(): + return + except AttributeError: + pass + else: raise ProgrammingError( "SQLite objects created in a thread can only be used in that " "same thread. The object was created in thread id %d and this " - "is thread id %d", self.thread_ident, _thread_get_ident()) + "is thread id %d", self.__thread_ident, _thread_get_ident()) def _check_thread_wrap(func): @wraps(func) @@ -480,29 +437,29 @@ def _get_exception(self, error_code=None): if error_code is None: - error_code = lib.sqlite3_errcode(self.db) - error_message = ffi.string(lib.sqlite3_errmsg(self.db)) + error_code = _lib.sqlite3_errcode(self._db) + error_message = _lib.sqlite3_errmsg(self._db).decode('utf-8') - if error_code == lib.SQLITE_OK: - raise ValueError("error signalled but got lib.SQLITE_OK") - elif error_code in (lib.SQLITE_INTERNAL, lib.SQLITE_NOTFOUND): + if error_code == _lib.SQLITE_OK: + raise ValueError("error signalled but got SQLITE_OK") + elif error_code in (_lib.SQLITE_INTERNAL, _lib.SQLITE_NOTFOUND): exc = InternalError - elif error_code == lib.SQLITE_NOMEM: + elif error_code == _lib.SQLITE_NOMEM: exc = MemoryError elif error_code in ( - lib.SQLITE_ERROR, lib.SQLITE_PERM, lib.SQLITE_ABORT, - lib.SQLITE_BUSY, lib.SQLITE_LOCKED, lib.SQLITE_READONLY, - lib.SQLITE_INTERRUPT, lib.SQLITE_IOERR, lib.SQLITE_FULL, - lib.SQLITE_CANTOPEN, lib.SQLITE_PROTOCOL, lib.SQLITE_EMPTY, - lib.SQLITE_SCHEMA): + _lib.SQLITE_ERROR, _lib.SQLITE_PERM, _lib.SQLITE_ABORT, + _lib.SQLITE_BUSY, _lib.SQLITE_LOCKED, _lib.SQLITE_READONLY, + _lib.SQLITE_INTERRUPT, _lib.SQLITE_IOERR, _lib.SQLITE_FULL, + _lib.SQLITE_CANTOPEN, _lib.SQLITE_PROTOCOL, _lib.SQLITE_EMPTY, + _lib.SQLITE_SCHEMA): exc = OperationalError - elif error_code == lib.SQLITE_CORRUPT: + elif error_code == _lib.SQLITE_CORRUPT: exc = DatabaseError - elif error_code == lib.SQLITE_TOOBIG: + elif error_code == _lib.SQLITE_TOOBIG: exc = DataError - elif error_code in (lib.SQLITE_CONSTRAINT, lib.SQLITE_MISMATCH): + elif error_code in (_lib.SQLITE_CONSTRAINT, _lib.SQLITE_MISMATCH): exc = IntegrityError - elif error_code == lib.SQLITE_MISUSE: + elif error_code == _lib.SQLITE_MISUSE: exc = ProgrammingError else: exc = DatabaseError @@ -510,26 +467,38 @@ exc.error_code = error_code return exc + def _remember_cursor(self, cursor): + self.__cursors.append(weakref.ref(cursor)) + self.__cursors_counter += 1 + if self.__cursors_counter < 200: + return + self.__cursors_counter = 0 + self.__cursors = [r for r in self.__cursors if r() is not None] + def _remember_statement(self, statement): - self.statements.append(weakref.ref(statement)) - self.statement_counter += 1 + self.__statements.append(weakref.ref(statement)) + self.__statements_counter += 1 + if self.__statements_counter < 200: + return + self.__statements_counter = 0 + self.__statements = [r for r in self.__statements if r() is not None] - if self.statement_counter % 100 == 0: - self.statements = [ref for ref in self.statements - if ref() is not None] + def __do_all_statements(self, action, reset_cursors): + for weakref in self.__statements: + statement = weakref() + if statement is not None: + action(statement) - def _reset_cursors(self): - for cursor_ref in self.cursors: - cursor = cursor_ref() - if cursor: - cursor.reset = True + if reset_cursors: + for weakref in self.__cursors: + cursor = weakref() + if cursor is not None: + cursor._reset = True @_check_thread_wrap @_check_closed_wrap def __call__(self, sql): - if not isinstance(sql, basestring): - raise Warning("SQL is of wrong type. Must be string or unicode.") - return self.statement_cache.get(sql, self.row_factory) + return self._statement_cache.get(sql, self.row_factory) def cursor(self, factory=None): self._check_thread() @@ -558,73 +527,60 @@ return _iterdump(self) def _begin(self): - self._check_closed() - if self._isolation_level is None: - return - if not lib.sqlite3_get_autocommit(self.db): - return - sql = "BEGIN " + self._isolation_level - statement_star = ffi.new('sqlite3_stmt **') - next_char = ffi.new('char **') - ret = lib.sqlite3_prepare_v2(self.db, sql, -1, statement_star, - next_char) + statement = c_void_p() + ret = _lib.sqlite3_prepare_v2(self._db, self.__begin_statement, -1, + byref(statement), None) try: - if ret != lib.SQLITE_OK: + if ret != _lib.SQLITE_OK: raise self._get_exception(ret) - ret = lib.sqlite3_step(statement_star[0]) - if ret != lib.SQLITE_DONE: + ret = _lib.sqlite3_step(statement) + if ret != _lib.SQLITE_DONE: raise self._get_exception(ret) + self._in_transaction = True finally: - lib.sqlite3_finalize(statement_star[0]) + _lib.sqlite3_finalize(statement) def commit(self): self._check_thread() self._check_closed() - if lib.sqlite3_get_autocommit(self.db): + if not self._in_transaction: return - for statement in self.statements: - obj = statement() - if obj is not None: - obj.reset() + self.__do_all_statements(Statement._reset, False) - statement_star = ffi.new('sqlite3_stmt **') - next_char = ffi.new('char **') - ret = lib.sqlite3_prepare_v2(self.db, b"COMMIT", -1, statement_star, - next_char) + statement = c_void_p() + ret = _lib.sqlite3_prepare_v2(self._db, b"COMMIT", -1, + byref(statement), None) try: - if ret != lib.SQLITE_OK: + if ret != _lib.SQLITE_OK: raise self._get_exception(ret) - ret = lib.sqlite3_step(statement_star[0]) - if ret != lib.SQLITE_DONE: + ret = _lib.sqlite3_step(statement) + if ret != _lib.SQLITE_DONE: raise self._get_exception(ret) + self._in_transaction = False finally: - lib.sqlite3_finalize(statement_star[0]) + _lib.sqlite3_finalize(statement) def rollback(self): self._check_thread() self._check_closed() - if lib.sqlite3_get_autocommit(self.db): + if not self._in_transaction: return - for statement in self.statements: - obj = statement() - if obj is not None: - obj.reset() + self.__do_all_statements(Statement._reset, True) - statement_star = ffi.new('sqlite3_stmt **') - next_char = ffi.new('char **') - ret = lib.sqlite3_prepare_v2(self.db, b"ROLLBACK", -1, statement_star, - next_char) + statement = c_void_p() + ret = _lib.sqlite3_prepare_v2(self._db, b"ROLLBACK", -1, + byref(statement), None) try: - if ret != lib.SQLITE_OK: + if ret != _lib.SQLITE_OK: raise self._get_exception(ret) - ret = lib.sqlite3_step(statement_star[0]) - if ret != lib.SQLITE_DONE: + ret = _lib.sqlite3_step(statement) + if ret != _lib.SQLITE_DONE: raise self._get_exception(ret) + self._in_transaction = False finally: - lib.sqlite3_finalize(statement_star[0]) - self._reset_cursors() + _lib.sqlite3_finalize(statement) def __enter__(self): return self @@ -639,29 +595,34 @@ @_check_closed_wrap def create_function(self, name, num_args, callback): try: - closure = self.func_cache[callback] + c_closure, _ = self.__func_cache[callback] except KeyError: - @ffi.callback("void(sqlite3_context*, int, sqlite3_value**)") def closure(context, nargs, c_params): _function_callback(callback, context, nargs, c_params) - self.func_cache[callback] = closure - ret = lib.sqlite3_create_function(self.db, name, num_args, - lib.SQLITE_UTF8, ffi.NULL, - closure, ffi.NULL, ffi.NULL) - if ret != lib.SQLITE_OK: + c_closure = _FUNC(closure) + self.__func_cache[callback] = c_closure, closure + + if isinstance(name, unicode): + name = name.encode('utf-8') + ret = _lib.sqlite3_create_function(self._db, name, num_args, + _lib.SQLITE_UTF8, None, + c_closure, + cast(None, _STEP), + cast(None, _FINAL)) + if ret != _lib.SQLITE_OK: raise self.OperationalError("Error creating function") @_check_thread_wrap @_check_closed_wrap def create_aggregate(self, name, num_args, cls): try: - step_callback, final_callback = self._aggregates[cls] + c_step_callback, c_final_callback, _, _ = self.__aggregates[cls] except KeyError: - @ffi.callback("void(sqlite3_context*, int, sqlite3_value**)") def step_callback(context, argc, c_params): - res = lib.sqlite3_aggregate_context(context, - ffi.sizeof("size_t")) - aggregate_ptr = ffi.cast("size_t[1]", res) + aggregate_ptr = cast( + _lib.sqlite3_aggregate_context( + context, sizeof(c_ssize_t)), + POINTER(c_ssize_t)) if not aggregate_ptr[0]: try: @@ -669,13 +630,13 @@ except Exception: msg = (b"user-defined aggregate's '__init__' " b"method raised error") - lib.sqlite3_result_error(context, msg, len(msg)) + _lib.sqlite3_result_error(context, msg, len(msg)) return aggregate_id = id(aggregate) - self.aggregate_instances[aggregate_id] = aggregate + self.__aggregate_instances[aggregate_id] = aggregate aggregate_ptr[0] = aggregate_id else: - aggregate = self.aggregate_instances[aggregate_ptr[0]] + aggregate = self.__aggregate_instances[aggregate_ptr[0]] params = _convert_params(context, argc, c_params) try: @@ -683,33 +644,41 @@ except Exception: msg = (b"user-defined aggregate's 'step' " b"method raised error") - lib.sqlite3_result_error(context, msg, len(msg)) + _lib.sqlite3_result_error(context, msg, len(msg)) - @ffi.callback("void(sqlite3_context*)") def final_callback(context): - res = lib.sqlite3_aggregate_context(context, - ffi.sizeof("size_t")) - aggregate_ptr = ffi.cast("size_t[1]", res) + aggregate_ptr = cast( + _lib.sqlite3_aggregate_context( + context, sizeof(c_ssize_t)), + POINTER(c_ssize_t)) if aggregate_ptr[0]: - aggregate = self.aggregate_instances[aggregate_ptr[0]] + aggregate = self.__aggregate_instances[aggregate_ptr[0]] try: val = aggregate.finalize() except Exception: msg = (b"user-defined aggregate's 'finalize' " b"method raised error") - lib.sqlite3_result_error(context, msg, len(msg)) + _lib.sqlite3_result_error(context, msg, len(msg)) else: _convert_result(context, val) finally: - del self.aggregate_instances[aggregate_ptr[0]] + del self.__aggregate_instances[aggregate_ptr[0]] - self._aggregates[cls] = step_callback, final_callback + c_step_callback = _STEP(step_callback) + c_final_callback = _FINAL(final_callback) - ret = lib.sqlite3_create_function(self.db, name, num_args, - lib.SQLITE_UTF8, ffi.NULL, ffi.NULL, - step_callback, final_callback) - if ret != lib.SQLITE_OK: + self.__aggregates[cls] = (c_step_callback, c_final_callback, + step_callback, final_callback) + + if isinstance(name, unicode): + name = name.encode('utf-8') + ret = _lib.sqlite3_create_function(self._db, name, num_args, + _lib.SQLITE_UTF8, None, + cast(None, _FUNC), + c_step_callback, + c_final_callback) + if ret != _lib.SQLITE_OK: raise self._get_exception(ret) @_check_thread_wrap @@ -720,55 +689,60 @@ raise ProgrammingError("invalid character in collation name") if callback is None: - del self._collations[name] - collation_callback = ffi.NULL + del self.__collations[name] + c_collation_callback = cast(None, _COLLATION) else: if not callable(callback): raise TypeError("parameter must be callable") - @ffi.callback("int(void*, int, const void*, int, const void*)") def collation_callback(context, len1, str1, len2, str2): - text1 = ffi.buffer(str1, len1)[:] - text2 = ffi.buffer(str2, len2)[:] + text1 = string_at(str1, len1).decode('utf-8') + text2 = string_at(str2, len2).decode('utf-8') return callback(text1, text2) - self._collations[name] = collation_callback + c_collation_callback = _COLLATION(collation_callback) + self.__collations[name] = c_collation_callback - ret = lib.sqlite3_create_collation(self.db, name, lib.SQLITE_UTF8, - ffi.NULL, collation_callback) - if ret != lib.SQLITE_OK: + if isinstance(name, unicode): + name = name.encode('utf-8') + ret = _lib.sqlite3_create_collation(self._db, name, + _lib.SQLITE_UTF8, + None, + c_collation_callback) + if ret != _lib.SQLITE_OK: raise self._get_exception(ret) @_check_thread_wrap @_check_closed_wrap def set_authorizer(self, callback): try: - authorizer = self.func_cache[callback] + c_authorizer, _ = self.__func_cache[callback] except KeyError: - @ffi.callback("int(void*, int, const char*, const char*, " - "const char*, const char*)") def authorizer(userdata, action, arg1, arg2, dbname, source): try: return int(callback(action, arg1, arg2, dbname, source)) except Exception: - return lib.SQLITE_DENY - self.func_cache[callback] = authorizer + return SQLITE_DENY + c_authorizer = _AUTHORIZER(authorizer) - ret = lib.sqlite3_set_authorizer(self.db, authorizer, ffi.NULL) - if ret != lib.SQLITE_OK: + self.__func_cache[callback] = c_authorizer, authorizer + + ret = _lib.sqlite3_set_authorizer(self._db, + c_authorizer, + None) + if ret != _lib.SQLITE_OK: raise self._get_exception(ret) @_check_thread_wrap @_check_closed_wrap def set_progress_handler(self, callable, nsteps): if callable is None: - progress_handler = ffi.NULL + c_progress_handler = cast(None, _PROGRESS) else: try: - progress_handler = self.func_cache[callable] + c_progress_handler, _ = self.__func_cache[callable] except KeyError: - @ffi.callback("int(void*)") def progress_handler(userdata): try: ret = callable() @@ -776,14 +750,23 @@ except Exception: # abort query if error occurred return 1 + c_progress_handler = _PROGRESS(progress_handler) - self.func_cache[callable] = progress_handler - lib.sqlite3_progress_handler(self.db, nsteps, progress_handler, - ffi.NULL) + self.__func_cache[callable] = c_progress_handler, progress_handler + ret = _lib.sqlite3_progress_handler(self._db, nsteps, + c_progress_handler, + None) + if ret != _lib.SQLITE_OK: + raise self._get_exception(ret) + + if sys.version_info[0] >= 3: + def __get_in_transaction(self): + return self._in_transaction + in_transaction = property(__get_in_transaction) def __get_total_changes(self): self._check_closed() - return lib.sqlite3_total_changes(self.db) + return _lib.sqlite3_total_changes(self._db) total_changes = property(__get_total_changes) def __get_isolation_level(self): @@ -792,193 +775,190 @@ def __set_isolation_level(self, val): if val is None: self.commit() - if isinstance(val, unicode): - val = str(val) + else: + self.__begin_statement = str("BEGIN " + val).encode('utf-8') self._isolation_level = val isolation_level = property(__get_isolation_level, __set_isolation_level) - if hasattr(lib, 'sqlite3_enable_load_extension'): + if _HAS_LOAD_EXTENSION: @_check_thread_wrap @_check_closed_wrap def enable_load_extension(self, enabled): - rc = lib.sqlite3_enable_load_extension(self.db, int(enabled)) - if rc != lib.SQLITE_OK: + rc = _lib.sqlite3_enable_load_extension(self._db, int(enabled)) + if rc != _lib.SQLITE_OK: raise OperationalError("Error enabling load extension") -DML, DQL, DDL = range(3) +class Cursor(object): + __initialized = False + __statement = None - -class CursorLock(object): - def __init__(self, cursor): - self.cursor = cursor - - def __enter__(self): - if self.cursor.locked: - raise ProgrammingError("Recursive use of cursors not allowed.") - self.cursor.locked = True - - def __exit__(self, *args): - self.cursor.locked = False - - -class Cursor(object): def __init__(self, con): if not isinstance(con, Connection): raise TypeError - con._check_thread() - con._check_closed() - con.cursors.append(weakref.ref(self)) - self.connection = con - self._description = None + self.__connection = con + self.arraysize = 1 self.row_factory = None - self.rowcount = -1 - self.statement = None - self.reset = False - self.locked = False + self._reset = False + self.__locked = False + self.__closed = False + self.__description = None + self.__rowcount = -1 - def _check_closed(self): - if not getattr(self, 'connection', None): + con._check_thread() + con._remember_cursor(self) + + self.__initialized = True + + def __del__(self): + if self.__statement: + self.__statement._reset() + + def close(self): + self.__connection._check_thread() + self.__connection._check_closed() + if self.__statement: + self.__statement._reset() + self.__statement = None + self.__closed = True + + def __check_cursor(self): + if not self.__initialized: + raise ProgrammingError("Base Cursor.__init__ not called.") + if self.__closed: raise ProgrammingError("Cannot operate on a closed cursor.") - self.connection._check_thread() - self.connection._check_closed() + if self.__locked: + raise ProgrammingError("Recursive use of cursors not allowed.") + self.__connection._check_thread() + self.__connection._check_closed() - def _check_and_lock(self): - self._check_closed() - return CursorLock(self) + def __check_cursor_wrap(func): + @wraps(func) + def wrapper(self, *args, **kwargs): + self.__check_cursor() + return func(self, *args, **kwargs) + return wrapper - def execute(self, sql, params=None): - if type(sql) is unicode: - sql = sql.encode("utf-8") - - with self._check_and_lock(): - self._description = None - self.reset = False - self.statement = self.connection.statement_cache.get( + def __execute(self, multiple, sql, many_params): + self.__locked = True + try: + self._reset = False + if not isinstance(sql, basestring): + raise ValueError("operation parameter must be str or unicode") + self.__description = None + self.__rowcount = -1 + self.__statement = self.__connection._statement_cache.get( sql, self.row_factory) - if self.connection._isolation_level is not None: - if self.statement.kind == DDL: - self.connection.commit() - elif self.statement.kind == DML: - self.connection._begin() + if self.__connection._isolation_level is not None: + if self.__statement._kind == Statement._DDL: + if self.__connection._in_transaction: + self.__connection.commit() + elif self.__statement._kind == Statement._DML: + if not self.__connection._in_transaction: + self.__connection._begin() - self.statement.set_params(params) + if multiple and self.__statement._kind != Statement._DML: + raise ProgrammingError("executemany is only for DML statements") - # Actually execute the SQL statement - ret = lib.sqlite3_step(self.statement.statement) - if ret not in (lib.SQLITE_DONE, lib.SQLITE_ROW): - self.statement.reset() - raise self.connection._get_exception(ret) + for params in many_params: + self.__statement._set_params(params) - if self.statement.kind == DML: - self.statement.reset() + # Actually execute the SQL statement + ret = _lib.sqlite3_step(self.__statement._statement) + if ret not in (_lib.SQLITE_DONE, _lib.SQLITE_ROW): + self.__statement._reset() + self.__connection._in_transaction = \ + not _lib.sqlite3_get_autocommit(self.__connection._db) + raise self.__connection._get_exception(ret) - if self.statement.kind == DQL and ret == lib.SQLITE_ROW: - self.statement._build_row_cast_map() - self.statement._readahead(self) - else: - self.statement.item = None - self.statement.exhausted = True + if self.__statement._kind == Statement._DML: + self.__statement._reset() - self.rowcount = -1 - if self.statement.kind == DML: - self.rowcount = lib.sqlite3_changes(self.connection.db) + if self.__statement._kind == Statement._DQL and ret == _lib.SQLITE_ROW: + self.__statement._build_row_cast_map() + self.__statement._readahead(self) + if self.__statement._kind == Statement._DML: + if self.__rowcount == -1: + self.__rowcount = 0 + self.__rowcount += _lib.sqlite3_changes(self.__connection._db) + finally: + self.__locked = False return self + @__check_cursor_wrap + def execute(self, sql, params=[]): + return self.__execute(False, sql, [params]) + + @__check_cursor_wrap def executemany(self, sql, many_params): - if type(sql) is unicode: - sql = sql.encode("utf-8") - - with self._check_and_lock(): - self._description = None - self.reset = False - self.statement = self.connection.statement_cache.get( - sql, self.row_factory) - - if self.statement.kind == DML: - self.connection._begin() - else: - raise ProgrammingError( - "executemany is only for DML statements") - - self.rowcount = 0 - for params in many_params: - self.statement.set_params(params) - ret = lib.sqlite3_step(self.statement.statement) - if ret != lib.SQLITE_DONE: - raise self.connection._get_exception(ret) - self.rowcount += lib.sqlite3_changes(self.connection.db) - - return self + return self.__execute(True, sql, many_params) def executescript(self, sql): - self._description = None - self.reset = False - if type(sql) is unicode: - sql = sql.encode("utf-8") - self._check_closed() - statement_star = ffi.new('sqlite3_stmt **') - tail = ffi.new('char **') + self.__check_cursor() + self._reset = False + if isinstance(sql, unicode): + sql = sql.encode('utf-8') + elif not isinstance(sql, str): + raise ValueError("script argument must be unicode or string.") + sql = c_char_p(sql) + statement = c_void_p() - self.connection.commit() + self.__connection.commit() while True: - rc = lib.sqlite3_prepare(self.connection.db, sql, -1, - statement_star, tail) - sql = ffi.string(tail[0]) - if rc != lib.SQLITE_OK: - raise self.connection._get_exception(rc) + rc = _lib.sqlite3_prepare(self.__connection._db, sql, -1, + byref(statement), byref(sql)) + if rc != _lib.SQLITE_OK: + raise self.__connection._get_exception(rc) - rc = lib.SQLITE_ROW - while rc == lib.SQLITE_ROW: - if not statement_star[0]: - rc = lib.SQLITE_OK + rc = _lib.SQLITE_ROW + while rc == _lib.SQLITE_ROW: + if not statement: + rc = _lib.SQLITE_OK else: - rc = lib.sqlite3_step(statement_star[0]) + rc = _lib.sqlite3_step(statement) - if rc != lib.SQLITE_DONE: - lib.sqlite3_finalize(statement_star[0]) - if rc == lib.SQLITE_OK: - return self + if rc != _lib.SQLITE_DONE: + _lib.sqlite3_finalize(statement) + if rc == _lib.SQLITE_OK: + break else: - raise self.connection._get_exception(rc) - rc = lib.sqlite3_finalize(statement_star[0]) - if rc != lib.SQLITE_OK: - raise self.connection._get_exception(rc) + raise self.__connection._get_exception(rc) - if not sql: + rc = _lib.sqlite3_finalize(statement) + if rc != _lib.SQLITE_OK: + raise self.__connection._get_exception(rc) + + if not sql.value: break return self + def __check_reset(self): + if self._reset: + raise self.__connection.InterfaceError( + "Cursor needed to be reset because of commit/rollback " + "and can no longer be fetched from.") + def __iter__(self): - return iter(self.fetchone, None) + return self - def _check_reset(self): - if self.reset: - raise self.connection.InterfaceError( - "Cursor needed to be reset because of commit/rollback and can " - "no longer be fetched from.") + def __next__(self): + self.__check_cursor() + self.__check_reset() + if not self.__statement: + raise StopIteration + return self.__statement._next(self) - # do all statements + if sys.version_info[0] < 3: + next = __next__ + del __next__ + def fetchone(self): - self._check_closed() - self._check_reset() - - if self.statement is None: - return None - - try: - return self.statement.next(self) - except StopIteration: - return None + return next(self, None) def fetchmany(self, size=None): - self._check_closed() - self._check_reset() - if self.statement is None: - return [] if size is None: size = self.arraysize lst = [] @@ -989,29 +969,25 @@ return lst def fetchall(self): - self._check_closed() - self._check_reset() - if self.statement is None: - return [] return list(self) - def _getdescription(self): - if self._description is None: - self._description = self.statement._get_description() - return self._description + def __get_connection(self): + return self.__connection + connection = property(__get_connection) - def _getlastrowid(self): - return lib.sqlite3_last_insert_rowid(self.connection.db) + def __get_rowcount(self): + return self.__rowcount + rowcount = property(__get_rowcount) - def close(self): - if not self.connection: - return - self._check_closed() - if self.statement: - self.statement.reset() - self.statement = None - self.connection.cursors.remove(weakref.ref(self)) - self.connection = None + def __get_description(self): + if self.__description is None: + self.__description = self.__statement._get_description() + return self.__description + description = property(__get_description) + + def __get_lastrowid(self): + return _lib.sqlite3_last_insert_rowid(self.__connection._db) + lastrowid = property(__get_lastrowid) def setinputsizes(self, *args): pass @@ -1019,92 +995,71 @@ def setoutputsize(self, *args): pass - description = property(_getdescription) - lastrowid = property(_getlastrowid) - class Statement(object): + _DML, _DQL, _DDL = range(3) + + _statement = None + def __init__(self, connection, sql): - self.statement = ffi.NULL - if not isinstance(sql, str): - raise ValueError("sql must be a string") - self.con = connection - self.sql = sql # DEBUG ONLY + self.__con = connection + self.__con._remember_statement(self) + + if not isinstance(sql, basestring): + raise Warning("SQL is of wrong type. Must be string or unicode.") first_word = self._statement_kind = sql.lstrip().split(" ")[0].upper() if first_word in ("INSERT", "UPDATE", "DELETE", "REPLACE"): - self.kind = DML + self._kind = Statement._DML elif first_word in ("SELECT", "PRAGMA"): - self.kind = DQL + self._kind = Statement._DQL else: - self.kind = DDL - self.exhausted = False - self.in_use = False - # - # set by set_row_factory - self.row_factory = None + self._kind = Statement._DDL - statement_star = ffi.new('sqlite3_stmt **') - next_char = ffi.new('char **') - ret = lib.sqlite3_prepare_v2(self.con.db, sql, -1, - statement_star, next_char) - self.statement = statement_star[0] - if ret == lib.SQLITE_OK and not self.statement: - # an empty statement, we work around that as it's the least trouble - ret = lib.sqlite3_prepare_v2(self.con.db, "select 42", -1, - statement_star, next_char) - self.statement = statement_star[0] - self.kind = DQL + self._in_use = False + self._row_factory = None - if ret != lib.SQLITE_OK: - raise self.con._get_exception(ret) - self.con._remember_statement(self) - if _check_remaining_sql(ffi.string(next_char[0])): - raise Warning("One and only one statement required: %r" % ( - next_char[0],)) - # sql_char should remain alive until here + if isinstance(sql, unicode): + sql = sql.encode('utf-8') + sql = c_char_p(sql) + self._statement = c_void_p() - self._build_row_cast_map() + ret = _lib.sqlite3_prepare_v2(self.__con._db, sql, -1, + byref(self._statement), byref(sql)) + if ret == _lib.SQLITE_OK and self._statement.value is None: + # an empty statement, work around that, as it's the least trouble + sql = c_char_p(b"select 42") + ret = _lib.sqlite3_prepare_v2(self.__con._db, sql, -1, + byref(self._statement), byref(sql)) + self._kind = Statement._DQL + if ret != _lib.SQLITE_OK: + raise self.__con._get_exception(ret) - def set_row_factory(self, row_factory): - self.row_factory = row_factory + sql = sql.value.decode('utf-8') + if _check_remaining_sql(sql): + raise Warning("You can only execute one statement at a time.") - def _build_row_cast_map(self): - self.row_cast_map = [] - for i in xrange(lib.sqlite3_column_count(self.statement)): - converter = None + def __del__(self): + if self._statement: + _lib.sqlite3_finalize(self._statement) - if self.con.detect_types & PARSE_COLNAMES: - colname = lib.sqlite3_column_name(self.statement, i) - if colname != ffi.NULL: - colname = ffi.string(colname) - type_start = -1 - key = None - for pos in range(len(colname)): - if colname[pos] == '[': - type_start = pos + 1 - elif colname[pos] == ']' and type_start != -1: - key = colname[type_start:pos] - converter = converters[key.upper()] + def _finalize(self): + if self._statement: + _lib.sqlite3_finalize(self._statement) + self._statement = None + self._in_use = False - if converter is None and self.con.detect_types & PARSE_DECLTYPES: - decltype = lib.sqlite3_column_decltype(self.statement, i) - if decltype is not ffi.NULL: - # if multiple words, use first, - # eg. "INTEGER NOT NULL" => "INTEGER" - decltype = ffi.string(decltype).split()[0] - if '(' in decltype: - decltype = decltype[:decltype.index('(')] - converter = converters.get(decltype.upper(), None) - - self.row_cast_map.append(converter) + def _reset(self): + if self._in_use and self._statement: + _lib.sqlite3_reset(self._statement) + self._in_use = False if sys.version_info[0] < 3: def __check_decodable(self, param): - if self.con.text_factory in (unicode, OptimizedUnicode, - _unicode_text_factory): + if self.__con.text_factory in (unicode, OptimizedUnicode, + _unicode_text_factory): for c in param: if ord(c) & 0x80 != 0: - raise self.con.ProgrammingError( + raise self.__con.ProgrammingError( "You must not use 8-bit bytestrings unless " "you use a text_factory that can interpret " "8-bit bytestrings (like text_factory = str). " @@ -1119,149 +1074,171 @@ param = adapt(param) if param is None: - lib.sqlite3_bind_null(self.statement, idx) + rc = _lib.sqlite3_bind_null(self._statement, idx) elif isinstance(param, (bool, int, long)): if -2147483648 <= param <= 2147483647: - lib.sqlite3_bind_int(self.statement, idx, param) + rc = _lib.sqlite3_bind_int(self._statement, idx, param) else: - lib.sqlite3_bind_int64(self.statement, idx, param) + rc = _lib.sqlite3_bind_int64(self._statement, idx, param) elif isinstance(param, float): - lib.sqlite3_bind_double(self.statement, idx, param) + rc = _lib.sqlite3_bind_double(self._statement, idx, param) elif isinstance(param, unicode): param = param.encode("utf-8") - lib.sqlite3_bind_text(self.statement, idx, param, len(param), - _SQLITE_TRANSIENT) + rc = _lib.sqlite3_bind_text(self._statement, idx, param, + len(param), _lib.SQLITE_TRANSIENT) elif isinstance(param, str): self.__check_decodable(param) - lib.sqlite3_bind_text(self.statement, idx, param, len(param), - _SQLITE_TRANSIENT) + rc = _lib.sqlite3_bind_text(self._statement, idx, param, + len(param), _lib.SQLITE_TRANSIENT) elif isinstance(param, (buffer, bytes)): - lib.sqlite3_bind_blob(self.statement, idx, str(param), len(param), - _SQLITE_TRANSIENT) + param = bytes(param) + rc = _lib.sqlite3_bind_blob(self._statement, idx, param, + len(param), _lib.SQLITE_TRANSIENT) else: - raise InterfaceError( - "parameter type %s is not supported" % str(type(param))) + rc = -1 + return rc - def set_params(self, params): - ret = lib.sqlite3_reset(self.statement) - if ret != lib.SQLITE_OK: - raise self.con._get_exception(ret) - self.mark_dirty() + def _set_params(self, params): + self._in_use = True - if params is None: - if lib.sqlite3_bind_parameter_count(self.statement) != 0: - raise ProgrammingError("wrong number of arguments") - return - - params_type = None - if isinstance(params, dict): - params_type = dict - else: - params_type = list - - if params_type == list: - if len(params) != lib.sqlite3_bind_parameter_count(self.statement): - raise ProgrammingError("wrong number of arguments") - - for i in range(len(params)): - self.__set_param(i + 1, params[i]) - else: - param_count = lib.sqlite3_bind_parameter_count(self.statement) - for idx in range(1, param_count + 1): - param_name = lib.sqlite3_bind_parameter_name(self.statement, - idx) - if param_name == ffi.NULL: - raise ProgrammingError("need named parameters") - param_name = ffi.string(param_name)[1:] + num_params_needed = _lib.sqlite3_bind_parameter_count(self._statement) + if isinstance(params, (tuple, list)) or \ + not isinstance(params, dict) and \ + hasattr(params, '__getitem__'): + try: + num_params = len(params) + except TypeError: + num_params = -1 + if num_params != num_params_needed: + raise ProgrammingError("Incorrect number of bindings supplied. " + "The current statement uses %d, and " + "there are %d supplied." % + (num_params_needed, num_params)) + for i in range(num_params): + rc = self.__set_param(i + 1, params[i]) + if rc != _lib.SQLITE_OK: + raise InterfaceError("Error binding parameter %d - " + "probably unsupported type." % i) + elif isinstance(params, dict): + for i in range(1, num_params_needed + 1): + param_name = _lib.sqlite3_bind_parameter_name(self._statement, i) + if param_name is None: + raise ProgrammingError("Binding %d has no name, but you " + "supplied a dictionary (which has " + "only names)." % i) + param_name = param_name.decode('utf-8')[1:] try: param = params[param_name] except KeyError: - raise ProgrammingError("missing parameter '%s'" % param) - self.__set_param(idx, param) + raise ProgrammingError("You did not supply a value for " + "binding %d." % i) + rc = self.__set_param(i, param) + if rc != _lib.SQLITE_OK: + raise InterfaceError("Error binding parameter :%s - " + "probably unsupported type." % + param_name) + else: + raise ValueError("parameters are of unsupported type") - def next(self, cursor): - self.con._check_closed() - self.con._check_thread() - if self.exhausted: - raise StopIteration - item = self.item + def _build_row_cast_map(self): + if not self.__con._detect_types: + return + self.__row_cast_map = [] + for i in xrange(_lib.sqlite3_column_count(self._statement)): + converter = None - ret = lib.sqlite3_step(self.statement) - if ret == lib.SQLITE_DONE: - self.exhausted = True - self.item = None - elif ret != lib.SQLITE_ROW: - exc = self.con._get_exception(ret) - lib.sqlite3_reset(self.statement) - raise exc + if self.__con._detect_types & PARSE_COLNAMES: + colname = _lib.sqlite3_column_name(self._statement, i) + if colname is not None: + colname = colname.decode('utf-8') + type_start = -1 + key = None + for pos in range(len(colname)): + if colname[pos] == '[': + type_start = pos + 1 + elif colname[pos] == ']' and type_start != -1: + key = colname[type_start:pos] + converter = converters[key.upper()] - self._readahead(cursor) - return item + if converter is None and self.__con._detect_types & PARSE_DECLTYPES: + decltype = _lib.sqlite3_column_decltype(self._statement, i) + if decltype is not None: + decltype = decltype.decode('utf-8') + # if multiple words, use first, eg. + # "INTEGER NOT NULL" => "INTEGER" + decltype = decltype.split()[0] + if '(' in decltype: + decltype = decltype[:decltype.index('(')] + converter = converters.get(decltype.upper(), None) + + self.__row_cast_map.append(converter) def _readahead(self, cursor): - self.column_count = lib.sqlite3_column_count(self.statement) row = [] - for i in xrange(self.column_count): - typ = lib.sqlite3_column_type(self.statement, i) + num_cols = _lib.sqlite3_column_count(self._statement) + for i in xrange(num_cols): + if self.__con._detect_types: + converter = self.__row_cast_map[i] + else: + converter = None - converter = self.row_cast_map[i] - if converter is None: - if typ == lib.SQLITE_NULL: - val = None - elif typ == lib.SQLITE_INTEGER: - val = lib.sqlite3_column_int64(self.statement, i) - elif typ == lib.SQLITE_FLOAT: - val = lib.sqlite3_column_double(self.statement, i) - elif typ == lib.SQLITE_TEXT: - text = lib.sqlite3_column_text(self.statement, i) - text_len = lib.sqlite3_column_bytes(self.statement, i) - val = ffi.buffer(text, text_len)[:] - val = self.con.text_factory(val) - elif typ == lib.SQLITE_BLOB: - blob = lib.sqlite3_column_blob(self.statement, i) - blob_len = lib.sqlite3_column_bytes(self.statement, i) - val = _BLOB_TYPE(ffi.buffer(blob, blob_len)) - else: - blob = lib.sqlite3_column_blob(self.statement, i) + if converter is not None: + blob = _lib.sqlite3_column_blob(self._statement, i) if not blob: val = None else: - blob_len = lib.sqlite3_column_bytes(self.statement, i) - val = ffi.buffer(blob, blob_len)[:] + blob_len = _lib.sqlite3_column_bytes(self._statement, i) + val = bytes(string_at(blob, blob_len)) val = converter(val) + else: + typ = _lib.sqlite3_column_type(self._statement, i) + if typ == _lib.SQLITE_NULL: + val = None + elif typ == _lib.SQLITE_INTEGER: + val = _lib.sqlite3_column_int64(self._statement, i) + val = int(val) + elif typ == _lib.SQLITE_FLOAT: + val = _lib.sqlite3_column_double(self._statement, i) + elif typ == _lib.SQLITE_TEXT: + text = _lib.sqlite3_column_text(self._statement, i) + text_len = _lib.sqlite3_column_bytes(self._statement, i) + val = string_at(text, text_len) + val = self.__con.text_factory(val) + elif typ == _lib.SQLITE_BLOB: + blob = _lib.sqlite3_column_blob(self._statement, i) + blob_len = _lib.sqlite3_column_bytes(self._statement, i) + val = _BLOB_TYPE(string_at(blob, blob_len)) row.append(val) row = tuple(row) - if self.row_factory is not None: - row = self.row_factory(cursor, row) - self.item = row + if self._row_factory is not None: + row = self._row_factory(cursor, row) + self._item = row - def reset(self): - self.row_cast_map = None - ret = lib.sqlite3_reset(self.statement) - self.in_use = False - self.exhausted = False - return ret + def _next(self, cursor): + try: + item = self._item + except AttributeError: + raise StopIteration + del self._item - def finalize(self): - lib.sqlite3_finalize(self.statement) - self.statement = ffi.NULL - self.in_use = False + ret = _lib.sqlite3_step(self._statement) + if ret not in (_lib.SQLITE_DONE, _lib.SQLITE_ROW): + _lib.sqlite3_reset(self._statement) + raise self.__con._get_exception(ret) + elif ret == _lib.SQLITE_ROW: + self._readahead(cursor) - def mark_dirty(self): - self.in_use = True - - def __del__(self): - lib.sqlite3_finalize(self.statement) - self.statement = ffi.NULL + return item def _get_description(self): - if self.kind == DML: + if self._kind == Statement._DML: return None desc = [] - for i in xrange(lib.sqlite3_column_count(self.statement)): - name = lib.sqlite3_column_name(self.statement, i) - name = ffi.string(name).split("[")[0].strip() + for i in xrange(_lib.sqlite3_column_count(self._statement)): + name = _lib.sqlite3_column_name(self._statement, i) + if name is not None: + name = name.decode('utf-8').split("[")[0].strip() desc.append((name, None, None, None, None, None, None)) return desc @@ -1346,20 +1323,21 @@ def _convert_params(con, nargs, params): _params = [] for i in range(nargs): - typ = lib.sqlite3_value_type(params[i]) - if typ == lib.SQLITE_NULL: + typ = _lib.sqlite3_value_type(params[i]) + if typ == _lib.SQLITE_NULL: val = None - elif typ == lib.SQLITE_INTEGER: - val = lib.sqlite3_value_int64(params[i]) - elif typ == lib.SQLITE_FLOAT: - val = lib.sqlite3_value_double(params[i]) - elif typ == lib.SQLITE_TEXT: - val = lib.sqlite3_value_text(params[i]) - val = unicode(ffi.string(val), 'utf-8') - elif typ == lib.SQLITE_BLOB: - blob = lib.sqlite3_value_blob(params[i]) - blob_len = lib.sqlite3_value_bytes(params[i]) - val = _BLOB_TYPE(ffi.buffer(blob, blob_len)) + elif typ == _lib.SQLITE_INTEGER: + val = _lib.sqlite3_value_int64(params[i]) + val = int(val) + elif typ == _lib.SQLITE_FLOAT: + val = _lib.sqlite3_value_double(params[i]) + elif typ == _lib.SQLITE_TEXT: + val = _lib.sqlite3_value_text(params[i]) + val = val.decode('utf-8') + elif typ == _lib.SQLITE_BLOB: + blob = _lib.sqlite3_value_blob(params[i]) + blob_len = _lib.sqlite3_value_bytes(params[i]) + val = _BLOB_TYPE(string_at(blob, blob_len)) else: raise NotImplementedError _params.append(val) @@ -1368,18 +1346,18 @@ def _convert_result(con, val): if val is None: - lib.sqlite3_result_null(con) + _lib.sqlite3_result_null(con) elif isinstance(val, (bool, int, long)): - lib.sqlite3_result_int64(con, int(val)) + _lib.sqlite3_result_int64(con, int(val)) elif isinstance(val, float): - lib.sqlite3_result_double(con, val) + _lib.sqlite3_result_double(con, val) elif isinstance(val, unicode): val = val.encode('utf-8') - lib.sqlite3_result_text(con, val, len(val), _SQLITE_TRANSIENT) + _lib.sqlite3_result_text(con, val, len(val), _lib.SQLITE_TRANSIENT) elif isinstance(val, str): - lib.sqlite3_result_text(con, val, len(val), _SQLITE_TRANSIENT) + _lib.sqlite3_result_text(con, val, len(val), _lib.SQLITE_TRANSIENT) elif isinstance(val, (buffer, bytes)): - lib.sqlite3_result_blob(con, str(val), len(val), _SQLITE_TRANSIENT) + _lib.sqlite3_result_blob(con, bytes(val), len(val), _lib.SQLITE_TRANSIENT) else: raise NotImplementedError @@ -1390,10 +1368,30 @@ val = real_cb(*params) except Exception: msg = b"user-defined function raised exception" - lib.sqlite3_result_error(context, msg, len(msg)) + _lib.sqlite3_result_error(context, msg, len(msg)) else: _convert_result(context, val) +_FUNC = CFUNCTYPE(None, c_void_p, c_int, POINTER(c_void_p)) +_STEP = CFUNCTYPE(None, c_void_p, c_int, POINTER(c_void_p)) +_FINAL = CFUNCTYPE(None, c_void_p) +_lib.sqlite3_create_function.argtypes = [c_void_p, c_char_p, c_int, c_int, c_void_p, _FUNC, _STEP, _FINAL] +_lib.sqlite3_create_function.restype = c_int + +_lib.sqlite3_aggregate_context.argtypes = [c_void_p, c_int] +_lib.sqlite3_aggregate_context.restype = c_void_p + +_COLLATION = CFUNCTYPE(c_int, c_void_p, c_int, c_void_p, c_int, c_void_p) +_lib.sqlite3_create_collation.argtypes = [c_void_p, c_char_p, c_int, c_void_p, _COLLATION] +_lib.sqlite3_create_collation.restype = c_int + +_PROGRESS = CFUNCTYPE(c_int, c_void_p) +_lib.sqlite3_progress_handler.argtypes = [c_void_p, c_int, _PROGRESS, c_void_p] +_lib.sqlite3_progress_handler.restype = c_int + +_AUTHORIZER = CFUNCTYPE(c_int, c_void_p, c_int, c_char_p, c_char_p, c_char_p, c_char_p) +_lib.sqlite3_set_authorizer.argtypes = [c_void_p, _AUTHORIZER, c_void_p] +_lib.sqlite3_set_authorizer.restype = c_int converters = {} adapters = {} From noreply at buildbot.pypy.org Wed Apr 3 20:53:58 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 3 Apr 2013 20:53:58 +0200 (CEST) Subject: [pypy-commit] pypy default: remerge sqlite-cffi. Now with all tests passing Message-ID: <20130403185358.1385A1C0EFF@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r62981:d4cd0aad9244 Date: 2013-04-03 20:53 +0200 http://bitbucket.org/pypy/pypy/changeset/d4cd0aad9244/ Log: remerge sqlite-cffi. Now with all tests passing diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -23,9 +23,6 @@ # # Note: This software has been modified for use in PyPy. -from ctypes import c_void_p, c_int, c_double, c_int64, c_char_p, c_char, cdll -from ctypes import POINTER, byref, string_at, CFUNCTYPE, cast -from ctypes import sizeof, c_ssize_t from collections import OrderedDict from functools import wraps import datetime @@ -44,210 +41,264 @@ else: _BLOB_TYPE = buffer +from cffi import FFI as _FFI -def load_library(names): - for name in names: - try: - return cdll.LoadLibrary(name) - except OSError: - pass - else: - raise ImportError("Could not load C-library, tried: %s" % (names,)) +_ffi = _FFI() -_lib = load_library( - "sqlite3.dll libsqlite3.so.0 libsqlite3.so libsqlite3.dylib".split()) -del load_library +_ffi.cdef(""" +#define SQLITE_OK ... +#define SQLITE_ERROR ... +#define SQLITE_INTERNAL ... +#define SQLITE_PERM ... +#define SQLITE_ABORT ... +#define SQLITE_BUSY ... +#define SQLITE_LOCKED ... +#define SQLITE_NOMEM ... +#define SQLITE_READONLY ... +#define SQLITE_INTERRUPT ... +#define SQLITE_IOERR ... +#define SQLITE_CORRUPT ... +#define SQLITE_NOTFOUND ... +#define SQLITE_FULL ... +#define SQLITE_CANTOPEN ... +#define SQLITE_PROTOCOL ... +#define SQLITE_EMPTY ... +#define SQLITE_SCHEMA ... +#define SQLITE_TOOBIG ... +#define SQLITE_CONSTRAINT ... +#define SQLITE_MISMATCH ... +#define SQLITE_MISUSE ... +#define SQLITE_NOLFS ... +#define SQLITE_AUTH ... +#define SQLITE_FORMAT ... +#define SQLITE_RANGE ... +#define SQLITE_NOTADB ... +#define SQLITE_ROW ... +#define SQLITE_DONE ... +#define SQLITE_INTEGER ... +#define SQLITE_FLOAT ... +#define SQLITE_BLOB ... +#define SQLITE_NULL ... +#define SQLITE_TEXT ... +#define SQLITE3_TEXT ... -########################################## -# BEGIN Wrapped SQLite C API and constants -########################################## +#define SQLITE_TRANSIENT ... +#define SQLITE_UTF8 ... -_lib.SQLITE_OK = 0 -_lib.SQLITE_ERROR = 1 -_lib.SQLITE_INTERNAL = 2 -_lib.SQLITE_PERM = 3 -_lib.SQLITE_ABORT = 4 -_lib.SQLITE_BUSY = 5 -_lib.SQLITE_LOCKED = 6 -_lib.SQLITE_NOMEM = 7 -_lib.SQLITE_READONLY = 8 -_lib.SQLITE_INTERRUPT = 9 -_lib.SQLITE_IOERR = 10 -_lib.SQLITE_CORRUPT = 11 -_lib.SQLITE_NOTFOUND = 12 -_lib.SQLITE_FULL = 13 -_lib.SQLITE_CANTOPEN = 14 -_lib.SQLITE_PROTOCOL = 15 -_lib.SQLITE_EMPTY = 16 -_lib.SQLITE_SCHEMA = 17 -_lib.SQLITE_TOOBIG = 18 -_lib.SQLITE_CONSTRAINT = 19 -_lib.SQLITE_MISMATCH = 20 -_lib.SQLITE_MISUSE = 21 -_lib.SQLITE_NOLFS = 22 -_lib.SQLITE_AUTH = 23 -_lib.SQLITE_FORMAT = 24 -_lib.SQLITE_RANGE = 25 -_lib.SQLITE_NOTADB = 26 -_lib.SQLITE_ROW = 100 -_lib.SQLITE_DONE = 101 +#define SQLITE_DENY ... +#define SQLITE_IGNORE ... -_lib.SQLITE_INTEGER = 1 -_lib.SQLITE_FLOAT = 2 -_lib.SQLITE_TEXT = 3 -_lib.SQLITE_BLOB = 4 -_lib.SQLITE_NULL = 5 +#define SQLITE_CREATE_INDEX ... +#define SQLITE_CREATE_TABLE ... +#define SQLITE_CREATE_TEMP_INDEX ... +#define SQLITE_CREATE_TEMP_TABLE ... +#define SQLITE_CREATE_TEMP_TRIGGER ... +#define SQLITE_CREATE_TEMP_VIEW ... +#define SQLITE_CREATE_TRIGGER ... +#define SQLITE_CREATE_VIEW ... +#define SQLITE_DELETE ... +#define SQLITE_DROP_INDEX ... +#define SQLITE_DROP_TABLE ... +#define SQLITE_DROP_TEMP_INDEX ... +#define SQLITE_DROP_TEMP_TABLE ... +#define SQLITE_DROP_TEMP_TRIGGER ... +#define SQLITE_DROP_TEMP_VIEW ... +#define SQLITE_DROP_TRIGGER ... +#define SQLITE_DROP_VIEW ... +#define SQLITE_INSERT ... +#define SQLITE_PRAGMA ... +#define SQLITE_READ ... +#define SQLITE_SELECT ... +#define SQLITE_TRANSACTION ... +#define SQLITE_UPDATE ... +#define SQLITE_ATTACH ... +#define SQLITE_DETACH ... +#define SQLITE_ALTER_TABLE ... +#define SQLITE_REINDEX ... +#define SQLITE_ANALYZE ... +#define SQLITE_CREATE_VTABLE ... +#define SQLITE_DROP_VTABLE ... +#define SQLITE_FUNCTION ... -_lib.SQLITE_UTF8 = 1 +const char *sqlite3_libversion(void); -_lib.SQLITE_TRANSIENT = cast(-1, c_void_p) +typedef ... sqlite3; +typedef ... sqlite3_stmt; +typedef ... sqlite3_context; +typedef ... sqlite3_value; +typedef int64_t sqlite3_int64; +typedef uint64_t sqlite3_uint64; -SQLITE_OK = _lib.SQLITE_OK +int sqlite3_open( + const char *filename, /* Database filename (UTF-8) */ + sqlite3 **ppDb /* OUT: SQLite db handle */ +); -SQLITE_DENY = 1 -SQLITE_IGNORE = 2 +int sqlite3_close(sqlite3 *); -SQLITE_CREATE_INDEX = 1 -SQLITE_CREATE_TABLE = 2 -SQLITE_CREATE_TEMP_INDEX = 3 -SQLITE_CREATE_TEMP_TABLE = 4 -SQLITE_CREATE_TEMP_TRIGGER = 5 -SQLITE_CREATE_TEMP_VIEW = 6 -SQLITE_CREATE_TRIGGER = 7 -SQLITE_CREATE_VIEW = 8 -SQLITE_DELETE = 9 -SQLITE_DROP_INDEX = 10 -SQLITE_DROP_TABLE = 11 -SQLITE_DROP_TEMP_INDEX = 12 -SQLITE_DROP_TEMP_TABLE = 13 -SQLITE_DROP_TEMP_TRIGGER = 14 -SQLITE_DROP_TEMP_VIEW = 15 -SQLITE_DROP_TRIGGER = 16 -SQLITE_DROP_VIEW = 17 -SQLITE_INSERT = 18 -SQLITE_PRAGMA = 19 -SQLITE_READ = 20 -SQLITE_SELECT = 21 -SQLITE_TRANSACTION = 22 -SQLITE_UPDATE = 23 -SQLITE_ATTACH = 24 -SQLITE_DETACH = 25 -SQLITE_ALTER_TABLE = 26 -SQLITE_REINDEX = 27 -SQLITE_ANALYZE = 28 +int sqlite3_busy_timeout(sqlite3*, int ms); +int sqlite3_prepare_v2( + sqlite3 *db, /* Database handle */ + const char *zSql, /* SQL statement, UTF-8 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const char **pzTail /* OUT: Pointer to unused portion of zSql */ +); +int sqlite3_finalize(sqlite3_stmt *pStmt); +int sqlite3_column_count(sqlite3_stmt *pStmt); +const char *sqlite3_column_name(sqlite3_stmt*, int N); +int sqlite3_get_autocommit(sqlite3*); +int sqlite3_reset(sqlite3_stmt *pStmt); +int sqlite3_step(sqlite3_stmt*); +int sqlite3_errcode(sqlite3 *db); +const char *sqlite3_errmsg(sqlite3*); +int sqlite3_changes(sqlite3*); -# SQLite C API +int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); +int sqlite3_bind_double(sqlite3_stmt*, int, double); +int sqlite3_bind_int(sqlite3_stmt*, int, int); +int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); +int sqlite3_bind_null(sqlite3_stmt*, int); +int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*)); +int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); +int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); +int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); -_lib.sqlite3_value_int.argtypes = [c_void_p] -_lib.sqlite3_value_int.restype = c_int +const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); +int sqlite3_column_bytes(sqlite3_stmt*, int iCol); +double sqlite3_column_double(sqlite3_stmt*, int iCol); +int sqlite3_column_int(sqlite3_stmt*, int iCol); +sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol); +const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); +const void *sqlite3_column_text16(sqlite3_stmt*, int iCol); +int sqlite3_column_type(sqlite3_stmt*, int iCol); +const char *sqlite3_column_decltype(sqlite3_stmt*,int); -_lib.sqlite3_value_int64.argtypes = [c_void_p] -_lib.sqlite3_value_int64.restype = c_int64 +void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); +int sqlite3_create_collation( + sqlite3*, + const char *zName, + int eTextRep, + void*, + int(*xCompare)(void*,int,const void*,int,const void*) +); +int sqlite3_set_authorizer( + sqlite3*, + int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), + void *pUserData +); +int sqlite3_create_function( + sqlite3 *db, + const char *zFunctionName, + int nArg, + int eTextRep, + void *pApp, + void (*xFunc)(sqlite3_context*,int,sqlite3_value**), + void (*xStep)(sqlite3_context*,int,sqlite3_value**), + void (*xFinal)(sqlite3_context*) +); +void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); -_lib.sqlite3_value_blob.argtypes = [c_void_p] -_lib.sqlite3_value_blob.restype = c_void_p +sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); +int sqlite3_bind_parameter_count(sqlite3_stmt*); +const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); +int sqlite3_total_changes(sqlite3*); -_lib.sqlite3_value_bytes.argtypes = [c_void_p] -_lib.sqlite3_value_bytes.restype = c_int +int sqlite3_prepare( + sqlite3 *db, /* Database handle */ + const char *zSql, /* SQL statement, UTF-8 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const char **pzTail /* OUT: Pointer to unused portion of zSql */ +); -_lib.sqlite3_value_double.argtypes = [c_void_p] -_lib.sqlite3_value_double.restype = c_double +void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); +void sqlite3_result_double(sqlite3_context*, double); +void sqlite3_result_error(sqlite3_context*, const char*, int); +void sqlite3_result_error16(sqlite3_context*, const void*, int); +void sqlite3_result_error_toobig(sqlite3_context*); +void sqlite3_result_error_nomem(sqlite3_context*); +void sqlite3_result_error_code(sqlite3_context*, int); +void sqlite3_result_int(sqlite3_context*, int); +void sqlite3_result_int64(sqlite3_context*, sqlite3_int64); +void sqlite3_result_null(sqlite3_context*); +void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); +void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); +void sqlite3_result_text16le(sqlite3_context*,const void*, int,void(*)(void*)); +void sqlite3_result_text16be(sqlite3_context*,const void*, int,void(*)(void*)); +void sqlite3_result_value(sqlite3_context*, sqlite3_value*); +void sqlite3_result_zeroblob(sqlite3_context*, int n); -_lib.sqlite3_value_text.argtypes = [c_void_p] -_lib.sqlite3_value_text.restype = c_char_p +const void *sqlite3_value_blob(sqlite3_value*); +int sqlite3_value_bytes(sqlite3_value*); +int sqlite3_value_bytes16(sqlite3_value*); +double sqlite3_value_double(sqlite3_value*); +int sqlite3_value_int(sqlite3_value*); +sqlite3_int64 sqlite3_value_int64(sqlite3_value*); +const unsigned char *sqlite3_value_text(sqlite3_value*); +const void *sqlite3_value_text16(sqlite3_value*); +const void *sqlite3_value_text16le(sqlite3_value*); +const void *sqlite3_value_text16be(sqlite3_value*); +int sqlite3_value_type(sqlite3_value*); +int sqlite3_value_numeric_type(sqlite3_value*); +""") -_lib.sqlite3_value_type.argtypes = [c_void_p] -_lib.sqlite3_value_type.restype = c_int +def _has_load_extension(): + """Only available since 3.3.6""" + unverified_ffi = _FFI() + unverified_ffi.cdef(""" + typedef ... sqlite3; + int sqlite3_enable_load_extension(sqlite3 *db, int onoff); + """) + unverified_lib = unverified_ffi.dlopen('sqlite3') + return hasattr(unverified_lib, 'sqlite3_enable_load_extension') -_lib.sqlite3_bind_blob.argtypes = [c_void_p, c_int, c_void_p, c_int, c_void_p] -_lib.sqlite3_bind_blob.restype = c_int -_lib.sqlite3_bind_double.argtypes = [c_void_p, c_int, c_double] -_lib.sqlite3_bind_double.restype = c_int -_lib.sqlite3_bind_int.argtypes = [c_void_p, c_int, c_int] -_lib.sqlite3_bind_int.restype = c_int -_lib.sqlite3_bind_int64.argtypes = [c_void_p, c_int, c_int64] -_lib.sqlite3_bind_int64.restype = c_int -_lib.sqlite3_bind_null.argtypes = [c_void_p, c_int] -_lib.sqlite3_bind_null.restype = c_int -_lib.sqlite3_bind_parameter_count.argtypes = [c_void_p] -_lib.sqlite3_bind_parameter_count.restype = c_int -_lib.sqlite3_bind_parameter_index.argtypes = [c_void_p, c_char_p] -_lib.sqlite3_bind_parameter_index.restype = c_int -_lib.sqlite3_bind_parameter_name.argtypes = [c_void_p, c_int] -_lib.sqlite3_bind_parameter_name.restype = c_char_p -_lib.sqlite3_bind_text.argtypes = [c_void_p, c_int, c_char_p, c_int, c_void_p] -_lib.sqlite3_bind_text.restype = c_int -_lib.sqlite3_busy_timeout.argtypes = [c_void_p, c_int] -_lib.sqlite3_busy_timeout.restype = c_int -_lib.sqlite3_changes.argtypes = [c_void_p] -_lib.sqlite3_changes.restype = c_int -_lib.sqlite3_close.argtypes = [c_void_p] -_lib.sqlite3_close.restype = c_int -_lib.sqlite3_column_blob.argtypes = [c_void_p, c_int] -_lib.sqlite3_column_blob.restype = c_void_p -_lib.sqlite3_column_bytes.argtypes = [c_void_p, c_int] -_lib.sqlite3_column_bytes.restype = c_int -_lib.sqlite3_column_count.argtypes = [c_void_p] -_lib.sqlite3_column_count.restype = c_int -_lib.sqlite3_column_decltype.argtypes = [c_void_p, c_int] -_lib.sqlite3_column_decltype.restype = c_char_p -_lib.sqlite3_column_double.argtypes = [c_void_p, c_int] -_lib.sqlite3_column_double.restype = c_double -_lib.sqlite3_column_int64.argtypes = [c_void_p, c_int] -_lib.sqlite3_column_int64.restype = c_int64 -_lib.sqlite3_column_name.argtypes = [c_void_p, c_int] -_lib.sqlite3_column_name.restype = c_char_p -_lib.sqlite3_column_text.argtypes = [c_void_p, c_int] -_lib.sqlite3_column_text.restype = POINTER(c_char) -_lib.sqlite3_column_type.argtypes = [c_void_p, c_int] -_lib.sqlite3_column_type.restype = c_int -_lib.sqlite3_complete.argtypes = [c_char_p] -_lib.sqlite3_complete.restype = c_int -_lib.sqlite3_errcode.restype = c_int -_lib.sqlite3_errmsg.argtypes = [c_void_p] -_lib.sqlite3_errmsg.restype = c_char_p -_lib.sqlite3_finalize.argtypes = [c_void_p] -_lib.sqlite3_finalize.restype = c_int -_lib.sqlite3_get_autocommit.argtypes = [c_void_p] -_lib.sqlite3_get_autocommit.restype = c_int -_lib.sqlite3_last_insert_rowid.argtypes = [c_void_p] -_lib.sqlite3_last_insert_rowid.restype = c_int64 -_lib.sqlite3_libversion.argtypes = [] -_lib.sqlite3_libversion.restype = c_char_p -_lib.sqlite3_open.argtypes = [c_char_p, c_void_p] -_lib.sqlite3_open.restype = c_int -_lib.sqlite3_prepare.argtypes = [c_void_p, c_char_p, c_int, c_void_p, POINTER(c_char_p)] -_lib.sqlite3_prepare.restype = c_int -_lib.sqlite3_prepare_v2.argtypes = [c_void_p, c_char_p, c_int, c_void_p, POINTER(c_char_p)] -_lib.sqlite3_prepare_v2.restype = c_int -_lib.sqlite3_step.argtypes = [c_void_p] -_lib.sqlite3_step.restype = c_int -_lib.sqlite3_reset.argtypes = [c_void_p] -_lib.sqlite3_reset.restype = c_int -_lib.sqlite3_total_changes.argtypes = [c_void_p] -_lib.sqlite3_total_changes.restype = c_int +if _has_load_extension(): + _ffi.cdef("int sqlite3_enable_load_extension(sqlite3 *db, int onoff);") -_lib.sqlite3_result_blob.argtypes = [c_void_p, c_void_p, c_int, c_void_p] -_lib.sqlite3_result_blob.restype = None -_lib.sqlite3_result_int64.argtypes = [c_void_p, c_int64] -_lib.sqlite3_result_int64.restype = None -_lib.sqlite3_result_null.argtypes = [c_void_p] -_lib.sqlite3_result_null.restype = None -_lib.sqlite3_result_double.argtypes = [c_void_p, c_double] -_lib.sqlite3_result_double.restype = None -_lib.sqlite3_result_error.argtypes = [c_void_p, c_char_p, c_int] -_lib.sqlite3_result_error.restype = None -_lib.sqlite3_result_text.argtypes = [c_void_p, c_char_p, c_int, c_void_p] -_lib.sqlite3_result_text.restype = None +_lib = _ffi.verify(""" +#include +""", libraries=['sqlite3'] +) -_HAS_LOAD_EXTENSION = hasattr(_lib, "sqlite3_enable_load_extension") -if _HAS_LOAD_EXTENSION: - _lib.sqlite3_enable_load_extension.argtypes = [c_void_p, c_int] - _lib.sqlite3_enable_load_extension.restype = c_int +exported_sqlite_symbols = [ + 'SQLITE_ALTER_TABLE', + 'SQLITE_ANALYZE', + 'SQLITE_ATTACH', + 'SQLITE_CREATE_INDEX', + 'SQLITE_CREATE_TABLE', + 'SQLITE_CREATE_TEMP_INDEX', + 'SQLITE_CREATE_TEMP_TABLE', + 'SQLITE_CREATE_TEMP_TRIGGER', + 'SQLITE_CREATE_TEMP_VIEW', + 'SQLITE_CREATE_TRIGGER', + 'SQLITE_CREATE_VIEW', + 'SQLITE_DELETE', + 'SQLITE_DENY', + 'SQLITE_DETACH', + 'SQLITE_DROP_INDEX', + 'SQLITE_DROP_TABLE', + 'SQLITE_DROP_TEMP_INDEX', + 'SQLITE_DROP_TEMP_TABLE', + 'SQLITE_DROP_TEMP_TRIGGER', + 'SQLITE_DROP_TEMP_VIEW', + 'SQLITE_DROP_TRIGGER', + 'SQLITE_DROP_VIEW', + 'SQLITE_IGNORE', + 'SQLITE_INSERT', + 'SQLITE_OK', + 'SQLITE_PRAGMA', + 'SQLITE_READ', + 'SQLITE_REINDEX', + 'SQLITE_SELECT', + 'SQLITE_TRANSACTION', + 'SQLITE_UPDATE', +] -########################################## -# END Wrapped SQLite C API and constants -########################################## +for symbol in exported_sqlite_symbols: + globals()[symbol] = getattr(_lib, symbol) + +_SQLITE_TRANSIENT = _ffi.cast('void *', _lib.SQLITE_TRANSIENT) # pysqlite version information version = "2.6.0" @@ -257,7 +308,7 @@ PARSE_DECLTYPES = 2 # SQLite version information -sqlite_version = str(_lib.sqlite3_libversion().decode('ascii')) +sqlite_version = _ffi.string(_lib.sqlite3_libversion()) class Error(StandardError): @@ -347,12 +398,13 @@ def __init__(self, database, timeout=5.0, detect_types=0, isolation_level="", check_same_thread=True, factory=None, cached_statements=100): self.__initialized = True - self._db = c_void_p() + db_star = _ffi.new('sqlite3 **') if isinstance(database, unicode): database = database.encode('utf-8') - if _lib.sqlite3_open(database, byref(self._db)) != _lib.SQLITE_OK: + if _lib.sqlite3_open(database, db_star) != _lib.SQLITE_OK: raise OperationalError("Could not open database") + self._db = db_star[0] if timeout is not None: timeout = int(timeout * 1000) # pysqlite2 uses timeout in seconds _lib.sqlite3_busy_timeout(self._db, timeout) @@ -438,7 +490,7 @@ def _get_exception(self, error_code=None): if error_code is None: error_code = _lib.sqlite3_errcode(self._db) - error_message = _lib.sqlite3_errmsg(self._db).decode('utf-8') + error_message = _ffi.string(_lib.sqlite3_errmsg(self._db)).decode('utf-8') if error_code == _lib.SQLITE_OK: raise ValueError("error signalled but got SQLITE_OK") @@ -527,18 +579,20 @@ return _iterdump(self) def _begin(self): - statement = c_void_p() + self._check_closed() + statement_star = _ffi.new('sqlite3_stmt **') + next_char = _ffi.new('char **') ret = _lib.sqlite3_prepare_v2(self._db, self.__begin_statement, -1, - byref(statement), None) + statement_star, next_char) try: if ret != _lib.SQLITE_OK: raise self._get_exception(ret) - ret = _lib.sqlite3_step(statement) + ret = _lib.sqlite3_step(statement_star[0]) if ret != _lib.SQLITE_DONE: raise self._get_exception(ret) self._in_transaction = True finally: - _lib.sqlite3_finalize(statement) + _lib.sqlite3_finalize(statement_star[0]) def commit(self): self._check_thread() @@ -548,18 +602,19 @@ self.__do_all_statements(Statement._reset, False) - statement = c_void_p() + statement_star = _ffi.new('sqlite3_stmt **') + next_char = _ffi.new('char **') ret = _lib.sqlite3_prepare_v2(self._db, b"COMMIT", -1, - byref(statement), None) + statement_star, next_char) try: if ret != _lib.SQLITE_OK: raise self._get_exception(ret) - ret = _lib.sqlite3_step(statement) + ret = _lib.sqlite3_step(statement_star[0]) if ret != _lib.SQLITE_DONE: raise self._get_exception(ret) self._in_transaction = False finally: - _lib.sqlite3_finalize(statement) + _lib.sqlite3_finalize(statement_star[0]) def rollback(self): self._check_thread() @@ -569,18 +624,19 @@ self.__do_all_statements(Statement._reset, True) - statement = c_void_p() + statement_star = _ffi.new('sqlite3_stmt **') + next_char = _ffi.new('char **') ret = _lib.sqlite3_prepare_v2(self._db, b"ROLLBACK", -1, - byref(statement), None) + statement_star, next_char) try: if ret != _lib.SQLITE_OK: raise self._get_exception(ret) - ret = _lib.sqlite3_step(statement) + ret = _lib.sqlite3_step(statement_star[0]) if ret != _lib.SQLITE_DONE: raise self._get_exception(ret) self._in_transaction = False finally: - _lib.sqlite3_finalize(statement) + _lib.sqlite3_finalize(statement_star[0]) def __enter__(self): return self @@ -595,20 +651,18 @@ @_check_closed_wrap def create_function(self, name, num_args, callback): try: - c_closure, _ = self.__func_cache[callback] + closure = self.__func_cache[callback] except KeyError: + @_ffi.callback("void(sqlite3_context*, int, sqlite3_value**)") def closure(context, nargs, c_params): _function_callback(callback, context, nargs, c_params) - c_closure = _FUNC(closure) - self.__func_cache[callback] = c_closure, closure + self.__func_cache[callback] = closure if isinstance(name, unicode): name = name.encode('utf-8') ret = _lib.sqlite3_create_function(self._db, name, num_args, - _lib.SQLITE_UTF8, None, - c_closure, - cast(None, _STEP), - cast(None, _FINAL)) + _lib.SQLITE_UTF8, _ffi.NULL, + closure, _ffi.NULL, _ffi.NULL) if ret != _lib.SQLITE_OK: raise self.OperationalError("Error creating function") @@ -616,13 +670,13 @@ @_check_closed_wrap def create_aggregate(self, name, num_args, cls): try: - c_step_callback, c_final_callback, _, _ = self.__aggregates[cls] + step_callback, final_callback = self.__aggregates[cls] except KeyError: + @_ffi.callback("void(sqlite3_context*, int, sqlite3_value**)") def step_callback(context, argc, c_params): - aggregate_ptr = cast( - _lib.sqlite3_aggregate_context( - context, sizeof(c_ssize_t)), - POINTER(c_ssize_t)) + res = _lib.sqlite3_aggregate_context(context, + _ffi.sizeof("size_t")) + aggregate_ptr = _ffi.cast("size_t[1]", res) if not aggregate_ptr[0]: try: @@ -646,11 +700,11 @@ b"method raised error") _lib.sqlite3_result_error(context, msg, len(msg)) + @_ffi.callback("void(sqlite3_context*)") def final_callback(context): - aggregate_ptr = cast( - _lib.sqlite3_aggregate_context( - context, sizeof(c_ssize_t)), - POINTER(c_ssize_t)) + res = _lib.sqlite3_aggregate_context(context, + _ffi.sizeof("size_t")) + aggregate_ptr = _ffi.cast("size_t[1]", res) if aggregate_ptr[0]: aggregate = self.__aggregate_instances[aggregate_ptr[0]] @@ -665,19 +719,15 @@ finally: del self.__aggregate_instances[aggregate_ptr[0]] - c_step_callback = _STEP(step_callback) - c_final_callback = _FINAL(final_callback) - - self.__aggregates[cls] = (c_step_callback, c_final_callback, - step_callback, final_callback) + self.__aggregates[cls] = (step_callback, final_callback) if isinstance(name, unicode): name = name.encode('utf-8') ret = _lib.sqlite3_create_function(self._db, name, num_args, - _lib.SQLITE_UTF8, None, - cast(None, _FUNC), - c_step_callback, - c_final_callback) + _lib.SQLITE_UTF8, _ffi.NULL, + _ffi.NULL, + step_callback, + final_callback) if ret != _lib.SQLITE_OK: raise self._get_exception(ret) @@ -690,26 +740,26 @@ if callback is None: del self.__collations[name] - c_collation_callback = cast(None, _COLLATION) + collation_callback = _ffi.NULL else: if not callable(callback): raise TypeError("parameter must be callable") + @_ffi.callback("int(void*, int, const void*, int, const void*)") def collation_callback(context, len1, str1, len2, str2): - text1 = string_at(str1, len1).decode('utf-8') - text2 = string_at(str2, len2).decode('utf-8') + text1 = _ffi.buffer(str1, len1)[:] + text2 = _ffi.buffer(str2, len2)[:] return callback(text1, text2) - c_collation_callback = _COLLATION(collation_callback) - self.__collations[name] = c_collation_callback + self.__collations[name] = collation_callback if isinstance(name, unicode): name = name.encode('utf-8') ret = _lib.sqlite3_create_collation(self._db, name, _lib.SQLITE_UTF8, - None, - c_collation_callback) + _ffi.NULL, + collation_callback) if ret != _lib.SQLITE_OK: raise self._get_exception(ret) @@ -717,20 +767,20 @@ @_check_closed_wrap def set_authorizer(self, callback): try: - c_authorizer, _ = self.__func_cache[callback] + authorizer = self.__func_cache[callback] except KeyError: + @_ffi.callback("int(void*, int, const char*, const char*, " + "const char*, const char*)") def authorizer(userdata, action, arg1, arg2, dbname, source): try: return int(callback(action, arg1, arg2, dbname, source)) except Exception: - return SQLITE_DENY - c_authorizer = _AUTHORIZER(authorizer) - - self.__func_cache[callback] = c_authorizer, authorizer + return _lib.SQLITE_DENY + self.__func_cache[callback] = authorizer ret = _lib.sqlite3_set_authorizer(self._db, - c_authorizer, - None) + authorizer, + _ffi.NULL) if ret != _lib.SQLITE_OK: raise self._get_exception(ret) @@ -738,11 +788,12 @@ @_check_closed_wrap def set_progress_handler(self, callable, nsteps): if callable is None: - c_progress_handler = cast(None, _PROGRESS) + progress_handler = _ffi.NULL else: try: - c_progress_handler, _ = self.__func_cache[callable] + progress_handler = self.__func_cache[callable] except KeyError: + @_ffi.callback("int(void*)") def progress_handler(userdata): try: ret = callable() @@ -750,14 +801,10 @@ except Exception: # abort query if error occurred return 1 - c_progress_handler = _PROGRESS(progress_handler) - - self.__func_cache[callable] = c_progress_handler, progress_handler - ret = _lib.sqlite3_progress_handler(self._db, nsteps, - c_progress_handler, - None) - if ret != _lib.SQLITE_OK: - raise self._get_exception(ret) + self.__func_cache[callable] = progress_handler + _lib.sqlite3_progress_handler(self._db, nsteps, + progress_handler, + _ffi.NULL) if sys.version_info[0] >= 3: def __get_in_transaction(self): @@ -780,7 +827,7 @@ self._isolation_level = val isolation_level = property(__get_isolation_level, __set_isolation_level) - if _HAS_LOAD_EXTENSION: + if hasattr(_lib, 'sqlite3_enable_load_extension'): @_check_thread_wrap @_check_closed_wrap def enable_load_extension(self, enabled): @@ -903,35 +950,36 @@ sql = sql.encode('utf-8') elif not isinstance(sql, str): raise ValueError("script argument must be unicode or string.") - sql = c_char_p(sql) - statement = c_void_p() + statement_star = _ffi.new('sqlite3_stmt **') + tail = _ffi.new('char **') self.__connection.commit() while True: rc = _lib.sqlite3_prepare(self.__connection._db, sql, -1, - byref(statement), byref(sql)) + statement_star, tail) + sql = _ffi.string(tail[0]) if rc != _lib.SQLITE_OK: raise self.__connection._get_exception(rc) rc = _lib.SQLITE_ROW while rc == _lib.SQLITE_ROW: - if not statement: + if not statement_star[0]: rc = _lib.SQLITE_OK else: - rc = _lib.sqlite3_step(statement) + rc = _lib.sqlite3_step(statement_star[0]) if rc != _lib.SQLITE_DONE: - _lib.sqlite3_finalize(statement) + _lib.sqlite3_finalize(statement_star[0]) if rc == _lib.SQLITE_OK: break else: raise self.__connection._get_exception(rc) - rc = _lib.sqlite3_finalize(statement) + rc = _lib.sqlite3_finalize(statement_star[0]) if rc != _lib.SQLITE_OK: raise self.__connection._get_exception(rc) - if not sql.value: + if not sql: break return self @@ -1020,22 +1068,22 @@ if isinstance(sql, unicode): sql = sql.encode('utf-8') - sql = c_char_p(sql) - self._statement = c_void_p() + statement_star = _ffi.new('sqlite3_stmt **') + next_char = _ffi.new('char **') + ret = _lib.sqlite3_prepare_v2(self.__con._db, sql, -1, + statement_star, next_char) + self._statement = statement_star[0] - ret = _lib.sqlite3_prepare_v2(self.__con._db, sql, -1, - byref(self._statement), byref(sql)) - if ret == _lib.SQLITE_OK and self._statement.value is None: + if ret == _lib.SQLITE_OK and not self._statement: # an empty statement, work around that, as it's the least trouble - sql = c_char_p(b"select 42") - ret = _lib.sqlite3_prepare_v2(self.__con._db, sql, -1, - byref(self._statement), byref(sql)) + ret = _lib.sqlite3_prepare_v2(self.__con._db, "select 42", -1, + statement_star, next_char) + self._statement = statement_star[0] self._kind = Statement._DQL if ret != _lib.SQLITE_OK: raise self.__con._get_exception(ret) - sql = sql.value.decode('utf-8') - if _check_remaining_sql(sql): + if _check_remaining_sql(_ffi.string(next_char[0])): raise Warning("You can only execute one statement at a time.") def __del__(self): @@ -1085,15 +1133,15 @@ elif isinstance(param, unicode): param = param.encode("utf-8") rc = _lib.sqlite3_bind_text(self._statement, idx, param, - len(param), _lib.SQLITE_TRANSIENT) + len(param), _SQLITE_TRANSIENT) elif isinstance(param, str): self.__check_decodable(param) rc = _lib.sqlite3_bind_text(self._statement, idx, param, - len(param), _lib.SQLITE_TRANSIENT) + len(param), _SQLITE_TRANSIENT) elif isinstance(param, (buffer, bytes)): param = bytes(param) rc = _lib.sqlite3_bind_blob(self._statement, idx, param, - len(param), _lib.SQLITE_TRANSIENT) + len(param), _SQLITE_TRANSIENT) else: rc = -1 return rc @@ -1122,11 +1170,11 @@ elif isinstance(params, dict): for i in range(1, num_params_needed + 1): param_name = _lib.sqlite3_bind_parameter_name(self._statement, i) - if param_name is None: + if not param_name: raise ProgrammingError("Binding %d has no name, but you " "supplied a dictionary (which has " "only names)." % i) - param_name = param_name.decode('utf-8')[1:] + param_name = _ffi.string(param_name)[1:] try: param = params[param_name] except KeyError: @@ -1150,7 +1198,7 @@ if self.__con._detect_types & PARSE_COLNAMES: colname = _lib.sqlite3_column_name(self._statement, i) if colname is not None: - colname = colname.decode('utf-8') + colname = _ffi.string(colname) type_start = -1 key = None for pos in range(len(colname)): @@ -1163,7 +1211,7 @@ if converter is None and self.__con._detect_types & PARSE_DECLTYPES: decltype = _lib.sqlite3_column_decltype(self._statement, i) if decltype is not None: - decltype = decltype.decode('utf-8') + decltype = _ffi.string(decltype) # if multiple words, use first, eg. # "INTEGER NOT NULL" => "INTEGER" decltype = decltype.split()[0] @@ -1188,7 +1236,7 @@ val = None else: blob_len = _lib.sqlite3_column_bytes(self._statement, i) - val = bytes(string_at(blob, blob_len)) + val = _ffi.buffer(blob, blob_len)[:] val = converter(val) else: typ = _lib.sqlite3_column_type(self._statement, i) @@ -1202,12 +1250,12 @@ elif typ == _lib.SQLITE_TEXT: text = _lib.sqlite3_column_text(self._statement, i) text_len = _lib.sqlite3_column_bytes(self._statement, i) - val = string_at(text, text_len) + val = _ffi.buffer(text, text_len)[:] val = self.__con.text_factory(val) elif typ == _lib.SQLITE_BLOB: blob = _lib.sqlite3_column_blob(self._statement, i) blob_len = _lib.sqlite3_column_bytes(self._statement, i) - val = _BLOB_TYPE(string_at(blob, blob_len)) + val = _BLOB_TYPE(_ffi.buffer(blob, blob_len)) row.append(val) row = tuple(row) @@ -1237,8 +1285,7 @@ desc = [] for i in xrange(_lib.sqlite3_column_count(self._statement)): name = _lib.sqlite3_column_name(self._statement, i) - if name is not None: - name = name.decode('utf-8').split("[")[0].strip() + name = _ffi.string(name).split("[")[0].strip() desc.append((name, None, None, None, None, None, None)) return desc @@ -1333,11 +1380,11 @@ val = _lib.sqlite3_value_double(params[i]) elif typ == _lib.SQLITE_TEXT: val = _lib.sqlite3_value_text(params[i]) - val = val.decode('utf-8') + val = unicode(_ffi.string(val), 'utf-8') elif typ == _lib.SQLITE_BLOB: blob = _lib.sqlite3_value_blob(params[i]) blob_len = _lib.sqlite3_value_bytes(params[i]) - val = _BLOB_TYPE(string_at(blob, blob_len)) + val = _BLOB_TYPE(_ffi.buffer(blob, blob_len)) else: raise NotImplementedError _params.append(val) @@ -1353,11 +1400,11 @@ _lib.sqlite3_result_double(con, val) elif isinstance(val, unicode): val = val.encode('utf-8') - _lib.sqlite3_result_text(con, val, len(val), _lib.SQLITE_TRANSIENT) + _lib.sqlite3_result_text(con, val, len(val), _SQLITE_TRANSIENT) elif isinstance(val, str): - _lib.sqlite3_result_text(con, val, len(val), _lib.SQLITE_TRANSIENT) + _lib.sqlite3_result_text(con, val, len(val), _SQLITE_TRANSIENT) elif isinstance(val, (buffer, bytes)): - _lib.sqlite3_result_blob(con, bytes(val), len(val), _lib.SQLITE_TRANSIENT) + _lib.sqlite3_result_blob(con, bytes(val), len(val), _SQLITE_TRANSIENT) else: raise NotImplementedError @@ -1372,27 +1419,6 @@ else: _convert_result(context, val) -_FUNC = CFUNCTYPE(None, c_void_p, c_int, POINTER(c_void_p)) -_STEP = CFUNCTYPE(None, c_void_p, c_int, POINTER(c_void_p)) -_FINAL = CFUNCTYPE(None, c_void_p) -_lib.sqlite3_create_function.argtypes = [c_void_p, c_char_p, c_int, c_int, c_void_p, _FUNC, _STEP, _FINAL] -_lib.sqlite3_create_function.restype = c_int - -_lib.sqlite3_aggregate_context.argtypes = [c_void_p, c_int] -_lib.sqlite3_aggregate_context.restype = c_void_p - -_COLLATION = CFUNCTYPE(c_int, c_void_p, c_int, c_void_p, c_int, c_void_p) -_lib.sqlite3_create_collation.argtypes = [c_void_p, c_char_p, c_int, c_void_p, _COLLATION] -_lib.sqlite3_create_collation.restype = c_int - -_PROGRESS = CFUNCTYPE(c_int, c_void_p) -_lib.sqlite3_progress_handler.argtypes = [c_void_p, c_int, _PROGRESS, c_void_p] -_lib.sqlite3_progress_handler.restype = c_int - -_AUTHORIZER = CFUNCTYPE(c_int, c_void_p, c_int, c_char_p, c_char_p, c_char_p, c_char_p) -_lib.sqlite3_set_authorizer.argtypes = [c_void_p, _AUTHORIZER, c_void_p] -_lib.sqlite3_set_authorizer.restype = c_int - converters = {} adapters = {} From noreply at buildbot.pypy.org Wed Apr 3 20:58:56 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 3 Apr 2013 20:58:56 +0200 (CEST) Subject: [pypy-commit] pypy release-2.0-beta2: merge default Message-ID: <20130403185856.872D21C00BD@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: release-2.0-beta2 Changeset: r62982:a082031faece Date: 2013-04-03 20:58 +0200 http://bitbucket.org/pypy/pypy/changeset/a082031faece/ Log: merge default diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -41,11 +41,11 @@ else: _BLOB_TYPE = buffer -from cffi import FFI +from cffi import FFI as _FFI -ffi = FFI() +_ffi = _FFI() -ffi.cdef(""" +_ffi.cdef(""" #define SQLITE_OK ... #define SQLITE_ERROR ... #define SQLITE_INTERNAL ... @@ -243,10 +243,9 @@ int sqlite3_value_numeric_type(sqlite3_value*); """) - def _has_load_extension(): """Only available since 3.3.6""" - unverified_ffi = FFI() + unverified_ffi = _FFI() unverified_ffi.cdef(""" typedef ... sqlite3; int sqlite3_enable_load_extension(sqlite3 *db, int onoff); @@ -254,13 +253,13 @@ unverified_lib = unverified_ffi.dlopen('sqlite3') return hasattr(unverified_lib, 'sqlite3_enable_load_extension') +if _has_load_extension(): + _ffi.cdef("int sqlite3_enable_load_extension(sqlite3 *db, int onoff);") -if _has_load_extension(): - ffi.cdef("int sqlite3_enable_load_extension(sqlite3 *db, int onoff);") - -lib = ffi.verify(""" +_lib = _ffi.verify(""" #include -""", libraries=['sqlite3']) +""", libraries=['sqlite3'] +) exported_sqlite_symbols = [ 'SQLITE_ALTER_TABLE', @@ -297,10 +296,9 @@ ] for symbol in exported_sqlite_symbols: - globals()[symbol] = getattr(lib, symbol) + globals()[symbol] = getattr(_lib, symbol) -_SQLITE_TRANSIENT = ffi.cast('void *', lib.SQLITE_TRANSIENT) - +_SQLITE_TRANSIENT = _ffi.cast('void *', _lib.SQLITE_TRANSIENT) # pysqlite version information version = "2.6.0" @@ -310,7 +308,7 @@ PARSE_DECLTYPES = 2 # SQLite version information -sqlite_version = ffi.string(lib.sqlite3_libversion()) +sqlite_version = _ffi.string(_lib.sqlite3_libversion()) class Error(StandardError): @@ -387,36 +385,49 @@ if len(self.cache) > self.maxcount: self.cache.popitem(0) - if stat.in_use: + if stat._in_use: stat = Statement(self.connection, sql) - stat.set_row_factory(row_factory) + stat._row_factory = row_factory return stat class Connection(object): - def __init__(self, database, timeout=5.0, detect_types=0, - isolation_level="", check_same_thread=True, factory=None, - cached_statements=100): - db_star = ffi.new('sqlite3 **') + __initialized = False + _db = None + + def __init__(self, database, timeout=5.0, detect_types=0, isolation_level="", + check_same_thread=True, factory=None, cached_statements=100): + self.__initialized = True + db_star = _ffi.new('sqlite3 **') + if isinstance(database, unicode): database = database.encode('utf-8') - if lib.sqlite3_open(database, db_star) != lib.SQLITE_OK: + if _lib.sqlite3_open(database, db_star) != _lib.SQLITE_OK: raise OperationalError("Could not open database") - self.db = db_star[0] + self._db = db_star[0] if timeout is not None: timeout = int(timeout * 1000) # pysqlite2 uses timeout in seconds - lib.sqlite3_busy_timeout(self.db, timeout) + _lib.sqlite3_busy_timeout(self._db, timeout) + self.row_factory = None self.text_factory = _unicode_text_factory - self.closed = False - self.statements = [] - self.statement_counter = 0 - self.row_factory = None - self._isolation_level = isolation_level - self.detect_types = detect_types - self.statement_cache = _StatementCache(self, cached_statements) - self.cursors = [] + self._detect_types = detect_types + self._in_transaction = False + self.isolation_level = isolation_level + + self.__cursors = [] + self.__cursors_counter = 0 + self.__statements = [] + self.__statements_counter = 0 + self._statement_cache = _StatementCache(self, cached_statements) + + self.__func_cache = {} + self.__aggregates = {} + self.__aggregate_instances = {} + self.__collations = {} + if check_same_thread: + self.__thread_ident = _thread_get_ident() self.Error = Error self.Warning = Warning @@ -429,30 +440,25 @@ self.DataError = DataError self.NotSupportedError = NotSupportedError - self.func_cache = {} - self._aggregates = {} - self.aggregate_instances = {} - self._collations = {} - if check_same_thread: - self.thread_ident = _thread_get_ident() + def __del__(self): + if self._db: + _lib.sqlite3_close(self._db) def close(self): self._check_thread() - if self.closed: - return - for statement in self.statements: - obj = statement() - if obj is not None: - obj.finalize() - self.closed = True - ret = lib.sqlite3_close(self.db) - self._reset_cursors() - if ret != lib.SQLITE_OK: - raise self._get_exception(ret) + self.__do_all_statements(Statement._finalize, True) + + if self._db: + ret = _lib.sqlite3_close(self._db) + if ret != _lib.SQLITE_OK: + raise self._get_exception(ret) + self._db = None def _check_closed(self): - if getattr(self, 'closed', True): + if not self.__initialized: + raise ProgrammingError("Base Connection.__init__ not called.") + if not self._db: raise ProgrammingError("Cannot operate on a closed database.") def _check_closed_wrap(func): @@ -463,13 +469,16 @@ return wrapper def _check_thread(self): - if not hasattr(self, 'thread_ident'): - return - if self.thread_ident != _thread_get_ident(): + try: + if self.__thread_ident == _thread_get_ident(): + return + except AttributeError: + pass + else: raise ProgrammingError( "SQLite objects created in a thread can only be used in that " "same thread. The object was created in thread id %d and this " - "is thread id %d", self.thread_ident, _thread_get_ident()) + "is thread id %d", self.__thread_ident, _thread_get_ident()) def _check_thread_wrap(func): @wraps(func) @@ -480,29 +489,29 @@ def _get_exception(self, error_code=None): if error_code is None: - error_code = lib.sqlite3_errcode(self.db) - error_message = ffi.string(lib.sqlite3_errmsg(self.db)) + error_code = _lib.sqlite3_errcode(self._db) + error_message = _ffi.string(_lib.sqlite3_errmsg(self._db)).decode('utf-8') - if error_code == lib.SQLITE_OK: - raise ValueError("error signalled but got lib.SQLITE_OK") - elif error_code in (lib.SQLITE_INTERNAL, lib.SQLITE_NOTFOUND): + if error_code == _lib.SQLITE_OK: + raise ValueError("error signalled but got SQLITE_OK") + elif error_code in (_lib.SQLITE_INTERNAL, _lib.SQLITE_NOTFOUND): exc = InternalError - elif error_code == lib.SQLITE_NOMEM: + elif error_code == _lib.SQLITE_NOMEM: exc = MemoryError elif error_code in ( - lib.SQLITE_ERROR, lib.SQLITE_PERM, lib.SQLITE_ABORT, - lib.SQLITE_BUSY, lib.SQLITE_LOCKED, lib.SQLITE_READONLY, - lib.SQLITE_INTERRUPT, lib.SQLITE_IOERR, lib.SQLITE_FULL, - lib.SQLITE_CANTOPEN, lib.SQLITE_PROTOCOL, lib.SQLITE_EMPTY, - lib.SQLITE_SCHEMA): + _lib.SQLITE_ERROR, _lib.SQLITE_PERM, _lib.SQLITE_ABORT, + _lib.SQLITE_BUSY, _lib.SQLITE_LOCKED, _lib.SQLITE_READONLY, + _lib.SQLITE_INTERRUPT, _lib.SQLITE_IOERR, _lib.SQLITE_FULL, + _lib.SQLITE_CANTOPEN, _lib.SQLITE_PROTOCOL, _lib.SQLITE_EMPTY, + _lib.SQLITE_SCHEMA): exc = OperationalError - elif error_code == lib.SQLITE_CORRUPT: + elif error_code == _lib.SQLITE_CORRUPT: exc = DatabaseError - elif error_code == lib.SQLITE_TOOBIG: + elif error_code == _lib.SQLITE_TOOBIG: exc = DataError - elif error_code in (lib.SQLITE_CONSTRAINT, lib.SQLITE_MISMATCH): + elif error_code in (_lib.SQLITE_CONSTRAINT, _lib.SQLITE_MISMATCH): exc = IntegrityError - elif error_code == lib.SQLITE_MISUSE: + elif error_code == _lib.SQLITE_MISUSE: exc = ProgrammingError else: exc = DatabaseError @@ -510,26 +519,38 @@ exc.error_code = error_code return exc + def _remember_cursor(self, cursor): + self.__cursors.append(weakref.ref(cursor)) + self.__cursors_counter += 1 + if self.__cursors_counter < 200: + return + self.__cursors_counter = 0 + self.__cursors = [r for r in self.__cursors if r() is not None] + def _remember_statement(self, statement): - self.statements.append(weakref.ref(statement)) - self.statement_counter += 1 + self.__statements.append(weakref.ref(statement)) + self.__statements_counter += 1 + if self.__statements_counter < 200: + return + self.__statements_counter = 0 + self.__statements = [r for r in self.__statements if r() is not None] - if self.statement_counter % 100 == 0: - self.statements = [ref for ref in self.statements - if ref() is not None] + def __do_all_statements(self, action, reset_cursors): + for weakref in self.__statements: + statement = weakref() + if statement is not None: + action(statement) - def _reset_cursors(self): - for cursor_ref in self.cursors: - cursor = cursor_ref() - if cursor: - cursor.reset = True + if reset_cursors: + for weakref in self.__cursors: + cursor = weakref() + if cursor is not None: + cursor._reset = True @_check_thread_wrap @_check_closed_wrap def __call__(self, sql): - if not isinstance(sql, basestring): - raise Warning("SQL is of wrong type. Must be string or unicode.") - return self.statement_cache.get(sql, self.row_factory) + return self._statement_cache.get(sql, self.row_factory) def cursor(self, factory=None): self._check_thread() @@ -559,72 +580,63 @@ def _begin(self): self._check_closed() - if self._isolation_level is None: - return - if not lib.sqlite3_get_autocommit(self.db): - return - sql = "BEGIN " + self._isolation_level - statement_star = ffi.new('sqlite3_stmt **') - next_char = ffi.new('char **') - ret = lib.sqlite3_prepare_v2(self.db, sql, -1, statement_star, - next_char) + statement_star = _ffi.new('sqlite3_stmt **') + next_char = _ffi.new('char **') + ret = _lib.sqlite3_prepare_v2(self._db, self.__begin_statement, -1, + statement_star, next_char) try: - if ret != lib.SQLITE_OK: + if ret != _lib.SQLITE_OK: raise self._get_exception(ret) - ret = lib.sqlite3_step(statement_star[0]) - if ret != lib.SQLITE_DONE: + ret = _lib.sqlite3_step(statement_star[0]) + if ret != _lib.SQLITE_DONE: raise self._get_exception(ret) + self._in_transaction = True finally: - lib.sqlite3_finalize(statement_star[0]) + _lib.sqlite3_finalize(statement_star[0]) def commit(self): self._check_thread() self._check_closed() - if lib.sqlite3_get_autocommit(self.db): + if not self._in_transaction: return - for statement in self.statements: - obj = statement() - if obj is not None: - obj.reset() + self.__do_all_statements(Statement._reset, False) - statement_star = ffi.new('sqlite3_stmt **') - next_char = ffi.new('char **') - ret = lib.sqlite3_prepare_v2(self.db, b"COMMIT", -1, statement_star, - next_char) + statement_star = _ffi.new('sqlite3_stmt **') + next_char = _ffi.new('char **') + ret = _lib.sqlite3_prepare_v2(self._db, b"COMMIT", -1, + statement_star, next_char) try: - if ret != lib.SQLITE_OK: + if ret != _lib.SQLITE_OK: raise self._get_exception(ret) - ret = lib.sqlite3_step(statement_star[0]) - if ret != lib.SQLITE_DONE: + ret = _lib.sqlite3_step(statement_star[0]) + if ret != _lib.SQLITE_DONE: raise self._get_exception(ret) + self._in_transaction = False finally: - lib.sqlite3_finalize(statement_star[0]) + _lib.sqlite3_finalize(statement_star[0]) def rollback(self): self._check_thread() self._check_closed() - if lib.sqlite3_get_autocommit(self.db): + if not self._in_transaction: return - for statement in self.statements: - obj = statement() - if obj is not None: - obj.reset() + self.__do_all_statements(Statement._reset, True) - statement_star = ffi.new('sqlite3_stmt **') - next_char = ffi.new('char **') - ret = lib.sqlite3_prepare_v2(self.db, b"ROLLBACK", -1, statement_star, - next_char) + statement_star = _ffi.new('sqlite3_stmt **') + next_char = _ffi.new('char **') + ret = _lib.sqlite3_prepare_v2(self._db, b"ROLLBACK", -1, + statement_star, next_char) try: - if ret != lib.SQLITE_OK: + if ret != _lib.SQLITE_OK: raise self._get_exception(ret) - ret = lib.sqlite3_step(statement_star[0]) - if ret != lib.SQLITE_DONE: + ret = _lib.sqlite3_step(statement_star[0]) + if ret != _lib.SQLITE_DONE: raise self._get_exception(ret) + self._in_transaction = False finally: - lib.sqlite3_finalize(statement_star[0]) - self._reset_cursors() + _lib.sqlite3_finalize(statement_star[0]) def __enter__(self): return self @@ -639,29 +651,32 @@ @_check_closed_wrap def create_function(self, name, num_args, callback): try: - closure = self.func_cache[callback] + closure = self.__func_cache[callback] except KeyError: - @ffi.callback("void(sqlite3_context*, int, sqlite3_value**)") + @_ffi.callback("void(sqlite3_context*, int, sqlite3_value**)") def closure(context, nargs, c_params): _function_callback(callback, context, nargs, c_params) - self.func_cache[callback] = closure - ret = lib.sqlite3_create_function(self.db, name, num_args, - lib.SQLITE_UTF8, ffi.NULL, - closure, ffi.NULL, ffi.NULL) - if ret != lib.SQLITE_OK: + self.__func_cache[callback] = closure + + if isinstance(name, unicode): + name = name.encode('utf-8') + ret = _lib.sqlite3_create_function(self._db, name, num_args, + _lib.SQLITE_UTF8, _ffi.NULL, + closure, _ffi.NULL, _ffi.NULL) + if ret != _lib.SQLITE_OK: raise self.OperationalError("Error creating function") @_check_thread_wrap @_check_closed_wrap def create_aggregate(self, name, num_args, cls): try: - step_callback, final_callback = self._aggregates[cls] + step_callback, final_callback = self.__aggregates[cls] except KeyError: - @ffi.callback("void(sqlite3_context*, int, sqlite3_value**)") + @_ffi.callback("void(sqlite3_context*, int, sqlite3_value**)") def step_callback(context, argc, c_params): - res = lib.sqlite3_aggregate_context(context, - ffi.sizeof("size_t")) - aggregate_ptr = ffi.cast("size_t[1]", res) + res = _lib.sqlite3_aggregate_context(context, + _ffi.sizeof("size_t")) + aggregate_ptr = _ffi.cast("size_t[1]", res) if not aggregate_ptr[0]: try: @@ -669,13 +684,13 @@ except Exception: msg = (b"user-defined aggregate's '__init__' " b"method raised error") - lib.sqlite3_result_error(context, msg, len(msg)) + _lib.sqlite3_result_error(context, msg, len(msg)) return aggregate_id = id(aggregate) - self.aggregate_instances[aggregate_id] = aggregate + self.__aggregate_instances[aggregate_id] = aggregate aggregate_ptr[0] = aggregate_id else: - aggregate = self.aggregate_instances[aggregate_ptr[0]] + aggregate = self.__aggregate_instances[aggregate_ptr[0]] params = _convert_params(context, argc, c_params) try: @@ -683,33 +698,37 @@ except Exception: msg = (b"user-defined aggregate's 'step' " b"method raised error") - lib.sqlite3_result_error(context, msg, len(msg)) + _lib.sqlite3_result_error(context, msg, len(msg)) - @ffi.callback("void(sqlite3_context*)") + @_ffi.callback("void(sqlite3_context*)") def final_callback(context): - res = lib.sqlite3_aggregate_context(context, - ffi.sizeof("size_t")) - aggregate_ptr = ffi.cast("size_t[1]", res) + res = _lib.sqlite3_aggregate_context(context, + _ffi.sizeof("size_t")) + aggregate_ptr = _ffi.cast("size_t[1]", res) if aggregate_ptr[0]: - aggregate = self.aggregate_instances[aggregate_ptr[0]] + aggregate = self.__aggregate_instances[aggregate_ptr[0]] try: val = aggregate.finalize() except Exception: msg = (b"user-defined aggregate's 'finalize' " b"method raised error") - lib.sqlite3_result_error(context, msg, len(msg)) + _lib.sqlite3_result_error(context, msg, len(msg)) else: _convert_result(context, val) finally: - del self.aggregate_instances[aggregate_ptr[0]] + del self.__aggregate_instances[aggregate_ptr[0]] - self._aggregates[cls] = step_callback, final_callback + self.__aggregates[cls] = (step_callback, final_callback) - ret = lib.sqlite3_create_function(self.db, name, num_args, - lib.SQLITE_UTF8, ffi.NULL, ffi.NULL, - step_callback, final_callback) - if ret != lib.SQLITE_OK: + if isinstance(name, unicode): + name = name.encode('utf-8') + ret = _lib.sqlite3_create_function(self._db, name, num_args, + _lib.SQLITE_UTF8, _ffi.NULL, + _ffi.NULL, + step_callback, + final_callback) + if ret != _lib.SQLITE_OK: raise self._get_exception(ret) @_check_thread_wrap @@ -720,55 +739,61 @@ raise ProgrammingError("invalid character in collation name") if callback is None: - del self._collations[name] - collation_callback = ffi.NULL + del self.__collations[name] + collation_callback = _ffi.NULL else: if not callable(callback): raise TypeError("parameter must be callable") - @ffi.callback("int(void*, int, const void*, int, const void*)") + @_ffi.callback("int(void*, int, const void*, int, const void*)") def collation_callback(context, len1, str1, len2, str2): - text1 = ffi.buffer(str1, len1)[:] - text2 = ffi.buffer(str2, len2)[:] + text1 = _ffi.buffer(str1, len1)[:] + text2 = _ffi.buffer(str2, len2)[:] return callback(text1, text2) - self._collations[name] = collation_callback + self.__collations[name] = collation_callback - ret = lib.sqlite3_create_collation(self.db, name, lib.SQLITE_UTF8, - ffi.NULL, collation_callback) - if ret != lib.SQLITE_OK: + if isinstance(name, unicode): + name = name.encode('utf-8') + ret = _lib.sqlite3_create_collation(self._db, name, + _lib.SQLITE_UTF8, + _ffi.NULL, + collation_callback) + if ret != _lib.SQLITE_OK: raise self._get_exception(ret) @_check_thread_wrap @_check_closed_wrap def set_authorizer(self, callback): try: - authorizer = self.func_cache[callback] + authorizer = self.__func_cache[callback] except KeyError: - @ffi.callback("int(void*, int, const char*, const char*, " - "const char*, const char*)") + @_ffi.callback("int(void*, int, const char*, const char*, " + "const char*, const char*)") def authorizer(userdata, action, arg1, arg2, dbname, source): try: return int(callback(action, arg1, arg2, dbname, source)) except Exception: - return lib.SQLITE_DENY - self.func_cache[callback] = authorizer + return _lib.SQLITE_DENY + self.__func_cache[callback] = authorizer - ret = lib.sqlite3_set_authorizer(self.db, authorizer, ffi.NULL) - if ret != lib.SQLITE_OK: + ret = _lib.sqlite3_set_authorizer(self._db, + authorizer, + _ffi.NULL) + if ret != _lib.SQLITE_OK: raise self._get_exception(ret) @_check_thread_wrap @_check_closed_wrap def set_progress_handler(self, callable, nsteps): if callable is None: - progress_handler = ffi.NULL + progress_handler = _ffi.NULL else: try: - progress_handler = self.func_cache[callable] + progress_handler = self.__func_cache[callable] except KeyError: - @ffi.callback("int(void*)") + @_ffi.callback("int(void*)") def progress_handler(userdata): try: ret = callable() @@ -776,14 +801,19 @@ except Exception: # abort query if error occurred return 1 + self.__func_cache[callable] = progress_handler + _lib.sqlite3_progress_handler(self._db, nsteps, + progress_handler, + _ffi.NULL) - self.func_cache[callable] = progress_handler - lib.sqlite3_progress_handler(self.db, nsteps, progress_handler, - ffi.NULL) + if sys.version_info[0] >= 3: + def __get_in_transaction(self): + return self._in_transaction + in_transaction = property(__get_in_transaction) def __get_total_changes(self): self._check_closed() - return lib.sqlite3_total_changes(self.db) + return _lib.sqlite3_total_changes(self._db) total_changes = property(__get_total_changes) def __get_isolation_level(self): @@ -792,193 +822,191 @@ def __set_isolation_level(self, val): if val is None: self.commit() - if isinstance(val, unicode): - val = str(val) + else: + self.__begin_statement = str("BEGIN " + val).encode('utf-8') self._isolation_level = val isolation_level = property(__get_isolation_level, __set_isolation_level) - if hasattr(lib, 'sqlite3_enable_load_extension'): + if hasattr(_lib, 'sqlite3_enable_load_extension'): @_check_thread_wrap @_check_closed_wrap def enable_load_extension(self, enabled): - rc = lib.sqlite3_enable_load_extension(self.db, int(enabled)) - if rc != lib.SQLITE_OK: + rc = _lib.sqlite3_enable_load_extension(self._db, int(enabled)) + if rc != _lib.SQLITE_OK: raise OperationalError("Error enabling load extension") -DML, DQL, DDL = range(3) +class Cursor(object): + __initialized = False + __statement = None - -class CursorLock(object): - def __init__(self, cursor): - self.cursor = cursor - - def __enter__(self): - if self.cursor.locked: - raise ProgrammingError("Recursive use of cursors not allowed.") - self.cursor.locked = True - - def __exit__(self, *args): - self.cursor.locked = False - - -class Cursor(object): def __init__(self, con): if not isinstance(con, Connection): raise TypeError - con._check_thread() - con._check_closed() - con.cursors.append(weakref.ref(self)) - self.connection = con - self._description = None + self.__connection = con + self.arraysize = 1 self.row_factory = None - self.rowcount = -1 - self.statement = None - self.reset = False - self.locked = False + self._reset = False + self.__locked = False + self.__closed = False + self.__description = None + self.__rowcount = -1 - def _check_closed(self): - if not getattr(self, 'connection', None): + con._check_thread() + con._remember_cursor(self) + + self.__initialized = True + + def __del__(self): + if self.__statement: + self.__statement._reset() + + def close(self): + self.__connection._check_thread() + self.__connection._check_closed() + if self.__statement: + self.__statement._reset() + self.__statement = None + self.__closed = True + + def __check_cursor(self): + if not self.__initialized: + raise ProgrammingError("Base Cursor.__init__ not called.") + if self.__closed: raise ProgrammingError("Cannot operate on a closed cursor.") - self.connection._check_thread() - self.connection._check_closed() + if self.__locked: + raise ProgrammingError("Recursive use of cursors not allowed.") + self.__connection._check_thread() + self.__connection._check_closed() - def _check_and_lock(self): - self._check_closed() - return CursorLock(self) + def __check_cursor_wrap(func): + @wraps(func) + def wrapper(self, *args, **kwargs): + self.__check_cursor() + return func(self, *args, **kwargs) + return wrapper - def execute(self, sql, params=None): - if type(sql) is unicode: - sql = sql.encode("utf-8") - - with self._check_and_lock(): - self._description = None - self.reset = False - self.statement = self.connection.statement_cache.get( + def __execute(self, multiple, sql, many_params): + self.__locked = True + try: + self._reset = False + if not isinstance(sql, basestring): + raise ValueError("operation parameter must be str or unicode") + self.__description = None + self.__rowcount = -1 + self.__statement = self.__connection._statement_cache.get( sql, self.row_factory) - if self.connection._isolation_level is not None: - if self.statement.kind == DDL: - self.connection.commit() - elif self.statement.kind == DML: - self.connection._begin() + if self.__connection._isolation_level is not None: + if self.__statement._kind == Statement._DDL: + if self.__connection._in_transaction: + self.__connection.commit() + elif self.__statement._kind == Statement._DML: + if not self.__connection._in_transaction: + self.__connection._begin() - self.statement.set_params(params) + if multiple and self.__statement._kind != Statement._DML: + raise ProgrammingError("executemany is only for DML statements") - # Actually execute the SQL statement - ret = lib.sqlite3_step(self.statement.statement) - if ret not in (lib.SQLITE_DONE, lib.SQLITE_ROW): - self.statement.reset() - raise self.connection._get_exception(ret) + for params in many_params: + self.__statement._set_params(params) - if self.statement.kind == DML: - self.statement.reset() + # Actually execute the SQL statement + ret = _lib.sqlite3_step(self.__statement._statement) + if ret not in (_lib.SQLITE_DONE, _lib.SQLITE_ROW): + self.__statement._reset() + self.__connection._in_transaction = \ + not _lib.sqlite3_get_autocommit(self.__connection._db) + raise self.__connection._get_exception(ret) - if self.statement.kind == DQL and ret == lib.SQLITE_ROW: - self.statement._build_row_cast_map() - self.statement._readahead(self) - else: - self.statement.item = None - self.statement.exhausted = True + if self.__statement._kind == Statement._DML: + self.__statement._reset() - self.rowcount = -1 - if self.statement.kind == DML: - self.rowcount = lib.sqlite3_changes(self.connection.db) + if self.__statement._kind == Statement._DQL and ret == _lib.SQLITE_ROW: + self.__statement._build_row_cast_map() + self.__statement._readahead(self) + if self.__statement._kind == Statement._DML: + if self.__rowcount == -1: + self.__rowcount = 0 + self.__rowcount += _lib.sqlite3_changes(self.__connection._db) + finally: + self.__locked = False return self + @__check_cursor_wrap + def execute(self, sql, params=[]): + return self.__execute(False, sql, [params]) + + @__check_cursor_wrap def executemany(self, sql, many_params): - if type(sql) is unicode: - sql = sql.encode("utf-8") - - with self._check_and_lock(): - self._description = None - self.reset = False - self.statement = self.connection.statement_cache.get( - sql, self.row_factory) - - if self.statement.kind == DML: - self.connection._begin() - else: - raise ProgrammingError( - "executemany is only for DML statements") - - self.rowcount = 0 - for params in many_params: - self.statement.set_params(params) - ret = lib.sqlite3_step(self.statement.statement) - if ret != lib.SQLITE_DONE: - raise self.connection._get_exception(ret) - self.rowcount += lib.sqlite3_changes(self.connection.db) - - return self + return self.__execute(True, sql, many_params) def executescript(self, sql): - self._description = None - self.reset = False - if type(sql) is unicode: - sql = sql.encode("utf-8") - self._check_closed() - statement_star = ffi.new('sqlite3_stmt **') - tail = ffi.new('char **') + self.__check_cursor() + self._reset = False + if isinstance(sql, unicode): + sql = sql.encode('utf-8') + elif not isinstance(sql, str): + raise ValueError("script argument must be unicode or string.") + statement_star = _ffi.new('sqlite3_stmt **') + tail = _ffi.new('char **') - self.connection.commit() + self.__connection.commit() while True: - rc = lib.sqlite3_prepare(self.connection.db, sql, -1, - statement_star, tail) - sql = ffi.string(tail[0]) - if rc != lib.SQLITE_OK: - raise self.connection._get_exception(rc) + rc = _lib.sqlite3_prepare(self.__connection._db, sql, -1, + statement_star, tail) + sql = _ffi.string(tail[0]) + if rc != _lib.SQLITE_OK: + raise self.__connection._get_exception(rc) - rc = lib.SQLITE_ROW - while rc == lib.SQLITE_ROW: + rc = _lib.SQLITE_ROW + while rc == _lib.SQLITE_ROW: if not statement_star[0]: - rc = lib.SQLITE_OK + rc = _lib.SQLITE_OK else: - rc = lib.sqlite3_step(statement_star[0]) + rc = _lib.sqlite3_step(statement_star[0]) - if rc != lib.SQLITE_DONE: - lib.sqlite3_finalize(statement_star[0]) - if rc == lib.SQLITE_OK: - return self + if rc != _lib.SQLITE_DONE: + _lib.sqlite3_finalize(statement_star[0]) + if rc == _lib.SQLITE_OK: + break else: - raise self.connection._get_exception(rc) - rc = lib.sqlite3_finalize(statement_star[0]) - if rc != lib.SQLITE_OK: - raise self.connection._get_exception(rc) + raise self.__connection._get_exception(rc) + + rc = _lib.sqlite3_finalize(statement_star[0]) + if rc != _lib.SQLITE_OK: + raise self.__connection._get_exception(rc) if not sql: break return self + def __check_reset(self): + if self._reset: + raise self.__connection.InterfaceError( + "Cursor needed to be reset because of commit/rollback " + "and can no longer be fetched from.") + def __iter__(self): - return iter(self.fetchone, None) + return self - def _check_reset(self): - if self.reset: - raise self.connection.InterfaceError( - "Cursor needed to be reset because of commit/rollback and can " - "no longer be fetched from.") + def __next__(self): + self.__check_cursor() + self.__check_reset() + if not self.__statement: + raise StopIteration + return self.__statement._next(self) - # do all statements + if sys.version_info[0] < 3: + next = __next__ + del __next__ + def fetchone(self): - self._check_closed() - self._check_reset() - - if self.statement is None: - return None - - try: - return self.statement.next(self) - except StopIteration: - return None + return next(self, None) def fetchmany(self, size=None): - self._check_closed() - self._check_reset() - if self.statement is None: - return [] if size is None: size = self.arraysize lst = [] @@ -989,29 +1017,25 @@ return lst def fetchall(self): - self._check_closed() - self._check_reset() - if self.statement is None: - return [] return list(self) - def _getdescription(self): - if self._description is None: - self._description = self.statement._get_description() - return self._description + def __get_connection(self): + return self.__connection + connection = property(__get_connection) - def _getlastrowid(self): - return lib.sqlite3_last_insert_rowid(self.connection.db) + def __get_rowcount(self): + return self.__rowcount + rowcount = property(__get_rowcount) - def close(self): - if not self.connection: - return - self._check_closed() - if self.statement: - self.statement.reset() - self.statement = None - self.connection.cursors.remove(weakref.ref(self)) - self.connection = None + def __get_description(self): + if self.__description is None: + self.__description = self.__statement._get_description() + return self.__description + description = property(__get_description) + + def __get_lastrowid(self): + return _lib.sqlite3_last_insert_rowid(self.__connection._db) + lastrowid = property(__get_lastrowid) def setinputsizes(self, *args): pass @@ -1019,92 +1043,71 @@ def setoutputsize(self, *args): pass - description = property(_getdescription) - lastrowid = property(_getlastrowid) - class Statement(object): + _DML, _DQL, _DDL = range(3) + + _statement = None + def __init__(self, connection, sql): - self.statement = ffi.NULL - if not isinstance(sql, str): - raise ValueError("sql must be a string") - self.con = connection - self.sql = sql # DEBUG ONLY + self.__con = connection + self.__con._remember_statement(self) + + if not isinstance(sql, basestring): + raise Warning("SQL is of wrong type. Must be string or unicode.") first_word = self._statement_kind = sql.lstrip().split(" ")[0].upper() if first_word in ("INSERT", "UPDATE", "DELETE", "REPLACE"): - self.kind = DML + self._kind = Statement._DML elif first_word in ("SELECT", "PRAGMA"): - self.kind = DQL + self._kind = Statement._DQL else: - self.kind = DDL - self.exhausted = False - self.in_use = False - # - # set by set_row_factory - self.row_factory = None + self._kind = Statement._DDL - statement_star = ffi.new('sqlite3_stmt **') - next_char = ffi.new('char **') - ret = lib.sqlite3_prepare_v2(self.con.db, sql, -1, - statement_star, next_char) - self.statement = statement_star[0] - if ret == lib.SQLITE_OK and not self.statement: - # an empty statement, we work around that as it's the least trouble - ret = lib.sqlite3_prepare_v2(self.con.db, "select 42", -1, - statement_star, next_char) - self.statement = statement_star[0] - self.kind = DQL + self._in_use = False + self._row_factory = None - if ret != lib.SQLITE_OK: - raise self.con._get_exception(ret) - self.con._remember_statement(self) - if _check_remaining_sql(ffi.string(next_char[0])): - raise Warning("One and only one statement required: %r" % ( - next_char[0],)) - # sql_char should remain alive until here + if isinstance(sql, unicode): + sql = sql.encode('utf-8') + statement_star = _ffi.new('sqlite3_stmt **') + next_char = _ffi.new('char **') + ret = _lib.sqlite3_prepare_v2(self.__con._db, sql, -1, + statement_star, next_char) + self._statement = statement_star[0] - self._build_row_cast_map() + if ret == _lib.SQLITE_OK and not self._statement: + # an empty statement, work around that, as it's the least trouble + ret = _lib.sqlite3_prepare_v2(self.__con._db, "select 42", -1, + statement_star, next_char) + self._statement = statement_star[0] + self._kind = Statement._DQL + if ret != _lib.SQLITE_OK: + raise self.__con._get_exception(ret) - def set_row_factory(self, row_factory): - self.row_factory = row_factory + if _check_remaining_sql(_ffi.string(next_char[0])): + raise Warning("You can only execute one statement at a time.") - def _build_row_cast_map(self): - self.row_cast_map = [] - for i in xrange(lib.sqlite3_column_count(self.statement)): - converter = None + def __del__(self): + if self._statement: + _lib.sqlite3_finalize(self._statement) - if self.con.detect_types & PARSE_COLNAMES: - colname = lib.sqlite3_column_name(self.statement, i) - if colname != ffi.NULL: - colname = ffi.string(colname) - type_start = -1 - key = None - for pos in range(len(colname)): - if colname[pos] == '[': - type_start = pos + 1 - elif colname[pos] == ']' and type_start != -1: - key = colname[type_start:pos] - converter = converters[key.upper()] + def _finalize(self): + if self._statement: + _lib.sqlite3_finalize(self._statement) + self._statement = None + self._in_use = False - if converter is None and self.con.detect_types & PARSE_DECLTYPES: - decltype = lib.sqlite3_column_decltype(self.statement, i) - if decltype is not ffi.NULL: - # if multiple words, use first, - # eg. "INTEGER NOT NULL" => "INTEGER" - decltype = ffi.string(decltype).split()[0] - if '(' in decltype: - decltype = decltype[:decltype.index('(')] - converter = converters.get(decltype.upper(), None) - - self.row_cast_map.append(converter) + def _reset(self): + if self._in_use and self._statement: + _lib.sqlite3_reset(self._statement) + self._in_use = False if sys.version_info[0] < 3: def __check_decodable(self, param): - if self.con.text_factory in (unicode, OptimizedUnicode, - _unicode_text_factory): + if self.__con.text_factory in (unicode, OptimizedUnicode, + _unicode_text_factory): for c in param: if ord(c) & 0x80 != 0: - raise self.con.ProgrammingError( + raise self.__con.ProgrammingError( "You must not use 8-bit bytestrings unless " "you use a text_factory that can interpret " "8-bit bytestrings (like text_factory = str). " @@ -1119,149 +1122,170 @@ param = adapt(param) if param is None: - lib.sqlite3_bind_null(self.statement, idx) + rc = _lib.sqlite3_bind_null(self._statement, idx) elif isinstance(param, (bool, int, long)): if -2147483648 <= param <= 2147483647: - lib.sqlite3_bind_int(self.statement, idx, param) + rc = _lib.sqlite3_bind_int(self._statement, idx, param) else: - lib.sqlite3_bind_int64(self.statement, idx, param) + rc = _lib.sqlite3_bind_int64(self._statement, idx, param) elif isinstance(param, float): - lib.sqlite3_bind_double(self.statement, idx, param) + rc = _lib.sqlite3_bind_double(self._statement, idx, param) elif isinstance(param, unicode): param = param.encode("utf-8") - lib.sqlite3_bind_text(self.statement, idx, param, len(param), - _SQLITE_TRANSIENT) + rc = _lib.sqlite3_bind_text(self._statement, idx, param, + len(param), _SQLITE_TRANSIENT) elif isinstance(param, str): self.__check_decodable(param) - lib.sqlite3_bind_text(self.statement, idx, param, len(param), - _SQLITE_TRANSIENT) + rc = _lib.sqlite3_bind_text(self._statement, idx, param, + len(param), _SQLITE_TRANSIENT) elif isinstance(param, (buffer, bytes)): - lib.sqlite3_bind_blob(self.statement, idx, str(param), len(param), - _SQLITE_TRANSIENT) + param = bytes(param) + rc = _lib.sqlite3_bind_blob(self._statement, idx, param, + len(param), _SQLITE_TRANSIENT) else: - raise InterfaceError( - "parameter type %s is not supported" % str(type(param))) + rc = -1 + return rc - def set_params(self, params): - ret = lib.sqlite3_reset(self.statement) - if ret != lib.SQLITE_OK: - raise self.con._get_exception(ret) - self.mark_dirty() + def _set_params(self, params): + self._in_use = True - if params is None: - if lib.sqlite3_bind_parameter_count(self.statement) != 0: - raise ProgrammingError("wrong number of arguments") - return - - params_type = None - if isinstance(params, dict): - params_type = dict - else: - params_type = list - - if params_type == list: - if len(params) != lib.sqlite3_bind_parameter_count(self.statement): - raise ProgrammingError("wrong number of arguments") - - for i in range(len(params)): - self.__set_param(i + 1, params[i]) - else: - param_count = lib.sqlite3_bind_parameter_count(self.statement) - for idx in range(1, param_count + 1): - param_name = lib.sqlite3_bind_parameter_name(self.statement, - idx) - if param_name == ffi.NULL: - raise ProgrammingError("need named parameters") - param_name = ffi.string(param_name)[1:] + num_params_needed = _lib.sqlite3_bind_parameter_count(self._statement) + if isinstance(params, (tuple, list)) or \ + not isinstance(params, dict) and \ + hasattr(params, '__getitem__'): + try: + num_params = len(params) + except TypeError: + num_params = -1 + if num_params != num_params_needed: + raise ProgrammingError("Incorrect number of bindings supplied. " + "The current statement uses %d, and " + "there are %d supplied." % + (num_params_needed, num_params)) + for i in range(num_params): + rc = self.__set_param(i + 1, params[i]) + if rc != _lib.SQLITE_OK: + raise InterfaceError("Error binding parameter %d - " + "probably unsupported type." % i) + elif isinstance(params, dict): + for i in range(1, num_params_needed + 1): + param_name = _lib.sqlite3_bind_parameter_name(self._statement, i) + if not param_name: + raise ProgrammingError("Binding %d has no name, but you " + "supplied a dictionary (which has " + "only names)." % i) + param_name = _ffi.string(param_name)[1:] try: param = params[param_name] except KeyError: - raise ProgrammingError("missing parameter '%s'" % param) - self.__set_param(idx, param) + raise ProgrammingError("You did not supply a value for " + "binding %d." % i) + rc = self.__set_param(i, param) + if rc != _lib.SQLITE_OK: + raise InterfaceError("Error binding parameter :%s - " + "probably unsupported type." % + param_name) + else: + raise ValueError("parameters are of unsupported type") - def next(self, cursor): - self.con._check_closed() - self.con._check_thread() - if self.exhausted: - raise StopIteration - item = self.item + def _build_row_cast_map(self): + if not self.__con._detect_types: + return + self.__row_cast_map = [] + for i in xrange(_lib.sqlite3_column_count(self._statement)): + converter = None - ret = lib.sqlite3_step(self.statement) - if ret == lib.SQLITE_DONE: - self.exhausted = True - self.item = None - elif ret != lib.SQLITE_ROW: - exc = self.con._get_exception(ret) - lib.sqlite3_reset(self.statement) - raise exc + if self.__con._detect_types & PARSE_COLNAMES: + colname = _lib.sqlite3_column_name(self._statement, i) + if colname is not None: + colname = _ffi.string(colname) + type_start = -1 + key = None + for pos in range(len(colname)): + if colname[pos] == '[': + type_start = pos + 1 + elif colname[pos] == ']' and type_start != -1: + key = colname[type_start:pos] + converter = converters[key.upper()] - self._readahead(cursor) - return item + if converter is None and self.__con._detect_types & PARSE_DECLTYPES: + decltype = _lib.sqlite3_column_decltype(self._statement, i) + if decltype is not None: + decltype = _ffi.string(decltype) + # if multiple words, use first, eg. + # "INTEGER NOT NULL" => "INTEGER" + decltype = decltype.split()[0] + if '(' in decltype: + decltype = decltype[:decltype.index('(')] + converter = converters.get(decltype.upper(), None) + + self.__row_cast_map.append(converter) def _readahead(self, cursor): - self.column_count = lib.sqlite3_column_count(self.statement) row = [] - for i in xrange(self.column_count): - typ = lib.sqlite3_column_type(self.statement, i) + num_cols = _lib.sqlite3_column_count(self._statement) + for i in xrange(num_cols): + if self.__con._detect_types: + converter = self.__row_cast_map[i] + else: + converter = None - converter = self.row_cast_map[i] - if converter is None: - if typ == lib.SQLITE_NULL: - val = None - elif typ == lib.SQLITE_INTEGER: - val = lib.sqlite3_column_int64(self.statement, i) - elif typ == lib.SQLITE_FLOAT: - val = lib.sqlite3_column_double(self.statement, i) - elif typ == lib.SQLITE_TEXT: - text = lib.sqlite3_column_text(self.statement, i) - text_len = lib.sqlite3_column_bytes(self.statement, i) - val = ffi.buffer(text, text_len)[:] - val = self.con.text_factory(val) - elif typ == lib.SQLITE_BLOB: - blob = lib.sqlite3_column_blob(self.statement, i) - blob_len = lib.sqlite3_column_bytes(self.statement, i) - val = _BLOB_TYPE(ffi.buffer(blob, blob_len)) - else: - blob = lib.sqlite3_column_blob(self.statement, i) + if converter is not None: + blob = _lib.sqlite3_column_blob(self._statement, i) if not blob: val = None else: - blob_len = lib.sqlite3_column_bytes(self.statement, i) - val = ffi.buffer(blob, blob_len)[:] + blob_len = _lib.sqlite3_column_bytes(self._statement, i) + val = _ffi.buffer(blob, blob_len)[:] val = converter(val) + else: + typ = _lib.sqlite3_column_type(self._statement, i) + if typ == _lib.SQLITE_NULL: + val = None + elif typ == _lib.SQLITE_INTEGER: + val = _lib.sqlite3_column_int64(self._statement, i) + val = int(val) + elif typ == _lib.SQLITE_FLOAT: + val = _lib.sqlite3_column_double(self._statement, i) + elif typ == _lib.SQLITE_TEXT: + text = _lib.sqlite3_column_text(self._statement, i) + text_len = _lib.sqlite3_column_bytes(self._statement, i) + val = _ffi.buffer(text, text_len)[:] + val = self.__con.text_factory(val) + elif typ == _lib.SQLITE_BLOB: + blob = _lib.sqlite3_column_blob(self._statement, i) + blob_len = _lib.sqlite3_column_bytes(self._statement, i) + val = _BLOB_TYPE(_ffi.buffer(blob, blob_len)) row.append(val) row = tuple(row) - if self.row_factory is not None: - row = self.row_factory(cursor, row) - self.item = row + if self._row_factory is not None: + row = self._row_factory(cursor, row) + self._item = row - def reset(self): - self.row_cast_map = None - ret = lib.sqlite3_reset(self.statement) - self.in_use = False - self.exhausted = False - return ret + def _next(self, cursor): + try: + item = self._item + except AttributeError: + raise StopIteration + del self._item - def finalize(self): - lib.sqlite3_finalize(self.statement) - self.statement = ffi.NULL - self.in_use = False + ret = _lib.sqlite3_step(self._statement) + if ret not in (_lib.SQLITE_DONE, _lib.SQLITE_ROW): + _lib.sqlite3_reset(self._statement) + raise self.__con._get_exception(ret) + elif ret == _lib.SQLITE_ROW: + self._readahead(cursor) - def mark_dirty(self): - self.in_use = True - - def __del__(self): - lib.sqlite3_finalize(self.statement) - self.statement = ffi.NULL + return item def _get_description(self): - if self.kind == DML: + if self._kind == Statement._DML: return None desc = [] - for i in xrange(lib.sqlite3_column_count(self.statement)): - name = lib.sqlite3_column_name(self.statement, i) - name = ffi.string(name).split("[")[0].strip() + for i in xrange(_lib.sqlite3_column_count(self._statement)): + name = _lib.sqlite3_column_name(self._statement, i) + name = _ffi.string(name).split("[")[0].strip() desc.append((name, None, None, None, None, None, None)) return desc @@ -1346,20 +1370,21 @@ def _convert_params(con, nargs, params): _params = [] for i in range(nargs): - typ = lib.sqlite3_value_type(params[i]) - if typ == lib.SQLITE_NULL: + typ = _lib.sqlite3_value_type(params[i]) + if typ == _lib.SQLITE_NULL: val = None - elif typ == lib.SQLITE_INTEGER: - val = lib.sqlite3_value_int64(params[i]) - elif typ == lib.SQLITE_FLOAT: - val = lib.sqlite3_value_double(params[i]) - elif typ == lib.SQLITE_TEXT: - val = lib.sqlite3_value_text(params[i]) - val = unicode(ffi.string(val), 'utf-8') - elif typ == lib.SQLITE_BLOB: - blob = lib.sqlite3_value_blob(params[i]) - blob_len = lib.sqlite3_value_bytes(params[i]) - val = _BLOB_TYPE(ffi.buffer(blob, blob_len)) + elif typ == _lib.SQLITE_INTEGER: + val = _lib.sqlite3_value_int64(params[i]) + val = int(val) + elif typ == _lib.SQLITE_FLOAT: + val = _lib.sqlite3_value_double(params[i]) + elif typ == _lib.SQLITE_TEXT: + val = _lib.sqlite3_value_text(params[i]) + val = unicode(_ffi.string(val), 'utf-8') + elif typ == _lib.SQLITE_BLOB: + blob = _lib.sqlite3_value_blob(params[i]) + blob_len = _lib.sqlite3_value_bytes(params[i]) + val = _BLOB_TYPE(_ffi.buffer(blob, blob_len)) else: raise NotImplementedError _params.append(val) @@ -1368,18 +1393,18 @@ def _convert_result(con, val): if val is None: - lib.sqlite3_result_null(con) + _lib.sqlite3_result_null(con) elif isinstance(val, (bool, int, long)): - lib.sqlite3_result_int64(con, int(val)) + _lib.sqlite3_result_int64(con, int(val)) elif isinstance(val, float): - lib.sqlite3_result_double(con, val) + _lib.sqlite3_result_double(con, val) elif isinstance(val, unicode): val = val.encode('utf-8') - lib.sqlite3_result_text(con, val, len(val), _SQLITE_TRANSIENT) + _lib.sqlite3_result_text(con, val, len(val), _SQLITE_TRANSIENT) elif isinstance(val, str): - lib.sqlite3_result_text(con, val, len(val), _SQLITE_TRANSIENT) + _lib.sqlite3_result_text(con, val, len(val), _SQLITE_TRANSIENT) elif isinstance(val, (buffer, bytes)): - lib.sqlite3_result_blob(con, str(val), len(val), _SQLITE_TRANSIENT) + _lib.sqlite3_result_blob(con, bytes(val), len(val), _SQLITE_TRANSIENT) else: raise NotImplementedError @@ -1390,11 +1415,10 @@ val = real_cb(*params) except Exception: msg = b"user-defined function raised exception" - lib.sqlite3_result_error(context, msg, len(msg)) + _lib.sqlite3_result_error(context, msg, len(msg)) else: _convert_result(context, val) - converters = {} adapters = {} diff --git a/pypy/module/test_lib_pypy/pyrepl/test_bugs.py b/pypy/module/test_lib_pypy/pyrepl/test_bugs.py --- a/pypy/module/test_lib_pypy/pyrepl/test_bugs.py +++ b/pypy/module/test_lib_pypy/pyrepl/test_bugs.py @@ -24,6 +24,7 @@ # (applicable) bug reports import pytest +import os, sys class HistoricalTestReader(HistoricalReader, BaseTestReader): @@ -46,7 +47,7 @@ read_spec(spec, HistoricalTestReader) - at pytest.mark.skipif("os.name != 'posix'") + at pytest.mark.skipif("os.name != 'posix' or 'darwin' in sys.platform") def test_signal_failure(monkeypatch): import os import pty diff --git a/pypy/module/test_lib_pypy/pyrepl/test_readline.py b/pypy/module/test_lib_pypy/pyrepl/test_readline.py --- a/pypy/module/test_lib_pypy/pyrepl/test_readline.py +++ b/pypy/module/test_lib_pypy/pyrepl/test_readline.py @@ -1,7 +1,8 @@ import pytest +import os, sys - at pytest.mark.skipif("os.name != 'posix'") + at pytest.mark.skipif("os.name != 'posix' or 'darwin' in sys.platform") def test_raw_input(): import os import pty From noreply at buildbot.pypy.org Wed Apr 3 20:59:19 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Wed, 3 Apr 2013 20:59:19 +0200 (CEST) Subject: [pypy-commit] pypy default: this shouldn't have been re-added in merge Message-ID: <20130403185919.F02E11C00BD@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r62983:e63b943c2ee2 Date: 2013-04-03 14:58 -0400 http://bitbucket.org/pypy/pypy/changeset/e63b943c2ee2/ Log: this shouldn't have been re-added in merge diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -579,7 +579,6 @@ return _iterdump(self) def _begin(self): - self._check_closed() statement_star = _ffi.new('sqlite3_stmt **') next_char = _ffi.new('char **') ret = _lib.sqlite3_prepare_v2(self._db, self.__begin_statement, -1, From noreply at buildbot.pypy.org Wed Apr 3 22:21:26 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 3 Apr 2013 22:21:26 +0200 (CEST) Subject: [pypy-commit] pypy default: fix whatsnew Message-ID: <20130403202126.B63D11C00BD@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r62984:bcfaa7d5bb72 Date: 2013-04-03 16:27 +0200 http://bitbucket.org/pypy/pypy/changeset/bcfaa7d5bb72/ Log: fix whatsnew diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -117,3 +117,7 @@ .. branch: curses_cffi cffi implementation of _curses + +.. branch: sqlite-cffi + +cffi implementation of sqlite3 From noreply at buildbot.pypy.org Wed Apr 3 22:21:27 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Wed, 3 Apr 2013 22:21:27 +0200 (CEST) Subject: [pypy-commit] pypy release-2.0-beta2: merge default Message-ID: <20130403202127.F3B2A1C00BD@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: release-2.0-beta2 Changeset: r62985:18eb5468f8b5 Date: 2013-04-03 16:20 -0400 http://bitbucket.org/pypy/pypy/changeset/18eb5468f8b5/ Log: merge default diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -579,7 +579,6 @@ return _iterdump(self) def _begin(self): - self._check_closed() statement_star = _ffi.new('sqlite3_stmt **') next_char = _ffi.new('char **') ret = _lib.sqlite3_prepare_v2(self._db, self.__begin_statement, -1, From noreply at buildbot.pypy.org Wed Apr 3 22:34:38 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 3 Apr 2013 22:34:38 +0200 (CEST) Subject: [pypy-commit] pypy default: (fijal, bdk) make sure we use statement cache when doing fetchall Message-ID: <20130403203438.13F011C06BD@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r62986:8818eacb9e98 Date: 2013-04-03 22:33 +0200 http://bitbucket.org/pypy/pypy/changeset/8818eacb9e98/ Log: (fijal, bdk) make sure we use statement cache when doing fetchall diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -1275,6 +1275,8 @@ raise self.__con._get_exception(ret) elif ret == _lib.SQLITE_ROW: self._readahead(cursor) + else: + self._reset() return item From noreply at buildbot.pypy.org Wed Apr 3 22:34:39 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 3 Apr 2013 22:34:39 +0200 (CEST) Subject: [pypy-commit] pypy default: merge Message-ID: <20130403203439.6EFE61C06BD@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r62987:9aafc2947dd7 Date: 2013-04-03 22:34 +0200 http://bitbucket.org/pypy/pypy/changeset/9aafc2947dd7/ Log: merge diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -117,3 +117,7 @@ .. branch: curses_cffi cffi implementation of _curses + +.. branch: sqlite-cffi + +cffi implementation of sqlite3 From noreply at buildbot.pypy.org Wed Apr 3 22:51:08 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Wed, 3 Apr 2013 22:51:08 +0200 (CEST) Subject: [pypy-commit] pypy default: call reset here instead to match cpython sqlite Message-ID: <20130403205108.142C41C00BD@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r62988:96285c0d4fd6 Date: 2013-04-03 16:50 -0400 http://bitbucket.org/pypy/pypy/changeset/96285c0d4fd6/ Log: call reset here instead to match cpython sqlite diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -1266,6 +1266,7 @@ try: item = self._item except AttributeError: + self._reset() raise StopIteration del self._item @@ -1275,8 +1276,6 @@ raise self.__con._get_exception(ret) elif ret == _lib.SQLITE_ROW: self._readahead(cursor) - else: - self._reset() return item From noreply at buildbot.pypy.org Wed Apr 3 22:55:01 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 3 Apr 2013 22:55:01 +0200 (CEST) Subject: [pypy-commit] pypy default: merge Message-ID: <20130403205501.F1DD91C0F0E@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r62990:d60870d842a8 Date: 2013-04-03 22:54 +0200 http://bitbucket.org/pypy/pypy/changeset/d60870d842a8/ Log: merge diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -1266,6 +1266,7 @@ try: item = self._item except AttributeError: + self._reset() raise StopIteration del self._item @@ -1275,8 +1276,6 @@ raise self.__con._get_exception(ret) elif ret == _lib.SQLITE_ROW: self._readahead(cursor) - else: - self._reset() return item From noreply at buildbot.pypy.org Wed Apr 3 22:55:00 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 3 Apr 2013 22:55:00 +0200 (CEST) Subject: [pypy-commit] pypy default: fix Message-ID: <20130403205500.C60681C0EFF@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r62989:1f81991c8cdd Date: 2013-04-03 22:54 +0200 http://bitbucket.org/pypy/pypy/changeset/1f81991c8cdd/ Log: fix diff --git a/lib_pypy/_curses.py b/lib_pypy/_curses.py --- a/lib_pypy/_curses.py +++ b/lib_pypy/_curses.py @@ -1328,7 +1328,7 @@ def tigetstr(capname): _ensure_initialised_setupterm() val = lib.tigetstr(capname) - if val in (0, -1, ffi.NULL): + if int(ffi.cast("intptr_t", val)) in (0, -1): return None return ffi.string(val) From noreply at buildbot.pypy.org Wed Apr 3 23:09:19 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Wed, 3 Apr 2013 23:09:19 +0200 (CEST) Subject: [pypy-commit] pypy default: slightly more correct, may matter in obscure or future cases Message-ID: <20130403210919.85C0B1C00BD@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r62991:fa9fd512a0bb Date: 2013-04-03 17:08 -0400 http://bitbucket.org/pypy/pypy/changeset/fa9fd512a0bb/ Log: slightly more correct, may matter in obscure or future cases diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -145,6 +145,7 @@ const char **pzTail /* OUT: Pointer to unused portion of zSql */ ); int sqlite3_finalize(sqlite3_stmt *pStmt); +int sqlite3_data_count(sqlite3_stmt *pStmt); int sqlite3_column_count(sqlite3_stmt *pStmt); const char *sqlite3_column_name(sqlite3_stmt*, int N); int sqlite3_get_autocommit(sqlite3*); @@ -1222,7 +1223,7 @@ def _readahead(self, cursor): row = [] - num_cols = _lib.sqlite3_column_count(self._statement) + num_cols = _lib.sqlite3_data_count(self._statement) for i in xrange(num_cols): if self.__con._detect_types: converter = self.__row_cast_map[i] From noreply at buildbot.pypy.org Wed Apr 3 23:09:20 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Wed, 3 Apr 2013 23:09:20 +0200 (CEST) Subject: [pypy-commit] pypy default: merge heads Message-ID: <20130403210920.DE9871C00BD@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r62992:eaa86aa10390 Date: 2013-04-03 17:09 -0400 http://bitbucket.org/pypy/pypy/changeset/eaa86aa10390/ Log: merge heads diff --git a/lib_pypy/_curses.py b/lib_pypy/_curses.py --- a/lib_pypy/_curses.py +++ b/lib_pypy/_curses.py @@ -1328,7 +1328,7 @@ def tigetstr(capname): _ensure_initialised_setupterm() val = lib.tigetstr(capname) - if val in (0, -1, ffi.NULL): + if int(ffi.cast("intptr_t", val)) in (0, -1): return None return ffi.string(val) From noreply at buildbot.pypy.org Wed Apr 3 23:16:51 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Wed, 3 Apr 2013 23:16:51 +0200 (CEST) Subject: [pypy-commit] pypy default: redo another change lost in sqlite-cffi merge Message-ID: <20130403211651.8C8171C0EFF@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r62993:5fab32c7353d Date: 2013-04-03 17:16 -0400 http://bitbucket.org/pypy/pypy/changeset/5fab32c7353d/ Log: redo another change lost in sqlite-cffi merge diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -581,9 +581,8 @@ def _begin(self): statement_star = _ffi.new('sqlite3_stmt **') - next_char = _ffi.new('char **') ret = _lib.sqlite3_prepare_v2(self._db, self.__begin_statement, -1, - statement_star, next_char) + statement_star, _ffi.NULL) try: if ret != _lib.SQLITE_OK: raise self._get_exception(ret) @@ -603,9 +602,8 @@ self.__do_all_statements(Statement._reset, False) statement_star = _ffi.new('sqlite3_stmt **') - next_char = _ffi.new('char **') ret = _lib.sqlite3_prepare_v2(self._db, b"COMMIT", -1, - statement_star, next_char) + statement_star, _ffi.NULL) try: if ret != _lib.SQLITE_OK: raise self._get_exception(ret) @@ -625,9 +623,8 @@ self.__do_all_statements(Statement._reset, True) statement_star = _ffi.new('sqlite3_stmt **') - next_char = _ffi.new('char **') ret = _lib.sqlite3_prepare_v2(self._db, b"ROLLBACK", -1, - statement_star, next_char) + statement_star, _ffi.NULL) try: if ret != _lib.SQLITE_OK: raise self._get_exception(ret) From noreply at buildbot.pypy.org Wed Apr 3 23:45:44 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Wed, 3 Apr 2013 23:45:44 +0200 (CEST) Subject: [pypy-commit] pypy default: redo more changes lost in sqlite-cffi merge Message-ID: <20130403214544.2C70A1C0F0E@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r62994:bd32583a3f11 Date: 2013-04-03 17:45 -0400 http://bitbucket.org/pypy/pypy/changeset/bd32583a3f11/ Log: redo more changes lost in sqlite-cffi merge diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -309,7 +309,7 @@ PARSE_DECLTYPES = 2 # SQLite version information -sqlite_version = _ffi.string(_lib.sqlite3_libversion()) +sqlite_version = str(_ffi.string(_lib.sqlite3_libversion()).decode('ascii')) class Error(StandardError): @@ -948,13 +948,12 @@ elif not isinstance(sql, str): raise ValueError("script argument must be unicode or string.") statement_star = _ffi.new('sqlite3_stmt **') - tail = _ffi.new('char **') + next_char = _ffi.new('char **') self.__connection.commit() while True: rc = _lib.sqlite3_prepare(self.__connection._db, sql, -1, - statement_star, tail) - sql = _ffi.string(tail[0]) + statement_star, next_char) if rc != _lib.SQLITE_OK: raise self.__connection._get_exception(rc) @@ -976,6 +975,7 @@ if rc != _lib.SQLITE_OK: raise self.__connection._get_exception(rc) + sql = _ffi.string(next_char[0]) if not sql: break return self @@ -1080,7 +1080,8 @@ if ret != _lib.SQLITE_OK: raise self.__con._get_exception(ret) - if _check_remaining_sql(_ffi.string(next_char[0])): + sql = _ffi.string(next_char[0]).decode('utf-8') + if _check_remaining_sql(sql): raise Warning("You can only execute one statement at a time.") def __del__(self): @@ -1171,7 +1172,7 @@ raise ProgrammingError("Binding %d has no name, but you " "supplied a dictionary (which has " "only names)." % i) - param_name = _ffi.string(param_name)[1:] + param_name = _ffi.string(param_name).decode('utf-8')[1:] try: param = params[param_name] except KeyError: @@ -1195,7 +1196,7 @@ if self.__con._detect_types & PARSE_COLNAMES: colname = _lib.sqlite3_column_name(self._statement, i) if colname is not None: - colname = _ffi.string(colname) + colname = _ffi.string(colname).decode('utf-8') type_start = -1 key = None for pos in range(len(colname)): @@ -1208,7 +1209,7 @@ if converter is None and self.__con._detect_types & PARSE_DECLTYPES: decltype = _lib.sqlite3_column_decltype(self._statement, i) if decltype is not None: - decltype = _ffi.string(decltype) + decltype = _ffi.string(decltype).decode('utf-8') # if multiple words, use first, eg. # "INTEGER NOT NULL" => "INTEGER" decltype = decltype.split()[0] @@ -1283,7 +1284,8 @@ desc = [] for i in xrange(_lib.sqlite3_column_count(self._statement)): name = _lib.sqlite3_column_name(self._statement, i) - name = _ffi.string(name).split("[")[0].strip() + if name is not None: + name = _ffi.string(name).decode('utf-8').split("[")[0].strip() desc.append((name, None, None, None, None, None, None)) return desc @@ -1378,7 +1380,7 @@ val = _lib.sqlite3_value_double(params[i]) elif typ == _lib.SQLITE_TEXT: val = _lib.sqlite3_value_text(params[i]) - val = unicode(_ffi.string(val), 'utf-8') + val = _ffi.string(val).decode('utf-8') elif typ == _lib.SQLITE_BLOB: blob = _lib.sqlite3_value_blob(params[i]) blob_len = _lib.sqlite3_value_bytes(params[i]) From noreply at buildbot.pypy.org Thu Apr 4 01:39:09 2013 From: noreply at buildbot.pypy.org (carljm) Date: Thu, 4 Apr 2013 01:39:09 +0200 (CEST) Subject: [pypy-commit] pypy default: Fix home and user distutils installation schemes. (issue1272) Message-ID: <20130403233909.C4B281C06BD@cobra.cs.uni-duesseldorf.de> Author: Carl Meyer Branch: Changeset: r62995:5b253d146851 Date: 2013-04-03 17:38 -0600 http://bitbucket.org/pypy/pypy/changeset/5b253d146851/ Log: Fix home and user distutils installation schemes. (issue1272) diff --git a/lib-python/2.7/distutils/command/install.py b/lib-python/2.7/distutils/command/install.py --- a/lib-python/2.7/distutils/command/install.py +++ b/lib-python/2.7/distutils/command/install.py @@ -474,7 +474,8 @@ def select_scheme (self, name): # it's the caller's problem if they supply a bad name! - if hasattr(sys, 'pypy_version_info'): + if hasattr(sys, 'pypy_version_info') and not ( + name.endswith('_user') or name.endswith('_home')): name = 'pypy' scheme = INSTALL_SCHEMES[name] for key in SCHEME_KEYS: diff --git a/lib-python/2.7/distutils/sysconfig_pypy.py b/lib-python/2.7/distutils/sysconfig_pypy.py --- a/lib-python/2.7/distutils/sysconfig_pypy.py +++ b/lib-python/2.7/distutils/sysconfig_pypy.py @@ -96,6 +96,9 @@ else: _config_vars = {} + _config_vars['prefix'] = PREFIX + _config_vars['exec_prefix'] = EXEC_PREFIX + if args: vals = [] for name in args: diff --git a/lib-python/2.7/distutils/tests/test_install.py b/lib-python/2.7/distutils/tests/test_install.py --- a/lib-python/2.7/distutils/tests/test_install.py +++ b/lib-python/2.7/distutils/tests/test_install.py @@ -4,7 +4,6 @@ import sys import unittest import site -from test import test_support from test.test_support import captured_stdout, run_unittest @@ -57,15 +56,14 @@ expected = os.path.normpath(expected) self.assertEqual(got, expected) - if test_support.check_impl_detail(): - libdir = os.path.join(destination, "lib", "python") - check_path(cmd.install_lib, libdir) - check_path(cmd.install_platlib, libdir) - check_path(cmd.install_purelib, libdir) - check_path(cmd.install_headers, - os.path.join(destination, "include", "python", "foopkg")) - check_path(cmd.install_scripts, os.path.join(destination, "bin")) - check_path(cmd.install_data, destination) + libdir = os.path.join(destination, "lib", "python") + check_path(cmd.install_lib, libdir) + check_path(cmd.install_platlib, libdir) + check_path(cmd.install_purelib, libdir) + check_path(cmd.install_headers, + os.path.join(destination, "include", "python", "foopkg")) + check_path(cmd.install_scripts, os.path.join(destination, "bin")) + check_path(cmd.install_data, destination) def test_user_site(self): # site.USER_SITE was introduced in 2.6 From noreply at buildbot.pypy.org Thu Apr 4 07:49:24 2013 From: noreply at buildbot.pypy.org (fijal) Date: Thu, 4 Apr 2013 07:49:24 +0200 (CEST) Subject: [pypy-commit] pypy default: cffi does not return none from externals (but can return NULL), Message-ID: <20130404054924.844A31C0228@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r62996:27d82b8799d6 Date: 2013-04-04 07:49 +0200 http://bitbucket.org/pypy/pypy/changeset/27d82b8799d6/ Log: cffi does not return none from externals (but can return NULL), such things should be tested though!!! diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -1284,7 +1284,7 @@ desc = [] for i in xrange(_lib.sqlite3_column_count(self._statement)): name = _lib.sqlite3_column_name(self._statement, i) - if name is not None: + if name: name = _ffi.string(name).decode('utf-8').split("[")[0].strip() desc.append((name, None, None, None, None, None, None)) return desc From noreply at buildbot.pypy.org Thu Apr 4 08:01:23 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Thu, 4 Apr 2013 08:01:23 +0200 (CEST) Subject: [pypy-commit] pypy default: more sqlite adaptations for cffi Message-ID: <20130404060123.C3D541C0305@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r62997:b0cf3609c4c6 Date: 2013-04-04 02:00 -0400 http://bitbucket.org/pypy/pypy/changeset/b0cf3609c4c6/ Log: more sqlite adaptations for cffi diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -1195,7 +1195,7 @@ if self.__con._detect_types & PARSE_COLNAMES: colname = _lib.sqlite3_column_name(self._statement, i) - if colname is not None: + if colname: colname = _ffi.string(colname).decode('utf-8') type_start = -1 key = None @@ -1208,7 +1208,7 @@ if converter is None and self.__con._detect_types & PARSE_DECLTYPES: decltype = _lib.sqlite3_column_decltype(self._statement, i) - if decltype is not None: + if decltype: decltype = _ffi.string(decltype).decode('utf-8') # if multiple words, use first, eg. # "INTEGER NOT NULL" => "INTEGER" From noreply at buildbot.pypy.org Thu Apr 4 08:24:33 2013 From: noreply at buildbot.pypy.org (fijal) Date: Thu, 4 Apr 2013 08:24:33 +0200 (CEST) Subject: [pypy-commit] pypy default: We need to keep alive the sql statement for a bit longer, since next_char Message-ID: <20130404062433.7ABD51C039A@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r62998:1d4ae971e56f Date: 2013-04-04 08:24 +0200 http://bitbucket.org/pypy/pypy/changeset/1d4ae971e56f/ Log: We need to keep alive the sql statement for a bit longer, since next_char will point to some memory that we have to own at the point of reading it. diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -1067,7 +1067,8 @@ sql = sql.encode('utf-8') statement_star = _ffi.new('sqlite3_stmt **') next_char = _ffi.new('char **') - ret = _lib.sqlite3_prepare_v2(self.__con._db, sql, -1, + llsql = _ffi.new("char[]", sql) + ret = _lib.sqlite3_prepare_v2(self.__con._db, llsql, -1, statement_star, next_char) self._statement = statement_star[0] @@ -1080,8 +1081,8 @@ if ret != _lib.SQLITE_OK: raise self.__con._get_exception(ret) - sql = _ffi.string(next_char[0]).decode('utf-8') - if _check_remaining_sql(sql): + remaining_sql = _ffi.string(next_char[0]).decode('utf-8') + if _check_remaining_sql(remaining_sql): raise Warning("You can only execute one statement at a time.") def __del__(self): From noreply at buildbot.pypy.org Thu Apr 4 08:51:25 2013 From: noreply at buildbot.pypy.org (fijal) Date: Thu, 4 Apr 2013 08:51:25 +0200 (CEST) Subject: [pypy-commit] pypy default: detect BEGIN. (CPython does check of statement type) Message-ID: <20130404065125.CEF0B1C039A@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r62999:c1c610355c04 Date: 2013-04-04 08:51 +0200 http://bitbucket.org/pypy/pypy/changeset/c1c610355c04/ Log: detect BEGIN. (CPython does check of statement type) diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -892,6 +892,11 @@ raise ValueError("operation parameter must be str or unicode") self.__description = None self.__rowcount = -1 + + if sql == 'BEGIN': + self.__connection._begin() + return + self.__statement = self.__connection._statement_cache.get( sql, self.row_factory) @@ -1050,6 +1055,9 @@ self.__con = connection self.__con._remember_statement(self) + self._in_use = False + self._row_factory = None + if not isinstance(sql, basestring): raise Warning("SQL is of wrong type. Must be string or unicode.") first_word = self._statement_kind = sql.lstrip().split(" ")[0].upper() @@ -1060,9 +1068,6 @@ else: self._kind = Statement._DDL - self._in_use = False - self._row_factory = None - if isinstance(sql, unicode): sql = sql.encode('utf-8') statement_star = _ffi.new('sqlite3_stmt **') From noreply at buildbot.pypy.org Thu Apr 4 08:54:00 2013 From: noreply at buildbot.pypy.org (fijal) Date: Thu, 4 Apr 2013 08:54:00 +0200 (CEST) Subject: [pypy-commit] pypy default: write some tests Message-ID: <20130404065400.8265E1C039A@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r63000:8fd632265209 Date: 2013-04-04 08:53 +0200 http://bitbucket.org/pypy/pypy/changeset/8fd632265209/ Log: write some tests diff --git a/pypy/module/test_lib_pypy/test_sqlite3.py b/pypy/module/test_lib_pypy/test_sqlite3.py --- a/pypy/module/test_lib_pypy/test_sqlite3.py +++ b/pypy/module/test_lib_pypy/test_sqlite3.py @@ -196,3 +196,10 @@ con.execute('insert into foo(x) values (?)', 2) assert str(e.value) == 'parameters are of unsupported type' con.close() + +def test_explicit_begin(): + con = _sqlite3.connect(':memory:') + con.execute('BEGIN') + con.commit() + con.execute('BEGIN') + con.commit() From noreply at buildbot.pypy.org Thu Apr 4 10:01:37 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Thu, 4 Apr 2013 10:01:37 +0200 (CEST) Subject: [pypy-commit] pypy default: a more proper fix than the one applied in c1c610355c04 Message-ID: <20130404080137.D35571C0305@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63001:ace23a4657c0 Date: 2013-04-04 04:01 -0400 http://bitbucket.org/pypy/pypy/changeset/ace23a4657c0/ Log: a more proper fix than the one applied in c1c610355c04 diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -892,11 +892,6 @@ raise ValueError("operation parameter must be str or unicode") self.__description = None self.__rowcount = -1 - - if sql == 'BEGIN': - self.__connection._begin() - return - self.__statement = self.__connection._statement_cache.get( sql, self.row_factory) @@ -918,8 +913,6 @@ ret = _lib.sqlite3_step(self.__statement._statement) if ret not in (_lib.SQLITE_DONE, _lib.SQLITE_ROW): self.__statement._reset() - self.__connection._in_transaction = \ - not _lib.sqlite3_get_autocommit(self.__connection._db) raise self.__connection._get_exception(ret) if self.__statement._kind == Statement._DML: @@ -934,6 +927,8 @@ self.__rowcount = 0 self.__rowcount += _lib.sqlite3_changes(self.__connection._db) finally: + self.__connection._in_transaction = \ + not _lib.sqlite3_get_autocommit(self.__connection._db) self.__locked = False return self From noreply at buildbot.pypy.org Thu Apr 4 10:21:15 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Thu, 4 Apr 2013 10:21:15 +0200 (CEST) Subject: [pypy-commit] pypy default: take care about next_char's memory in a couple more places Message-ID: <20130404082115.E5E8C1C06BD@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63002:5705899a3a6a Date: 2013-04-04 04:20 -0400 http://bitbucket.org/pypy/pypy/changeset/5705899a3a6a/ Log: take care about next_char's memory in a couple more places diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -952,7 +952,8 @@ self.__connection.commit() while True: - rc = _lib.sqlite3_prepare(self.__connection._db, sql, -1, + c_sql = _ffi.new("char[]", sql) + rc = _lib.sqlite3_prepare(self.__connection._db, c_sql, -1, statement_star, next_char) if rc != _lib.SQLITE_OK: raise self.__connection._get_exception(rc) @@ -1067,22 +1068,23 @@ sql = sql.encode('utf-8') statement_star = _ffi.new('sqlite3_stmt **') next_char = _ffi.new('char **') - llsql = _ffi.new("char[]", sql) - ret = _lib.sqlite3_prepare_v2(self.__con._db, llsql, -1, + c_sql = _ffi.new("char[]", sql) + ret = _lib.sqlite3_prepare_v2(self.__con._db, c_sql, -1, statement_star, next_char) self._statement = statement_star[0] if ret == _lib.SQLITE_OK and not self._statement: # an empty statement, work around that, as it's the least trouble - ret = _lib.sqlite3_prepare_v2(self.__con._db, "select 42", -1, + c_sql = _ffi.new("char[]", "select 42") + ret = _lib.sqlite3_prepare_v2(self.__con._db, c_sql, -1, statement_star, next_char) self._statement = statement_star[0] self._kind = Statement._DQL if ret != _lib.SQLITE_OK: raise self.__con._get_exception(ret) - remaining_sql = _ffi.string(next_char[0]).decode('utf-8') - if _check_remaining_sql(remaining_sql): + tail = _ffi.string(next_char[0]).decode('utf-8') + if _check_remaining_sql(tail): raise Warning("You can only execute one statement at a time.") def __del__(self): From noreply at buildbot.pypy.org Thu Apr 4 10:35:15 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Thu, 4 Apr 2013 10:35:15 +0200 (CEST) Subject: [pypy-commit] pypy default: enhance this test to demonstrate flaws in the initial fix Message-ID: <20130404083515.C32E61C0F0E@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63003:5f25d776122e Date: 2013-04-04 04:33 -0400 http://bitbucket.org/pypy/pypy/changeset/5f25d776122e/ Log: enhance this test to demonstrate flaws in the initial fix diff --git a/pypy/module/test_lib_pypy/test_sqlite3.py b/pypy/module/test_lib_pypy/test_sqlite3.py --- a/pypy/module/test_lib_pypy/test_sqlite3.py +++ b/pypy/module/test_lib_pypy/test_sqlite3.py @@ -200,6 +200,8 @@ def test_explicit_begin(): con = _sqlite3.connect(':memory:') con.execute('BEGIN') + con.execute('BEGIN ') + con.execute('BEGIN') con.commit() con.execute('BEGIN') con.commit() From noreply at buildbot.pypy.org Thu Apr 4 10:46:41 2013 From: noreply at buildbot.pypy.org (fijal) Date: Thu, 4 Apr 2013 10:46:41 +0200 (CEST) Subject: [pypy-commit] pypy release-2.0-beta2: merge default Message-ID: <20130404084641.5F2621C0305@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: release-2.0-beta2 Changeset: r63004:b330a6e08a7e Date: 2013-04-04 10:46 +0200 http://bitbucket.org/pypy/pypy/changeset/b330a6e08a7e/ Log: merge default diff --git a/lib-python/2.7/distutils/command/install.py b/lib-python/2.7/distutils/command/install.py --- a/lib-python/2.7/distutils/command/install.py +++ b/lib-python/2.7/distutils/command/install.py @@ -474,7 +474,8 @@ def select_scheme (self, name): # it's the caller's problem if they supply a bad name! - if hasattr(sys, 'pypy_version_info'): + if hasattr(sys, 'pypy_version_info') and not ( + name.endswith('_user') or name.endswith('_home')): name = 'pypy' scheme = INSTALL_SCHEMES[name] for key in SCHEME_KEYS: diff --git a/lib-python/2.7/distutils/sysconfig_pypy.py b/lib-python/2.7/distutils/sysconfig_pypy.py --- a/lib-python/2.7/distutils/sysconfig_pypy.py +++ b/lib-python/2.7/distutils/sysconfig_pypy.py @@ -96,6 +96,9 @@ else: _config_vars = {} + _config_vars['prefix'] = PREFIX + _config_vars['exec_prefix'] = EXEC_PREFIX + if args: vals = [] for name in args: diff --git a/lib-python/2.7/distutils/tests/test_install.py b/lib-python/2.7/distutils/tests/test_install.py --- a/lib-python/2.7/distutils/tests/test_install.py +++ b/lib-python/2.7/distutils/tests/test_install.py @@ -4,7 +4,6 @@ import sys import unittest import site -from test import test_support from test.test_support import captured_stdout, run_unittest @@ -57,15 +56,14 @@ expected = os.path.normpath(expected) self.assertEqual(got, expected) - if test_support.check_impl_detail(): - libdir = os.path.join(destination, "lib", "python") - check_path(cmd.install_lib, libdir) - check_path(cmd.install_platlib, libdir) - check_path(cmd.install_purelib, libdir) - check_path(cmd.install_headers, - os.path.join(destination, "include", "python", "foopkg")) - check_path(cmd.install_scripts, os.path.join(destination, "bin")) - check_path(cmd.install_data, destination) + libdir = os.path.join(destination, "lib", "python") + check_path(cmd.install_lib, libdir) + check_path(cmd.install_platlib, libdir) + check_path(cmd.install_purelib, libdir) + check_path(cmd.install_headers, + os.path.join(destination, "include", "python", "foopkg")) + check_path(cmd.install_scripts, os.path.join(destination, "bin")) + check_path(cmd.install_data, destination) def test_user_site(self): # site.USER_SITE was introduced in 2.6 diff --git a/lib_pypy/_curses.py b/lib_pypy/_curses.py --- a/lib_pypy/_curses.py +++ b/lib_pypy/_curses.py @@ -1328,7 +1328,7 @@ def tigetstr(capname): _ensure_initialised_setupterm() val = lib.tigetstr(capname) - if val in (0, -1, ffi.NULL): + if int(ffi.cast("intptr_t", val)) in (0, -1): return None return ffi.string(val) diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -145,6 +145,7 @@ const char **pzTail /* OUT: Pointer to unused portion of zSql */ ); int sqlite3_finalize(sqlite3_stmt *pStmt); +int sqlite3_data_count(sqlite3_stmt *pStmt); int sqlite3_column_count(sqlite3_stmt *pStmt); const char *sqlite3_column_name(sqlite3_stmt*, int N); int sqlite3_get_autocommit(sqlite3*); @@ -308,7 +309,7 @@ PARSE_DECLTYPES = 2 # SQLite version information -sqlite_version = _ffi.string(_lib.sqlite3_libversion()) +sqlite_version = str(_ffi.string(_lib.sqlite3_libversion()).decode('ascii')) class Error(StandardError): @@ -580,9 +581,8 @@ def _begin(self): statement_star = _ffi.new('sqlite3_stmt **') - next_char = _ffi.new('char **') ret = _lib.sqlite3_prepare_v2(self._db, self.__begin_statement, -1, - statement_star, next_char) + statement_star, _ffi.NULL) try: if ret != _lib.SQLITE_OK: raise self._get_exception(ret) @@ -602,9 +602,8 @@ self.__do_all_statements(Statement._reset, False) statement_star = _ffi.new('sqlite3_stmt **') - next_char = _ffi.new('char **') ret = _lib.sqlite3_prepare_v2(self._db, b"COMMIT", -1, - statement_star, next_char) + statement_star, _ffi.NULL) try: if ret != _lib.SQLITE_OK: raise self._get_exception(ret) @@ -624,9 +623,8 @@ self.__do_all_statements(Statement._reset, True) statement_star = _ffi.new('sqlite3_stmt **') - next_char = _ffi.new('char **') ret = _lib.sqlite3_prepare_v2(self._db, b"ROLLBACK", -1, - statement_star, next_char) + statement_star, _ffi.NULL) try: if ret != _lib.SQLITE_OK: raise self._get_exception(ret) @@ -915,8 +913,6 @@ ret = _lib.sqlite3_step(self.__statement._statement) if ret not in (_lib.SQLITE_DONE, _lib.SQLITE_ROW): self.__statement._reset() - self.__connection._in_transaction = \ - not _lib.sqlite3_get_autocommit(self.__connection._db) raise self.__connection._get_exception(ret) if self.__statement._kind == Statement._DML: @@ -931,6 +927,8 @@ self.__rowcount = 0 self.__rowcount += _lib.sqlite3_changes(self.__connection._db) finally: + self.__connection._in_transaction = \ + not _lib.sqlite3_get_autocommit(self.__connection._db) self.__locked = False return self @@ -950,13 +948,13 @@ elif not isinstance(sql, str): raise ValueError("script argument must be unicode or string.") statement_star = _ffi.new('sqlite3_stmt **') - tail = _ffi.new('char **') + next_char = _ffi.new('char **') self.__connection.commit() while True: - rc = _lib.sqlite3_prepare(self.__connection._db, sql, -1, - statement_star, tail) - sql = _ffi.string(tail[0]) + c_sql = _ffi.new("char[]", sql) + rc = _lib.sqlite3_prepare(self.__connection._db, c_sql, -1, + statement_star, next_char) if rc != _lib.SQLITE_OK: raise self.__connection._get_exception(rc) @@ -978,6 +976,7 @@ if rc != _lib.SQLITE_OK: raise self.__connection._get_exception(rc) + sql = _ffi.string(next_char[0]) if not sql: break return self @@ -1052,6 +1051,9 @@ self.__con = connection self.__con._remember_statement(self) + self._in_use = False + self._row_factory = None + if not isinstance(sql, basestring): raise Warning("SQL is of wrong type. Must be string or unicode.") first_word = self._statement_kind = sql.lstrip().split(" ")[0].upper() @@ -1062,27 +1064,27 @@ else: self._kind = Statement._DDL - self._in_use = False - self._row_factory = None - if isinstance(sql, unicode): sql = sql.encode('utf-8') statement_star = _ffi.new('sqlite3_stmt **') next_char = _ffi.new('char **') - ret = _lib.sqlite3_prepare_v2(self.__con._db, sql, -1, + c_sql = _ffi.new("char[]", sql) + ret = _lib.sqlite3_prepare_v2(self.__con._db, c_sql, -1, statement_star, next_char) self._statement = statement_star[0] if ret == _lib.SQLITE_OK and not self._statement: # an empty statement, work around that, as it's the least trouble - ret = _lib.sqlite3_prepare_v2(self.__con._db, "select 42", -1, + c_sql = _ffi.new("char[]", "select 42") + ret = _lib.sqlite3_prepare_v2(self.__con._db, c_sql, -1, statement_star, next_char) self._statement = statement_star[0] self._kind = Statement._DQL if ret != _lib.SQLITE_OK: raise self.__con._get_exception(ret) - if _check_remaining_sql(_ffi.string(next_char[0])): + tail = _ffi.string(next_char[0]).decode('utf-8') + if _check_remaining_sql(tail): raise Warning("You can only execute one statement at a time.") def __del__(self): @@ -1173,7 +1175,7 @@ raise ProgrammingError("Binding %d has no name, but you " "supplied a dictionary (which has " "only names)." % i) - param_name = _ffi.string(param_name)[1:] + param_name = _ffi.string(param_name).decode('utf-8')[1:] try: param = params[param_name] except KeyError: @@ -1196,8 +1198,8 @@ if self.__con._detect_types & PARSE_COLNAMES: colname = _lib.sqlite3_column_name(self._statement, i) - if colname is not None: - colname = _ffi.string(colname) + if colname: + colname = _ffi.string(colname).decode('utf-8') type_start = -1 key = None for pos in range(len(colname)): @@ -1209,8 +1211,8 @@ if converter is None and self.__con._detect_types & PARSE_DECLTYPES: decltype = _lib.sqlite3_column_decltype(self._statement, i) - if decltype is not None: - decltype = _ffi.string(decltype) + if decltype: + decltype = _ffi.string(decltype).decode('utf-8') # if multiple words, use first, eg. # "INTEGER NOT NULL" => "INTEGER" decltype = decltype.split()[0] @@ -1222,7 +1224,7 @@ def _readahead(self, cursor): row = [] - num_cols = _lib.sqlite3_column_count(self._statement) + num_cols = _lib.sqlite3_data_count(self._statement) for i in xrange(num_cols): if self.__con._detect_types: converter = self.__row_cast_map[i] @@ -1266,6 +1268,7 @@ try: item = self._item except AttributeError: + self._reset() raise StopIteration del self._item @@ -1284,7 +1287,8 @@ desc = [] for i in xrange(_lib.sqlite3_column_count(self._statement)): name = _lib.sqlite3_column_name(self._statement, i) - name = _ffi.string(name).split("[")[0].strip() + if name: + name = _ffi.string(name).decode('utf-8').split("[")[0].strip() desc.append((name, None, None, None, None, None, None)) return desc @@ -1379,7 +1383,7 @@ val = _lib.sqlite3_value_double(params[i]) elif typ == _lib.SQLITE_TEXT: val = _lib.sqlite3_value_text(params[i]) - val = unicode(_ffi.string(val), 'utf-8') + val = _ffi.string(val).decode('utf-8') elif typ == _lib.SQLITE_BLOB: blob = _lib.sqlite3_value_blob(params[i]) blob_len = _lib.sqlite3_value_bytes(params[i]) diff --git a/pypy/module/test_lib_pypy/test_sqlite3.py b/pypy/module/test_lib_pypy/test_sqlite3.py --- a/pypy/module/test_lib_pypy/test_sqlite3.py +++ b/pypy/module/test_lib_pypy/test_sqlite3.py @@ -196,3 +196,12 @@ con.execute('insert into foo(x) values (?)', 2) assert str(e.value) == 'parameters are of unsupported type' con.close() + +def test_explicit_begin(): + con = _sqlite3.connect(':memory:') + con.execute('BEGIN') + con.execute('BEGIN ') + con.execute('BEGIN') + con.commit() + con.execute('BEGIN') + con.commit() From noreply at buildbot.pypy.org Thu Apr 4 12:17:53 2013 From: noreply at buildbot.pypy.org (arigo) Date: Thu, 4 Apr 2013 12:17:53 +0200 (CEST) Subject: [pypy-commit] cffi default: Add a comment. Message-ID: <20130404101753.F11981C06BD@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r1229:3935c49ed238 Date: 2013-04-04 12:17 +0200 http://bitbucket.org/cffi/cffi/changeset/3935c49ed238/ Log: Add a comment. diff --git a/doc/source/index.rst b/doc/source/index.rst --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -1383,7 +1383,8 @@ cdata object that is a "view" of all items from ``start`` to ``stop``. It is a cdata of type "array" (so e.g. passing it as an argument to a C function would just convert it to a pointer to the ``start`` item). - As with indexing, negative bounds mean really negative indices, like in + It makes cdata's of type "array" behave more like a Python list, but + as with indexing, negative bounds mean really negative indices, like in C. As for slice assignment, it accepts any iterable, including a list of items or another array-like cdata object, but the length must match. (Note that this behavior differs from initialization: e.g. if you pass From noreply at buildbot.pypy.org Thu Apr 4 13:04:56 2013 From: noreply at buildbot.pypy.org (fijal) Date: Thu, 4 Apr 2013 13:04:56 +0200 (CEST) Subject: [pypy-commit] pypy default: fix packaging to include .so Message-ID: <20130404110456.E13891C2FF8@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r63008:c371b51f6734 Date: 2013-04-04 12:59 +0200 http://bitbucket.org/pypy/pypy/changeset/c371b51f6734/ Log: fix packaging to include .so diff --git a/lib_pypy/cffi/api.py b/lib_pypy/cffi/api.py --- a/lib_pypy/cffi/api.py +++ b/lib_pypy/cffi/api.py @@ -25,7 +25,6 @@ line = '' return '%s%s' % (line, self.args[0]) - class FFI(object): r''' The main top-level class that you instantiate once, or once per module. diff --git a/pypy/tool/release/package.py b/pypy/tool/release/package.py --- a/pypy/tool/release/package.py +++ b/pypy/tool/release/package.py @@ -17,6 +17,7 @@ import py import fnmatch from rpython.tool.udir import udir +import subprocess if sys.version_info < (2,6): py.test.skip("requires 2.6 so far") @@ -64,6 +65,8 @@ raise PyPyCNotFound( 'Bogus path: %r does not exist (see docstring for more info)' % (os.path.dirname(str(pypy_c)),)) + subprocess.check_call([str(pypy_c), '-c', 'import _sqlite3']) + subprocess.check_call([str(pypy_c), '-c', 'import _curses']) if sys.platform == 'win32' and not rename_pypy_c.lower().endswith('.exe'): rename_pypy_c += '.exe' binaries = [(pypy_c, rename_pypy_c)] @@ -73,9 +76,9 @@ #Instructions are provided on the website. # Can't rename a DLL: it is always called 'libpypy-c.dll' - + for extra in ['libpypy-c.dll', - 'libexpat.dll', 'sqlite3.dll', + 'libexpat.dll', 'sqlite3.dll', 'libeay32.dll', 'ssleay32.dll']: p = pypy_c.dirpath().join(extra) if not p.check(): @@ -93,7 +96,8 @@ ignore=ignore_patterns('.svn', 'py', '*.pyc', '*~')) shutil.copytree(str(basedir.join('lib_pypy')), str(pypydir.join('lib_pypy')), - ignore=ignore_patterns('.svn', 'py', '*.pyc', '*~')) + ignore=ignore_patterns('.svn', 'py', '*.pyc', '*~', + '*.c', '*.o')) for file in ['LICENSE', 'README.rst']: shutil.copy(str(basedir.join(file)), str(pypydir)) pypydir.ensure('include', dir=True) From noreply at buildbot.pypy.org Thu Apr 4 13:04:58 2013 From: noreply at buildbot.pypy.org (fijal) Date: Thu, 4 Apr 2013 13:04:58 +0200 (CEST) Subject: [pypy-commit] pypy default: merge Message-ID: <20130404110458.242821C3016@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r63009:94f30b2a233c Date: 2013-04-04 13:04 +0200 http://bitbucket.org/pypy/pypy/changeset/94f30b2a233c/ Log: merge diff --git a/pypy/module/test_lib_pypy/lextab.py b/pypy/module/test_lib_pypy/lextab.py deleted file mode 100644 --- a/pypy/module/test_lib_pypy/lextab.py +++ /dev/null @@ -1,9 +0,0 @@ -# pycparser.lextab.py. This file automatically created by PLY (version 3.4). Don't edit! -_tabversion = '3.4' -_lextokens = {'VOID': 1, 'LBRACKET': 1, 'WCHAR_CONST': 1, 'FLOAT_CONST': 1, 'MINUS': 1, 'RPAREN': 1, 'LONG': 1, 'PLUS': 1, 'ELLIPSIS': 1, 'GT': 1, 'GOTO': 1, 'ENUM': 1, 'PERIOD': 1, 'GE': 1, 'INT_CONST_DEC': 1, 'ARROW': 1, 'HEX_FLOAT_CONST': 1, 'DOUBLE': 1, 'MINUSEQUAL': 1, 'INT_CONST_OCT': 1, 'TIMESEQUAL': 1, 'OR': 1, 'SHORT': 1, 'RETURN': 1, 'RSHIFTEQUAL': 1, 'RESTRICT': 1, 'STATIC': 1, 'SIZEOF': 1, 'UNSIGNED': 1, 'UNION': 1, 'COLON': 1, 'WSTRING_LITERAL': 1, 'DIVIDE': 1, 'FOR': 1, 'PLUSPLUS': 1, 'EQUALS': 1, 'ELSE': 1, 'INLINE': 1, 'EQ': 1, 'AND': 1, 'TYPEID': 1, 'LBRACE': 1, 'PPHASH': 1, 'INT': 1, 'SIGNED': 1, 'CONTINUE': 1, 'NOT': 1, 'OREQUAL': 1, 'MOD': 1, 'RSHIFT': 1, 'DEFAULT': 1, 'CHAR': 1, 'WHILE': 1, 'DIVEQUAL': 1, 'EXTERN': 1, 'CASE': 1, 'LAND': 1, 'REGISTER': 1, 'MODEQUAL': 1, 'NE': 1, 'SWITCH': 1, 'INT_CONST_HEX': 1, '_COMPLEX': 1, 'PLUSEQUAL': 1, 'STRUCT': 1, 'CONDOP': 1, 'BREAK': 1, 'VOLATILE': 1, 'ANDEQUAL': 1, 'DO': 1, 'LNOT': 1, 'CONST': 1, 'LOR': 1, 'CHAR_CONST': 1, 'LSHIFT': 1, 'RBRACE': 1, '_BOOL': 1, 'LE': 1, 'SEMI': 1, 'LT': 1, 'COMMA': 1, 'TYPEDEF': 1, 'XOR': 1, 'AUTO': 1, 'TIMES': 1, 'LPAREN': 1, 'MINUSMINUS': 1, 'ID': 1, 'IF': 1, 'STRING_LITERAL': 1, 'FLOAT': 1, 'XOREQUAL': 1, 'LSHIFTEQUAL': 1, 'RBRACKET': 1} -_lexreflags = 0 -_lexliterals = '' -_lexstateinfo = {'ppline': 'exclusive', 'pppragma': 'exclusive', 'INITIAL': 'inclusive'} -_lexstatere = {'ppline': [('(?P"([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*")|(?P(0(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?)|([1-9][0-9]*(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?))|(?P\\n)|(?Pline)', [None, ('t_ppline_FILENAME', 'FILENAME'), None, None, None, None, None, None, ('t_ppline_LINE_NUMBER', 'LINE_NUMBER'), None, None, None, None, None, None, None, None, ('t_ppline_NEWLINE', 'NEWLINE'), ('t_ppline_PPLINE', 'PPLINE')])], 'pppragma': [('(?P\\n)|(?Ppragma)|(?P"([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*")|(?P[a-zA-Z_][0-9a-zA-Z_]*)', [None, ('t_pppragma_NEWLINE', 'NEWLINE'), ('t_pppragma_PPPRAGMA', 'PPPRAGMA'), ('t_pppragma_STR', 'STR'), None, None, None, None, None, None, ('t_pppragma_ID', 'ID')])], 'INITIAL': [('(?P[ \\t]*\\#)|(?P\\n+)|(?P((((([0-9]*\\.[0-9]+)|([0-9]+\\.))([eE][-+]?[0-9]+)?)|([0-9]+([eE][-+]?[0-9]+)))[FfLl]?))|(?P(0[xX]([0-9a-fA-F]+|((([0-9a-fA-F]+)?\\.[0-9a-fA-F]+)|([0-9a-fA-F]+\\.)))([pP][+-]?[0-9]+)[FfLl]?))|(?P0[xX][0-9a-fA-F]+(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?)|(?P0[0-7]*[89])|(?P0[0-7]*(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?)', [None, ('t_PPHASH', 'PPHASH'), ('t_NEWLINE', 'NEWLINE'), ('t_FLOAT_CONST', 'FLOAT_CONST'), None, None, None, None, None, None, None, None, None, ('t_HEX_FLOAT_CONST', 'HEX_FLOAT_CONST'), None, None, None, None, None, None, None, ('t_INT_CONST_HEX', 'INT_CONST_HEX'), None, None, None, ('t_BAD_CONST_OCT', 'BAD_CONST_OCT'), ('t_INT_CONST_OCT', 'INT_CONST_OCT')]), ('(?P(0(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?)|([1-9][0-9]*(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?))|(?P\'([^\'\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))\')|(?PL\'([^\'\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))\')|(?P(\'([^\'\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*\\n)|(\'([^\'\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*$))|(?P(\'([^\'\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))[^\'\n]+\')|(\'\')|(\'([\\\\][^a-zA-Z._~^!=&\\^\\-\\\\?\'"x0-7])[^\'\\n]*\'))|(?PL"([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*")|(?P"([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*([\\\\][^a-zA-Z._~^!=&\\^\\-\\\\?\'"x0-7])([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*")|(?P[a-zA-Z_][0-9a-zA-Z_]*)', [None, ('t_INT_CONST_DEC', 'INT_CONST_DEC'), None, None, None, None, None, None, None, None, ('t_CHAR_CONST', 'CHAR_CONST'), None, None, None, None, None, None, ('t_WCHAR_CONST', 'WCHAR_CONST'), None, None, None, None, None, None, ('t_UNMATCHED_QUOTE', 'UNMATCHED_QUOTE'), None, None, None, None, None, None, None, None, None, None, None, None, None, None, ('t_BAD_CHAR_CONST', 'BAD_CHAR_CONST'), None, None, None, None, None, None, None, None, None, None, ('t_WSTRING_LITERAL', 'WSTRING_LITERAL'), None, None, None, None, None, None, ('t_BAD_STRING_LITERAL', 'BAD_STRING_LITERAL'), None, None, None, None, None, None, None, None, None, None, None, None, None, ('t_ID', 'ID')]), ('(?P"([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*")|(?P\\.\\.\\.)|(?P\\+\\+)|(?P\\|\\|)|(?P\\^=)|(?P\\|=)|(?P<<=)|(?P>>=)|(?P\\+=)|(?P\\*=)|(?P\\+)|(?P%=)|(?P\\{)|(?P/=)|(?P\\])|(?P\\?)', [None, (None, 'STRING_LITERAL'), None, None, None, None, None, None, (None, 'ELLIPSIS'), (None, 'PLUSPLUS'), (None, 'LOR'), (None, 'XOREQUAL'), (None, 'OREQUAL'), (None, 'LSHIFTEQUAL'), (None, 'RSHIFTEQUAL'), (None, 'PLUSEQUAL'), (None, 'TIMESEQUAL'), (None, 'PLUS'), (None, 'MODEQUAL'), (None, 'LBRACE'), (None, 'DIVEQUAL'), (None, 'RBRACKET'), (None, 'CONDOP')]), ('(?P\\^)|(?P<<)|(?P<=)|(?P\\()|(?P->)|(?P==)|(?P\\})|(?P!=)|(?P--)|(?P\\|)|(?P\\*)|(?P\\[)|(?P>=)|(?P\\))|(?P&&)|(?P>>)|(?P&=)|(?P-=)|(?P\\.)|(?P=)|(?P<)|(?P,)|(?P/)|(?P&)|(?P%)|(?P;)|(?P-)|(?P>)|(?P:)|(?P~)|(?P!)', [None, (None, 'XOR'), (None, 'LSHIFT'), (None, 'LE'), (None, 'LPAREN'), (None, 'ARROW'), (None, 'EQ'), (None, 'RBRACE'), (None, 'NE'), (None, 'MINUSMINUS'), (None, 'OR'), (None, 'TIMES'), (None, 'LBRACKET'), (None, 'GE'), (None, 'RPAREN'), (None, 'LAND'), (None, 'RSHIFT'), (None, 'ANDEQUAL'), (None, 'MINUSEQUAL'), (None, 'PERIOD'), (None, 'EQUALS'), (None, 'LT'), (None, 'COMMA'), (None, 'DIVIDE'), (None, 'AND'), (None, 'MOD'), (None, 'SEMI'), (None, 'MINUS'), (None, 'GT'), (None, 'COLON'), (None, 'NOT'), (None, 'LNOT')])]} -_lexstateignore = {'ppline': ' \t', 'pppragma': ' \t<>.-{}();+-*/$%@&^~!?:,0123456789', 'INITIAL': ' \t'} -_lexstateerrorf = {'ppline': 't_ppline_error', 'pppragma': 't_pppragma_error', 'INITIAL': 't_error'} diff --git a/pypy/module/test_lib_pypy/pyrepl/test_bugs.py b/pypy/module/test_lib_pypy/pyrepl/test_bugs.py --- a/pypy/module/test_lib_pypy/pyrepl/test_bugs.py +++ b/pypy/module/test_lib_pypy/pyrepl/test_bugs.py @@ -24,7 +24,6 @@ # (applicable) bug reports import pytest -import os, sys class HistoricalTestReader(HistoricalReader, BaseTestReader): diff --git a/pypy/module/test_lib_pypy/pyrepl/test_readline.py b/pypy/module/test_lib_pypy/pyrepl/test_readline.py --- a/pypy/module/test_lib_pypy/pyrepl/test_readline.py +++ b/pypy/module/test_lib_pypy/pyrepl/test_readline.py @@ -1,5 +1,4 @@ import pytest -import os, sys @pytest.mark.skipif("os.name != 'posix' or 'darwin' in sys.platform") diff --git a/pypy/module/test_lib_pypy/yacctab.py b/pypy/module/test_lib_pypy/yacctab.py deleted file mode 100644 --- a/pypy/module/test_lib_pypy/yacctab.py +++ /dev/null @@ -1,280 +0,0 @@ - -# yacctab.py -# This file is automatically generated. Do not edit. -_tabversion = '3.2' - -_lr_method = 'LALR' - -_lr_signature = '\x9er\xf1|P\xb6\xbb\x13\xed\xf52\xa1\xb1\xc3J\x12' - -_lr_action_items = {'VOID':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[6,6,-61,-72,-71,-58,-54,-55,-33,-29,-59,6,-34,-53,-68,-63,-52,6,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,6,-67,6,-70,-74,6,-57,-82,-249,-81,6,-107,-30,6,-97,-96,6,-45,-46,6,-109,6,6,6,6,-88,6,6,-36,6,-47,6,6,-83,-89,-250,6,-110,6,6,-111,-113,-112,6,6,-98,-37,-39,-42,-38,-40,6,-148,-147,-43,-149,-41,-85,-84,-90,6,6,-100,-99,-167,-166,6,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'LBRACKET':([1,2,3,5,6,9,10,13,14,17,18,19,21,23,24,25,27,28,29,32,33,35,37,39,40,42,43,44,45,46,49,50,51,52,54,55,56,58,59,63,64,66,67,68,69,76,77,83,87,89,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,129,138,139,149,151,152,153,154,155,174,178,180,184,185,191,195,216,217,218,223,224,231,235,262,264,265,273,274,277,281,285,286,314,318,319,323,329,350,351,357,359,360,361,362,366,369,371,387,388,389,390,400,401,409,],[-251,-61,-72,-71,-58,-54,-55,-59,-251,-53,-68,-63,-52,-56,-170,61,-66,-251,-69,-73,-108,-64,-60,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-249,-81,-49,61,-97,-96,-116,-114,-26,-25,-48,-51,-109,-251,-251,-233,-243,-247,-244,-241,-231,-232,182,-240,-220,-237,-245,-238,-242,-239,-230,221,-115,-117,-83,-250,-21,-80,-22,-79,-248,-246,-226,-227,-110,-111,221,-113,-112,221,312,221,-98,325,-237,-85,-84,-225,-224,-223,-234,221,221,312,-100,-99,-132,325,-221,-222,325,-146,-140,-142,-144,-135,325,-133,-141,-143,-145,-134,325,-228,-229,]),'WCHAR_CONST':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,96,-45,-219,96,-217,96,-216,96,-215,96,96,-214,-218,96,96,-250,96,-176,-179,-177,-173,-174,-178,-180,96,-182,-183,-175,-181,96,-215,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,-251,-39,-42,-38,96,-40,96,96,-148,-147,-43,-149,96,-41,96,96,96,-215,96,-12,96,96,-11,-167,-166,96,-164,96,96,-150,96,-163,-151,96,96,96,96,-251,96,-215,-251,-131,-162,-165,96,-154,96,-152,96,96,96,-153,96,96,96,-251,96,-158,-157,-155,96,96,96,-159,-156,96,-161,-160,]),'FLOAT_CONST':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,97,-45,-219,97,-217,97,-216,97,-215,97,97,-214,-218,97,97,-250,97,-176,-179,-177,-173,-174,-178,-180,97,-182,-183,-175,-181,97,-215,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,-251,-39,-42,-38,97,-40,97,97,-148,-147,-43,-149,97,-41,97,97,97,-215,97,-12,97,97,-11,-167,-166,97,-164,97,97,-150,97,-163,-151,97,97,97,97,-251,97,-215,-251,-131,-162,-165,97,-154,97,-152,97,97,97,-153,97,97,97,-251,97,-158,-157,-155,97,97,97,-159,-156,97,-161,-160,]),'MINUS':([55,61,75,91,92,93,94,95,96,97,98,99,100,101,102,104,105,106,108,109,110,111,112,113,114,115,116,117,118,119,120,123,124,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,180,182,183,184,186,187,188,189,190,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,262,270,273,274,277,281,282,283,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,349,350,351,352,353,356,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[-249,100,-45,-219,-206,-233,-243,-247,-244,-241,-231,100,-217,-232,-208,-187,100,-216,100,-240,-215,-220,100,100,-237,-245,-214,-238,200,-242,-239,-218,-230,100,100,-250,100,-176,-179,-177,-173,-174,-178,-180,100,-182,-183,-175,-181,-248,100,-212,-215,-246,-226,100,100,-227,100,-206,-211,100,-209,-210,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,-251,-39,-42,-38,100,-40,100,100,-148,-147,-43,-149,100,-41,-237,100,-225,-224,-223,-234,100,100,200,200,200,-192,200,200,200,-191,200,200,-189,-188,200,200,200,200,200,-190,-215,100,-12,100,100,-11,-167,-166,100,-164,100,100,-150,100,-163,-151,100,100,-213,-221,-222,100,100,-207,-251,100,-215,-251,-131,-162,-165,100,-154,100,-152,100,100,100,-153,100,100,100,-251,-228,100,-158,-157,-155,-229,100,100,100,-159,-156,100,-161,-160,]),'RPAREN':([1,2,3,5,6,9,10,13,14,17,18,19,21,23,24,25,27,28,29,32,33,35,37,39,40,42,43,44,45,46,49,50,51,52,53,54,56,58,59,62,63,64,66,67,68,69,76,77,83,87,89,92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,122,124,125,126,127,128,129,130,131,132,138,139,149,151,152,153,154,155,174,176,178,180,183,184,185,187,188,190,191,192,193,194,195,196,216,217,218,219,220,222,223,224,225,231,247,264,265,271,272,273,274,276,277,278,279,280,281,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,306,307,308,309,313,314,315,316,317,318,319,339,349,350,351,355,356,359,360,361,362,365,378,380,383,384,386,387,388,389,401,404,407,409,410,411,414,],[-251,-61,-72,-71,-58,-54,-55,-59,-251,-53,-68,-63,-52,-56,-170,-106,-66,-251,-69,-73,-108,-64,-60,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,83,-82,-81,-49,-107,-251,-97,-96,-116,-114,-26,-25,-48,-51,-109,-251,-251,-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,-185,-242,-239,-171,-230,216,-15,217,-120,-251,-16,-118,-124,-115,-117,-83,-250,-21,-80,-22,-79,-248,-212,-246,-226,277,-227,-110,-206,-211,-209,-111,281,283,-168,-251,-210,-113,-112,-251,-123,-2,-122,-139,-137,-1,-98,-14,-85,-84,-172,349,-225,-224,-235,-223,351,353,354,-234,-136,-251,-137,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-19,-20,359,360,-251,-138,-125,-119,-121,-100,-99,-13,-213,-221,-222,-169,-207,-146,-140,-142,-144,389,395,397,399,-236,-186,-141,-143,-145,-228,-251,412,-229,-251,415,418,]),'LONG':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[19,19,-61,-72,-71,-58,-54,-55,-33,-29,-59,19,-34,-53,-68,-63,-52,19,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,19,-67,19,-70,-74,19,-57,-82,-249,-81,19,-107,-30,19,-97,-96,19,-45,-46,19,-109,19,19,19,19,-88,19,19,-36,19,-47,19,19,-83,-89,-250,19,-110,19,19,-111,-113,-112,19,19,-98,-37,-39,-42,-38,-40,19,-148,-147,-43,-149,-41,-85,-84,-90,19,19,-100,-99,-167,-166,19,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'PLUS':([55,61,75,91,92,93,94,95,96,97,98,99,100,101,102,104,105,106,108,109,110,111,112,113,114,115,116,117,118,119,120,123,124,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,180,182,183,184,186,187,188,189,190,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,262,270,273,274,277,281,282,283,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,349,350,351,352,353,356,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[-249,106,-45,-219,-206,-233,-243,-247,-244,-241,-231,106,-217,-232,-208,-187,106,-216,106,-240,-215,-220,106,106,-237,-245,-214,-238,204,-242,-239,-218,-230,106,106,-250,106,-176,-179,-177,-173,-174,-178,-180,106,-182,-183,-175,-181,-248,106,-212,-215,-246,-226,106,106,-227,106,-206,-211,106,-209,-210,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,-251,-39,-42,-38,106,-40,106,106,-148,-147,-43,-149,106,-41,-237,106,-225,-224,-223,-234,106,106,204,204,204,-192,204,204,204,-191,204,204,-189,-188,204,204,204,204,204,-190,-215,106,-12,106,106,-11,-167,-166,106,-164,106,106,-150,106,-163,-151,106,106,-213,-221,-222,106,106,-207,-251,106,-215,-251,-131,-162,-165,106,-154,106,-152,106,106,106,-153,106,106,106,-251,-228,106,-158,-157,-155,-229,106,106,106,-159,-156,106,-161,-160,]),'ELLIPSIS':([227,],[316,]),'GT':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,205,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,205,-194,-192,-196,205,-195,-191,-198,205,-189,-188,-197,205,205,205,205,-190,-213,-221,-222,-207,-228,-229,]),'GOTO':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,240,-250,-39,-42,-38,-40,240,-148,-147,-43,-149,240,-41,-167,-166,-164,240,-150,-163,-151,240,-162,-165,-154,240,-152,240,-153,240,240,-158,-157,-155,240,240,-159,-156,240,-161,-160,]),'ENUM':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[26,26,-61,-72,-71,-58,-54,-55,-33,-29,-59,26,-34,-53,-68,-63,-52,26,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,26,-67,26,-70,-74,26,-57,-82,-249,-81,26,-107,-30,26,-97,-96,26,-45,-46,26,-109,26,26,26,26,-88,26,26,-36,26,-47,26,26,-83,-89,-250,26,-110,26,26,-111,-113,-112,26,26,-98,-37,-39,-42,-38,-40,26,-148,-147,-43,-149,-41,-85,-84,-90,26,26,-100,-99,-167,-166,26,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'PERIOD':([55,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,178,180,184,235,262,273,274,277,281,323,329,350,351,357,366,369,371,390,400,401,409,],[-249,-233,-243,-247,-244,-241,-231,-232,181,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-246,-226,-227,324,-237,-225,-224,-223,-234,-132,324,-221,-222,324,-135,324,-133,-134,324,-228,-229,]),'GE':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,209,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,209,-194,-192,-196,209,-195,-191,-198,209,-189,-188,-197,209,209,209,209,-190,-213,-221,-222,-207,-228,-229,]),'INT_CONST_DEC':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,117,-45,-219,117,-217,117,-216,117,-215,117,117,-214,-218,117,117,-250,117,-176,-179,-177,-173,-174,-178,-180,117,-182,-183,-175,-181,117,-215,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,-251,-39,-42,-38,117,-40,117,117,-148,-147,-43,-149,117,-41,117,117,117,-215,117,-12,117,117,-11,-167,-166,117,-164,117,117,-150,117,-163,-151,117,117,117,117,-251,117,-215,-251,-131,-162,-165,117,-154,117,-152,117,117,117,-153,117,117,117,-251,117,-158,-157,-155,117,117,117,-159,-156,117,-161,-160,]),'ARROW':([93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,178,180,184,262,273,274,277,281,350,351,401,409,],[-233,-243,-247,-244,-241,-231,-232,179,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-246,-226,-227,-237,-225,-224,-223,-234,-221,-222,-228,-229,]),'HEX_FLOAT_CONST':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,119,-45,-219,119,-217,119,-216,119,-215,119,119,-214,-218,119,119,-250,119,-176,-179,-177,-173,-174,-178,-180,119,-182,-183,-175,-181,119,-215,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,-251,-39,-42,-38,119,-40,119,119,-148,-147,-43,-149,119,-41,119,119,119,-215,119,-12,119,119,-11,-167,-166,119,-164,119,119,-150,119,-163,-151,119,119,119,119,-251,119,-215,-251,-131,-162,-165,119,-154,119,-152,119,119,119,-153,119,119,119,-251,119,-158,-157,-155,119,119,119,-159,-156,119,-161,-160,]),'DOUBLE':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[40,40,-61,-72,-71,-58,-54,-55,-33,-29,-59,40,-34,-53,-68,-63,-52,40,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,40,-67,40,-70,-74,40,-57,-82,-249,-81,40,-107,-30,40,-97,-96,40,-45,-46,40,-109,40,40,40,40,-88,40,40,-36,40,-47,40,40,-83,-89,-250,40,-110,40,40,-111,-113,-112,40,40,-98,-37,-39,-42,-38,-40,40,-148,-147,-43,-149,-41,-85,-84,-90,40,40,-100,-99,-167,-166,40,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'MINUSEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[163,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'INT_CONST_OCT':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,120,-45,-219,120,-217,120,-216,120,-215,120,120,-214,-218,120,120,-250,120,-176,-179,-177,-173,-174,-178,-180,120,-182,-183,-175,-181,120,-215,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,-251,-39,-42,-38,120,-40,120,120,-148,-147,-43,-149,120,-41,120,120,120,-215,120,-12,120,120,-11,-167,-166,120,-164,120,120,-150,120,-163,-151,120,120,120,120,-251,120,-215,-251,-131,-162,-165,120,-154,120,-152,120,120,120,-153,120,120,120,-251,120,-158,-157,-155,120,120,120,-159,-156,120,-161,-160,]),'TIMESEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[172,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'OR':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,214,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,214,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,214,-199,-201,-202,-190,-213,-221,-222,-207,-228,-229,]),'SHORT':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[2,2,-61,-72,-71,-58,-54,-55,-33,-29,-59,2,-34,-53,-68,-63,-52,2,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,2,-67,2,-70,-74,2,-57,-82,-249,-81,2,-107,-30,2,-97,-96,2,-45,-46,2,-109,2,2,2,2,-88,2,2,-36,2,-47,2,2,-83,-89,-250,2,-110,2,2,-111,-113,-112,2,2,-98,-37,-39,-42,-38,-40,2,-148,-147,-43,-149,-41,-85,-84,-90,2,2,-100,-99,-167,-166,2,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'RETURN':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,243,-250,-39,-42,-38,-40,243,-148,-147,-43,-149,243,-41,-167,-166,-164,243,-150,-163,-151,243,-162,-165,-154,243,-152,243,-153,243,243,-158,-157,-155,243,243,-159,-156,243,-161,-160,]),'RSHIFTEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[173,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'RESTRICT':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,28,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,66,68,73,75,80,82,83,84,85,86,87,88,89,112,139,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[32,32,-61,-72,-71,-58,-54,-55,-33,-29,-59,32,-34,-53,-68,-63,-52,32,-56,-170,-106,-66,32,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,32,-67,32,-70,-74,32,-57,-82,-249,-81,32,-107,-30,32,-97,-96,-116,32,32,-45,-46,32,-109,32,32,32,32,-88,32,32,-117,-36,32,-47,32,32,-83,-89,-250,32,-110,32,32,-111,-113,-112,32,32,-98,-37,-39,-42,-38,-40,32,-148,-147,-43,-149,-41,-85,-84,-90,32,32,-100,-99,-167,-166,32,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'STATIC':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[9,9,-61,-72,-71,-58,-54,-55,-33,-29,-59,9,-34,-53,-68,-63,-52,9,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,9,-67,9,-70,-74,9,-57,-82,-249,-81,-107,-30,9,-97,-96,9,-45,-46,9,-109,-36,9,-47,-83,-250,-110,-111,-113,-112,9,9,-98,-37,-39,-42,-38,-40,9,-148,-147,-43,-149,-41,-85,-84,9,9,-100,-99,-167,-166,9,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'SIZEOF':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,99,-45,-219,99,-217,99,-216,99,-215,99,99,-214,-218,99,99,-250,99,-176,-179,-177,-173,-174,-178,-180,99,-182,-183,-175,-181,99,-215,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,-251,-39,-42,-38,99,-40,99,99,-148,-147,-43,-149,99,-41,99,99,99,-215,99,-12,99,99,-11,-167,-166,99,-164,99,99,-150,99,-163,-151,99,99,99,99,-251,99,-215,-251,-131,-162,-165,99,-154,99,-152,99,99,99,-153,99,99,99,-251,99,-158,-157,-155,99,99,99,-159,-156,99,-161,-160,]),'UNSIGNED':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[18,18,-61,-72,-71,-58,-54,-55,-33,-29,-59,18,-34,-53,-68,-63,-52,18,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,18,-67,18,-70,-74,18,-57,-82,-249,-81,18,-107,-30,18,-97,-96,18,-45,-46,18,-109,18,18,18,18,-88,18,18,-36,18,-47,18,18,-83,-89,-250,18,-110,18,18,-111,-113,-112,18,18,-98,-37,-39,-42,-38,-40,18,-148,-147,-43,-149,-41,-85,-84,-90,18,18,-100,-99,-167,-166,18,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'UNION':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[20,20,-61,-72,-71,-58,-54,-55,-33,-29,-59,20,-34,-53,-68,-63,-52,20,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,20,-67,20,-70,-74,20,-57,-82,-249,-81,20,-107,-30,20,-97,-96,20,-45,-46,20,-109,20,20,20,20,-88,20,20,-36,20,-47,20,20,-83,-89,-250,20,-110,20,20,-111,-113,-112,20,20,-98,-37,-39,-42,-38,-40,20,-148,-147,-43,-149,-41,-85,-84,-90,20,20,-100,-99,-167,-166,20,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'COLON':([2,3,5,6,13,18,19,24,25,27,29,32,33,35,37,39,40,43,45,46,54,56,59,63,64,83,87,89,90,92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,122,124,149,151,152,153,154,155,161,174,176,178,180,184,185,187,188,190,191,194,196,216,217,231,248,262,264,265,267,268,271,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,318,319,338,349,350,351,355,356,386,401,409,],[-61,-72,-71,-58,-59,-68,-63,-170,-106,-66,-69,-73,-108,-64,-60,-62,-65,-67,-70,-74,-82,-81,-107,-97,-96,-109,-251,-251,156,-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,-185,-242,-239,-171,-230,-83,-250,-21,-80,-22,-79,270,-248,-212,-246,-226,-227,-110,-206,-211,-209,-111,-168,-210,-113,-112,-98,336,345,-85,-84,-184,156,-172,-225,-224,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,358,-202,-190,-100,-99,379,-213,-221,-222,-169,-207,-186,-228,-229,]),'$end':([0,8,11,12,15,22,31,36,38,47,60,75,144,151,237,344,],[-251,0,-33,-29,-34,-27,-32,-31,-35,-28,-30,-45,-36,-250,-37,-151,]),'WSTRING_LITERAL':([55,61,75,91,93,95,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,95,-45,-219,174,-247,95,-217,95,-216,95,-215,95,95,-214,-218,95,95,-250,95,-176,-179,-177,-173,-174,-178,-180,95,-182,-183,-175,-181,-248,95,-215,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,-251,-39,-42,-38,95,-40,95,95,-148,-147,-43,-149,95,-41,95,95,95,-215,95,-12,95,95,-11,-167,-166,95,-164,95,95,-150,95,-163,-151,95,95,95,95,-251,95,-215,-251,-131,-162,-165,95,-154,95,-152,95,95,95,-153,95,95,95,-251,95,-158,-157,-155,95,95,95,-159,-156,95,-161,-160,]),'DIVIDE':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,207,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,207,207,207,207,207,207,207,207,207,207,-189,-188,207,207,207,207,207,-190,-213,-221,-222,-207,-228,-229,]),'FOR':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,245,-250,-39,-42,-38,-40,245,-148,-147,-43,-149,245,-41,-167,-166,-164,245,-150,-163,-151,245,-162,-165,-154,245,-152,245,-153,245,245,-158,-157,-155,245,245,-159,-156,245,-161,-160,]),'PLUSPLUS':([55,61,75,91,93,94,95,96,97,98,99,100,101,102,105,106,108,109,110,111,112,113,114,115,116,117,119,120,123,124,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,177,178,180,182,183,184,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,262,270,273,274,277,281,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,350,351,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[-249,108,-45,-219,-233,-243,-247,-244,-241,-231,108,-217,-232,180,108,-216,108,-240,-215,-220,108,108,-237,-245,-214,-238,-242,-239,-218,-230,108,108,-250,108,-176,-179,-177,-173,-174,-178,-180,108,-182,-183,-175,-181,-248,108,-215,-246,-226,108,108,-227,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,-251,-39,-42,-38,108,-40,108,108,-148,-147,-43,-149,108,-41,-237,108,-225,-224,-223,-234,108,108,-215,108,-12,108,108,-11,-167,-166,108,-164,108,108,-150,108,-163,-151,108,108,-221,-222,108,108,-251,108,-215,-251,-131,-162,-165,108,-154,108,-152,108,108,108,-153,108,108,108,-251,-228,108,-158,-157,-155,-229,108,108,108,-159,-156,108,-161,-160,]),'EQUALS':([25,33,59,73,83,92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,137,143,151,174,176,178,180,184,185,187,188,190,191,196,216,217,262,273,274,277,281,323,329,349,350,351,356,366,371,390,401,409,],[-106,-108,-107,141,-109,165,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,232,141,-250,-248,-212,-246,-226,-227,-110,-206,-211,-209,-111,-210,-113,-112,-237,-225,-224,-223,-234,-132,372,-213,-221,-222,-207,-135,-133,-134,-228,-229,]),'ELSE':([151,238,239,242,244,255,260,331,332,335,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[-250,-39,-42,-38,-40,-43,-41,-167,-166,-164,-163,-151,-162,-165,-154,-152,-153,-158,-157,413,-159,-156,-161,-160,]),'ANDEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[170,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'EQ':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,211,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,211,-194,-192,-196,-200,-195,-191,-198,211,-189,-188,-197,211,-199,211,211,-190,-213,-221,-222,-207,-228,-229,]),'AND':([55,61,75,91,92,93,94,95,96,97,98,99,100,101,102,104,105,106,108,109,110,111,112,113,114,115,116,117,118,119,120,123,124,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,180,182,183,184,186,187,188,189,190,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,262,270,273,274,277,281,282,283,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,349,350,351,352,353,356,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[-249,116,-45,-219,-206,-233,-243,-247,-244,-241,-231,116,-217,-232,-208,-187,116,-216,116,-240,-215,-220,116,116,-237,-245,-214,-238,212,-242,-239,-218,-230,116,116,-250,116,-176,-179,-177,-173,-174,-178,-180,116,-182,-183,-175,-181,-248,116,-212,-215,-246,-226,116,116,-227,116,-206,-211,116,-209,-210,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,-251,-39,-42,-38,116,-40,116,116,-148,-147,-43,-149,116,-41,-237,116,-225,-224,-223,-234,116,116,-193,212,-194,-192,-196,-200,-195,-191,-198,212,-189,-188,-197,212,-199,-201,212,-190,-215,116,-12,116,116,-11,-167,-166,116,-164,116,116,-150,116,-163,-151,116,116,-213,-221,-222,116,116,-207,-251,116,-215,-251,-131,-162,-165,116,-154,116,-152,116,116,116,-153,116,116,116,-251,-228,116,-158,-157,-155,-229,116,116,116,-159,-156,116,-161,-160,]),'TYPEID':([0,1,2,3,5,6,7,9,10,11,12,13,14,15,17,18,19,20,21,22,23,24,25,26,27,29,31,32,33,34,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[24,24,-61,-72,-71,-58,54,-54,-55,-33,-29,-59,24,-34,-53,-68,-63,-87,-52,24,-56,-170,-106,63,-66,-69,-32,-73,-108,-86,-64,-31,-60,-35,-62,-65,24,-67,24,-70,-74,24,-57,-82,-249,-81,24,-107,-30,24,-97,-96,24,-45,-46,24,-109,24,24,24,24,-88,24,24,-36,24,-47,24,24,-83,-89,-250,24,-110,24,24,-111,-113,-112,24,24,-98,-37,-39,-42,-38,-40,24,-148,-147,-43,-149,-41,-85,-84,-90,24,24,-100,-99,-167,-166,24,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'LBRACE':([7,20,25,26,33,34,48,54,55,56,59,63,64,73,75,78,80,81,82,83,141,142,145,146,151,185,191,216,217,235,238,239,242,244,251,253,254,255,257,259,260,283,322,326,327,331,332,335,336,340,342,344,345,349,353,354,357,369,372,373,374,377,379,382,391,395,396,397,399,400,405,406,408,413,415,416,417,418,419,420,],[55,-87,-106,55,-108,-86,-251,55,-249,55,-107,55,55,-251,-45,-7,-46,55,-8,-109,55,55,55,-47,-250,-110,-111,-113,-112,-251,-39,-42,-38,-40,55,-148,-147,-43,-149,55,-41,55,-12,55,-11,-167,-166,-164,55,-150,-163,-151,55,55,55,55,-251,-251,-131,-162,-165,-154,55,-152,55,55,-153,55,55,-251,-158,-157,-155,55,55,-159,-156,55,-161,-160,]),'PPHASH':([0,11,12,15,22,31,36,38,60,75,144,151,237,344,],[38,-33,-29,-34,38,-32,-31,-35,-30,-45,-36,-250,-37,-151,]),'INT':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[39,39,-61,-72,-71,-58,-54,-55,-33,-29,-59,39,-34,-53,-68,-63,-52,39,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,39,-67,39,-70,-74,39,-57,-82,-249,-81,39,-107,-30,39,-97,-96,39,-45,-46,39,-109,39,39,39,39,-88,39,39,-36,39,-47,39,39,-83,-89,-250,39,-110,39,39,-111,-113,-112,39,39,-98,-37,-39,-42,-38,-40,39,-148,-147,-43,-149,-41,-85,-84,-90,39,39,-100,-99,-167,-166,39,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'SIGNED':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[43,43,-61,-72,-71,-58,-54,-55,-33,-29,-59,43,-34,-53,-68,-63,-52,43,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,43,-67,43,-70,-74,43,-57,-82,-249,-81,43,-107,-30,43,-97,-96,43,-45,-46,43,-109,43,43,43,43,-88,43,43,-36,43,-47,43,43,-83,-89,-250,43,-110,43,43,-111,-113,-112,43,43,-98,-37,-39,-42,-38,-40,43,-148,-147,-43,-149,-41,-85,-84,-90,43,43,-100,-99,-167,-166,43,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'CONTINUE':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,246,-250,-39,-42,-38,-40,246,-148,-147,-43,-149,246,-41,-167,-166,-164,246,-150,-163,-151,246,-162,-165,-154,246,-152,246,-153,246,246,-158,-157,-155,246,246,-159,-156,246,-161,-160,]),'NOT':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,123,-45,-219,123,-217,123,-216,123,-215,123,123,-214,-218,123,123,-250,123,-176,-179,-177,-173,-174,-178,-180,123,-182,-183,-175,-181,123,-215,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,-251,-39,-42,-38,123,-40,123,123,-148,-147,-43,-149,123,-41,123,123,123,-215,123,-12,123,123,-11,-167,-166,123,-164,123,123,-150,123,-163,-151,123,123,123,123,-251,123,-215,-251,-131,-162,-165,123,-154,123,-152,123,123,123,-153,123,123,123,-251,123,-158,-157,-155,123,123,123,-159,-156,123,-161,-160,]),'OREQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[171,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'MOD':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,215,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,215,215,215,215,215,215,215,215,215,215,-189,-188,215,215,215,215,215,-190,-213,-221,-222,-207,-228,-229,]),'RSHIFT':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,197,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,197,-194,-192,197,197,197,-191,197,197,-189,-188,197,197,197,197,197,-190,-213,-221,-222,-207,-228,-229,]),'DEFAULT':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,248,-250,-39,-42,-38,-40,248,-148,-147,-43,-149,248,-41,-167,-166,-164,248,-150,-163,-151,248,-162,-165,-154,248,-152,248,-153,248,248,-158,-157,-155,248,248,-159,-156,248,-161,-160,]),'CHAR':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[37,37,-61,-72,-71,-58,-54,-55,-33,-29,-59,37,-34,-53,-68,-63,-52,37,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,37,-67,37,-70,-74,37,-57,-82,-249,-81,37,-107,-30,37,-97,-96,37,-45,-46,37,-109,37,37,37,37,-88,37,37,-36,37,-47,37,37,-83,-89,-250,37,-110,37,37,-111,-113,-112,37,37,-98,-37,-39,-42,-38,-40,37,-148,-147,-43,-149,-41,-85,-84,-90,37,37,-100,-99,-167,-166,37,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'WHILE':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,343,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,249,-250,-39,-42,-38,-40,249,-148,-147,-43,-149,249,-41,-167,-166,-164,249,-150,-163,381,-151,249,-162,-165,-154,249,-152,249,-153,249,249,-158,-157,-155,249,249,-159,-156,249,-161,-160,]),'DIVEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[162,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'EXTERN':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[10,10,-61,-72,-71,-58,-54,-55,-33,-29,-59,10,-34,-53,-68,-63,-52,10,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,10,-67,10,-70,-74,10,-57,-82,-249,-81,-107,-30,10,-97,-96,10,-45,-46,10,-109,-36,10,-47,-83,-250,-110,-111,-113,-112,10,10,-98,-37,-39,-42,-38,-40,10,-148,-147,-43,-149,-41,-85,-84,10,10,-100,-99,-167,-166,10,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'CASE':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,250,-250,-39,-42,-38,-40,250,-148,-147,-43,-149,250,-41,-167,-166,-164,250,-150,-163,-151,250,-162,-165,-154,250,-152,250,-153,250,250,-158,-157,-155,250,250,-159,-156,250,-161,-160,]),'LAND':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,210,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,210,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-213,-221,-222,-207,-228,-229,]),'REGISTER':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[17,17,-61,-72,-71,-58,-54,-55,-33,-29,-59,17,-34,-53,-68,-63,-52,17,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,17,-67,17,-70,-74,17,-57,-82,-249,-81,-107,-30,17,-97,-96,17,-45,-46,17,-109,-36,17,-47,-83,-250,-110,-111,-113,-112,17,17,-98,-37,-39,-42,-38,-40,17,-148,-147,-43,-149,-41,-85,-84,17,17,-100,-99,-167,-166,17,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'MODEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[164,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'NE':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,202,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,202,-194,-192,-196,-200,-195,-191,-198,202,-189,-188,-197,202,-199,202,202,-190,-213,-221,-222,-207,-228,-229,]),'SWITCH':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,252,-250,-39,-42,-38,-40,252,-148,-147,-43,-149,252,-41,-167,-166,-164,252,-150,-163,-151,252,-162,-165,-154,252,-152,252,-153,252,252,-158,-157,-155,252,252,-159,-156,252,-161,-160,]),'INT_CONST_HEX':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,109,-45,-219,109,-217,109,-216,109,-215,109,109,-214,-218,109,109,-250,109,-176,-179,-177,-173,-174,-178,-180,109,-182,-183,-175,-181,109,-215,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,-251,-39,-42,-38,109,-40,109,109,-148,-147,-43,-149,109,-41,109,109,109,-215,109,-12,109,109,-11,-167,-166,109,-164,109,109,-150,109,-163,-151,109,109,109,109,-251,109,-215,-251,-131,-162,-165,109,-154,109,-152,109,109,109,-153,109,109,109,-251,109,-158,-157,-155,109,109,109,-159,-156,109,-161,-160,]),'_COMPLEX':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[27,27,-61,-72,-71,-58,-54,-55,-33,-29,-59,27,-34,-53,-68,-63,-52,27,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,27,-67,27,-70,-74,27,-57,-82,-249,-81,27,-107,-30,27,-97,-96,27,-45,-46,27,-109,27,27,27,27,-88,27,27,-36,27,-47,27,27,-83,-89,-250,27,-110,27,27,-111,-113,-112,27,27,-98,-37,-39,-42,-38,-40,27,-148,-147,-43,-149,-41,-85,-84,-90,27,27,-100,-99,-167,-166,27,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'PLUSEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[167,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'STRUCT':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[34,34,-61,-72,-71,-58,-54,-55,-33,-29,-59,34,-34,-53,-68,-63,-52,34,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,34,-67,34,-70,-74,34,-57,-82,-249,-81,34,-107,-30,34,-97,-96,34,-45,-46,34,-109,34,34,34,34,-88,34,34,-36,34,-47,34,34,-83,-89,-250,34,-110,34,34,-111,-113,-112,34,34,-98,-37,-39,-42,-38,-40,34,-148,-147,-43,-149,-41,-85,-84,-90,34,34,-100,-99,-167,-166,34,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'CONDOP':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,213,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-213,-221,-222,-207,-228,-229,]),'BREAK':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,256,-250,-39,-42,-38,-40,256,-148,-147,-43,-149,256,-41,-167,-166,-164,256,-150,-163,-151,256,-162,-165,-154,256,-152,256,-153,256,256,-158,-157,-155,256,256,-159,-156,256,-161,-160,]),'VOLATILE':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,28,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,66,68,73,75,80,82,83,84,85,86,87,88,89,112,139,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[46,46,-61,-72,-71,-58,-54,-55,-33,-29,-59,46,-34,-53,-68,-63,-52,46,-56,-170,-106,-66,46,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,46,-67,46,-70,-74,46,-57,-82,-249,-81,46,-107,-30,46,-97,-96,-116,46,46,-45,-46,46,-109,46,46,46,46,-88,46,46,-117,-36,46,-47,46,46,-83,-89,-250,46,-110,46,46,-111,-113,-112,46,46,-98,-37,-39,-42,-38,-40,46,-148,-147,-43,-149,-41,-85,-84,-90,46,46,-100,-99,-167,-166,46,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'INLINE':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[49,49,-61,-72,-71,-58,-54,-55,-33,-29,-59,49,-34,-53,-68,-63,-52,49,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,49,-67,49,-70,-74,49,-57,-82,-249,-81,-107,-30,49,-97,-96,49,-45,-46,49,-109,-36,49,-47,-83,-250,-110,-111,-113,-112,49,49,-98,-37,-39,-42,-38,-40,49,-148,-147,-43,-149,-41,-85,-84,49,49,-100,-99,-167,-166,49,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'DO':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,259,-250,-39,-42,-38,-40,259,-148,-147,-43,-149,259,-41,-167,-166,-164,259,-150,-163,-151,259,-162,-165,-154,259,-152,259,-153,259,259,-158,-157,-155,259,259,-159,-156,259,-161,-160,]),'LNOT':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,91,-45,-219,91,-217,91,-216,91,-215,91,91,-214,-218,91,91,-250,91,-176,-179,-177,-173,-174,-178,-180,91,-182,-183,-175,-181,91,-215,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,-251,-39,-42,-38,91,-40,91,91,-148,-147,-43,-149,91,-41,91,91,91,-215,91,-12,91,91,-11,-167,-166,91,-164,91,91,-150,91,-163,-151,91,91,91,91,-251,91,-215,-251,-131,-162,-165,91,-154,91,-152,91,91,91,-153,91,91,91,-251,91,-158,-157,-155,91,91,91,-159,-156,91,-161,-160,]),'CONST':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,28,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,66,68,73,75,80,82,83,84,85,86,87,88,89,112,139,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[3,3,-61,-72,-71,-58,-54,-55,-33,-29,-59,3,-34,-53,-68,-63,-52,3,-56,-170,-106,-66,3,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,3,-67,3,-70,-74,3,-57,-82,-249,-81,3,-107,-30,3,-97,-96,-116,3,3,-45,-46,3,-109,3,3,3,3,-88,3,3,-117,-36,3,-47,3,3,-83,-89,-250,3,-110,3,3,-111,-113,-112,3,3,-98,-37,-39,-42,-38,-40,3,-148,-147,-43,-149,-41,-85,-84,-90,3,3,-100,-99,-167,-166,3,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'LOR':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,198,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-213,-221,-222,-207,-228,-229,]),'CHAR_CONST':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,94,-45,-219,94,-217,94,-216,94,-215,94,94,-214,-218,94,94,-250,94,-176,-179,-177,-173,-174,-178,-180,94,-182,-183,-175,-181,94,-215,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,-251,-39,-42,-38,94,-40,94,94,-148,-147,-43,-149,94,-41,94,94,94,-215,94,-12,94,94,-11,-167,-166,94,-164,94,94,-150,94,-163,-151,94,94,94,94,-251,94,-215,-251,-131,-162,-165,94,-154,94,-152,94,94,94,-153,94,94,94,-251,94,-158,-157,-155,94,94,94,-159,-156,94,-161,-160,]),'LSHIFT':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,199,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,199,-194,-192,199,199,199,-191,199,199,-189,-188,199,199,199,199,199,-190,-213,-221,-222,-207,-228,-229,]),'RBRACE':([55,75,86,88,92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,122,124,135,136,137,145,147,148,150,151,174,176,178,180,184,187,188,190,196,228,229,230,236,238,239,242,244,251,253,254,255,257,258,260,261,267,269,271,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,320,321,328,331,332,335,340,342,344,349,350,351,356,368,369,370,373,374,377,382,385,386,392,396,400,401,402,405,406,408,409,416,417,419,420,],[-249,-45,151,-88,-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,-185,-242,-239,-171,-230,-101,151,-104,-251,151,151,-89,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,151,151,-102,-126,-39,-42,-38,-40,-6,-148,-147,-43,-149,-5,-41,151,-184,-90,-172,-225,-224,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-103,-105,151,-167,-166,-164,-150,-163,-151,-213,-221,-222,-207,-129,151,-127,-162,-165,-154,-152,151,-186,-128,-153,151,-228,-130,-158,-157,-155,-229,-159,-156,-161,-160,]),'_BOOL':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[13,13,-61,-72,-71,-58,-54,-55,-33,-29,-59,13,-34,-53,-68,-63,-52,13,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,13,-67,13,-70,-74,13,-57,-82,-249,-81,13,-107,-30,13,-97,-96,13,-45,-46,13,-109,13,13,13,13,-88,13,13,-36,13,-47,13,13,-83,-89,-250,13,-110,13,13,-111,-113,-112,13,13,-98,-37,-39,-42,-38,-40,13,-148,-147,-43,-149,-41,-85,-84,-90,13,13,-100,-99,-167,-166,13,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'LE':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,201,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,201,-194,-192,-196,201,-195,-191,-198,201,-189,-188,-197,201,201,201,201,-190,-213,-221,-222,-207,-228,-229,]),'SEMI':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,30,31,32,33,35,36,37,38,39,40,41,42,43,44,45,46,49,50,51,52,54,55,56,58,59,60,63,64,70,71,72,73,74,75,76,77,79,83,87,89,90,92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,122,124,143,144,145,149,151,152,153,154,155,157,158,159,160,161,174,176,178,180,184,185,187,188,190,191,194,196,216,217,231,233,234,236,237,238,239,241,242,243,244,246,247,251,253,254,255,256,257,258,259,260,262,264,265,266,267,271,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,318,319,330,331,332,333,334,335,336,339,340,342,344,345,347,348,349,350,351,355,356,370,373,374,375,376,377,379,382,386,392,393,394,395,396,397,399,401,403,405,406,408,409,412,413,415,416,417,418,419,420,],[15,-251,-61,-72,-71,-58,-54,-55,-33,-29,-59,-251,-34,-53,-68,-63,-52,15,-56,-170,-106,-66,-69,-251,-32,-73,-108,-64,-31,-60,-35,-62,-65,75,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-249,-81,-49,-107,-30,-97,-96,-18,-44,-17,-77,-75,-45,-48,-51,-251,-109,-251,-251,-251,-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,-185,-242,-239,-171,-230,-77,-36,-251,-83,-250,-21,-80,-22,-79,-24,269,-91,-23,-93,-248,-212,-246,-226,-227,-110,-206,-211,-209,-111,-168,-210,-113,-112,-98,-76,-78,-126,-37,-39,-42,331,-38,332,-40,335,-14,-251,-148,-147,-43,342,-149,-13,-251,-41,-237,-85,-84,-95,-184,-172,-225,-224,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-100,-99,373,-167,-166,374,-251,-164,-251,-13,-150,-163,-151,-251,-92,-94,-213,-221,-222,-169,-207,-127,-162,-165,393,-251,-154,-251,-152,-186,-128,-251,404,-251,-153,-251,-251,-228,410,-158,-157,-155,-229,416,-251,-251,-159,-156,-251,-161,-160,]),'LT':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,203,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,203,-194,-192,-196,203,-195,-191,-198,203,-189,-188,-197,203,203,203,203,-190,-213,-221,-222,-207,-228,-229,]),'COMMA':([1,2,3,5,6,9,10,13,14,17,18,19,21,23,24,25,27,28,29,32,33,35,37,39,40,42,43,44,45,46,49,50,51,52,54,56,58,59,63,64,66,67,68,69,70,73,74,76,77,83,92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,122,124,128,129,130,131,132,135,136,137,138,139,143,149,151,157,159,161,174,176,178,180,184,185,187,188,190,191,192,194,196,216,217,219,220,222,223,224,225,228,229,230,231,233,234,236,247,262,264,265,266,267,271,273,274,275,276,277,278,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,314,315,317,318,319,320,321,328,333,347,348,349,350,351,355,356,359,360,361,362,368,370,378,380,383,384,385,386,387,388,389,392,401,402,407,409,],[-251,-61,-72,-71,-58,-54,-55,-59,-251,-53,-68,-63,-52,-56,-170,-106,-66,-251,-69,-73,-108,-64,-60,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-81,-49,-107,-97,-96,-116,-114,-26,-25,140,-77,-75,-48,-51,-109,-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,-185,-242,-239,-171,-230,-120,-251,226,227,-124,-101,230,-104,-115,-117,-77,-83,-250,268,-91,-93,-248,-212,-246,-226,-227,-110,-206,-211,-209,-111,282,-168,-210,-113,-112,-123,-2,-122,-139,-137,-1,230,230,-102,-98,-76,-78,-126,282,-237,-85,-84,-95,-184,-172,-225,-224,282,-235,-223,352,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,282,-202,-190,-138,-125,-121,-100,-99,-103,-105,369,282,-92,-94,-213,-221,-222,-169,-207,-146,-140,-142,-144,-129,-127,282,282,282,-236,400,-186,-141,-143,-145,-128,-228,-130,282,-229,]),'TYPEDEF':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[23,23,-61,-72,-71,-58,-54,-55,-33,-29,-59,23,-34,-53,-68,-63,-52,23,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,23,-67,23,-70,-74,23,-57,-82,-249,-81,-107,-30,23,-97,-96,23,-45,-46,23,-109,-36,23,-47,-83,-250,-110,-111,-113,-112,23,23,-98,-37,-39,-42,-38,-40,23,-148,-147,-43,-149,-41,-85,-84,23,23,-100,-99,-167,-166,23,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'XOR':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,206,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,206,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,206,-199,-201,206,-190,-213,-221,-222,-207,-228,-229,]),'AUTO':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[21,21,-61,-72,-71,-58,-54,-55,-33,-29,-59,21,-34,-53,-68,-63,-52,21,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,21,-67,21,-70,-74,21,-57,-82,-249,-81,-107,-30,21,-97,-96,21,-45,-46,21,-109,-36,21,-47,-83,-250,-110,-111,-113,-112,21,21,-98,-37,-39,-42,-38,-40,21,-148,-147,-43,-149,-41,-85,-84,21,21,-100,-99,-167,-166,21,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'TIMES':([0,1,2,3,4,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,27,28,29,30,31,32,35,36,37,38,39,40,42,43,44,45,46,49,50,51,52,54,55,56,58,60,61,63,64,66,67,68,69,75,76,77,79,87,89,90,91,92,93,94,95,96,97,98,99,100,101,102,104,105,106,108,109,110,111,112,113,114,115,116,117,118,119,120,123,124,129,139,140,141,144,145,149,151,152,153,154,155,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,180,182,183,184,186,187,188,189,190,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,218,221,231,232,235,237,238,239,242,243,244,250,251,253,254,255,257,259,260,262,264,265,268,270,273,274,277,281,282,283,285,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,311,312,318,319,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,349,350,351,352,353,356,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[28,-251,-61,-72,28,-71,-58,-54,-55,-33,-29,-59,-251,-34,-53,-68,-63,-52,28,-56,-170,-66,-251,-69,28,-32,-73,-64,-31,-60,-35,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-249,-81,-49,-30,110,-97,-96,-116,28,-26,-25,-45,-48,-51,28,-251,-251,28,-219,-206,-233,-243,-247,-244,-241,-231,177,-217,-232,-208,-187,177,-216,177,-240,-215,-220,177,177,-237,-245,-214,-238,208,-242,-239,-218,-230,28,-117,28,177,-36,177,-83,-250,-21,-80,-22,-79,177,-176,-179,-177,-173,-174,-178,-180,177,-182,-183,-175,-181,-248,177,-212,-215,-246,-226,177,177,-227,177,-206,-211,177,-209,28,-210,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,28,311,-98,177,-251,-37,-39,-42,-38,177,-40,177,177,-148,-147,-43,-149,177,-41,-237,-85,-84,28,177,-225,-224,-223,-234,177,177,28,208,208,208,208,208,208,208,208,208,208,-189,-188,208,208,208,208,208,-190,-215,364,-100,-99,-12,177,177,-11,-167,-166,177,-164,177,177,-150,177,-163,-151,177,177,-213,-221,-222,177,177,-207,-251,177,-215,-251,-131,-162,-165,177,-154,177,-152,177,177,177,-153,177,177,177,-251,-228,177,-158,-157,-155,-229,177,177,177,-159,-156,177,-161,-160,]),'LPAREN':([0,1,2,3,4,5,6,9,10,11,12,13,14,15,16,17,18,19,21,22,23,24,25,27,28,29,30,31,32,33,35,36,37,38,39,40,42,43,44,45,46,49,50,51,52,54,55,56,58,59,60,61,63,64,66,67,68,69,75,76,77,79,83,87,89,90,91,93,94,95,96,97,98,99,100,101,102,105,106,108,109,110,111,112,113,114,115,116,117,119,120,123,124,129,138,139,140,141,144,145,149,151,152,153,154,155,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,177,178,180,182,183,184,185,186,189,191,195,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,221,223,224,231,232,235,237,238,239,242,243,244,245,249,250,251,252,253,254,255,257,259,260,262,263,264,265,268,270,273,274,277,281,282,283,285,286,311,312,314,318,319,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,350,351,352,353,357,358,359,360,361,362,364,369,372,373,374,376,377,379,381,382,387,388,389,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[4,-251,-61,-72,4,-71,-58,-54,-55,-33,-29,-59,-251,-34,4,-53,-68,-63,-52,4,-56,-170,62,-66,-251,-69,4,-32,-73,-108,-64,-31,-60,-35,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-249,-81,-49,62,-30,112,-97,-96,-116,-114,-26,-25,-45,-48,-51,4,-109,-251,-251,4,-219,-233,-243,-247,-244,-241,-231,175,-217,-232,183,186,-216,189,-240,-215,-220,112,189,-237,-245,-214,-238,-242,-239,-218,-230,218,-115,-117,4,112,-36,112,-83,-250,-21,-80,-22,-79,186,-176,-179,-177,-173,-174,-178,-180,112,-182,-183,-175,-181,-248,112,-215,-246,-226,112,112,-227,-110,112,112,-111,285,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,112,186,186,-113,-112,218,112,313,218,-98,186,-251,-37,-39,-42,-38,112,-40,334,337,186,112,341,-148,-147,-43,-149,112,-41,-237,346,-85,-84,4,186,-225,-224,-223,-234,112,186,285,285,-215,112,313,-100,-99,-12,186,112,-11,-167,-166,112,-164,112,112,-150,112,-163,-151,112,112,-221,-222,112,186,-251,186,-146,-140,-142,-144,-215,-251,-131,-162,-165,112,-154,112,398,-152,-141,-143,-145,112,112,112,-153,112,112,112,-251,-228,112,-158,-157,-155,-229,112,112,112,-159,-156,112,-161,-160,]),'MINUSMINUS':([55,61,75,91,93,94,95,96,97,98,99,100,101,102,105,106,108,109,110,111,112,113,114,115,116,117,119,120,123,124,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,177,178,180,182,183,184,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,262,270,273,274,277,281,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,350,351,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[-249,113,-45,-219,-233,-243,-247,-244,-241,-231,113,-217,-232,184,113,-216,113,-240,-215,-220,113,113,-237,-245,-214,-238,-242,-239,-218,-230,113,113,-250,113,-176,-179,-177,-173,-174,-178,-180,113,-182,-183,-175,-181,-248,113,-215,-246,-226,113,113,-227,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,-251,-39,-42,-38,113,-40,113,113,-148,-147,-43,-149,113,-41,-237,113,-225,-224,-223,-234,113,113,-215,113,-12,113,113,-11,-167,-166,113,-164,113,113,-150,113,-163,-151,113,113,-221,-222,113,113,-251,113,-215,-251,-131,-162,-165,113,-154,113,-152,113,113,113,-153,113,113,113,-251,-228,113,-158,-157,-155,-229,113,113,113,-159,-156,113,-161,-160,]),'ID':([0,1,2,3,4,5,6,7,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,39,40,42,43,44,45,46,49,50,51,52,54,55,56,58,60,61,62,63,64,65,66,67,68,69,75,76,77,79,87,89,90,91,99,100,105,106,108,110,112,113,116,123,129,133,134,138,139,140,141,144,145,149,151,152,153,154,155,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,179,181,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,218,221,224,226,230,231,232,235,237,238,239,240,242,243,244,250,251,253,254,255,257,259,260,264,265,268,270,282,283,311,312,318,319,322,324,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[33,-251,-61,-72,33,-71,-58,56,-54,-55,-33,-29,-59,-251,-34,33,-53,-68,-63,-87,-52,33,-56,-170,64,-66,-251,-69,33,-32,-73,-86,-64,-31,-60,-35,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-249,-81,-49,-30,114,114,-97,-96,137,-116,-114,-26,-25,-45,-48,-51,33,-251,-251,33,-219,114,-217,114,-216,114,-215,114,114,-214,-218,33,137,137,-115,-117,33,114,-36,262,-83,-250,-21,-80,-22,-79,114,-176,-179,-177,-173,-174,-178,-180,114,-182,-183,-175,-181,114,-215,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,33,114,33,114,137,-98,114,-251,-37,-39,-42,330,-38,114,-40,114,262,-148,-147,-43,-149,262,-41,-85,-84,33,114,114,114,-215,114,-100,-99,-12,114,114,114,-11,-167,-166,114,-164,262,114,-150,114,-163,-151,262,114,114,114,-251,114,-215,-251,-131,-162,-165,114,-154,262,-152,114,114,262,-153,262,114,262,-251,114,-158,-157,-155,114,262,262,-159,-156,262,-161,-160,]),'IF':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,263,-250,-39,-42,-38,-40,263,-148,-147,-43,-149,263,-41,-167,-166,-164,263,-150,-163,-151,263,-162,-165,-154,263,-152,263,-153,263,263,-158,-157,-155,263,263,-159,-156,263,-161,-160,]),'STRING_LITERAL':([55,61,75,91,99,100,101,105,106,108,110,112,113,115,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,178,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,115,-45,-219,115,-217,178,115,-216,115,-215,115,115,-245,-214,-218,115,115,-250,115,-176,-179,-177,-173,-174,-178,-180,115,-182,-183,-175,-181,115,-215,-246,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,-251,-39,-42,-38,115,-40,115,115,-148,-147,-43,-149,115,-41,115,115,115,-215,115,-12,115,115,-11,-167,-166,115,-164,115,115,-150,115,-163,-151,115,115,115,115,-251,115,-215,-251,-131,-162,-165,115,-154,115,-152,115,115,115,-153,115,115,115,-251,115,-158,-157,-155,115,115,115,-159,-156,115,-161,-160,]),'FLOAT':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[35,35,-61,-72,-71,-58,-54,-55,-33,-29,-59,35,-34,-53,-68,-63,-52,35,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,35,-67,35,-70,-74,35,-57,-82,-249,-81,35,-107,-30,35,-97,-96,35,-45,-46,35,-109,35,35,35,35,-88,35,35,-36,35,-47,35,35,-83,-89,-250,35,-110,35,35,-111,-113,-112,35,35,-98,-37,-39,-42,-38,-40,35,-148,-147,-43,-149,-41,-85,-84,-90,35,35,-100,-99,-167,-166,35,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'XOREQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[166,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'LSHIFTEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[168,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'RBRACKET':([61,92,93,94,95,96,97,98,101,102,103,104,107,109,110,111,114,115,117,118,119,120,121,122,124,151,174,176,178,180,184,187,188,190,194,196,221,267,271,273,274,275,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,310,311,312,349,350,351,355,356,363,364,367,386,401,409,],[-251,-206,-233,-243,-247,-244,-241,-231,-232,-208,185,-187,-4,-240,191,-220,-237,-245,-238,-185,-242,-239,-3,-171,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-168,-210,-251,-184,-172,-225,-224,350,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,361,362,-251,-213,-221,-222,-169,-207,387,388,390,-186,-228,-229,]),} - -_lr_action = { } -for _k, _v in _lr_action_items.items(): - for _x,_y in zip(_v[0],_v[1]): - if not _x in _lr_action: _lr_action[_x] = { } - _lr_action[_x][_k] = _y -del _lr_action_items - -_lr_goto_items = {'storage_class_specifier':([0,1,14,22,42,44,48,62,73,82,145,218,227,251,285,313,334,],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,]),'identifier_list_opt':([62,],[125,]),'selection_statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[260,260,260,260,260,260,260,260,260,260,260,260,]),'constant':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,]),'unary_expression':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[92,176,187,190,92,196,92,92,187,92,92,92,92,92,92,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,92,187,187,92,187,92,187,92,92,187,92,187,92,187,92,92,92,92,92,92,92,92,187,187,92,92,92,92,92,92,92,92,92,92,92,92,92,]),'conditional_expression':([61,112,141,145,156,169,175,182,183,186,189,213,221,232,243,250,251,259,270,282,312,325,326,334,336,337,341,345,346,352,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[122,122,122,122,267,122,122,122,122,122,122,122,122,267,122,267,122,122,267,122,122,267,122,122,122,122,122,122,122,122,386,122,122,122,122,122,122,122,122,122,122,122,122,122,]),'brace_close':([86,136,147,148,228,229,261,328,369,385,400,],[149,231,264,265,318,319,344,370,392,401,409,]),'struct_or_union_specifier':([0,1,14,22,42,44,48,57,62,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,]),'unified_wstring_literal':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,]),'abstract_declarator_opt':([129,195,],[219,284,]),'iteration_statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[239,239,239,239,239,239,239,239,239,239,239,239,]),'init_declarator_list':([30,79,],[70,70,]),'translation_unit_or_empty':([0,],[8,]),'struct_declaration_list':([57,84,85,],[86,147,148,]),'enumerator':([65,133,134,230,],[135,135,135,320,]),'pp_directive':([0,22,],[11,11,]),'declaration_list':([48,73,],[82,82,]),'declaration_specifiers_opt':([1,14,42,44,],[50,58,76,77,]),'abstract_declarator':([129,195,218,285,],[220,220,309,309,]),'external_declaration':([0,22,],[12,60,]),'type_specifier':([0,1,14,22,42,44,48,57,62,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[14,14,14,14,14,14,14,87,14,14,14,87,87,87,87,87,87,14,87,87,87,87,87,14,14,14,14,14,14,]),'designation':([235,357,369,400,],[322,322,322,322,]),'compound_statement':([81,142,145,251,259,336,345,379,395,397,399,413,415,418,],[144,237,244,244,244,244,244,244,244,244,244,244,244,244,]),'pointer':([0,4,22,30,67,79,90,129,140,195,218,268,285,],[16,16,16,16,138,16,16,224,16,286,224,16,286,]),'type_name':([112,175,186,189,],[193,272,279,280,]),'unified_string_literal':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,]),'postfix_expression':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,]),'assignment_expression_opt':([61,221,312,],[103,310,363,]),'designation_opt':([235,357,369,400,],[326,326,391,391,]),'expression_statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[238,238,238,238,238,238,238,238,238,238,238,238,]),'unary_operator':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,]),'cast_expression':([61,105,112,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[104,188,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,356,104,104,104,104,104,104,104,104,104,104,356,104,104,104,104,104,104,104,104,104,104,104,104,104,104,]),'brace_open':([7,26,54,56,63,64,81,141,142,145,251,259,283,326,336,345,349,353,354,379,391,395,397,399,413,415,418,],[57,65,84,85,133,134,145,235,145,145,145,145,357,235,145,145,357,357,357,145,235,145,145,145,145,145,145,]),'init_declarator':([30,79,140,],[74,74,233,]),'translation_unit':([0,],[22,]),'assignment_operator':([92,],[169,]),'struct_or_union':([0,1,14,22,42,44,48,57,62,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,]),'block_item_list_opt':([145,],[261,]),'struct_declaration':([57,84,85,86,147,148,],[88,88,88,150,150,150,]),'assignment_expression':([61,112,141,145,169,175,182,183,186,189,213,221,243,251,259,282,312,326,334,336,337,341,345,346,352,376,379,391,393,395,397,398,399,404,410,413,415,418,],[107,194,236,194,271,194,194,276,194,194,194,107,194,194,194,355,107,236,194,194,194,194,194,194,384,194,194,236,194,194,194,194,194,194,194,194,194,194,]),'parameter_type_list':([62,218,285,313,],[127,307,307,307,]),'type_qualifier_list_opt':([28,],[67,]),'direct_declarator':([0,4,16,22,30,79,90,129,140,218,224,268,],[25,25,59,25,25,25,25,25,25,25,59,25,]),'type_qualifier_list':([28,],[68,]),'designator':([235,329,357,369,400,],[323,371,323,323,323,]),'argument_expression_list':([183,],[278,]),'initializer':([141,326,391,],[234,368,402,]),'direct_abstract_declarator':([129,195,218,224,285,286,],[223,223,223,314,223,314,]),'specifier_qualifier_list_opt':([87,89,],[153,155,]),'constant_expression':([156,232,250,270,325,],[266,321,338,348,367,]),'expression_opt':([145,251,259,334,336,345,376,379,393,395,397,399,404,410,413,415,418,],[241,241,241,375,241,241,394,241,403,241,241,241,411,414,241,241,241,]),'primary_expression':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,]),'declaration_specifiers':([0,1,14,22,42,44,48,62,73,82,145,218,227,251,285,313,334,],[30,52,52,30,52,52,79,129,79,79,79,129,129,79,129,129,79,]),'declaration':([0,22,48,73,82,145,251,334,],[31,31,80,80,146,254,254,376,]),'struct_declarator_list_opt':([90,],[158,]),'identifier_list':([62,],[130,]),'typedef_name':([0,1,14,22,42,44,48,57,62,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,]),'parameter_type_list_opt':([218,285,313,],[308,308,365,]),'jump_statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[255,255,255,255,255,255,255,255,255,255,255,255,]),'declaration_list_opt':([48,73,],[81,142,]),'struct_declarator':([90,268,],[159,347,]),'function_definition':([0,22,],[36,36,]),'binary_expression':([61,112,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,312,325,326,334,336,337,341,345,346,352,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[118,118,118,118,118,118,118,118,118,118,118,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,118,304,305,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,]),'parameter_list':([62,218,285,313,],[131,131,131,131,]),'init_declarator_list_opt':([30,79,],[71,71,]),'enum_specifier':([0,1,14,22,42,44,48,57,62,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,]),'struct_declarator_list':([90,],[157,]),'decl_body':([0,22,48,73,82,145,251,334,],[41,41,41,41,41,41,41,41,]),'type_qualifier':([0,1,14,22,28,42,44,48,57,62,68,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[42,42,42,42,66,42,42,42,89,42,139,42,42,89,89,89,89,89,89,42,89,89,89,89,89,42,42,42,42,42,42,]),'enumerator_list':([65,133,134,],[136,228,229,]),'labeled_statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[242,242,242,242,242,242,242,242,242,242,242,242,]),'function_specifier':([0,1,14,22,42,44,48,62,73,82,145,218,227,251,285,313,334,],[44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,]),'specifier_qualifier_list':([57,84,85,86,87,89,112,147,148,175,186,189,],[90,90,90,90,154,154,195,90,90,195,195,195,]),'block_item':([145,251,],[257,340,]),'block_item_list':([145,],[251,]),'statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[253,253,343,377,382,396,405,406,408,417,419,420,]),'empty':([0,1,14,28,30,42,44,48,61,62,73,79,87,89,90,129,145,195,218,221,235,251,259,285,312,313,334,336,345,357,369,376,379,393,395,397,399,400,404,410,413,415,418,],[47,51,51,69,72,51,51,78,121,126,78,72,152,152,160,225,258,225,306,121,327,339,339,306,121,306,339,339,339,327,327,339,339,339,339,339,339,327,339,339,339,339,339,]),'initializer_list':([235,357,],[328,385,]),'declarator':([0,4,22,30,79,90,129,140,218,268,],[48,53,48,73,143,161,222,143,53,161,]),'parameter_declaration':([62,218,227,285,313,],[128,128,317,128,128,]),'designator_list':([235,357,369,400,],[329,329,329,329,]),'identifier':([61,62,99,105,108,112,113,141,145,156,169,175,179,181,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,226,232,243,250,251,259,270,282,283,312,324,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[124,132,124,124,124,124,124,124,124,124,124,124,273,274,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,315,124,124,124,124,124,124,124,124,124,366,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,]),'expression':([112,145,175,182,186,189,213,243,251,259,334,336,337,341,345,346,376,379,393,395,397,398,399,404,410,413,415,418,],[192,247,192,275,192,192,303,333,247,247,247,247,378,380,247,383,247,247,247,247,247,407,247,247,247,247,247,247,]),} - -_lr_goto = { } -for _k, _v in _lr_goto_items.items(): - for _x,_y in zip(_v[0],_v[1]): - if not _x in _lr_goto: _lr_goto[_x] = { } - _lr_goto[_x][_k] = _y -del _lr_goto_items -_lr_productions = [ - ("S' -> translation_unit_or_empty","S'",1,None,None,None), - ('abstract_declarator_opt -> empty','abstract_declarator_opt',1,'p_abstract_declarator_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('abstract_declarator_opt -> abstract_declarator','abstract_declarator_opt',1,'p_abstract_declarator_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('assignment_expression_opt -> empty','assignment_expression_opt',1,'p_assignment_expression_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('assignment_expression_opt -> assignment_expression','assignment_expression_opt',1,'p_assignment_expression_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('block_item_list_opt -> empty','block_item_list_opt',1,'p_block_item_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('block_item_list_opt -> block_item_list','block_item_list_opt',1,'p_block_item_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('declaration_list_opt -> empty','declaration_list_opt',1,'p_declaration_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('declaration_list_opt -> declaration_list','declaration_list_opt',1,'p_declaration_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('declaration_specifiers_opt -> empty','declaration_specifiers_opt',1,'p_declaration_specifiers_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('declaration_specifiers_opt -> declaration_specifiers','declaration_specifiers_opt',1,'p_declaration_specifiers_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('designation_opt -> empty','designation_opt',1,'p_designation_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('designation_opt -> designation','designation_opt',1,'p_designation_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('expression_opt -> empty','expression_opt',1,'p_expression_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('expression_opt -> expression','expression_opt',1,'p_expression_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('identifier_list_opt -> empty','identifier_list_opt',1,'p_identifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('identifier_list_opt -> identifier_list','identifier_list_opt',1,'p_identifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('init_declarator_list_opt -> empty','init_declarator_list_opt',1,'p_init_declarator_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('init_declarator_list_opt -> init_declarator_list','init_declarator_list_opt',1,'p_init_declarator_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('parameter_type_list_opt -> empty','parameter_type_list_opt',1,'p_parameter_type_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('parameter_type_list_opt -> parameter_type_list','parameter_type_list_opt',1,'p_parameter_type_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('specifier_qualifier_list_opt -> empty','specifier_qualifier_list_opt',1,'p_specifier_qualifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('specifier_qualifier_list_opt -> specifier_qualifier_list','specifier_qualifier_list_opt',1,'p_specifier_qualifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('struct_declarator_list_opt -> empty','struct_declarator_list_opt',1,'p_struct_declarator_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('struct_declarator_list_opt -> struct_declarator_list','struct_declarator_list_opt',1,'p_struct_declarator_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('type_qualifier_list_opt -> empty','type_qualifier_list_opt',1,'p_type_qualifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('type_qualifier_list_opt -> type_qualifier_list','type_qualifier_list_opt',1,'p_type_qualifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('translation_unit_or_empty -> translation_unit','translation_unit_or_empty',1,'p_translation_unit_or_empty','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',355), - ('translation_unit_or_empty -> empty','translation_unit_or_empty',1,'p_translation_unit_or_empty','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',356), - ('translation_unit -> external_declaration','translation_unit',1,'p_translation_unit_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',364), - ('translation_unit -> translation_unit external_declaration','translation_unit',2,'p_translation_unit_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',371), - ('external_declaration -> function_definition','external_declaration',1,'p_external_declaration_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',383), - ('external_declaration -> declaration','external_declaration',1,'p_external_declaration_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',388), - ('external_declaration -> pp_directive','external_declaration',1,'p_external_declaration_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',393), - ('external_declaration -> SEMI','external_declaration',1,'p_external_declaration_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',398), - ('pp_directive -> PPHASH','pp_directive',1,'p_pp_directive','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',403), - ('function_definition -> declarator declaration_list_opt compound_statement','function_definition',3,'p_function_definition_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',412), - ('function_definition -> declaration_specifiers declarator declaration_list_opt compound_statement','function_definition',4,'p_function_definition_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',424), - ('statement -> labeled_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',435), - ('statement -> expression_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',436), - ('statement -> compound_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',437), - ('statement -> selection_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',438), - ('statement -> iteration_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',439), - ('statement -> jump_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',440), - ('decl_body -> declaration_specifiers init_declarator_list_opt','decl_body',2,'p_decl_body','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',454), - ('declaration -> decl_body SEMI','declaration',2,'p_declaration','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',537), - ('declaration_list -> declaration','declaration_list',1,'p_declaration_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',546), - ('declaration_list -> declaration_list declaration','declaration_list',2,'p_declaration_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',547), - ('declaration_specifiers -> type_qualifier declaration_specifiers_opt','declaration_specifiers',2,'p_declaration_specifiers_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',552), - ('declaration_specifiers -> type_specifier declaration_specifiers_opt','declaration_specifiers',2,'p_declaration_specifiers_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',557), - ('declaration_specifiers -> storage_class_specifier declaration_specifiers_opt','declaration_specifiers',2,'p_declaration_specifiers_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',562), - ('declaration_specifiers -> function_specifier declaration_specifiers_opt','declaration_specifiers',2,'p_declaration_specifiers_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',567), - ('storage_class_specifier -> AUTO','storage_class_specifier',1,'p_storage_class_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',572), - ('storage_class_specifier -> REGISTER','storage_class_specifier',1,'p_storage_class_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',573), - ('storage_class_specifier -> STATIC','storage_class_specifier',1,'p_storage_class_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',574), - ('storage_class_specifier -> EXTERN','storage_class_specifier',1,'p_storage_class_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',575), - ('storage_class_specifier -> TYPEDEF','storage_class_specifier',1,'p_storage_class_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',576), - ('function_specifier -> INLINE','function_specifier',1,'p_function_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',581), - ('type_specifier -> VOID','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',586), - ('type_specifier -> _BOOL','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',587), - ('type_specifier -> CHAR','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',588), - ('type_specifier -> SHORT','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',589), - ('type_specifier -> INT','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',590), - ('type_specifier -> LONG','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',591), - ('type_specifier -> FLOAT','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',592), - ('type_specifier -> DOUBLE','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',593), - ('type_specifier -> _COMPLEX','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',594), - ('type_specifier -> SIGNED','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',595), - ('type_specifier -> UNSIGNED','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',596), - ('type_specifier -> typedef_name','type_specifier',1,'p_type_specifier_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',601), - ('type_specifier -> enum_specifier','type_specifier',1,'p_type_specifier_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',602), - ('type_specifier -> struct_or_union_specifier','type_specifier',1,'p_type_specifier_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',603), - ('type_qualifier -> CONST','type_qualifier',1,'p_type_qualifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',608), - ('type_qualifier -> RESTRICT','type_qualifier',1,'p_type_qualifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',609), - ('type_qualifier -> VOLATILE','type_qualifier',1,'p_type_qualifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',610), - ('init_declarator_list -> init_declarator','init_declarator_list',1,'p_init_declarator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',615), - ('init_declarator_list -> init_declarator_list COMMA init_declarator','init_declarator_list',3,'p_init_declarator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',616), - ('init_declarator -> declarator','init_declarator',1,'p_init_declarator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',624), - ('init_declarator -> declarator EQUALS initializer','init_declarator',3,'p_init_declarator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',625), - ('specifier_qualifier_list -> type_qualifier specifier_qualifier_list_opt','specifier_qualifier_list',2,'p_specifier_qualifier_list_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',630), - ('specifier_qualifier_list -> type_specifier specifier_qualifier_list_opt','specifier_qualifier_list',2,'p_specifier_qualifier_list_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',635), - ('struct_or_union_specifier -> struct_or_union ID','struct_or_union_specifier',2,'p_struct_or_union_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',643), - ('struct_or_union_specifier -> struct_or_union TYPEID','struct_or_union_specifier',2,'p_struct_or_union_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',644), - ('struct_or_union_specifier -> struct_or_union brace_open struct_declaration_list brace_close','struct_or_union_specifier',4,'p_struct_or_union_specifier_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',653), - ('struct_or_union_specifier -> struct_or_union ID brace_open struct_declaration_list brace_close','struct_or_union_specifier',5,'p_struct_or_union_specifier_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',662), - ('struct_or_union_specifier -> struct_or_union TYPEID brace_open struct_declaration_list brace_close','struct_or_union_specifier',5,'p_struct_or_union_specifier_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',663), - ('struct_or_union -> STRUCT','struct_or_union',1,'p_struct_or_union','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',672), - ('struct_or_union -> UNION','struct_or_union',1,'p_struct_or_union','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',673), - ('struct_declaration_list -> struct_declaration','struct_declaration_list',1,'p_struct_declaration_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',680), - ('struct_declaration_list -> struct_declaration_list struct_declaration','struct_declaration_list',2,'p_struct_declaration_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',681), - ('struct_declaration -> specifier_qualifier_list struct_declarator_list_opt SEMI','struct_declaration',3,'p_struct_declaration_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',686), - ('struct_declarator_list -> struct_declarator','struct_declarator_list',1,'p_struct_declarator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',737), - ('struct_declarator_list -> struct_declarator_list COMMA struct_declarator','struct_declarator_list',3,'p_struct_declarator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',738), - ('struct_declarator -> declarator','struct_declarator',1,'p_struct_declarator_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',746), - ('struct_declarator -> declarator COLON constant_expression','struct_declarator',3,'p_struct_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',751), - ('struct_declarator -> COLON constant_expression','struct_declarator',2,'p_struct_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',752), - ('enum_specifier -> ENUM ID','enum_specifier',2,'p_enum_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',760), - ('enum_specifier -> ENUM TYPEID','enum_specifier',2,'p_enum_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',761), - ('enum_specifier -> ENUM brace_open enumerator_list brace_close','enum_specifier',4,'p_enum_specifier_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',766), - ('enum_specifier -> ENUM ID brace_open enumerator_list brace_close','enum_specifier',5,'p_enum_specifier_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',771), - ('enum_specifier -> ENUM TYPEID brace_open enumerator_list brace_close','enum_specifier',5,'p_enum_specifier_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',772), - ('enumerator_list -> enumerator','enumerator_list',1,'p_enumerator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',777), - ('enumerator_list -> enumerator_list COMMA','enumerator_list',2,'p_enumerator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',778), - ('enumerator_list -> enumerator_list COMMA enumerator','enumerator_list',3,'p_enumerator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',779), - ('enumerator -> ID','enumerator',1,'p_enumerator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',790), - ('enumerator -> ID EQUALS constant_expression','enumerator',3,'p_enumerator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',791), - ('declarator -> direct_declarator','declarator',1,'p_declarator_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',803), - ('declarator -> pointer direct_declarator','declarator',2,'p_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',808), - ('direct_declarator -> ID','direct_declarator',1,'p_direct_declarator_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',813), - ('direct_declarator -> LPAREN declarator RPAREN','direct_declarator',3,'p_direct_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',822), - ('direct_declarator -> direct_declarator LBRACKET assignment_expression_opt RBRACKET','direct_declarator',4,'p_direct_declarator_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',827), - ('direct_declarator -> direct_declarator LBRACKET TIMES RBRACKET','direct_declarator',4,'p_direct_declarator_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',839), - ('direct_declarator -> direct_declarator LPAREN parameter_type_list RPAREN','direct_declarator',4,'p_direct_declarator_5','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',849), - ('direct_declarator -> direct_declarator LPAREN identifier_list_opt RPAREN','direct_declarator',4,'p_direct_declarator_5','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',850), - ('pointer -> TIMES type_qualifier_list_opt','pointer',2,'p_pointer','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',860), - ('pointer -> TIMES type_qualifier_list_opt pointer','pointer',3,'p_pointer','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',861), - ('type_qualifier_list -> type_qualifier','type_qualifier_list',1,'p_type_qualifier_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',871), - ('type_qualifier_list -> type_qualifier_list type_qualifier','type_qualifier_list',2,'p_type_qualifier_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',872), - ('parameter_type_list -> parameter_list','parameter_type_list',1,'p_parameter_type_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',877), - ('parameter_type_list -> parameter_list COMMA ELLIPSIS','parameter_type_list',3,'p_parameter_type_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',878), - ('parameter_list -> parameter_declaration','parameter_list',1,'p_parameter_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',886), - ('parameter_list -> parameter_list COMMA parameter_declaration','parameter_list',3,'p_parameter_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',887), - ('parameter_declaration -> declaration_specifiers declarator','parameter_declaration',2,'p_parameter_declaration_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',896), - ('parameter_declaration -> declaration_specifiers abstract_declarator_opt','parameter_declaration',2,'p_parameter_declaration_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',915), - ('identifier_list -> identifier','identifier_list',1,'p_identifier_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',927), - ('identifier_list -> identifier_list COMMA identifier','identifier_list',3,'p_identifier_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',928), - ('initializer -> assignment_expression','initializer',1,'p_initializer_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',937), - ('initializer -> brace_open initializer_list brace_close','initializer',3,'p_initializer_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',942), - ('initializer -> brace_open initializer_list COMMA brace_close','initializer',4,'p_initializer_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',943), - ('initializer_list -> designation_opt initializer','initializer_list',2,'p_initializer_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',948), - ('initializer_list -> initializer_list COMMA designation_opt initializer','initializer_list',4,'p_initializer_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',949), - ('designation -> designator_list EQUALS','designation',2,'p_designation','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',960), - ('designator_list -> designator','designator_list',1,'p_designator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',968), - ('designator_list -> designator_list designator','designator_list',2,'p_designator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',969), - ('designator -> LBRACKET constant_expression RBRACKET','designator',3,'p_designator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',974), - ('designator -> PERIOD identifier','designator',2,'p_designator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',975), - ('type_name -> specifier_qualifier_list abstract_declarator_opt','type_name',2,'p_type_name','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',980), - ('abstract_declarator -> pointer','abstract_declarator',1,'p_abstract_declarator_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',996), - ('abstract_declarator -> pointer direct_abstract_declarator','abstract_declarator',2,'p_abstract_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1004), - ('abstract_declarator -> direct_abstract_declarator','abstract_declarator',1,'p_abstract_declarator_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1009), - ('direct_abstract_declarator -> LPAREN abstract_declarator RPAREN','direct_abstract_declarator',3,'p_direct_abstract_declarator_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1019), - ('direct_abstract_declarator -> direct_abstract_declarator LBRACKET assignment_expression_opt RBRACKET','direct_abstract_declarator',4,'p_direct_abstract_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1023), - ('direct_abstract_declarator -> LBRACKET assignment_expression_opt RBRACKET','direct_abstract_declarator',3,'p_direct_abstract_declarator_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1033), - ('direct_abstract_declarator -> direct_abstract_declarator LBRACKET TIMES RBRACKET','direct_abstract_declarator',4,'p_direct_abstract_declarator_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1041), - ('direct_abstract_declarator -> LBRACKET TIMES RBRACKET','direct_abstract_declarator',3,'p_direct_abstract_declarator_5','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1051), - ('direct_abstract_declarator -> direct_abstract_declarator LPAREN parameter_type_list_opt RPAREN','direct_abstract_declarator',4,'p_direct_abstract_declarator_6','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1059), - ('direct_abstract_declarator -> LPAREN parameter_type_list_opt RPAREN','direct_abstract_declarator',3,'p_direct_abstract_declarator_7','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1069), - ('block_item -> declaration','block_item',1,'p_block_item','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1080), - ('block_item -> statement','block_item',1,'p_block_item','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1081), - ('block_item_list -> block_item','block_item_list',1,'p_block_item_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1088), - ('block_item_list -> block_item_list block_item','block_item_list',2,'p_block_item_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1089), - ('compound_statement -> brace_open block_item_list_opt brace_close','compound_statement',3,'p_compound_statement_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1095), - ('labeled_statement -> ID COLON statement','labeled_statement',3,'p_labeled_statement_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1101), - ('labeled_statement -> CASE constant_expression COLON statement','labeled_statement',4,'p_labeled_statement_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1105), - ('labeled_statement -> DEFAULT COLON statement','labeled_statement',3,'p_labeled_statement_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1109), - ('selection_statement -> IF LPAREN expression RPAREN statement','selection_statement',5,'p_selection_statement_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1113), - ('selection_statement -> IF LPAREN expression RPAREN statement ELSE statement','selection_statement',7,'p_selection_statement_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1117), - ('selection_statement -> SWITCH LPAREN expression RPAREN statement','selection_statement',5,'p_selection_statement_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1121), - ('iteration_statement -> WHILE LPAREN expression RPAREN statement','iteration_statement',5,'p_iteration_statement_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1126), - ('iteration_statement -> DO statement WHILE LPAREN expression RPAREN SEMI','iteration_statement',7,'p_iteration_statement_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1130), - ('iteration_statement -> FOR LPAREN expression_opt SEMI expression_opt SEMI expression_opt RPAREN statement','iteration_statement',9,'p_iteration_statement_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1134), - ('iteration_statement -> FOR LPAREN declaration expression_opt SEMI expression_opt RPAREN statement','iteration_statement',8,'p_iteration_statement_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1138), - ('jump_statement -> GOTO ID SEMI','jump_statement',3,'p_jump_statement_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1142), - ('jump_statement -> BREAK SEMI','jump_statement',2,'p_jump_statement_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1146), - ('jump_statement -> CONTINUE SEMI','jump_statement',2,'p_jump_statement_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1150), - ('jump_statement -> RETURN expression SEMI','jump_statement',3,'p_jump_statement_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1154), - ('jump_statement -> RETURN SEMI','jump_statement',2,'p_jump_statement_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1155), - ('expression_statement -> expression_opt SEMI','expression_statement',2,'p_expression_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1160), - ('expression -> assignment_expression','expression',1,'p_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1167), - ('expression -> expression COMMA assignment_expression','expression',3,'p_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1168), - ('typedef_name -> TYPEID','typedef_name',1,'p_typedef_name','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1180), - ('assignment_expression -> conditional_expression','assignment_expression',1,'p_assignment_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1184), - ('assignment_expression -> unary_expression assignment_operator assignment_expression','assignment_expression',3,'p_assignment_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1185), - ('assignment_operator -> EQUALS','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1198), - ('assignment_operator -> XOREQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1199), - ('assignment_operator -> TIMESEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1200), - ('assignment_operator -> DIVEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1201), - ('assignment_operator -> MODEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1202), - ('assignment_operator -> PLUSEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1203), - ('assignment_operator -> MINUSEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1204), - ('assignment_operator -> LSHIFTEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1205), - ('assignment_operator -> RSHIFTEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1206), - ('assignment_operator -> ANDEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1207), - ('assignment_operator -> OREQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1208), - ('constant_expression -> conditional_expression','constant_expression',1,'p_constant_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1213), - ('conditional_expression -> binary_expression','conditional_expression',1,'p_conditional_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1217), - ('conditional_expression -> binary_expression CONDOP expression COLON conditional_expression','conditional_expression',5,'p_conditional_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1218), - ('binary_expression -> cast_expression','binary_expression',1,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1226), - ('binary_expression -> binary_expression TIMES binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1227), - ('binary_expression -> binary_expression DIVIDE binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1228), - ('binary_expression -> binary_expression MOD binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1229), - ('binary_expression -> binary_expression PLUS binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1230), - ('binary_expression -> binary_expression MINUS binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1231), - ('binary_expression -> binary_expression RSHIFT binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1232), - ('binary_expression -> binary_expression LSHIFT binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1233), - ('binary_expression -> binary_expression LT binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1234), - ('binary_expression -> binary_expression LE binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1235), - ('binary_expression -> binary_expression GE binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1236), - ('binary_expression -> binary_expression GT binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1237), - ('binary_expression -> binary_expression EQ binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1238), - ('binary_expression -> binary_expression NE binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1239), - ('binary_expression -> binary_expression AND binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1240), - ('binary_expression -> binary_expression OR binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1241), - ('binary_expression -> binary_expression XOR binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1242), - ('binary_expression -> binary_expression LAND binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1243), - ('binary_expression -> binary_expression LOR binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1244), - ('cast_expression -> unary_expression','cast_expression',1,'p_cast_expression_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1252), - ('cast_expression -> LPAREN type_name RPAREN cast_expression','cast_expression',4,'p_cast_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1256), - ('unary_expression -> postfix_expression','unary_expression',1,'p_unary_expression_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1260), - ('unary_expression -> PLUSPLUS unary_expression','unary_expression',2,'p_unary_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1264), - ('unary_expression -> MINUSMINUS unary_expression','unary_expression',2,'p_unary_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1265), - ('unary_expression -> unary_operator cast_expression','unary_expression',2,'p_unary_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1266), - ('unary_expression -> SIZEOF unary_expression','unary_expression',2,'p_unary_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1271), - ('unary_expression -> SIZEOF LPAREN type_name RPAREN','unary_expression',4,'p_unary_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1272), - ('unary_operator -> AND','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1280), - ('unary_operator -> TIMES','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1281), - ('unary_operator -> PLUS','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1282), - ('unary_operator -> MINUS','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1283), - ('unary_operator -> NOT','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1284), - ('unary_operator -> LNOT','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1285), - ('postfix_expression -> primary_expression','postfix_expression',1,'p_postfix_expression_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1290), - ('postfix_expression -> postfix_expression LBRACKET expression RBRACKET','postfix_expression',4,'p_postfix_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1294), - ('postfix_expression -> postfix_expression LPAREN argument_expression_list RPAREN','postfix_expression',4,'p_postfix_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1298), - ('postfix_expression -> postfix_expression LPAREN RPAREN','postfix_expression',3,'p_postfix_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1299), - ('postfix_expression -> postfix_expression PERIOD identifier','postfix_expression',3,'p_postfix_expression_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1304), - ('postfix_expression -> postfix_expression ARROW identifier','postfix_expression',3,'p_postfix_expression_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1305), - ('postfix_expression -> postfix_expression PLUSPLUS','postfix_expression',2,'p_postfix_expression_5','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1310), - ('postfix_expression -> postfix_expression MINUSMINUS','postfix_expression',2,'p_postfix_expression_5','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1311), - ('postfix_expression -> LPAREN type_name RPAREN brace_open initializer_list brace_close','postfix_expression',6,'p_postfix_expression_6','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1316), - ('postfix_expression -> LPAREN type_name RPAREN brace_open initializer_list COMMA brace_close','postfix_expression',7,'p_postfix_expression_6','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1317), - ('primary_expression -> identifier','primary_expression',1,'p_primary_expression_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1322), - ('primary_expression -> constant','primary_expression',1,'p_primary_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1326), - ('primary_expression -> unified_string_literal','primary_expression',1,'p_primary_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1330), - ('primary_expression -> unified_wstring_literal','primary_expression',1,'p_primary_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1331), - ('primary_expression -> LPAREN expression RPAREN','primary_expression',3,'p_primary_expression_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1336), - ('argument_expression_list -> assignment_expression','argument_expression_list',1,'p_argument_expression_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1340), - ('argument_expression_list -> argument_expression_list COMMA assignment_expression','argument_expression_list',3,'p_argument_expression_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1341), - ('identifier -> ID','identifier',1,'p_identifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1350), - ('constant -> INT_CONST_DEC','constant',1,'p_constant_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1354), - ('constant -> INT_CONST_OCT','constant',1,'p_constant_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1355), - ('constant -> INT_CONST_HEX','constant',1,'p_constant_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1356), - ('constant -> FLOAT_CONST','constant',1,'p_constant_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1362), - ('constant -> HEX_FLOAT_CONST','constant',1,'p_constant_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1363), - ('constant -> CHAR_CONST','constant',1,'p_constant_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1369), - ('constant -> WCHAR_CONST','constant',1,'p_constant_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1370), - ('unified_string_literal -> STRING_LITERAL','unified_string_literal',1,'p_unified_string_literal','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1381), - ('unified_string_literal -> unified_string_literal STRING_LITERAL','unified_string_literal',2,'p_unified_string_literal','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1382), - ('unified_wstring_literal -> WSTRING_LITERAL','unified_wstring_literal',1,'p_unified_wstring_literal','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1392), - ('unified_wstring_literal -> unified_wstring_literal WSTRING_LITERAL','unified_wstring_literal',2,'p_unified_wstring_literal','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1393), - ('brace_open -> LBRACE','brace_open',1,'p_brace_open','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1403), - ('brace_close -> RBRACE','brace_close',1,'p_brace_close','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1409), - ('empty -> ','empty',0,'p_empty','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1415), -] From noreply at buildbot.pypy.org Thu Apr 4 16:41:27 2013 From: noreply at buildbot.pypy.org (arigo) Date: Thu, 4 Apr 2013 16:41:27 +0200 (CEST) Subject: [pypy-commit] cffi default: Add CFFI_MEM_DEBUG and CFFI_MEM_LEAK defines, to build versions of Message-ID: <20130404144127.593061C06BD@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r1230:292e7e661406 Date: 2013-04-04 16:39 +0200 http://bitbucket.org/cffi/cffi/changeset/292e7e661406/ Log: Add CFFI_MEM_DEBUG and CFFI_MEM_LEAK defines, to build versions of _cffi_backend that help in debugging early frees. diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c --- a/c/_cffi_backend.c +++ b/c/_cffi_backend.c @@ -1382,7 +1382,9 @@ PyObject_ClearWeakRefs((PyObject *) cd); Py_DECREF(cd->c_type); +#ifndef CFFI_MEM_LEAK /* never release anything, tests only */ PyObject_Del(cd); +#endif } static void cdataowning_dealloc(CDataObject *cd) @@ -1397,6 +1399,19 @@ Py_XDECREF(args); cffi_closure_free(closure); } +#if defined(CFFI_MEM_DEBUG) || defined(CFFI_MEM_LEAK) + if (cd->c_type->ct_flags & (CT_PRIMITIVE_ANY | CT_STRUCT | CT_UNION)) { + assert(cd->c_type->ct_size >= 0); + memset(cd->c_data, 0xDD, cd->c_type->ct_size); + } + else if (cd->c_type->ct_flags & CT_ARRAY) { + Py_ssize_t x = get_array_length(cd); + assert(x >= 0); + x *= cd->c_type->ct_itemdescr->ct_size; + assert(x >= 0); + memset(cd->c_data, 0xDD, x); + } +#endif cdata_dealloc(cd); } From noreply at buildbot.pypy.org Thu Apr 4 17:10:49 2013 From: noreply at buildbot.pypy.org (arigo) Date: Thu, 4 Apr 2013 17:10:49 +0200 (CEST) Subject: [pypy-commit] cffi default: more Message-ID: <20130404151049.AFDD61C039A@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r1231:2caa2bbd137b Date: 2013-04-04 17:08 +0200 http://bitbucket.org/cffi/cffi/changeset/2caa2bbd137b/ Log: more diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c --- a/c/_cffi_backend.c +++ b/c/_cffi_backend.c @@ -2087,8 +2087,12 @@ if ((ctptr->ct_flags & CT_CAST_ANYTHING) || ((ctitem->ct_flags & (CT_PRIMITIVE_SIGNED|CT_PRIMITIVE_UNSIGNED)) && (ctitem->ct_size == sizeof(char)))) { +#if defined(CFFI_MEM_DEBUG) || defined(CFFI_MEM_LEAK) + length = PyBytes_GET_SIZE(init) + 1; +#else *output_data = PyBytes_AS_STRING(init); return 0; +#endif } else goto convert_default; From noreply at buildbot.pypy.org Thu Apr 4 18:20:55 2013 From: noreply at buildbot.pypy.org (arigo) Date: Thu, 4 Apr 2013 18:20:55 +0200 (CEST) Subject: [pypy-commit] pypy default: (fijal, arigo around) try to fix statements going away under our feet. Message-ID: <20130404162055.C28501C039A@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63010:d6dd0008297b Date: 2013-04-04 18:22 +0200 http://bitbucket.org/pypy/pypy/changeset/d6dd0008297b/ Log: (fijal, arigo around) try to fix statements going away under our feet. diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -388,6 +388,7 @@ if stat._in_use: stat = Statement(self.connection, sql) + self.cache[sql] = stat stat._row_factory = row_factory return stat @@ -855,10 +856,6 @@ self.__initialized = True - def __del__(self): - if self.__statement: - self.__statement._reset() - def close(self): self.__connection._check_thread() self.__connection._check_closed() From noreply at buildbot.pypy.org Thu Apr 4 19:49:18 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Thu, 4 Apr 2013 19:49:18 +0200 (CEST) Subject: [pypy-commit] pypy default: only need to check in_use if it isn't a new statement Message-ID: <20130404174918.2178F1C301F@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63011:1ecbb83c374b Date: 2013-04-04 13:47 -0400 http://bitbucket.org/pypy/pypy/changeset/1ecbb83c374b/ Log: only need to check in_use if it isn't a new statement diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -385,10 +385,10 @@ self.cache[sql] = stat if len(self.cache) > self.maxcount: self.cache.popitem(0) - - if stat._in_use: - stat = Statement(self.connection, sql) - self.cache[sql] = stat + else: + if stat._in_use: + stat = Statement(self.connection, sql) + self.cache[sql] = stat stat._row_factory = row_factory return stat From noreply at buildbot.pypy.org Thu Apr 4 19:49:19 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Thu, 4 Apr 2013 19:49:19 +0200 (CEST) Subject: [pypy-commit] pypy default: remove test of cursor.__del__ Message-ID: <20130404174919.6936C1C301F@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63012:0bf476dc4617 Date: 2013-04-04 13:48 -0400 http://bitbucket.org/pypy/pypy/changeset/0bf476dc4617/ Log: remove test of cursor.__del__ diff --git a/pypy/module/test_lib_pypy/test_sqlite3.py b/pypy/module/test_lib_pypy/test_sqlite3.py --- a/pypy/module/test_lib_pypy/test_sqlite3.py +++ b/pypy/module/test_lib_pypy/test_sqlite3.py @@ -96,18 +96,6 @@ pytest.raises(_sqlite3.ProgrammingError, "cur.executemany(1,2,3,4,5)") @pytest.mark.skipif("not hasattr(sys, 'pypy_translation_info')") -def test_cursor_del(): - con = _sqlite3.connect(':memory:') - cur = con.execute('select 1') - stmt = cur._Cursor__statement - cur.close() - cur = con.execute('select 1') - assert cur._Cursor__statement is stmt - del cur; import gc; gc.collect(); gc.collect() - cur = con.execute('select 1') - assert cur._Cursor__statement is stmt - - at pytest.mark.skipif("not hasattr(sys, 'pypy_translation_info')") def test_connection_del(tmpdir): """For issue1325.""" import os From noreply at buildbot.pypy.org Thu Apr 4 19:50:54 2013 From: noreply at buildbot.pypy.org (arigo) Date: Thu, 4 Apr 2013 19:50:54 +0200 (CEST) Subject: [pypy-commit] pypy default: Add a check (for lldebug builds) which points directly to where we forget to close the stack. Message-ID: <20130404175054.D7EB71C301F@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63013:82b07e9f1053 Date: 2013-04-04 19:52 +0200 http://bitbucket.org/pypy/pypy/changeset/82b07e9f1053/ Log: Add a check (for lldebug builds) which points directly to where we forget to close the stack. diff --git a/rpython/translator/c/src/mem.h b/rpython/translator/c/src/mem.h --- a/rpython/translator/c/src/mem.h +++ b/rpython/translator/c/src/mem.h @@ -195,8 +195,24 @@ "g" (v)) /* marker for trackgcroot.py, and inhibits tail calls */ -#define pypy_asm_stack_bottom() asm volatile ("/* GC_STACK_BOTTOM */" : : : \ - "memory") +#define pypy_asm_stack_bottom() { asm volatile ("/* GC_STACK_BOTTOM */" : : : \ + "memory"); pypy_check_stack_count(); } + +static void pypy_check_stack_count(void) +{ +#ifdef RPY_ASSERT + void *anchor = (void*)&pypy_g_ASM_FRAMEDATA_HEAD; + void *fd = ((void* *) (((char *)anchor) + sizeof(void*)))[0]; + long got = 0; + long stacks_counter = + (&pypy_g_rpython_rtyper_lltypesystem_rffi_StackCounter)->sc_inst_stacks_counter; + while (fd != anchor) { + got += 1; + fd = ((void* *) (((char *)fd) + sizeof(void*)))[0]; + } + assert(got == stacks_counter || ((got == 0) && (stacks_counter == 1))); +#endif +} #define OP_GC_ASMGCROOT_STATIC(i, r) r = \ i == 0 ? (void*)&__gcmapstart : \ From noreply at buildbot.pypy.org Thu Apr 4 21:56:23 2013 From: noreply at buildbot.pypy.org (arigo) Date: Thu, 4 Apr 2013 21:56:23 +0200 (CEST) Subject: [pypy-commit] pypy default: Move gc_stack_bottom() around to after the GIL is acquired and the Message-ID: <20130404195623.2F5DD1C305C@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63014:c0808fc03a3a Date: 2013-04-04 21:56 +0200 http://bitbucket.org/pypy/pypy/changeset/c0808fc03a3a/ Log: Move gc_stack_bottom() around to after the GIL is acquired and the stacks_counter is increased. Now c/gcc/test passes. And now, test_zrpy_releasegil no longer passes, as expected. diff --git a/rpython/rtyper/lltypesystem/rffi.py b/rpython/rtyper/lltypesystem/rffi.py --- a/rpython/rtyper/lltypesystem/rffi.py +++ b/rpython/rtyper/lltypesystem/rffi.py @@ -282,13 +282,13 @@ args = ', '.join(['a%d' % i for i in range(len(TP.TO.ARGS))]) source = py.code.Source(r""" def wrapper(%(args)s): # no *args - no GIL for mallocing the tuple - llop.gc_stack_bottom(lltype.Void) # marker for trackgcroot.py if aroundstate is not None: after = aroundstate.after if after: after() # from now on we hold the GIL stackcounter.stacks_counter += 1 + llop.gc_stack_bottom(lltype.Void) # marker for trackgcroot.py try: result = callable(%(args)s) except Exception, e: diff --git a/rpython/translator/c/src/mem.h b/rpython/translator/c/src/mem.h --- a/rpython/translator/c/src/mem.h +++ b/rpython/translator/c/src/mem.h @@ -210,7 +210,7 @@ got += 1; fd = ((void* *) (((char *)fd) + sizeof(void*)))[0]; } - assert(got == stacks_counter || ((got == 0) && (stacks_counter == 1))); + assert(got == stacks_counter - 1); #endif } From noreply at buildbot.pypy.org Thu Apr 4 22:03:51 2013 From: noreply at buildbot.pypy.org (mattip) Date: Thu, 4 Apr 2013 22:03:51 +0200 (CEST) Subject: [pypy-commit] pypy default: add tests that expose crashes Message-ID: <20130404200351.E64691C305C@cobra.cs.uni-duesseldorf.de> Author: Matti Picus Branch: Changeset: r63015:8ac3a0de8854 Date: 2013-04-04 19:21 +0300 http://bitbucket.org/pypy/pypy/changeset/8ac3a0de8854/ Log: add tests that expose crashes diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py --- a/pypy/module/micronumpy/test/test_numarray.py +++ b/pypy/module/micronumpy/test/test_numarray.py @@ -1487,14 +1487,14 @@ a = concatenate((['abcdef'], ['abc'])) assert a[0] == 'abcdef' assert str(a.dtype) == '|S6' - + def test_record_concatenate(self): # only an exact match can succeed from numpypy import zeros, concatenate a = concatenate((zeros((2,),dtype=[('x', int), ('y', float)]), zeros((2,),dtype=[('x', int), ('y', float)]))) assert a.shape == (4,) - exc = raises(TypeError, concatenate, + exc = raises(TypeError, concatenate, (zeros((2,), dtype=[('x', int), ('y', float)]), (zeros((2,), dtype=[('x', float), ('y', float)])))) assert str(exc.value).startswith('record type mismatch') @@ -1678,8 +1678,12 @@ assert a.itemsize == 3 # scalar vs. array try: + a = array(['1', '2','3']).astype(float) + assert a[2] == 3.0 a = array([1, 2, 3.14156]).astype('S3').dtype assert a.itemsize == 3 + a = array(3.1415).astype('S3').dtype + assert a.itemsize == 3 except NotImplementedError: skip('astype("S3") not implemented for numeric arrays') From noreply at buildbot.pypy.org Thu Apr 4 22:03:53 2013 From: noreply at buildbot.pypy.org (mattip) Date: Thu, 4 Apr 2013 22:03:53 +0200 (CEST) Subject: [pypy-commit] pypy default: fix crashes by disallowing astype(numeric_type) for str arrays, allow astype(str) for numeric arrays since it was implemented previously Message-ID: <20130404200353.2E8741C305C@cobra.cs.uni-duesseldorf.de> Author: Matti Picus Branch: Changeset: r63016:c4b86631bce3 Date: 2013-04-04 19:33 +0300 http://bitbucket.org/pypy/pypy/changeset/c4b86631bce3/ Log: fix crashes by disallowing astype(numeric_type) for str arrays, allow astype(str) for numeric arrays since it was implemented previously diff --git a/pypy/module/micronumpy/arrayimpl/concrete.py b/pypy/module/micronumpy/arrayimpl/concrete.py --- a/pypy/module/micronumpy/arrayimpl/concrete.py +++ b/pypy/module/micronumpy/arrayimpl/concrete.py @@ -281,7 +281,7 @@ def astype(self, space, dtype): new_arr = W_NDimArray.from_shape(self.get_shape(), dtype) - if dtype.is_str_or_unicode(): + if self.dtype.is_str_or_unicode() and not dtype.is_str_or_unicode(): raise OperationError(space.w_NotImplementedError, space.wrap( "astype(%s) not implemented yet" % self.dtype)) else: diff --git a/pypy/module/micronumpy/interp_support.py b/pypy/module/micronumpy/interp_support.py --- a/pypy/module/micronumpy/interp_support.py +++ b/pypy/module/micronumpy/interp_support.py @@ -15,7 +15,7 @@ items = [] num_items = 0 idx = 0 - + while (num_items < count or count == -1) and idx < len(s): nextidx = s.find(sep, idx) if nextidx < 0: @@ -45,7 +45,7 @@ items.append(val) num_items += 1 idx = nextidx + 1 - + if count > num_items: raise OperationError(space.w_ValueError, space.wrap( "string is smaller than requested size")) @@ -70,7 +70,7 @@ if count * itemsize > length: raise OperationError(space.w_ValueError, space.wrap( "string is smaller than requested size")) - + a = W_NDimArray.from_shape([count], dtype=dtype) loop.fromstring_loop(a, dtype, itemsize, s) return space.wrap(a) diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py --- a/pypy/module/micronumpy/test/test_numarray.py +++ b/pypy/module/micronumpy/test/test_numarray.py @@ -1677,15 +1677,15 @@ a = array('x').astype('S3').dtype assert a.itemsize == 3 # scalar vs. array + a = array([1, 2, 3.14156]).astype('S3').dtype + assert a.itemsize == 3 + a = array(3.1415).astype('S3').dtype + assert a.itemsize == 3 try: a = array(['1', '2','3']).astype(float) assert a[2] == 3.0 - a = array([1, 2, 3.14156]).astype('S3').dtype - assert a.itemsize == 3 - a = array(3.1415).astype('S3').dtype - assert a.itemsize == 3 except NotImplementedError: - skip('astype("S3") not implemented for numeric arrays') + skip('astype("float") not implemented for str arrays') def test_base(self): from numpypy import array From noreply at buildbot.pypy.org Thu Apr 4 22:03:54 2013 From: noreply at buildbot.pypy.org (mattip) Date: Thu, 4 Apr 2013 22:03:54 +0200 (CEST) Subject: [pypy-commit] pypy default: merge heads Message-ID: <20130404200354.6CE241C305C@cobra.cs.uni-duesseldorf.de> Author: Matti Picus Branch: Changeset: r63017:8dc0b7d3bb76 Date: 2013-04-04 22:56 +0300 http://bitbucket.org/pypy/pypy/changeset/8dc0b7d3bb76/ Log: merge heads diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -385,9 +385,10 @@ self.cache[sql] = stat if len(self.cache) > self.maxcount: self.cache.popitem(0) - - if stat._in_use: - stat = Statement(self.connection, sql) + else: + if stat._in_use: + stat = Statement(self.connection, sql) + self.cache[sql] = stat stat._row_factory = row_factory return stat @@ -855,10 +856,6 @@ self.__initialized = True - def __del__(self): - if self.__statement: - self.__statement._reset() - def close(self): self.__connection._check_thread() self.__connection._check_closed() diff --git a/pypy/module/test_lib_pypy/test_sqlite3.py b/pypy/module/test_lib_pypy/test_sqlite3.py --- a/pypy/module/test_lib_pypy/test_sqlite3.py +++ b/pypy/module/test_lib_pypy/test_sqlite3.py @@ -96,18 +96,6 @@ pytest.raises(_sqlite3.ProgrammingError, "cur.executemany(1,2,3,4,5)") @pytest.mark.skipif("not hasattr(sys, 'pypy_translation_info')") -def test_cursor_del(): - con = _sqlite3.connect(':memory:') - cur = con.execute('select 1') - stmt = cur._Cursor__statement - cur.close() - cur = con.execute('select 1') - assert cur._Cursor__statement is stmt - del cur; import gc; gc.collect(); gc.collect() - cur = con.execute('select 1') - assert cur._Cursor__statement is stmt - - at pytest.mark.skipif("not hasattr(sys, 'pypy_translation_info')") def test_connection_del(tmpdir): """For issue1325.""" import os diff --git a/rpython/translator/c/src/mem.h b/rpython/translator/c/src/mem.h --- a/rpython/translator/c/src/mem.h +++ b/rpython/translator/c/src/mem.h @@ -195,8 +195,24 @@ "g" (v)) /* marker for trackgcroot.py, and inhibits tail calls */ -#define pypy_asm_stack_bottom() asm volatile ("/* GC_STACK_BOTTOM */" : : : \ - "memory") +#define pypy_asm_stack_bottom() { asm volatile ("/* GC_STACK_BOTTOM */" : : : \ + "memory"); pypy_check_stack_count(); } + +static void pypy_check_stack_count(void) +{ +#ifdef RPY_ASSERT + void *anchor = (void*)&pypy_g_ASM_FRAMEDATA_HEAD; + void *fd = ((void* *) (((char *)anchor) + sizeof(void*)))[0]; + long got = 0; + long stacks_counter = + (&pypy_g_rpython_rtyper_lltypesystem_rffi_StackCounter)->sc_inst_stacks_counter; + while (fd != anchor) { + got += 1; + fd = ((void* *) (((char *)fd) + sizeof(void*)))[0]; + } + assert(got == stacks_counter || ((got == 0) && (stacks_counter == 1))); +#endif +} #define OP_GC_ASMGCROOT_STATIC(i, r) r = \ i == 0 ? (void*)&__gcmapstart : \ From noreply at buildbot.pypy.org Thu Apr 4 22:03:55 2013 From: noreply at buildbot.pypy.org (mattip) Date: Thu, 4 Apr 2013 22:03:55 +0200 (CEST) Subject: [pypy-commit] pypy default: merge heads Message-ID: <20130404200355.A32171C305C@cobra.cs.uni-duesseldorf.de> Author: Matti Picus Branch: Changeset: r63018:6f4b36cb5382 Date: 2013-04-04 23:03 +0300 http://bitbucket.org/pypy/pypy/changeset/6f4b36cb5382/ Log: merge heads diff --git a/rpython/rtyper/lltypesystem/rffi.py b/rpython/rtyper/lltypesystem/rffi.py --- a/rpython/rtyper/lltypesystem/rffi.py +++ b/rpython/rtyper/lltypesystem/rffi.py @@ -282,13 +282,13 @@ args = ', '.join(['a%d' % i for i in range(len(TP.TO.ARGS))]) source = py.code.Source(r""" def wrapper(%(args)s): # no *args - no GIL for mallocing the tuple - llop.gc_stack_bottom(lltype.Void) # marker for trackgcroot.py if aroundstate is not None: after = aroundstate.after if after: after() # from now on we hold the GIL stackcounter.stacks_counter += 1 + llop.gc_stack_bottom(lltype.Void) # marker for trackgcroot.py try: result = callable(%(args)s) except Exception, e: diff --git a/rpython/translator/c/src/mem.h b/rpython/translator/c/src/mem.h --- a/rpython/translator/c/src/mem.h +++ b/rpython/translator/c/src/mem.h @@ -210,7 +210,7 @@ got += 1; fd = ((void* *) (((char *)fd) + sizeof(void*)))[0]; } - assert(got == stacks_counter || ((got == 0) && (stacks_counter == 1))); + assert(got == stacks_counter - 1); #endif } From noreply at buildbot.pypy.org Thu Apr 4 22:19:06 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Thu, 4 Apr 2013 22:19:06 +0200 (CEST) Subject: [pypy-commit] pypy default: store next_row on the cursor not the statement Message-ID: <20130404201906.5CB631C301F@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63019:db5b33a3f3c3 Date: 2013-04-04 16:17 -0400 http://bitbucket.org/pypy/pypy/changeset/db5b33a3f3c3/ Log: store next_row on the cursor not the statement diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -884,6 +884,10 @@ def __execute(self, multiple, sql, many_params): self.__locked = True try: + del self.__next_row + except AttributeError: + pass + try: self._reset = False if not isinstance(sql, basestring): raise ValueError("operation parameter must be str or unicode") @@ -915,9 +919,9 @@ if self.__statement._kind == Statement._DML: self.__statement._reset() - if self.__statement._kind == Statement._DQL and ret == _lib.SQLITE_ROW: + if ret == _lib.SQLITE_ROW: self.__statement._build_row_cast_map() - self.__statement._readahead(self) + self.__next_row = self.__statement._readahead(self) if self.__statement._kind == Statement._DML: if self.__rowcount == -1: @@ -992,7 +996,22 @@ self.__check_reset() if not self.__statement: raise StopIteration - return self.__statement._next(self) + + try: + next_row = self.__next_row + except AttributeError: + self.__statement._reset() + self.__statement = None + raise StopIteration + del self.__next_row + + ret = _lib.sqlite3_step(self.__statement._statement) + if ret not in (_lib.SQLITE_DONE, _lib.SQLITE_ROW): + self.__statement._reset() + raise self.__connection._get_exception(ret) + elif ret == _lib.SQLITE_ROW: + self.__next_row = self.__statement._readahead(self) + return next_row if sys.version_info[0] < 3: next = __next__ @@ -1259,24 +1278,7 @@ row = tuple(row) if self._row_factory is not None: row = self._row_factory(cursor, row) - self._item = row - - def _next(self, cursor): - try: - item = self._item - except AttributeError: - self._reset() - raise StopIteration - del self._item - - ret = _lib.sqlite3_step(self._statement) - if ret not in (_lib.SQLITE_DONE, _lib.SQLITE_ROW): - _lib.sqlite3_reset(self._statement) - raise self.__con._get_exception(ret) - elif ret == _lib.SQLITE_ROW: - self._readahead(cursor) - - return item + return row def _get_description(self): if self._kind == Statement._DML: From noreply at buildbot.pypy.org Thu Apr 4 22:59:49 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Thu, 4 Apr 2013 22:59:49 +0200 (CEST) Subject: [pypy-commit] pypy default: also store row_cast_map on cursor not statement, don't call row_factory unless row is actually fetched Message-ID: <20130404205949.EFE8C1C039A@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63020:1e485fc86788 Date: 2013-04-04 16:54 -0400 http://bitbucket.org/pypy/pypy/changeset/1e485fc86788/ Log: also store row_cast_map on cursor not statement, don't call row_factory unless row is actually fetched diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -377,7 +377,7 @@ self.maxcount = maxcount self.cache = OrderedDict() - def get(self, sql, row_factory): + def get(self, sql): try: stat = self.cache[sql] except KeyError: @@ -389,7 +389,6 @@ if stat._in_use: stat = Statement(self.connection, sql) self.cache[sql] = stat - stat._row_factory = row_factory return stat @@ -552,7 +551,7 @@ @_check_thread_wrap @_check_closed_wrap def __call__(self, sql): - return self._statement_cache.get(sql, self.row_factory) + return self._statement_cache.get(sql) def cursor(self, factory=None): self._check_thread() @@ -881,20 +880,96 @@ return func(self, *args, **kwargs) return wrapper + def __check_reset(self): + if self._reset: + raise InterfaceError( + "Cursor needed to be reset because of commit/rollback " + "and can no longer be fetched from.") + + def __build_row_cast_map(self): + if not self.__connection._detect_types: + return + self.__row_cast_map = [] + for i in xrange(_lib.sqlite3_column_count(self.__statement._statement)): + converter = None + + if self.__connection._detect_types & PARSE_COLNAMES: + colname = _lib.sqlite3_column_name(self.__statement._statement, i) + if colname: + colname = _ffi.string(colname).decode('utf-8') + type_start = -1 + key = None + for pos in range(len(colname)): + if colname[pos] == '[': + type_start = pos + 1 + elif colname[pos] == ']' and type_start != -1: + key = colname[type_start:pos] + converter = converters[key.upper()] + + if converter is None and self.__connection._detect_types & PARSE_DECLTYPES: + decltype = _lib.sqlite3_column_decltype(self.__statement._statement, i) + if decltype: + decltype = _ffi.string(decltype).decode('utf-8') + # if multiple words, use first, eg. + # "INTEGER NOT NULL" => "INTEGER" + decltype = decltype.split()[0] + if '(' in decltype: + decltype = decltype[:decltype.index('(')] + converter = converters.get(decltype.upper(), None) + + self.__row_cast_map.append(converter) + + def __fetch_one_row(self): + row = [] + num_cols = _lib.sqlite3_data_count(self.__statement._statement) + for i in xrange(num_cols): + if self.__connection._detect_types: + converter = self.__row_cast_map[i] + else: + converter = None + + if converter is not None: + blob = _lib.sqlite3_column_blob(self.__statement._statement, i) + if not blob: + val = None + else: + blob_len = _lib.sqlite3_column_bytes(self.__statement._statement, i) + val = _ffi.buffer(blob, blob_len)[:] + val = converter(val) + else: + typ = _lib.sqlite3_column_type(self.__statement._statement, i) + if typ == _lib.SQLITE_NULL: + val = None + elif typ == _lib.SQLITE_INTEGER: + val = _lib.sqlite3_column_int64(self.__statement._statement, i) + val = int(val) + elif typ == _lib.SQLITE_FLOAT: + val = _lib.sqlite3_column_double(self.__statement._statement, i) + elif typ == _lib.SQLITE_TEXT: + text = _lib.sqlite3_column_text(self.__statement._statement, i) + text_len = _lib.sqlite3_column_bytes(self.__statement._statement, i) + val = _ffi.buffer(text, text_len)[:] + val = self.__connection.text_factory(val) + elif typ == _lib.SQLITE_BLOB: + blob = _lib.sqlite3_column_blob(self.__statement._statement, i) + blob_len = _lib.sqlite3_column_bytes(self.__statement._statement, i) + val = _BLOB_TYPE(_ffi.buffer(blob, blob_len)) + row.append(val) + return tuple(row) + def __execute(self, multiple, sql, many_params): self.__locked = True + self._reset = False try: del self.__next_row except AttributeError: pass try: - self._reset = False if not isinstance(sql, basestring): raise ValueError("operation parameter must be str or unicode") self.__description = None self.__rowcount = -1 - self.__statement = self.__connection._statement_cache.get( - sql, self.row_factory) + self.__statement = self.__connection._statement_cache.get(sql) if self.__connection._isolation_level is not None: if self.__statement._kind == Statement._DDL: @@ -920,8 +995,8 @@ self.__statement._reset() if ret == _lib.SQLITE_ROW: - self.__statement._build_row_cast_map() - self.__next_row = self.__statement._readahead(self) + self.__build_row_cast_map() + self.__next_row = self.__fetch_one_row() if self.__statement._kind == Statement._DML: if self.__rowcount == -1: @@ -982,12 +1057,6 @@ break return self - def __check_reset(self): - if self._reset: - raise self.__connection.InterfaceError( - "Cursor needed to be reset because of commit/rollback " - "and can no longer be fetched from.") - def __iter__(self): return self @@ -1005,12 +1074,15 @@ raise StopIteration del self.__next_row + if self.row_factory is not None: + next_row = self.row_factory(self, next_row) + ret = _lib.sqlite3_step(self.__statement._statement) if ret not in (_lib.SQLITE_DONE, _lib.SQLITE_ROW): self.__statement._reset() raise self.__connection._get_exception(ret) elif ret == _lib.SQLITE_ROW: - self.__next_row = self.__statement._readahead(self) + self.__next_row = self.__fetch_one_row() return next_row if sys.version_info[0] < 3: @@ -1068,7 +1140,6 @@ self.__con._remember_statement(self) self._in_use = False - self._row_factory = None if not isinstance(sql, basestring): raise Warning("SQL is of wrong type. Must be string or unicode.") @@ -1205,81 +1276,6 @@ else: raise ValueError("parameters are of unsupported type") - def _build_row_cast_map(self): - if not self.__con._detect_types: - return - self.__row_cast_map = [] - for i in xrange(_lib.sqlite3_column_count(self._statement)): - converter = None - - if self.__con._detect_types & PARSE_COLNAMES: - colname = _lib.sqlite3_column_name(self._statement, i) - if colname: - colname = _ffi.string(colname).decode('utf-8') - type_start = -1 - key = None - for pos in range(len(colname)): - if colname[pos] == '[': - type_start = pos + 1 - elif colname[pos] == ']' and type_start != -1: - key = colname[type_start:pos] - converter = converters[key.upper()] - - if converter is None and self.__con._detect_types & PARSE_DECLTYPES: - decltype = _lib.sqlite3_column_decltype(self._statement, i) - if decltype: - decltype = _ffi.string(decltype).decode('utf-8') - # if multiple words, use first, eg. - # "INTEGER NOT NULL" => "INTEGER" - decltype = decltype.split()[0] - if '(' in decltype: - decltype = decltype[:decltype.index('(')] - converter = converters.get(decltype.upper(), None) - - self.__row_cast_map.append(converter) - - def _readahead(self, cursor): - row = [] - num_cols = _lib.sqlite3_data_count(self._statement) - for i in xrange(num_cols): - if self.__con._detect_types: - converter = self.__row_cast_map[i] - else: - converter = None - - if converter is not None: - blob = _lib.sqlite3_column_blob(self._statement, i) - if not blob: - val = None - else: - blob_len = _lib.sqlite3_column_bytes(self._statement, i) - val = _ffi.buffer(blob, blob_len)[:] - val = converter(val) - else: - typ = _lib.sqlite3_column_type(self._statement, i) - if typ == _lib.SQLITE_NULL: - val = None - elif typ == _lib.SQLITE_INTEGER: - val = _lib.sqlite3_column_int64(self._statement, i) - val = int(val) - elif typ == _lib.SQLITE_FLOAT: - val = _lib.sqlite3_column_double(self._statement, i) - elif typ == _lib.SQLITE_TEXT: - text = _lib.sqlite3_column_text(self._statement, i) - text_len = _lib.sqlite3_column_bytes(self._statement, i) - val = _ffi.buffer(text, text_len)[:] - val = self.__con.text_factory(val) - elif typ == _lib.SQLITE_BLOB: - blob = _lib.sqlite3_column_blob(self._statement, i) - blob_len = _lib.sqlite3_column_bytes(self._statement, i) - val = _BLOB_TYPE(_ffi.buffer(blob, blob_len)) - row.append(val) - - row = tuple(row) - if self._row_factory is not None: - row = self._row_factory(cursor, row) - return row - def _get_description(self): if self._kind == Statement._DML: return None From noreply at buildbot.pypy.org Thu Apr 4 22:59:51 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Thu, 4 Apr 2013 22:59:51 +0200 (CEST) Subject: [pypy-commit] pypy default: test for row_factory change in last commit Message-ID: <20130404205951.28BBC1C039A@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63021:92adf3e58b66 Date: 2013-04-04 16:58 -0400 http://bitbucket.org/pypy/pypy/changeset/92adf3e58b66/ Log: test for row_factory change in last commit diff --git a/pypy/module/test_lib_pypy/test_sqlite3.py b/pypy/module/test_lib_pypy/test_sqlite3.py --- a/pypy/module/test_lib_pypy/test_sqlite3.py +++ b/pypy/module/test_lib_pypy/test_sqlite3.py @@ -193,3 +193,8 @@ con.commit() con.execute('BEGIN') con.commit() + +def test_row_factory_use(): + con = _sqlite3.connect(':memory:') + con.row_factory = 42 + con.execute('select 1') From noreply at buildbot.pypy.org Thu Apr 4 23:09:44 2013 From: noreply at buildbot.pypy.org (arigo) Date: Thu, 4 Apr 2013 23:09:44 +0200 (CEST) Subject: [pypy-commit] pypy default: Improve the test (still failing) Message-ID: <20130404210944.75CD81C039A@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63022:001750ff2866 Date: 2013-04-04 21:57 +0200 http://bitbucket.org/pypy/pypy/changeset/001750ff2866/ Log: Improve the test (still failing) diff --git a/rpython/jit/backend/x86/test/test_zrpy_releasegil.py b/rpython/jit/backend/x86/test/test_zrpy_releasegil.py --- a/rpython/jit/backend/x86/test/test_zrpy_releasegil.py +++ b/rpython/jit/backend/x86/test/test_zrpy_releasegil.py @@ -68,10 +68,12 @@ c_qsort = rffi.llexternal('qsort', [rffi.VOIDP, rffi.SIZE_T, rffi.SIZE_T, CALLBACK], lltype.Void) # - def f42(): + def f42(n): length = len(glob.lst) raw = alloc1() fn = llhelper(CALLBACK, rffi._make_wrapper_for(CALLBACK, callback)) + if n & 1: # to create a loop and a bridge, and also + pass # to run the qsort() call in the blackhole interp c_qsort(rffi.cast(rffi.VOIDP, raw), rffi.cast(rffi.SIZE_T, 2), rffi.cast(rffi.SIZE_T, 8), fn) free1(raw) @@ -85,7 +87,7 @@ None, None, None, None, None, None) # def f(n, x, *args): - f42() + f42(n) n -= 1 return (n, x) + args return before, f, None From noreply at buildbot.pypy.org Thu Apr 4 23:09:45 2013 From: noreply at buildbot.pypy.org (arigo) Date: Thu, 4 Apr 2013 23:09:45 +0200 (CEST) Subject: [pypy-commit] pypy default: Fixes fixes fixes. Now test_zrpy_releasegil passes, and other Message-ID: <20130404210945.B235F1C039A@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63023:a31ea3dedb23 Date: 2013-04-04 23:09 +0200 http://bitbucket.org/pypy/pypy/changeset/a31ea3dedb23/ Log: Fixes fixes fixes. Now test_zrpy_releasegil passes, and other previously-broken tests too. diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py --- a/pypy/module/cpyext/api.py +++ b/pypy/module/cpyext/api.py @@ -554,8 +554,8 @@ from pypy.module.cpyext.pyobject import Reference # we hope that malloc removal removes the newtuple() that is # inserted exactly here by the varargs specializer + rffi.stackcounter.stacks_counter += 1 llop.gc_stack_bottom(lltype.Void) # marker for trackgcroot.py - rffi.stackcounter.stacks_counter += 1 retval = fatal_value boxed_args = () try: diff --git a/rpython/memory/gctransform/asmgcroot.py b/rpython/memory/gctransform/asmgcroot.py --- a/rpython/memory/gctransform/asmgcroot.py +++ b/rpython/memory/gctransform/asmgcroot.py @@ -1,13 +1,15 @@ from rpython.flowspace.model import (Constant, Variable, Block, Link, - copygraph, SpaceOperation) + copygraph, SpaceOperation, checkgraph) from rpython.rlib.debug import ll_assert +from rpython.rlib.nonconst import NonConstant from rpython.rtyper.annlowlevel import llhelper from rpython.rtyper.lltypesystem import lltype, llmemory, rffi from rpython.rtyper.lltypesystem.lloperation import llop from rpython.memory.gctransform.framework import ( BaseFrameworkGCTransformer, BaseRootWalker) from rpython.rtyper.rbuiltin import gen_cast -from rpython.translator.unsimplify import copyvar +from rpython.translator.unsimplify import copyvar, varoftype +from rpython.translator.tool.cbuild import ExternalCompilationInfo import sys @@ -22,6 +24,7 @@ class AsmGcRootFrameworkGCTransformer(BaseFrameworkGCTransformer): _asmgcc_save_restore_arguments = None + _seen_gctransformer_hint_close_stack = None def push_roots(self, hop, keep_current_args=False): livevars = self.get_livevars_for_roots(hop, keep_current_args) @@ -57,10 +60,22 @@ def handle_call_with_close_stack(self, hop): fnptr = hop.spaceop.args[0].value + if self._seen_gctransformer_hint_close_stack is None: + self._seen_gctransformer_hint_close_stack = {} + if fnptr._obj.graph not in self._seen_gctransformer_hint_close_stack: + self._transform_hint_close_stack(fnptr) + self._seen_gctransformer_hint_close_stack[fnptr._obj.graph] = True + # + livevars = self.push_roots(hop) + self.default(hop) + self.pop_roots(hop, livevars) + + def _transform_hint_close_stack(self, fnptr): # We cannot easily pass variable amount of arguments of the call # across the call to the pypy_asm_stackwalk helper. So we store - # them away and restore them. We need to make a new graph - # that starts with restoring the arguments. + # them away and restore them. More precisely, we need to + # replace 'graph' with code that saves the arguments, and make + # a new graph that starts with restoring the arguments. if self._asmgcc_save_restore_arguments is None: self._asmgcc_save_restore_arguments = {} sradict = self._asmgcc_save_restore_arguments @@ -80,25 +95,52 @@ sradict[key] = Constant(p, lltype.Ptr(CONTAINER)) sra.append(sradict[key]) # - # store the value of the arguments - livevars = self.push_roots(hop) + # make a copy of the graph that will reload the values + graph = fnptr._obj.graph + graph2 = copygraph(graph) + # + # edit the original graph to only store the value of the arguments + block = Block(graph.startblock.inputargs) c_item0 = Constant('item0', lltype.Void) - for v_arg, c_p in zip(hop.spaceop.args[1:], sra): + assert len(block.inputargs) == len(sra) + for v_arg, c_p in zip(block.inputargs, sra): if isinstance(v_arg.concretetype, lltype.Ptr): - v_arg = hop.genop("cast_ptr_to_adr", [v_arg], - resulttype=llmemory.Address) - hop.genop("bare_setfield", [c_p, c_item0, v_arg]) + v_adr = varoftype(llmemory.Address) + block.operations.append( + SpaceOperation("cast_ptr_to_adr", [v_arg], v_adr)) + v_arg = v_adr + v_void = varoftype(lltype.Void) + block.operations.append( + SpaceOperation("bare_setfield", [c_p, c_item0, v_arg], v_void)) # - # make a copy of the graph that will reload the values - graph2 = copygraph(fnptr._obj.graph) + # call asm_stackwalk(graph2) + FUNC2 = lltype.FuncType([], FUNC1.RESULT) + fnptr2 = lltype.functionptr(FUNC2, + fnptr._obj._name + '_reload', + graph=graph2) + c_fnptr2 = Constant(fnptr2, lltype.Ptr(FUNC2)) + HELPERFUNC = lltype.FuncType([lltype.Ptr(FUNC2), + ASM_FRAMEDATA_HEAD_PTR], FUNC1.RESULT) + v_asm_stackwalk = varoftype(lltype.Ptr(HELPERFUNC), "asm_stackwalk") + block.operations.append( + SpaceOperation("cast_pointer", [c_asm_stackwalk], v_asm_stackwalk)) + v_result = varoftype(FUNC1.RESULT) + block.operations.append( + SpaceOperation("indirect_call", [v_asm_stackwalk, c_fnptr2, + c_gcrootanchor, + Constant(None, lltype.Void)], + v_result)) + block.closeblock(Link([v_result], graph.returnblock)) + graph.startblock = block + # + # edit the copy of the graph to reload the values block2 = graph2.startblock block1 = Block([]) reloadedvars = [] for v, c_p in zip(block2.inputargs, sra): v = copyvar(None, v) if isinstance(v.concretetype, lltype.Ptr): - w = Variable('tmp') - w.concretetype = llmemory.Address + w = varoftype(llmemory.Address) else: w = v block1.operations.append(SpaceOperation('getfield', @@ -109,21 +151,9 @@ reloadedvars.append(v) block1.closeblock(Link(reloadedvars, block2)) graph2.startblock = block1 - FUNC2 = lltype.FuncType([], FUNC1.RESULT) - fnptr2 = lltype.functionptr(FUNC2, - fnptr._obj._name + '_reload', - graph=graph2) - c_fnptr2 = Constant(fnptr2, lltype.Ptr(FUNC2)) - HELPERFUNC = lltype.FuncType([lltype.Ptr(FUNC2), - ASM_FRAMEDATA_HEAD_PTR], FUNC1.RESULT) # - v_asm_stackwalk = hop.genop("cast_pointer", [c_asm_stackwalk], - resulttype=lltype.Ptr(HELPERFUNC)) - hop.genop("indirect_call", - [v_asm_stackwalk, c_fnptr2, c_gcrootanchor, - Constant(None, lltype.Void)], - resultvar=hop.spaceop.result) - self.pop_roots(hop, livevars) + checkgraph(graph) + checkgraph(graph2) class AsmStackRootWalker(BaseRootWalker): @@ -284,6 +314,8 @@ stackscount += 1 # expected = rffi.stackcounter.stacks_counter + if NonConstant(0): + rffi.stackcounter.stacks_counter += 42 # hack to force it ll_assert(not (stackscount < expected), "non-closed stacks around") ll_assert(not (stackscount > expected), "stacks counter corruption?") lltype.free(otherframe, flavor='raw') @@ -681,13 +713,16 @@ gcrootanchor.next = gcrootanchor c_gcrootanchor = Constant(gcrootanchor, ASM_FRAMEDATA_HEAD_PTR) +eci = ExternalCompilationInfo(pre_include_bits=['#define PYPY_USE_ASMGCC']) + pypy_asm_stackwalk = rffi.llexternal('pypy_asm_stackwalk', [ASM_CALLBACK_PTR, ASM_FRAMEDATA_HEAD_PTR], lltype.Signed, sandboxsafe=True, _nowrapper=True, - random_effects_on_gcobjs=True) + random_effects_on_gcobjs=True, + compilation_info=eci) c_asm_stackwalk = Constant(pypy_asm_stackwalk, lltype.typeOf(pypy_asm_stackwalk)) diff --git a/rpython/translator/c/gcc/test/test_asmgcroot.py b/rpython/translator/c/gcc/test/test_asmgcroot.py --- a/rpython/translator/c/gcc/test/test_asmgcroot.py +++ b/rpython/translator/c/gcc/test/test_asmgcroot.py @@ -195,8 +195,8 @@ @entrypoint("x42", [lltype.Signed, lltype.Signed], c_name='callback') def mycallback(a, b): + rffi.stackcounter.stacks_counter += 1 llop.gc_stack_bottom(lltype.Void) - rffi.stackcounter.stacks_counter += 1 gc.collect() rffi.stackcounter.stacks_counter -= 1 return a + b diff --git a/rpython/translator/c/src/mem.c b/rpython/translator/c/src/mem.c --- a/rpython/translator/c/src/mem.c +++ b/rpython/translator/c/src/mem.c @@ -96,3 +96,27 @@ GC_set_warn_proc(mem_boehm_ignore); } #endif /* BOEHM GC */ + + +#ifdef RPY_ASSERT +# ifdef PYPY_USE_ASMGCC +# include "structdef.h" +# include "forwarddecl.h" +# endif +void pypy_check_stack_count(void) +{ +# ifdef PYPY_USE_ASMGCC + void *anchor = (void*)&pypy_g_ASM_FRAMEDATA_HEAD; + void *fd = ((void* *) (((char *)anchor) + sizeof(void*)))[0]; + long got = 0; + long stacks_counter = + pypy_g_rpython_rtyper_lltypesystem_rffi_StackCounter.sc_inst_stacks_counter; + while (fd != anchor) { + got += 1; + fd = ((void* *) (((char *)fd) + sizeof(void*)))[0]; + } + RPyAssert(got == stacks_counter - 1, + "bad stacks_counter or non-closed stacks around"); +# endif +} +#endif diff --git a/rpython/translator/c/src/mem.h b/rpython/translator/c/src/mem.h --- a/rpython/translator/c/src/mem.h +++ b/rpython/translator/c/src/mem.h @@ -195,24 +195,14 @@ "g" (v)) /* marker for trackgcroot.py, and inhibits tail calls */ -#define pypy_asm_stack_bottom() { asm volatile ("/* GC_STACK_BOTTOM */" : : : \ - "memory"); pypy_check_stack_count(); } +#define pypy_asm_stack_bottom() { asm volatile ("/* GC_STACK_BOTTOM */" : : : \ + "memory"); pypy_check_stack_count(); } +#ifdef RPY_ASSERT +void pypy_check_stack_count(void); +#else +static void pypy_check_stack_count(void) { } +#endif -static void pypy_check_stack_count(void) -{ -#ifdef RPY_ASSERT - void *anchor = (void*)&pypy_g_ASM_FRAMEDATA_HEAD; - void *fd = ((void* *) (((char *)anchor) + sizeof(void*)))[0]; - long got = 0; - long stacks_counter = - (&pypy_g_rpython_rtyper_lltypesystem_rffi_StackCounter)->sc_inst_stacks_counter; - while (fd != anchor) { - got += 1; - fd = ((void* *) (((char *)fd) + sizeof(void*)))[0]; - } - assert(got == stacks_counter - 1); -#endif -} #define OP_GC_ASMGCROOT_STATIC(i, r) r = \ i == 0 ? (void*)&__gcmapstart : \ From noreply at buildbot.pypy.org Thu Apr 4 23:09:47 2013 From: noreply at buildbot.pypy.org (arigo) Date: Thu, 4 Apr 2013 23:09:47 +0200 (CEST) Subject: [pypy-commit] pypy default: merge heads Message-ID: <20130404210947.2237E1C039A@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63024:8e8cbf7127f1 Date: 2013-04-04 23:09 +0200 http://bitbucket.org/pypy/pypy/changeset/8e8cbf7127f1/ Log: merge heads diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -377,7 +377,7 @@ self.maxcount = maxcount self.cache = OrderedDict() - def get(self, sql, row_factory): + def get(self, sql): try: stat = self.cache[sql] except KeyError: @@ -389,7 +389,6 @@ if stat._in_use: stat = Statement(self.connection, sql) self.cache[sql] = stat - stat._row_factory = row_factory return stat @@ -552,7 +551,7 @@ @_check_thread_wrap @_check_closed_wrap def __call__(self, sql): - return self._statement_cache.get(sql, self.row_factory) + return self._statement_cache.get(sql) def cursor(self, factory=None): self._check_thread() @@ -881,16 +880,96 @@ return func(self, *args, **kwargs) return wrapper + def __check_reset(self): + if self._reset: + raise InterfaceError( + "Cursor needed to be reset because of commit/rollback " + "and can no longer be fetched from.") + + def __build_row_cast_map(self): + if not self.__connection._detect_types: + return + self.__row_cast_map = [] + for i in xrange(_lib.sqlite3_column_count(self.__statement._statement)): + converter = None + + if self.__connection._detect_types & PARSE_COLNAMES: + colname = _lib.sqlite3_column_name(self.__statement._statement, i) + if colname: + colname = _ffi.string(colname).decode('utf-8') + type_start = -1 + key = None + for pos in range(len(colname)): + if colname[pos] == '[': + type_start = pos + 1 + elif colname[pos] == ']' and type_start != -1: + key = colname[type_start:pos] + converter = converters[key.upper()] + + if converter is None and self.__connection._detect_types & PARSE_DECLTYPES: + decltype = _lib.sqlite3_column_decltype(self.__statement._statement, i) + if decltype: + decltype = _ffi.string(decltype).decode('utf-8') + # if multiple words, use first, eg. + # "INTEGER NOT NULL" => "INTEGER" + decltype = decltype.split()[0] + if '(' in decltype: + decltype = decltype[:decltype.index('(')] + converter = converters.get(decltype.upper(), None) + + self.__row_cast_map.append(converter) + + def __fetch_one_row(self): + row = [] + num_cols = _lib.sqlite3_data_count(self.__statement._statement) + for i in xrange(num_cols): + if self.__connection._detect_types: + converter = self.__row_cast_map[i] + else: + converter = None + + if converter is not None: + blob = _lib.sqlite3_column_blob(self.__statement._statement, i) + if not blob: + val = None + else: + blob_len = _lib.sqlite3_column_bytes(self.__statement._statement, i) + val = _ffi.buffer(blob, blob_len)[:] + val = converter(val) + else: + typ = _lib.sqlite3_column_type(self.__statement._statement, i) + if typ == _lib.SQLITE_NULL: + val = None + elif typ == _lib.SQLITE_INTEGER: + val = _lib.sqlite3_column_int64(self.__statement._statement, i) + val = int(val) + elif typ == _lib.SQLITE_FLOAT: + val = _lib.sqlite3_column_double(self.__statement._statement, i) + elif typ == _lib.SQLITE_TEXT: + text = _lib.sqlite3_column_text(self.__statement._statement, i) + text_len = _lib.sqlite3_column_bytes(self.__statement._statement, i) + val = _ffi.buffer(text, text_len)[:] + val = self.__connection.text_factory(val) + elif typ == _lib.SQLITE_BLOB: + blob = _lib.sqlite3_column_blob(self.__statement._statement, i) + blob_len = _lib.sqlite3_column_bytes(self.__statement._statement, i) + val = _BLOB_TYPE(_ffi.buffer(blob, blob_len)) + row.append(val) + return tuple(row) + def __execute(self, multiple, sql, many_params): self.__locked = True + self._reset = False try: - self._reset = False + del self.__next_row + except AttributeError: + pass + try: if not isinstance(sql, basestring): raise ValueError("operation parameter must be str or unicode") self.__description = None self.__rowcount = -1 - self.__statement = self.__connection._statement_cache.get( - sql, self.row_factory) + self.__statement = self.__connection._statement_cache.get(sql) if self.__connection._isolation_level is not None: if self.__statement._kind == Statement._DDL: @@ -915,9 +994,9 @@ if self.__statement._kind == Statement._DML: self.__statement._reset() - if self.__statement._kind == Statement._DQL and ret == _lib.SQLITE_ROW: - self.__statement._build_row_cast_map() - self.__statement._readahead(self) + if ret == _lib.SQLITE_ROW: + self.__build_row_cast_map() + self.__next_row = self.__fetch_one_row() if self.__statement._kind == Statement._DML: if self.__rowcount == -1: @@ -978,12 +1057,6 @@ break return self - def __check_reset(self): - if self._reset: - raise self.__connection.InterfaceError( - "Cursor needed to be reset because of commit/rollback " - "and can no longer be fetched from.") - def __iter__(self): return self @@ -992,7 +1065,25 @@ self.__check_reset() if not self.__statement: raise StopIteration - return self.__statement._next(self) + + try: + next_row = self.__next_row + except AttributeError: + self.__statement._reset() + self.__statement = None + raise StopIteration + del self.__next_row + + if self.row_factory is not None: + next_row = self.row_factory(self, next_row) + + ret = _lib.sqlite3_step(self.__statement._statement) + if ret not in (_lib.SQLITE_DONE, _lib.SQLITE_ROW): + self.__statement._reset() + raise self.__connection._get_exception(ret) + elif ret == _lib.SQLITE_ROW: + self.__next_row = self.__fetch_one_row() + return next_row if sys.version_info[0] < 3: next = __next__ @@ -1049,7 +1140,6 @@ self.__con._remember_statement(self) self._in_use = False - self._row_factory = None if not isinstance(sql, basestring): raise Warning("SQL is of wrong type. Must be string or unicode.") @@ -1186,98 +1276,6 @@ else: raise ValueError("parameters are of unsupported type") - def _build_row_cast_map(self): - if not self.__con._detect_types: - return - self.__row_cast_map = [] - for i in xrange(_lib.sqlite3_column_count(self._statement)): - converter = None - - if self.__con._detect_types & PARSE_COLNAMES: - colname = _lib.sqlite3_column_name(self._statement, i) - if colname: - colname = _ffi.string(colname).decode('utf-8') - type_start = -1 - key = None - for pos in range(len(colname)): - if colname[pos] == '[': - type_start = pos + 1 - elif colname[pos] == ']' and type_start != -1: - key = colname[type_start:pos] - converter = converters[key.upper()] - - if converter is None and self.__con._detect_types & PARSE_DECLTYPES: - decltype = _lib.sqlite3_column_decltype(self._statement, i) - if decltype: - decltype = _ffi.string(decltype).decode('utf-8') - # if multiple words, use first, eg. - # "INTEGER NOT NULL" => "INTEGER" - decltype = decltype.split()[0] - if '(' in decltype: - decltype = decltype[:decltype.index('(')] - converter = converters.get(decltype.upper(), None) - - self.__row_cast_map.append(converter) - - def _readahead(self, cursor): - row = [] - num_cols = _lib.sqlite3_data_count(self._statement) - for i in xrange(num_cols): - if self.__con._detect_types: - converter = self.__row_cast_map[i] - else: - converter = None - - if converter is not None: - blob = _lib.sqlite3_column_blob(self._statement, i) - if not blob: - val = None - else: - blob_len = _lib.sqlite3_column_bytes(self._statement, i) - val = _ffi.buffer(blob, blob_len)[:] - val = converter(val) - else: - typ = _lib.sqlite3_column_type(self._statement, i) - if typ == _lib.SQLITE_NULL: - val = None - elif typ == _lib.SQLITE_INTEGER: - val = _lib.sqlite3_column_int64(self._statement, i) - val = int(val) - elif typ == _lib.SQLITE_FLOAT: - val = _lib.sqlite3_column_double(self._statement, i) - elif typ == _lib.SQLITE_TEXT: - text = _lib.sqlite3_column_text(self._statement, i) - text_len = _lib.sqlite3_column_bytes(self._statement, i) - val = _ffi.buffer(text, text_len)[:] - val = self.__con.text_factory(val) - elif typ == _lib.SQLITE_BLOB: - blob = _lib.sqlite3_column_blob(self._statement, i) - blob_len = _lib.sqlite3_column_bytes(self._statement, i) - val = _BLOB_TYPE(_ffi.buffer(blob, blob_len)) - row.append(val) - - row = tuple(row) - if self._row_factory is not None: - row = self._row_factory(cursor, row) - self._item = row - - def _next(self, cursor): - try: - item = self._item - except AttributeError: - self._reset() - raise StopIteration - del self._item - - ret = _lib.sqlite3_step(self._statement) - if ret not in (_lib.SQLITE_DONE, _lib.SQLITE_ROW): - _lib.sqlite3_reset(self._statement) - raise self.__con._get_exception(ret) - elif ret == _lib.SQLITE_ROW: - self._readahead(cursor) - - return item - def _get_description(self): if self._kind == Statement._DML: return None diff --git a/pypy/module/micronumpy/arrayimpl/concrete.py b/pypy/module/micronumpy/arrayimpl/concrete.py --- a/pypy/module/micronumpy/arrayimpl/concrete.py +++ b/pypy/module/micronumpy/arrayimpl/concrete.py @@ -281,7 +281,7 @@ def astype(self, space, dtype): new_arr = W_NDimArray.from_shape(self.get_shape(), dtype) - if dtype.is_str_or_unicode(): + if self.dtype.is_str_or_unicode() and not dtype.is_str_or_unicode(): raise OperationError(space.w_NotImplementedError, space.wrap( "astype(%s) not implemented yet" % self.dtype)) else: diff --git a/pypy/module/micronumpy/interp_support.py b/pypy/module/micronumpy/interp_support.py --- a/pypy/module/micronumpy/interp_support.py +++ b/pypy/module/micronumpy/interp_support.py @@ -15,7 +15,7 @@ items = [] num_items = 0 idx = 0 - + while (num_items < count or count == -1) and idx < len(s): nextidx = s.find(sep, idx) if nextidx < 0: @@ -45,7 +45,7 @@ items.append(val) num_items += 1 idx = nextidx + 1 - + if count > num_items: raise OperationError(space.w_ValueError, space.wrap( "string is smaller than requested size")) @@ -70,7 +70,7 @@ if count * itemsize > length: raise OperationError(space.w_ValueError, space.wrap( "string is smaller than requested size")) - + a = W_NDimArray.from_shape([count], dtype=dtype) loop.fromstring_loop(a, dtype, itemsize, s) return space.wrap(a) diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py --- a/pypy/module/micronumpy/test/test_numarray.py +++ b/pypy/module/micronumpy/test/test_numarray.py @@ -1487,14 +1487,14 @@ a = concatenate((['abcdef'], ['abc'])) assert a[0] == 'abcdef' assert str(a.dtype) == '|S6' - + def test_record_concatenate(self): # only an exact match can succeed from numpypy import zeros, concatenate a = concatenate((zeros((2,),dtype=[('x', int), ('y', float)]), zeros((2,),dtype=[('x', int), ('y', float)]))) assert a.shape == (4,) - exc = raises(TypeError, concatenate, + exc = raises(TypeError, concatenate, (zeros((2,), dtype=[('x', int), ('y', float)]), (zeros((2,), dtype=[('x', float), ('y', float)])))) assert str(exc.value).startswith('record type mismatch') @@ -1677,11 +1677,15 @@ a = array('x').astype('S3').dtype assert a.itemsize == 3 # scalar vs. array + a = array([1, 2, 3.14156]).astype('S3').dtype + assert a.itemsize == 3 + a = array(3.1415).astype('S3').dtype + assert a.itemsize == 3 try: - a = array([1, 2, 3.14156]).astype('S3').dtype - assert a.itemsize == 3 + a = array(['1', '2','3']).astype(float) + assert a[2] == 3.0 except NotImplementedError: - skip('astype("S3") not implemented for numeric arrays') + skip('astype("float") not implemented for str arrays') def test_base(self): from numpypy import array diff --git a/pypy/module/test_lib_pypy/test_sqlite3.py b/pypy/module/test_lib_pypy/test_sqlite3.py --- a/pypy/module/test_lib_pypy/test_sqlite3.py +++ b/pypy/module/test_lib_pypy/test_sqlite3.py @@ -193,3 +193,8 @@ con.commit() con.execute('BEGIN') con.commit() + +def test_row_factory_use(): + con = _sqlite3.connect(':memory:') + con.row_factory = 42 + con.execute('select 1') From noreply at buildbot.pypy.org Thu Apr 4 23:11:35 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Thu, 4 Apr 2013 23:11:35 +0200 (CEST) Subject: [pypy-commit] pypy default: use newlist_hint for fetching rows Message-ID: <20130404211135.C98B31C039A@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63025:47167fcc4f36 Date: 2013-04-04 17:10 -0400 http://bitbucket.org/pypy/pypy/changeset/47167fcc4f36/ Log: use newlist_hint for fetching rows diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -30,6 +30,11 @@ import sys import weakref from threading import _get_ident as _thread_get_ident +try: + from __pypy__ import newlist_hint +except ImportError: + assert '__pypy__' not in sys.builtin_module_names + newlist_hint = lambda sizehint: [] if sys.version_info[0] >= 3: StandardError = Exception @@ -920,8 +925,8 @@ self.__row_cast_map.append(converter) def __fetch_one_row(self): - row = [] num_cols = _lib.sqlite3_data_count(self.__statement._statement) + row = newlist_hint(num_cols) for i in xrange(num_cols): if self.__connection._detect_types: converter = self.__row_cast_map[i] From noreply at buildbot.pypy.org Thu Apr 4 23:11:37 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Thu, 4 Apr 2013 23:11:37 +0200 (CEST) Subject: [pypy-commit] pypy default: merge heads Message-ID: <20130404211137.17FBE1C039A@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63026:75eddd236125 Date: 2013-04-04 17:11 -0400 http://bitbucket.org/pypy/pypy/changeset/75eddd236125/ Log: merge heads diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py --- a/pypy/module/cpyext/api.py +++ b/pypy/module/cpyext/api.py @@ -554,8 +554,8 @@ from pypy.module.cpyext.pyobject import Reference # we hope that malloc removal removes the newtuple() that is # inserted exactly here by the varargs specializer + rffi.stackcounter.stacks_counter += 1 llop.gc_stack_bottom(lltype.Void) # marker for trackgcroot.py - rffi.stackcounter.stacks_counter += 1 retval = fatal_value boxed_args = () try: diff --git a/rpython/jit/backend/x86/test/test_zrpy_releasegil.py b/rpython/jit/backend/x86/test/test_zrpy_releasegil.py --- a/rpython/jit/backend/x86/test/test_zrpy_releasegil.py +++ b/rpython/jit/backend/x86/test/test_zrpy_releasegil.py @@ -68,10 +68,12 @@ c_qsort = rffi.llexternal('qsort', [rffi.VOIDP, rffi.SIZE_T, rffi.SIZE_T, CALLBACK], lltype.Void) # - def f42(): + def f42(n): length = len(glob.lst) raw = alloc1() fn = llhelper(CALLBACK, rffi._make_wrapper_for(CALLBACK, callback)) + if n & 1: # to create a loop and a bridge, and also + pass # to run the qsort() call in the blackhole interp c_qsort(rffi.cast(rffi.VOIDP, raw), rffi.cast(rffi.SIZE_T, 2), rffi.cast(rffi.SIZE_T, 8), fn) free1(raw) @@ -85,7 +87,7 @@ None, None, None, None, None, None) # def f(n, x, *args): - f42() + f42(n) n -= 1 return (n, x) + args return before, f, None diff --git a/rpython/memory/gctransform/asmgcroot.py b/rpython/memory/gctransform/asmgcroot.py --- a/rpython/memory/gctransform/asmgcroot.py +++ b/rpython/memory/gctransform/asmgcroot.py @@ -1,13 +1,15 @@ from rpython.flowspace.model import (Constant, Variable, Block, Link, - copygraph, SpaceOperation) + copygraph, SpaceOperation, checkgraph) from rpython.rlib.debug import ll_assert +from rpython.rlib.nonconst import NonConstant from rpython.rtyper.annlowlevel import llhelper from rpython.rtyper.lltypesystem import lltype, llmemory, rffi from rpython.rtyper.lltypesystem.lloperation import llop from rpython.memory.gctransform.framework import ( BaseFrameworkGCTransformer, BaseRootWalker) from rpython.rtyper.rbuiltin import gen_cast -from rpython.translator.unsimplify import copyvar +from rpython.translator.unsimplify import copyvar, varoftype +from rpython.translator.tool.cbuild import ExternalCompilationInfo import sys @@ -22,6 +24,7 @@ class AsmGcRootFrameworkGCTransformer(BaseFrameworkGCTransformer): _asmgcc_save_restore_arguments = None + _seen_gctransformer_hint_close_stack = None def push_roots(self, hop, keep_current_args=False): livevars = self.get_livevars_for_roots(hop, keep_current_args) @@ -57,10 +60,22 @@ def handle_call_with_close_stack(self, hop): fnptr = hop.spaceop.args[0].value + if self._seen_gctransformer_hint_close_stack is None: + self._seen_gctransformer_hint_close_stack = {} + if fnptr._obj.graph not in self._seen_gctransformer_hint_close_stack: + self._transform_hint_close_stack(fnptr) + self._seen_gctransformer_hint_close_stack[fnptr._obj.graph] = True + # + livevars = self.push_roots(hop) + self.default(hop) + self.pop_roots(hop, livevars) + + def _transform_hint_close_stack(self, fnptr): # We cannot easily pass variable amount of arguments of the call # across the call to the pypy_asm_stackwalk helper. So we store - # them away and restore them. We need to make a new graph - # that starts with restoring the arguments. + # them away and restore them. More precisely, we need to + # replace 'graph' with code that saves the arguments, and make + # a new graph that starts with restoring the arguments. if self._asmgcc_save_restore_arguments is None: self._asmgcc_save_restore_arguments = {} sradict = self._asmgcc_save_restore_arguments @@ -80,25 +95,52 @@ sradict[key] = Constant(p, lltype.Ptr(CONTAINER)) sra.append(sradict[key]) # - # store the value of the arguments - livevars = self.push_roots(hop) + # make a copy of the graph that will reload the values + graph = fnptr._obj.graph + graph2 = copygraph(graph) + # + # edit the original graph to only store the value of the arguments + block = Block(graph.startblock.inputargs) c_item0 = Constant('item0', lltype.Void) - for v_arg, c_p in zip(hop.spaceop.args[1:], sra): + assert len(block.inputargs) == len(sra) + for v_arg, c_p in zip(block.inputargs, sra): if isinstance(v_arg.concretetype, lltype.Ptr): - v_arg = hop.genop("cast_ptr_to_adr", [v_arg], - resulttype=llmemory.Address) - hop.genop("bare_setfield", [c_p, c_item0, v_arg]) + v_adr = varoftype(llmemory.Address) + block.operations.append( + SpaceOperation("cast_ptr_to_adr", [v_arg], v_adr)) + v_arg = v_adr + v_void = varoftype(lltype.Void) + block.operations.append( + SpaceOperation("bare_setfield", [c_p, c_item0, v_arg], v_void)) # - # make a copy of the graph that will reload the values - graph2 = copygraph(fnptr._obj.graph) + # call asm_stackwalk(graph2) + FUNC2 = lltype.FuncType([], FUNC1.RESULT) + fnptr2 = lltype.functionptr(FUNC2, + fnptr._obj._name + '_reload', + graph=graph2) + c_fnptr2 = Constant(fnptr2, lltype.Ptr(FUNC2)) + HELPERFUNC = lltype.FuncType([lltype.Ptr(FUNC2), + ASM_FRAMEDATA_HEAD_PTR], FUNC1.RESULT) + v_asm_stackwalk = varoftype(lltype.Ptr(HELPERFUNC), "asm_stackwalk") + block.operations.append( + SpaceOperation("cast_pointer", [c_asm_stackwalk], v_asm_stackwalk)) + v_result = varoftype(FUNC1.RESULT) + block.operations.append( + SpaceOperation("indirect_call", [v_asm_stackwalk, c_fnptr2, + c_gcrootanchor, + Constant(None, lltype.Void)], + v_result)) + block.closeblock(Link([v_result], graph.returnblock)) + graph.startblock = block + # + # edit the copy of the graph to reload the values block2 = graph2.startblock block1 = Block([]) reloadedvars = [] for v, c_p in zip(block2.inputargs, sra): v = copyvar(None, v) if isinstance(v.concretetype, lltype.Ptr): - w = Variable('tmp') - w.concretetype = llmemory.Address + w = varoftype(llmemory.Address) else: w = v block1.operations.append(SpaceOperation('getfield', @@ -109,21 +151,9 @@ reloadedvars.append(v) block1.closeblock(Link(reloadedvars, block2)) graph2.startblock = block1 - FUNC2 = lltype.FuncType([], FUNC1.RESULT) - fnptr2 = lltype.functionptr(FUNC2, - fnptr._obj._name + '_reload', - graph=graph2) - c_fnptr2 = Constant(fnptr2, lltype.Ptr(FUNC2)) - HELPERFUNC = lltype.FuncType([lltype.Ptr(FUNC2), - ASM_FRAMEDATA_HEAD_PTR], FUNC1.RESULT) # - v_asm_stackwalk = hop.genop("cast_pointer", [c_asm_stackwalk], - resulttype=lltype.Ptr(HELPERFUNC)) - hop.genop("indirect_call", - [v_asm_stackwalk, c_fnptr2, c_gcrootanchor, - Constant(None, lltype.Void)], - resultvar=hop.spaceop.result) - self.pop_roots(hop, livevars) + checkgraph(graph) + checkgraph(graph2) class AsmStackRootWalker(BaseRootWalker): @@ -284,6 +314,8 @@ stackscount += 1 # expected = rffi.stackcounter.stacks_counter + if NonConstant(0): + rffi.stackcounter.stacks_counter += 42 # hack to force it ll_assert(not (stackscount < expected), "non-closed stacks around") ll_assert(not (stackscount > expected), "stacks counter corruption?") lltype.free(otherframe, flavor='raw') @@ -681,13 +713,16 @@ gcrootanchor.next = gcrootanchor c_gcrootanchor = Constant(gcrootanchor, ASM_FRAMEDATA_HEAD_PTR) +eci = ExternalCompilationInfo(pre_include_bits=['#define PYPY_USE_ASMGCC']) + pypy_asm_stackwalk = rffi.llexternal('pypy_asm_stackwalk', [ASM_CALLBACK_PTR, ASM_FRAMEDATA_HEAD_PTR], lltype.Signed, sandboxsafe=True, _nowrapper=True, - random_effects_on_gcobjs=True) + random_effects_on_gcobjs=True, + compilation_info=eci) c_asm_stackwalk = Constant(pypy_asm_stackwalk, lltype.typeOf(pypy_asm_stackwalk)) diff --git a/rpython/translator/c/gcc/test/test_asmgcroot.py b/rpython/translator/c/gcc/test/test_asmgcroot.py --- a/rpython/translator/c/gcc/test/test_asmgcroot.py +++ b/rpython/translator/c/gcc/test/test_asmgcroot.py @@ -195,8 +195,8 @@ @entrypoint("x42", [lltype.Signed, lltype.Signed], c_name='callback') def mycallback(a, b): + rffi.stackcounter.stacks_counter += 1 llop.gc_stack_bottom(lltype.Void) - rffi.stackcounter.stacks_counter += 1 gc.collect() rffi.stackcounter.stacks_counter -= 1 return a + b diff --git a/rpython/translator/c/src/mem.c b/rpython/translator/c/src/mem.c --- a/rpython/translator/c/src/mem.c +++ b/rpython/translator/c/src/mem.c @@ -96,3 +96,27 @@ GC_set_warn_proc(mem_boehm_ignore); } #endif /* BOEHM GC */ + + +#ifdef RPY_ASSERT +# ifdef PYPY_USE_ASMGCC +# include "structdef.h" +# include "forwarddecl.h" +# endif +void pypy_check_stack_count(void) +{ +# ifdef PYPY_USE_ASMGCC + void *anchor = (void*)&pypy_g_ASM_FRAMEDATA_HEAD; + void *fd = ((void* *) (((char *)anchor) + sizeof(void*)))[0]; + long got = 0; + long stacks_counter = + pypy_g_rpython_rtyper_lltypesystem_rffi_StackCounter.sc_inst_stacks_counter; + while (fd != anchor) { + got += 1; + fd = ((void* *) (((char *)fd) + sizeof(void*)))[0]; + } + RPyAssert(got == stacks_counter - 1, + "bad stacks_counter or non-closed stacks around"); +# endif +} +#endif diff --git a/rpython/translator/c/src/mem.h b/rpython/translator/c/src/mem.h --- a/rpython/translator/c/src/mem.h +++ b/rpython/translator/c/src/mem.h @@ -195,24 +195,14 @@ "g" (v)) /* marker for trackgcroot.py, and inhibits tail calls */ -#define pypy_asm_stack_bottom() { asm volatile ("/* GC_STACK_BOTTOM */" : : : \ - "memory"); pypy_check_stack_count(); } +#define pypy_asm_stack_bottom() { asm volatile ("/* GC_STACK_BOTTOM */" : : : \ + "memory"); pypy_check_stack_count(); } +#ifdef RPY_ASSERT +void pypy_check_stack_count(void); +#else +static void pypy_check_stack_count(void) { } +#endif -static void pypy_check_stack_count(void) -{ -#ifdef RPY_ASSERT - void *anchor = (void*)&pypy_g_ASM_FRAMEDATA_HEAD; - void *fd = ((void* *) (((char *)anchor) + sizeof(void*)))[0]; - long got = 0; - long stacks_counter = - (&pypy_g_rpython_rtyper_lltypesystem_rffi_StackCounter)->sc_inst_stacks_counter; - while (fd != anchor) { - got += 1; - fd = ((void* *) (((char *)fd) + sizeof(void*)))[0]; - } - assert(got == stacks_counter - 1); -#endif -} #define OP_GC_ASMGCROOT_STATIC(i, r) r = \ i == 0 ? (void*)&__gcmapstart : \ From noreply at buildbot.pypy.org Thu Apr 4 23:23:01 2013 From: noreply at buildbot.pypy.org (fijal) Date: Thu, 4 Apr 2013 23:23:01 +0200 (CEST) Subject: [pypy-commit] pypy release-2.0-beta2: merge default Message-ID: <20130404212301.42E161C301F@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: release-2.0-beta2 Changeset: r63027:84dc290a5609 Date: 2013-04-04 23:22 +0200 http://bitbucket.org/pypy/pypy/changeset/84dc290a5609/ Log: merge default diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -30,6 +30,11 @@ import sys import weakref from threading import _get_ident as _thread_get_ident +try: + from __pypy__ import newlist_hint +except ImportError: + assert '__pypy__' not in sys.builtin_module_names + newlist_hint = lambda sizehint: [] if sys.version_info[0] >= 3: StandardError = Exception @@ -377,7 +382,7 @@ self.maxcount = maxcount self.cache = OrderedDict() - def get(self, sql, row_factory): + def get(self, sql): try: stat = self.cache[sql] except KeyError: @@ -385,10 +390,10 @@ self.cache[sql] = stat if len(self.cache) > self.maxcount: self.cache.popitem(0) - - if stat._in_use: - stat = Statement(self.connection, sql) - stat._row_factory = row_factory + else: + if stat._in_use: + stat = Statement(self.connection, sql) + self.cache[sql] = stat return stat @@ -551,7 +556,7 @@ @_check_thread_wrap @_check_closed_wrap def __call__(self, sql): - return self._statement_cache.get(sql, self.row_factory) + return self._statement_cache.get(sql) def cursor(self, factory=None): self._check_thread() @@ -855,10 +860,6 @@ self.__initialized = True - def __del__(self): - if self.__statement: - self.__statement._reset() - def close(self): self.__connection._check_thread() self.__connection._check_closed() @@ -884,16 +885,96 @@ return func(self, *args, **kwargs) return wrapper + def __check_reset(self): + if self._reset: + raise InterfaceError( + "Cursor needed to be reset because of commit/rollback " + "and can no longer be fetched from.") + + def __build_row_cast_map(self): + if not self.__connection._detect_types: + return + self.__row_cast_map = [] + for i in xrange(_lib.sqlite3_column_count(self.__statement._statement)): + converter = None + + if self.__connection._detect_types & PARSE_COLNAMES: + colname = _lib.sqlite3_column_name(self.__statement._statement, i) + if colname: + colname = _ffi.string(colname).decode('utf-8') + type_start = -1 + key = None + for pos in range(len(colname)): + if colname[pos] == '[': + type_start = pos + 1 + elif colname[pos] == ']' and type_start != -1: + key = colname[type_start:pos] + converter = converters[key.upper()] + + if converter is None and self.__connection._detect_types & PARSE_DECLTYPES: + decltype = _lib.sqlite3_column_decltype(self.__statement._statement, i) + if decltype: + decltype = _ffi.string(decltype).decode('utf-8') + # if multiple words, use first, eg. + # "INTEGER NOT NULL" => "INTEGER" + decltype = decltype.split()[0] + if '(' in decltype: + decltype = decltype[:decltype.index('(')] + converter = converters.get(decltype.upper(), None) + + self.__row_cast_map.append(converter) + + def __fetch_one_row(self): + num_cols = _lib.sqlite3_data_count(self.__statement._statement) + row = newlist_hint(num_cols) + for i in xrange(num_cols): + if self.__connection._detect_types: + converter = self.__row_cast_map[i] + else: + converter = None + + if converter is not None: + blob = _lib.sqlite3_column_blob(self.__statement._statement, i) + if not blob: + val = None + else: + blob_len = _lib.sqlite3_column_bytes(self.__statement._statement, i) + val = _ffi.buffer(blob, blob_len)[:] + val = converter(val) + else: + typ = _lib.sqlite3_column_type(self.__statement._statement, i) + if typ == _lib.SQLITE_NULL: + val = None + elif typ == _lib.SQLITE_INTEGER: + val = _lib.sqlite3_column_int64(self.__statement._statement, i) + val = int(val) + elif typ == _lib.SQLITE_FLOAT: + val = _lib.sqlite3_column_double(self.__statement._statement, i) + elif typ == _lib.SQLITE_TEXT: + text = _lib.sqlite3_column_text(self.__statement._statement, i) + text_len = _lib.sqlite3_column_bytes(self.__statement._statement, i) + val = _ffi.buffer(text, text_len)[:] + val = self.__connection.text_factory(val) + elif typ == _lib.SQLITE_BLOB: + blob = _lib.sqlite3_column_blob(self.__statement._statement, i) + blob_len = _lib.sqlite3_column_bytes(self.__statement._statement, i) + val = _BLOB_TYPE(_ffi.buffer(blob, blob_len)) + row.append(val) + return tuple(row) + def __execute(self, multiple, sql, many_params): self.__locked = True + self._reset = False try: - self._reset = False + del self.__next_row + except AttributeError: + pass + try: if not isinstance(sql, basestring): raise ValueError("operation parameter must be str or unicode") self.__description = None self.__rowcount = -1 - self.__statement = self.__connection._statement_cache.get( - sql, self.row_factory) + self.__statement = self.__connection._statement_cache.get(sql) if self.__connection._isolation_level is not None: if self.__statement._kind == Statement._DDL: @@ -918,9 +999,9 @@ if self.__statement._kind == Statement._DML: self.__statement._reset() - if self.__statement._kind == Statement._DQL and ret == _lib.SQLITE_ROW: - self.__statement._build_row_cast_map() - self.__statement._readahead(self) + if ret == _lib.SQLITE_ROW: + self.__build_row_cast_map() + self.__next_row = self.__fetch_one_row() if self.__statement._kind == Statement._DML: if self.__rowcount == -1: @@ -981,12 +1062,6 @@ break return self - def __check_reset(self): - if self._reset: - raise self.__connection.InterfaceError( - "Cursor needed to be reset because of commit/rollback " - "and can no longer be fetched from.") - def __iter__(self): return self @@ -995,7 +1070,25 @@ self.__check_reset() if not self.__statement: raise StopIteration - return self.__statement._next(self) + + try: + next_row = self.__next_row + except AttributeError: + self.__statement._reset() + self.__statement = None + raise StopIteration + del self.__next_row + + if self.row_factory is not None: + next_row = self.row_factory(self, next_row) + + ret = _lib.sqlite3_step(self.__statement._statement) + if ret not in (_lib.SQLITE_DONE, _lib.SQLITE_ROW): + self.__statement._reset() + raise self.__connection._get_exception(ret) + elif ret == _lib.SQLITE_ROW: + self.__next_row = self.__fetch_one_row() + return next_row if sys.version_info[0] < 3: next = __next__ @@ -1052,7 +1145,6 @@ self.__con._remember_statement(self) self._in_use = False - self._row_factory = None if not isinstance(sql, basestring): raise Warning("SQL is of wrong type. Must be string or unicode.") @@ -1189,98 +1281,6 @@ else: raise ValueError("parameters are of unsupported type") - def _build_row_cast_map(self): - if not self.__con._detect_types: - return - self.__row_cast_map = [] - for i in xrange(_lib.sqlite3_column_count(self._statement)): - converter = None - - if self.__con._detect_types & PARSE_COLNAMES: - colname = _lib.sqlite3_column_name(self._statement, i) - if colname: - colname = _ffi.string(colname).decode('utf-8') - type_start = -1 - key = None - for pos in range(len(colname)): - if colname[pos] == '[': - type_start = pos + 1 - elif colname[pos] == ']' and type_start != -1: - key = colname[type_start:pos] - converter = converters[key.upper()] - - if converter is None and self.__con._detect_types & PARSE_DECLTYPES: - decltype = _lib.sqlite3_column_decltype(self._statement, i) - if decltype: - decltype = _ffi.string(decltype).decode('utf-8') - # if multiple words, use first, eg. - # "INTEGER NOT NULL" => "INTEGER" - decltype = decltype.split()[0] - if '(' in decltype: - decltype = decltype[:decltype.index('(')] - converter = converters.get(decltype.upper(), None) - - self.__row_cast_map.append(converter) - - def _readahead(self, cursor): - row = [] - num_cols = _lib.sqlite3_data_count(self._statement) - for i in xrange(num_cols): - if self.__con._detect_types: - converter = self.__row_cast_map[i] - else: - converter = None - - if converter is not None: - blob = _lib.sqlite3_column_blob(self._statement, i) - if not blob: - val = None - else: - blob_len = _lib.sqlite3_column_bytes(self._statement, i) - val = _ffi.buffer(blob, blob_len)[:] - val = converter(val) - else: - typ = _lib.sqlite3_column_type(self._statement, i) - if typ == _lib.SQLITE_NULL: - val = None - elif typ == _lib.SQLITE_INTEGER: - val = _lib.sqlite3_column_int64(self._statement, i) - val = int(val) - elif typ == _lib.SQLITE_FLOAT: - val = _lib.sqlite3_column_double(self._statement, i) - elif typ == _lib.SQLITE_TEXT: - text = _lib.sqlite3_column_text(self._statement, i) - text_len = _lib.sqlite3_column_bytes(self._statement, i) - val = _ffi.buffer(text, text_len)[:] - val = self.__con.text_factory(val) - elif typ == _lib.SQLITE_BLOB: - blob = _lib.sqlite3_column_blob(self._statement, i) - blob_len = _lib.sqlite3_column_bytes(self._statement, i) - val = _BLOB_TYPE(_ffi.buffer(blob, blob_len)) - row.append(val) - - row = tuple(row) - if self._row_factory is not None: - row = self._row_factory(cursor, row) - self._item = row - - def _next(self, cursor): - try: - item = self._item - except AttributeError: - self._reset() - raise StopIteration - del self._item - - ret = _lib.sqlite3_step(self._statement) - if ret not in (_lib.SQLITE_DONE, _lib.SQLITE_ROW): - _lib.sqlite3_reset(self._statement) - raise self.__con._get_exception(ret) - elif ret == _lib.SQLITE_ROW: - self._readahead(cursor) - - return item - def _get_description(self): if self._kind == Statement._DML: return None diff --git a/lib_pypy/cffi/api.py b/lib_pypy/cffi/api.py --- a/lib_pypy/cffi/api.py +++ b/lib_pypy/cffi/api.py @@ -25,7 +25,6 @@ line = '' return '%s%s' % (line, self.args[0]) - class FFI(object): r''' The main top-level class that you instantiate once, or once per module. diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py --- a/pypy/module/cpyext/api.py +++ b/pypy/module/cpyext/api.py @@ -554,8 +554,8 @@ from pypy.module.cpyext.pyobject import Reference # we hope that malloc removal removes the newtuple() that is # inserted exactly here by the varargs specializer + rffi.stackcounter.stacks_counter += 1 llop.gc_stack_bottom(lltype.Void) # marker for trackgcroot.py - rffi.stackcounter.stacks_counter += 1 retval = fatal_value boxed_args = () try: diff --git a/pypy/module/micronumpy/arrayimpl/concrete.py b/pypy/module/micronumpy/arrayimpl/concrete.py --- a/pypy/module/micronumpy/arrayimpl/concrete.py +++ b/pypy/module/micronumpy/arrayimpl/concrete.py @@ -281,7 +281,7 @@ def astype(self, space, dtype): new_arr = W_NDimArray.from_shape(self.get_shape(), dtype) - if dtype.is_str_or_unicode(): + if self.dtype.is_str_or_unicode() and not dtype.is_str_or_unicode(): raise OperationError(space.w_NotImplementedError, space.wrap( "astype(%s) not implemented yet" % self.dtype)) else: diff --git a/pypy/module/micronumpy/interp_support.py b/pypy/module/micronumpy/interp_support.py --- a/pypy/module/micronumpy/interp_support.py +++ b/pypy/module/micronumpy/interp_support.py @@ -15,7 +15,7 @@ items = [] num_items = 0 idx = 0 - + while (num_items < count or count == -1) and idx < len(s): nextidx = s.find(sep, idx) if nextidx < 0: @@ -45,7 +45,7 @@ items.append(val) num_items += 1 idx = nextidx + 1 - + if count > num_items: raise OperationError(space.w_ValueError, space.wrap( "string is smaller than requested size")) @@ -70,7 +70,7 @@ if count * itemsize > length: raise OperationError(space.w_ValueError, space.wrap( "string is smaller than requested size")) - + a = W_NDimArray.from_shape([count], dtype=dtype) loop.fromstring_loop(a, dtype, itemsize, s) return space.wrap(a) diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py --- a/pypy/module/micronumpy/test/test_numarray.py +++ b/pypy/module/micronumpy/test/test_numarray.py @@ -1487,14 +1487,14 @@ a = concatenate((['abcdef'], ['abc'])) assert a[0] == 'abcdef' assert str(a.dtype) == '|S6' - + def test_record_concatenate(self): # only an exact match can succeed from numpypy import zeros, concatenate a = concatenate((zeros((2,),dtype=[('x', int), ('y', float)]), zeros((2,),dtype=[('x', int), ('y', float)]))) assert a.shape == (4,) - exc = raises(TypeError, concatenate, + exc = raises(TypeError, concatenate, (zeros((2,), dtype=[('x', int), ('y', float)]), (zeros((2,), dtype=[('x', float), ('y', float)])))) assert str(exc.value).startswith('record type mismatch') @@ -1677,11 +1677,15 @@ a = array('x').astype('S3').dtype assert a.itemsize == 3 # scalar vs. array + a = array([1, 2, 3.14156]).astype('S3').dtype + assert a.itemsize == 3 + a = array(3.1415).astype('S3').dtype + assert a.itemsize == 3 try: - a = array([1, 2, 3.14156]).astype('S3').dtype - assert a.itemsize == 3 + a = array(['1', '2','3']).astype(float) + assert a[2] == 3.0 except NotImplementedError: - skip('astype("S3") not implemented for numeric arrays') + skip('astype("float") not implemented for str arrays') def test_base(self): from numpypy import array diff --git a/pypy/module/test_lib_pypy/lextab.py b/pypy/module/test_lib_pypy/lextab.py deleted file mode 100644 --- a/pypy/module/test_lib_pypy/lextab.py +++ /dev/null @@ -1,9 +0,0 @@ -# pycparser.lextab.py. This file automatically created by PLY (version 3.4). Don't edit! -_tabversion = '3.4' -_lextokens = {'VOID': 1, 'LBRACKET': 1, 'WCHAR_CONST': 1, 'FLOAT_CONST': 1, 'MINUS': 1, 'RPAREN': 1, 'LONG': 1, 'PLUS': 1, 'ELLIPSIS': 1, 'GT': 1, 'GOTO': 1, 'ENUM': 1, 'PERIOD': 1, 'GE': 1, 'INT_CONST_DEC': 1, 'ARROW': 1, 'HEX_FLOAT_CONST': 1, 'DOUBLE': 1, 'MINUSEQUAL': 1, 'INT_CONST_OCT': 1, 'TIMESEQUAL': 1, 'OR': 1, 'SHORT': 1, 'RETURN': 1, 'RSHIFTEQUAL': 1, 'RESTRICT': 1, 'STATIC': 1, 'SIZEOF': 1, 'UNSIGNED': 1, 'UNION': 1, 'COLON': 1, 'WSTRING_LITERAL': 1, 'DIVIDE': 1, 'FOR': 1, 'PLUSPLUS': 1, 'EQUALS': 1, 'ELSE': 1, 'INLINE': 1, 'EQ': 1, 'AND': 1, 'TYPEID': 1, 'LBRACE': 1, 'PPHASH': 1, 'INT': 1, 'SIGNED': 1, 'CONTINUE': 1, 'NOT': 1, 'OREQUAL': 1, 'MOD': 1, 'RSHIFT': 1, 'DEFAULT': 1, 'CHAR': 1, 'WHILE': 1, 'DIVEQUAL': 1, 'EXTERN': 1, 'CASE': 1, 'LAND': 1, 'REGISTER': 1, 'MODEQUAL': 1, 'NE': 1, 'SWITCH': 1, 'INT_CONST_HEX': 1, '_COMPLEX': 1, 'PLUSEQUAL': 1, 'STRUCT': 1, 'CONDOP': 1, 'BREAK': 1, 'VOLATILE': 1, 'ANDEQUAL': 1, 'DO': 1, 'LNOT': 1, 'CONST': 1, 'LOR': 1, 'CHAR_CONST': 1, 'LSHIFT': 1, 'RBRACE': 1, '_BOOL': 1, 'LE': 1, 'SEMI': 1, 'LT': 1, 'COMMA': 1, 'TYPEDEF': 1, 'XOR': 1, 'AUTO': 1, 'TIMES': 1, 'LPAREN': 1, 'MINUSMINUS': 1, 'ID': 1, 'IF': 1, 'STRING_LITERAL': 1, 'FLOAT': 1, 'XOREQUAL': 1, 'LSHIFTEQUAL': 1, 'RBRACKET': 1} -_lexreflags = 0 -_lexliterals = '' -_lexstateinfo = {'ppline': 'exclusive', 'pppragma': 'exclusive', 'INITIAL': 'inclusive'} -_lexstatere = {'ppline': [('(?P"([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*")|(?P(0(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?)|([1-9][0-9]*(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?))|(?P\\n)|(?Pline)', [None, ('t_ppline_FILENAME', 'FILENAME'), None, None, None, None, None, None, ('t_ppline_LINE_NUMBER', 'LINE_NUMBER'), None, None, None, None, None, None, None, None, ('t_ppline_NEWLINE', 'NEWLINE'), ('t_ppline_PPLINE', 'PPLINE')])], 'pppragma': [('(?P\\n)|(?Ppragma)|(?P"([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*")|(?P[a-zA-Z_][0-9a-zA-Z_]*)', [None, ('t_pppragma_NEWLINE', 'NEWLINE'), ('t_pppragma_PPPRAGMA', 'PPPRAGMA'), ('t_pppragma_STR', 'STR'), None, None, None, None, None, None, ('t_pppragma_ID', 'ID')])], 'INITIAL': [('(?P[ \\t]*\\#)|(?P\\n+)|(?P((((([0-9]*\\.[0-9]+)|([0-9]+\\.))([eE][-+]?[0-9]+)?)|([0-9]+([eE][-+]?[0-9]+)))[FfLl]?))|(?P(0[xX]([0-9a-fA-F]+|((([0-9a-fA-F]+)?\\.[0-9a-fA-F]+)|([0-9a-fA-F]+\\.)))([pP][+-]?[0-9]+)[FfLl]?))|(?P0[xX][0-9a-fA-F]+(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?)|(?P0[0-7]*[89])|(?P0[0-7]*(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?)', [None, ('t_PPHASH', 'PPHASH'), ('t_NEWLINE', 'NEWLINE'), ('t_FLOAT_CONST', 'FLOAT_CONST'), None, None, None, None, None, None, None, None, None, ('t_HEX_FLOAT_CONST', 'HEX_FLOAT_CONST'), None, None, None, None, None, None, None, ('t_INT_CONST_HEX', 'INT_CONST_HEX'), None, None, None, ('t_BAD_CONST_OCT', 'BAD_CONST_OCT'), ('t_INT_CONST_OCT', 'INT_CONST_OCT')]), ('(?P(0(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?)|([1-9][0-9]*(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?))|(?P\'([^\'\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))\')|(?PL\'([^\'\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))\')|(?P(\'([^\'\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*\\n)|(\'([^\'\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*$))|(?P(\'([^\'\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))[^\'\n]+\')|(\'\')|(\'([\\\\][^a-zA-Z._~^!=&\\^\\-\\\\?\'"x0-7])[^\'\\n]*\'))|(?PL"([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*")|(?P"([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*([\\\\][^a-zA-Z._~^!=&\\^\\-\\\\?\'"x0-7])([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*")|(?P[a-zA-Z_][0-9a-zA-Z_]*)', [None, ('t_INT_CONST_DEC', 'INT_CONST_DEC'), None, None, None, None, None, None, None, None, ('t_CHAR_CONST', 'CHAR_CONST'), None, None, None, None, None, None, ('t_WCHAR_CONST', 'WCHAR_CONST'), None, None, None, None, None, None, ('t_UNMATCHED_QUOTE', 'UNMATCHED_QUOTE'), None, None, None, None, None, None, None, None, None, None, None, None, None, None, ('t_BAD_CHAR_CONST', 'BAD_CHAR_CONST'), None, None, None, None, None, None, None, None, None, None, ('t_WSTRING_LITERAL', 'WSTRING_LITERAL'), None, None, None, None, None, None, ('t_BAD_STRING_LITERAL', 'BAD_STRING_LITERAL'), None, None, None, None, None, None, None, None, None, None, None, None, None, ('t_ID', 'ID')]), ('(?P"([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*")|(?P\\.\\.\\.)|(?P\\+\\+)|(?P\\|\\|)|(?P\\^=)|(?P\\|=)|(?P<<=)|(?P>>=)|(?P\\+=)|(?P\\*=)|(?P\\+)|(?P%=)|(?P\\{)|(?P/=)|(?P\\])|(?P\\?)', [None, (None, 'STRING_LITERAL'), None, None, None, None, None, None, (None, 'ELLIPSIS'), (None, 'PLUSPLUS'), (None, 'LOR'), (None, 'XOREQUAL'), (None, 'OREQUAL'), (None, 'LSHIFTEQUAL'), (None, 'RSHIFTEQUAL'), (None, 'PLUSEQUAL'), (None, 'TIMESEQUAL'), (None, 'PLUS'), (None, 'MODEQUAL'), (None, 'LBRACE'), (None, 'DIVEQUAL'), (None, 'RBRACKET'), (None, 'CONDOP')]), ('(?P\\^)|(?P<<)|(?P<=)|(?P\\()|(?P->)|(?P==)|(?P\\})|(?P!=)|(?P--)|(?P\\|)|(?P\\*)|(?P\\[)|(?P>=)|(?P\\))|(?P&&)|(?P>>)|(?P&=)|(?P-=)|(?P\\.)|(?P=)|(?P<)|(?P,)|(?P/)|(?P&)|(?P%)|(?P;)|(?P-)|(?P>)|(?P:)|(?P~)|(?P!)', [None, (None, 'XOR'), (None, 'LSHIFT'), (None, 'LE'), (None, 'LPAREN'), (None, 'ARROW'), (None, 'EQ'), (None, 'RBRACE'), (None, 'NE'), (None, 'MINUSMINUS'), (None, 'OR'), (None, 'TIMES'), (None, 'LBRACKET'), (None, 'GE'), (None, 'RPAREN'), (None, 'LAND'), (None, 'RSHIFT'), (None, 'ANDEQUAL'), (None, 'MINUSEQUAL'), (None, 'PERIOD'), (None, 'EQUALS'), (None, 'LT'), (None, 'COMMA'), (None, 'DIVIDE'), (None, 'AND'), (None, 'MOD'), (None, 'SEMI'), (None, 'MINUS'), (None, 'GT'), (None, 'COLON'), (None, 'NOT'), (None, 'LNOT')])]} -_lexstateignore = {'ppline': ' \t', 'pppragma': ' \t<>.-{}();+-*/$%@&^~!?:,0123456789', 'INITIAL': ' \t'} -_lexstateerrorf = {'ppline': 't_ppline_error', 'pppragma': 't_pppragma_error', 'INITIAL': 't_error'} diff --git a/pypy/module/test_lib_pypy/pyrepl/test_bugs.py b/pypy/module/test_lib_pypy/pyrepl/test_bugs.py --- a/pypy/module/test_lib_pypy/pyrepl/test_bugs.py +++ b/pypy/module/test_lib_pypy/pyrepl/test_bugs.py @@ -24,7 +24,6 @@ # (applicable) bug reports import pytest -import os, sys class HistoricalTestReader(HistoricalReader, BaseTestReader): diff --git a/pypy/module/test_lib_pypy/pyrepl/test_readline.py b/pypy/module/test_lib_pypy/pyrepl/test_readline.py --- a/pypy/module/test_lib_pypy/pyrepl/test_readline.py +++ b/pypy/module/test_lib_pypy/pyrepl/test_readline.py @@ -1,5 +1,4 @@ import pytest -import os, sys @pytest.mark.skipif("os.name != 'posix' or 'darwin' in sys.platform") diff --git a/pypy/module/test_lib_pypy/test_sqlite3.py b/pypy/module/test_lib_pypy/test_sqlite3.py --- a/pypy/module/test_lib_pypy/test_sqlite3.py +++ b/pypy/module/test_lib_pypy/test_sqlite3.py @@ -96,18 +96,6 @@ pytest.raises(_sqlite3.ProgrammingError, "cur.executemany(1,2,3,4,5)") @pytest.mark.skipif("not hasattr(sys, 'pypy_translation_info')") -def test_cursor_del(): - con = _sqlite3.connect(':memory:') - cur = con.execute('select 1') - stmt = cur._Cursor__statement - cur.close() - cur = con.execute('select 1') - assert cur._Cursor__statement is stmt - del cur; import gc; gc.collect(); gc.collect() - cur = con.execute('select 1') - assert cur._Cursor__statement is stmt - - at pytest.mark.skipif("not hasattr(sys, 'pypy_translation_info')") def test_connection_del(tmpdir): """For issue1325.""" import os @@ -205,3 +193,8 @@ con.commit() con.execute('BEGIN') con.commit() + +def test_row_factory_use(): + con = _sqlite3.connect(':memory:') + con.row_factory = 42 + con.execute('select 1') diff --git a/pypy/module/test_lib_pypy/yacctab.py b/pypy/module/test_lib_pypy/yacctab.py deleted file mode 100644 --- a/pypy/module/test_lib_pypy/yacctab.py +++ /dev/null @@ -1,280 +0,0 @@ - -# yacctab.py -# This file is automatically generated. Do not edit. -_tabversion = '3.2' - -_lr_method = 'LALR' - -_lr_signature = '\x9er\xf1|P\xb6\xbb\x13\xed\xf52\xa1\xb1\xc3J\x12' - -_lr_action_items = {'VOID':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[6,6,-61,-72,-71,-58,-54,-55,-33,-29,-59,6,-34,-53,-68,-63,-52,6,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,6,-67,6,-70,-74,6,-57,-82,-249,-81,6,-107,-30,6,-97,-96,6,-45,-46,6,-109,6,6,6,6,-88,6,6,-36,6,-47,6,6,-83,-89,-250,6,-110,6,6,-111,-113,-112,6,6,-98,-37,-39,-42,-38,-40,6,-148,-147,-43,-149,-41,-85,-84,-90,6,6,-100,-99,-167,-166,6,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'LBRACKET':([1,2,3,5,6,9,10,13,14,17,18,19,21,23,24,25,27,28,29,32,33,35,37,39,40,42,43,44,45,46,49,50,51,52,54,55,56,58,59,63,64,66,67,68,69,76,77,83,87,89,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,129,138,139,149,151,152,153,154,155,174,178,180,184,185,191,195,216,217,218,223,224,231,235,262,264,265,273,274,277,281,285,286,314,318,319,323,329,350,351,357,359,360,361,362,366,369,371,387,388,389,390,400,401,409,],[-251,-61,-72,-71,-58,-54,-55,-59,-251,-53,-68,-63,-52,-56,-170,61,-66,-251,-69,-73,-108,-64,-60,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-249,-81,-49,61,-97,-96,-116,-114,-26,-25,-48,-51,-109,-251,-251,-233,-243,-247,-244,-241,-231,-232,182,-240,-220,-237,-245,-238,-242,-239,-230,221,-115,-117,-83,-250,-21,-80,-22,-79,-248,-246,-226,-227,-110,-111,221,-113,-112,221,312,221,-98,325,-237,-85,-84,-225,-224,-223,-234,221,221,312,-100,-99,-132,325,-221,-222,325,-146,-140,-142,-144,-135,325,-133,-141,-143,-145,-134,325,-228,-229,]),'WCHAR_CONST':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,96,-45,-219,96,-217,96,-216,96,-215,96,96,-214,-218,96,96,-250,96,-176,-179,-177,-173,-174,-178,-180,96,-182,-183,-175,-181,96,-215,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,-251,-39,-42,-38,96,-40,96,96,-148,-147,-43,-149,96,-41,96,96,96,-215,96,-12,96,96,-11,-167,-166,96,-164,96,96,-150,96,-163,-151,96,96,96,96,-251,96,-215,-251,-131,-162,-165,96,-154,96,-152,96,96,96,-153,96,96,96,-251,96,-158,-157,-155,96,96,96,-159,-156,96,-161,-160,]),'FLOAT_CONST':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,97,-45,-219,97,-217,97,-216,97,-215,97,97,-214,-218,97,97,-250,97,-176,-179,-177,-173,-174,-178,-180,97,-182,-183,-175,-181,97,-215,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,-251,-39,-42,-38,97,-40,97,97,-148,-147,-43,-149,97,-41,97,97,97,-215,97,-12,97,97,-11,-167,-166,97,-164,97,97,-150,97,-163,-151,97,97,97,97,-251,97,-215,-251,-131,-162,-165,97,-154,97,-152,97,97,97,-153,97,97,97,-251,97,-158,-157,-155,97,97,97,-159,-156,97,-161,-160,]),'MINUS':([55,61,75,91,92,93,94,95,96,97,98,99,100,101,102,104,105,106,108,109,110,111,112,113,114,115,116,117,118,119,120,123,124,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,180,182,183,184,186,187,188,189,190,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,262,270,273,274,277,281,282,283,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,349,350,351,352,353,356,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[-249,100,-45,-219,-206,-233,-243,-247,-244,-241,-231,100,-217,-232,-208,-187,100,-216,100,-240,-215,-220,100,100,-237,-245,-214,-238,200,-242,-239,-218,-230,100,100,-250,100,-176,-179,-177,-173,-174,-178,-180,100,-182,-183,-175,-181,-248,100,-212,-215,-246,-226,100,100,-227,100,-206,-211,100,-209,-210,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,-251,-39,-42,-38,100,-40,100,100,-148,-147,-43,-149,100,-41,-237,100,-225,-224,-223,-234,100,100,200,200,200,-192,200,200,200,-191,200,200,-189,-188,200,200,200,200,200,-190,-215,100,-12,100,100,-11,-167,-166,100,-164,100,100,-150,100,-163,-151,100,100,-213,-221,-222,100,100,-207,-251,100,-215,-251,-131,-162,-165,100,-154,100,-152,100,100,100,-153,100,100,100,-251,-228,100,-158,-157,-155,-229,100,100,100,-159,-156,100,-161,-160,]),'RPAREN':([1,2,3,5,6,9,10,13,14,17,18,19,21,23,24,25,27,28,29,32,33,35,37,39,40,42,43,44,45,46,49,50,51,52,53,54,56,58,59,62,63,64,66,67,68,69,76,77,83,87,89,92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,122,124,125,126,127,128,129,130,131,132,138,139,149,151,152,153,154,155,174,176,178,180,183,184,185,187,188,190,191,192,193,194,195,196,216,217,218,219,220,222,223,224,225,231,247,264,265,271,272,273,274,276,277,278,279,280,281,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,306,307,308,309,313,314,315,316,317,318,319,339,349,350,351,355,356,359,360,361,362,365,378,380,383,384,386,387,388,389,401,404,407,409,410,411,414,],[-251,-61,-72,-71,-58,-54,-55,-59,-251,-53,-68,-63,-52,-56,-170,-106,-66,-251,-69,-73,-108,-64,-60,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,83,-82,-81,-49,-107,-251,-97,-96,-116,-114,-26,-25,-48,-51,-109,-251,-251,-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,-185,-242,-239,-171,-230,216,-15,217,-120,-251,-16,-118,-124,-115,-117,-83,-250,-21,-80,-22,-79,-248,-212,-246,-226,277,-227,-110,-206,-211,-209,-111,281,283,-168,-251,-210,-113,-112,-251,-123,-2,-122,-139,-137,-1,-98,-14,-85,-84,-172,349,-225,-224,-235,-223,351,353,354,-234,-136,-251,-137,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-19,-20,359,360,-251,-138,-125,-119,-121,-100,-99,-13,-213,-221,-222,-169,-207,-146,-140,-142,-144,389,395,397,399,-236,-186,-141,-143,-145,-228,-251,412,-229,-251,415,418,]),'LONG':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[19,19,-61,-72,-71,-58,-54,-55,-33,-29,-59,19,-34,-53,-68,-63,-52,19,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,19,-67,19,-70,-74,19,-57,-82,-249,-81,19,-107,-30,19,-97,-96,19,-45,-46,19,-109,19,19,19,19,-88,19,19,-36,19,-47,19,19,-83,-89,-250,19,-110,19,19,-111,-113,-112,19,19,-98,-37,-39,-42,-38,-40,19,-148,-147,-43,-149,-41,-85,-84,-90,19,19,-100,-99,-167,-166,19,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'PLUS':([55,61,75,91,92,93,94,95,96,97,98,99,100,101,102,104,105,106,108,109,110,111,112,113,114,115,116,117,118,119,120,123,124,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,180,182,183,184,186,187,188,189,190,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,262,270,273,274,277,281,282,283,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,349,350,351,352,353,356,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[-249,106,-45,-219,-206,-233,-243,-247,-244,-241,-231,106,-217,-232,-208,-187,106,-216,106,-240,-215,-220,106,106,-237,-245,-214,-238,204,-242,-239,-218,-230,106,106,-250,106,-176,-179,-177,-173,-174,-178,-180,106,-182,-183,-175,-181,-248,106,-212,-215,-246,-226,106,106,-227,106,-206,-211,106,-209,-210,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,-251,-39,-42,-38,106,-40,106,106,-148,-147,-43,-149,106,-41,-237,106,-225,-224,-223,-234,106,106,204,204,204,-192,204,204,204,-191,204,204,-189,-188,204,204,204,204,204,-190,-215,106,-12,106,106,-11,-167,-166,106,-164,106,106,-150,106,-163,-151,106,106,-213,-221,-222,106,106,-207,-251,106,-215,-251,-131,-162,-165,106,-154,106,-152,106,106,106,-153,106,106,106,-251,-228,106,-158,-157,-155,-229,106,106,106,-159,-156,106,-161,-160,]),'ELLIPSIS':([227,],[316,]),'GT':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,205,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,205,-194,-192,-196,205,-195,-191,-198,205,-189,-188,-197,205,205,205,205,-190,-213,-221,-222,-207,-228,-229,]),'GOTO':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,240,-250,-39,-42,-38,-40,240,-148,-147,-43,-149,240,-41,-167,-166,-164,240,-150,-163,-151,240,-162,-165,-154,240,-152,240,-153,240,240,-158,-157,-155,240,240,-159,-156,240,-161,-160,]),'ENUM':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[26,26,-61,-72,-71,-58,-54,-55,-33,-29,-59,26,-34,-53,-68,-63,-52,26,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,26,-67,26,-70,-74,26,-57,-82,-249,-81,26,-107,-30,26,-97,-96,26,-45,-46,26,-109,26,26,26,26,-88,26,26,-36,26,-47,26,26,-83,-89,-250,26,-110,26,26,-111,-113,-112,26,26,-98,-37,-39,-42,-38,-40,26,-148,-147,-43,-149,-41,-85,-84,-90,26,26,-100,-99,-167,-166,26,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'PERIOD':([55,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,178,180,184,235,262,273,274,277,281,323,329,350,351,357,366,369,371,390,400,401,409,],[-249,-233,-243,-247,-244,-241,-231,-232,181,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-246,-226,-227,324,-237,-225,-224,-223,-234,-132,324,-221,-222,324,-135,324,-133,-134,324,-228,-229,]),'GE':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,209,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,209,-194,-192,-196,209,-195,-191,-198,209,-189,-188,-197,209,209,209,209,-190,-213,-221,-222,-207,-228,-229,]),'INT_CONST_DEC':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,117,-45,-219,117,-217,117,-216,117,-215,117,117,-214,-218,117,117,-250,117,-176,-179,-177,-173,-174,-178,-180,117,-182,-183,-175,-181,117,-215,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,-251,-39,-42,-38,117,-40,117,117,-148,-147,-43,-149,117,-41,117,117,117,-215,117,-12,117,117,-11,-167,-166,117,-164,117,117,-150,117,-163,-151,117,117,117,117,-251,117,-215,-251,-131,-162,-165,117,-154,117,-152,117,117,117,-153,117,117,117,-251,117,-158,-157,-155,117,117,117,-159,-156,117,-161,-160,]),'ARROW':([93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,178,180,184,262,273,274,277,281,350,351,401,409,],[-233,-243,-247,-244,-241,-231,-232,179,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-246,-226,-227,-237,-225,-224,-223,-234,-221,-222,-228,-229,]),'HEX_FLOAT_CONST':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,119,-45,-219,119,-217,119,-216,119,-215,119,119,-214,-218,119,119,-250,119,-176,-179,-177,-173,-174,-178,-180,119,-182,-183,-175,-181,119,-215,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,-251,-39,-42,-38,119,-40,119,119,-148,-147,-43,-149,119,-41,119,119,119,-215,119,-12,119,119,-11,-167,-166,119,-164,119,119,-150,119,-163,-151,119,119,119,119,-251,119,-215,-251,-131,-162,-165,119,-154,119,-152,119,119,119,-153,119,119,119,-251,119,-158,-157,-155,119,119,119,-159,-156,119,-161,-160,]),'DOUBLE':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[40,40,-61,-72,-71,-58,-54,-55,-33,-29,-59,40,-34,-53,-68,-63,-52,40,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,40,-67,40,-70,-74,40,-57,-82,-249,-81,40,-107,-30,40,-97,-96,40,-45,-46,40,-109,40,40,40,40,-88,40,40,-36,40,-47,40,40,-83,-89,-250,40,-110,40,40,-111,-113,-112,40,40,-98,-37,-39,-42,-38,-40,40,-148,-147,-43,-149,-41,-85,-84,-90,40,40,-100,-99,-167,-166,40,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'MINUSEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[163,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'INT_CONST_OCT':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,120,-45,-219,120,-217,120,-216,120,-215,120,120,-214,-218,120,120,-250,120,-176,-179,-177,-173,-174,-178,-180,120,-182,-183,-175,-181,120,-215,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,-251,-39,-42,-38,120,-40,120,120,-148,-147,-43,-149,120,-41,120,120,120,-215,120,-12,120,120,-11,-167,-166,120,-164,120,120,-150,120,-163,-151,120,120,120,120,-251,120,-215,-251,-131,-162,-165,120,-154,120,-152,120,120,120,-153,120,120,120,-251,120,-158,-157,-155,120,120,120,-159,-156,120,-161,-160,]),'TIMESEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[172,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'OR':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,214,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,214,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,214,-199,-201,-202,-190,-213,-221,-222,-207,-228,-229,]),'SHORT':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[2,2,-61,-72,-71,-58,-54,-55,-33,-29,-59,2,-34,-53,-68,-63,-52,2,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,2,-67,2,-70,-74,2,-57,-82,-249,-81,2,-107,-30,2,-97,-96,2,-45,-46,2,-109,2,2,2,2,-88,2,2,-36,2,-47,2,2,-83,-89,-250,2,-110,2,2,-111,-113,-112,2,2,-98,-37,-39,-42,-38,-40,2,-148,-147,-43,-149,-41,-85,-84,-90,2,2,-100,-99,-167,-166,2,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'RETURN':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,243,-250,-39,-42,-38,-40,243,-148,-147,-43,-149,243,-41,-167,-166,-164,243,-150,-163,-151,243,-162,-165,-154,243,-152,243,-153,243,243,-158,-157,-155,243,243,-159,-156,243,-161,-160,]),'RSHIFTEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[173,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'RESTRICT':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,28,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,66,68,73,75,80,82,83,84,85,86,87,88,89,112,139,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[32,32,-61,-72,-71,-58,-54,-55,-33,-29,-59,32,-34,-53,-68,-63,-52,32,-56,-170,-106,-66,32,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,32,-67,32,-70,-74,32,-57,-82,-249,-81,32,-107,-30,32,-97,-96,-116,32,32,-45,-46,32,-109,32,32,32,32,-88,32,32,-117,-36,32,-47,32,32,-83,-89,-250,32,-110,32,32,-111,-113,-112,32,32,-98,-37,-39,-42,-38,-40,32,-148,-147,-43,-149,-41,-85,-84,-90,32,32,-100,-99,-167,-166,32,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'STATIC':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[9,9,-61,-72,-71,-58,-54,-55,-33,-29,-59,9,-34,-53,-68,-63,-52,9,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,9,-67,9,-70,-74,9,-57,-82,-249,-81,-107,-30,9,-97,-96,9,-45,-46,9,-109,-36,9,-47,-83,-250,-110,-111,-113,-112,9,9,-98,-37,-39,-42,-38,-40,9,-148,-147,-43,-149,-41,-85,-84,9,9,-100,-99,-167,-166,9,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'SIZEOF':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,99,-45,-219,99,-217,99,-216,99,-215,99,99,-214,-218,99,99,-250,99,-176,-179,-177,-173,-174,-178,-180,99,-182,-183,-175,-181,99,-215,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,-251,-39,-42,-38,99,-40,99,99,-148,-147,-43,-149,99,-41,99,99,99,-215,99,-12,99,99,-11,-167,-166,99,-164,99,99,-150,99,-163,-151,99,99,99,99,-251,99,-215,-251,-131,-162,-165,99,-154,99,-152,99,99,99,-153,99,99,99,-251,99,-158,-157,-155,99,99,99,-159,-156,99,-161,-160,]),'UNSIGNED':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[18,18,-61,-72,-71,-58,-54,-55,-33,-29,-59,18,-34,-53,-68,-63,-52,18,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,18,-67,18,-70,-74,18,-57,-82,-249,-81,18,-107,-30,18,-97,-96,18,-45,-46,18,-109,18,18,18,18,-88,18,18,-36,18,-47,18,18,-83,-89,-250,18,-110,18,18,-111,-113,-112,18,18,-98,-37,-39,-42,-38,-40,18,-148,-147,-43,-149,-41,-85,-84,-90,18,18,-100,-99,-167,-166,18,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'UNION':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[20,20,-61,-72,-71,-58,-54,-55,-33,-29,-59,20,-34,-53,-68,-63,-52,20,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,20,-67,20,-70,-74,20,-57,-82,-249,-81,20,-107,-30,20,-97,-96,20,-45,-46,20,-109,20,20,20,20,-88,20,20,-36,20,-47,20,20,-83,-89,-250,20,-110,20,20,-111,-113,-112,20,20,-98,-37,-39,-42,-38,-40,20,-148,-147,-43,-149,-41,-85,-84,-90,20,20,-100,-99,-167,-166,20,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'COLON':([2,3,5,6,13,18,19,24,25,27,29,32,33,35,37,39,40,43,45,46,54,56,59,63,64,83,87,89,90,92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,122,124,149,151,152,153,154,155,161,174,176,178,180,184,185,187,188,190,191,194,196,216,217,231,248,262,264,265,267,268,271,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,318,319,338,349,350,351,355,356,386,401,409,],[-61,-72,-71,-58,-59,-68,-63,-170,-106,-66,-69,-73,-108,-64,-60,-62,-65,-67,-70,-74,-82,-81,-107,-97,-96,-109,-251,-251,156,-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,-185,-242,-239,-171,-230,-83,-250,-21,-80,-22,-79,270,-248,-212,-246,-226,-227,-110,-206,-211,-209,-111,-168,-210,-113,-112,-98,336,345,-85,-84,-184,156,-172,-225,-224,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,358,-202,-190,-100,-99,379,-213,-221,-222,-169,-207,-186,-228,-229,]),'$end':([0,8,11,12,15,22,31,36,38,47,60,75,144,151,237,344,],[-251,0,-33,-29,-34,-27,-32,-31,-35,-28,-30,-45,-36,-250,-37,-151,]),'WSTRING_LITERAL':([55,61,75,91,93,95,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,95,-45,-219,174,-247,95,-217,95,-216,95,-215,95,95,-214,-218,95,95,-250,95,-176,-179,-177,-173,-174,-178,-180,95,-182,-183,-175,-181,-248,95,-215,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,-251,-39,-42,-38,95,-40,95,95,-148,-147,-43,-149,95,-41,95,95,95,-215,95,-12,95,95,-11,-167,-166,95,-164,95,95,-150,95,-163,-151,95,95,95,95,-251,95,-215,-251,-131,-162,-165,95,-154,95,-152,95,95,95,-153,95,95,95,-251,95,-158,-157,-155,95,95,95,-159,-156,95,-161,-160,]),'DIVIDE':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,207,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,207,207,207,207,207,207,207,207,207,207,-189,-188,207,207,207,207,207,-190,-213,-221,-222,-207,-228,-229,]),'FOR':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,245,-250,-39,-42,-38,-40,245,-148,-147,-43,-149,245,-41,-167,-166,-164,245,-150,-163,-151,245,-162,-165,-154,245,-152,245,-153,245,245,-158,-157,-155,245,245,-159,-156,245,-161,-160,]),'PLUSPLUS':([55,61,75,91,93,94,95,96,97,98,99,100,101,102,105,106,108,109,110,111,112,113,114,115,116,117,119,120,123,124,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,177,178,180,182,183,184,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,262,270,273,274,277,281,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,350,351,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[-249,108,-45,-219,-233,-243,-247,-244,-241,-231,108,-217,-232,180,108,-216,108,-240,-215,-220,108,108,-237,-245,-214,-238,-242,-239,-218,-230,108,108,-250,108,-176,-179,-177,-173,-174,-178,-180,108,-182,-183,-175,-181,-248,108,-215,-246,-226,108,108,-227,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,-251,-39,-42,-38,108,-40,108,108,-148,-147,-43,-149,108,-41,-237,108,-225,-224,-223,-234,108,108,-215,108,-12,108,108,-11,-167,-166,108,-164,108,108,-150,108,-163,-151,108,108,-221,-222,108,108,-251,108,-215,-251,-131,-162,-165,108,-154,108,-152,108,108,108,-153,108,108,108,-251,-228,108,-158,-157,-155,-229,108,108,108,-159,-156,108,-161,-160,]),'EQUALS':([25,33,59,73,83,92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,137,143,151,174,176,178,180,184,185,187,188,190,191,196,216,217,262,273,274,277,281,323,329,349,350,351,356,366,371,390,401,409,],[-106,-108,-107,141,-109,165,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,232,141,-250,-248,-212,-246,-226,-227,-110,-206,-211,-209,-111,-210,-113,-112,-237,-225,-224,-223,-234,-132,372,-213,-221,-222,-207,-135,-133,-134,-228,-229,]),'ELSE':([151,238,239,242,244,255,260,331,332,335,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[-250,-39,-42,-38,-40,-43,-41,-167,-166,-164,-163,-151,-162,-165,-154,-152,-153,-158,-157,413,-159,-156,-161,-160,]),'ANDEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[170,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'EQ':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,211,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,211,-194,-192,-196,-200,-195,-191,-198,211,-189,-188,-197,211,-199,211,211,-190,-213,-221,-222,-207,-228,-229,]),'AND':([55,61,75,91,92,93,94,95,96,97,98,99,100,101,102,104,105,106,108,109,110,111,112,113,114,115,116,117,118,119,120,123,124,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,180,182,183,184,186,187,188,189,190,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,262,270,273,274,277,281,282,283,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,349,350,351,352,353,356,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[-249,116,-45,-219,-206,-233,-243,-247,-244,-241,-231,116,-217,-232,-208,-187,116,-216,116,-240,-215,-220,116,116,-237,-245,-214,-238,212,-242,-239,-218,-230,116,116,-250,116,-176,-179,-177,-173,-174,-178,-180,116,-182,-183,-175,-181,-248,116,-212,-215,-246,-226,116,116,-227,116,-206,-211,116,-209,-210,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,-251,-39,-42,-38,116,-40,116,116,-148,-147,-43,-149,116,-41,-237,116,-225,-224,-223,-234,116,116,-193,212,-194,-192,-196,-200,-195,-191,-198,212,-189,-188,-197,212,-199,-201,212,-190,-215,116,-12,116,116,-11,-167,-166,116,-164,116,116,-150,116,-163,-151,116,116,-213,-221,-222,116,116,-207,-251,116,-215,-251,-131,-162,-165,116,-154,116,-152,116,116,116,-153,116,116,116,-251,-228,116,-158,-157,-155,-229,116,116,116,-159,-156,116,-161,-160,]),'TYPEID':([0,1,2,3,5,6,7,9,10,11,12,13,14,15,17,18,19,20,21,22,23,24,25,26,27,29,31,32,33,34,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[24,24,-61,-72,-71,-58,54,-54,-55,-33,-29,-59,24,-34,-53,-68,-63,-87,-52,24,-56,-170,-106,63,-66,-69,-32,-73,-108,-86,-64,-31,-60,-35,-62,-65,24,-67,24,-70,-74,24,-57,-82,-249,-81,24,-107,-30,24,-97,-96,24,-45,-46,24,-109,24,24,24,24,-88,24,24,-36,24,-47,24,24,-83,-89,-250,24,-110,24,24,-111,-113,-112,24,24,-98,-37,-39,-42,-38,-40,24,-148,-147,-43,-149,-41,-85,-84,-90,24,24,-100,-99,-167,-166,24,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'LBRACE':([7,20,25,26,33,34,48,54,55,56,59,63,64,73,75,78,80,81,82,83,141,142,145,146,151,185,191,216,217,235,238,239,242,244,251,253,254,255,257,259,260,283,322,326,327,331,332,335,336,340,342,344,345,349,353,354,357,369,372,373,374,377,379,382,391,395,396,397,399,400,405,406,408,413,415,416,417,418,419,420,],[55,-87,-106,55,-108,-86,-251,55,-249,55,-107,55,55,-251,-45,-7,-46,55,-8,-109,55,55,55,-47,-250,-110,-111,-113,-112,-251,-39,-42,-38,-40,55,-148,-147,-43,-149,55,-41,55,-12,55,-11,-167,-166,-164,55,-150,-163,-151,55,55,55,55,-251,-251,-131,-162,-165,-154,55,-152,55,55,-153,55,55,-251,-158,-157,-155,55,55,-159,-156,55,-161,-160,]),'PPHASH':([0,11,12,15,22,31,36,38,60,75,144,151,237,344,],[38,-33,-29,-34,38,-32,-31,-35,-30,-45,-36,-250,-37,-151,]),'INT':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[39,39,-61,-72,-71,-58,-54,-55,-33,-29,-59,39,-34,-53,-68,-63,-52,39,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,39,-67,39,-70,-74,39,-57,-82,-249,-81,39,-107,-30,39,-97,-96,39,-45,-46,39,-109,39,39,39,39,-88,39,39,-36,39,-47,39,39,-83,-89,-250,39,-110,39,39,-111,-113,-112,39,39,-98,-37,-39,-42,-38,-40,39,-148,-147,-43,-149,-41,-85,-84,-90,39,39,-100,-99,-167,-166,39,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'SIGNED':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[43,43,-61,-72,-71,-58,-54,-55,-33,-29,-59,43,-34,-53,-68,-63,-52,43,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,43,-67,43,-70,-74,43,-57,-82,-249,-81,43,-107,-30,43,-97,-96,43,-45,-46,43,-109,43,43,43,43,-88,43,43,-36,43,-47,43,43,-83,-89,-250,43,-110,43,43,-111,-113,-112,43,43,-98,-37,-39,-42,-38,-40,43,-148,-147,-43,-149,-41,-85,-84,-90,43,43,-100,-99,-167,-166,43,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'CONTINUE':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,246,-250,-39,-42,-38,-40,246,-148,-147,-43,-149,246,-41,-167,-166,-164,246,-150,-163,-151,246,-162,-165,-154,246,-152,246,-153,246,246,-158,-157,-155,246,246,-159,-156,246,-161,-160,]),'NOT':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,123,-45,-219,123,-217,123,-216,123,-215,123,123,-214,-218,123,123,-250,123,-176,-179,-177,-173,-174,-178,-180,123,-182,-183,-175,-181,123,-215,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,-251,-39,-42,-38,123,-40,123,123,-148,-147,-43,-149,123,-41,123,123,123,-215,123,-12,123,123,-11,-167,-166,123,-164,123,123,-150,123,-163,-151,123,123,123,123,-251,123,-215,-251,-131,-162,-165,123,-154,123,-152,123,123,123,-153,123,123,123,-251,123,-158,-157,-155,123,123,123,-159,-156,123,-161,-160,]),'OREQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[171,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'MOD':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,215,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,215,215,215,215,215,215,215,215,215,215,-189,-188,215,215,215,215,215,-190,-213,-221,-222,-207,-228,-229,]),'RSHIFT':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,197,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,197,-194,-192,197,197,197,-191,197,197,-189,-188,197,197,197,197,197,-190,-213,-221,-222,-207,-228,-229,]),'DEFAULT':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,248,-250,-39,-42,-38,-40,248,-148,-147,-43,-149,248,-41,-167,-166,-164,248,-150,-163,-151,248,-162,-165,-154,248,-152,248,-153,248,248,-158,-157,-155,248,248,-159,-156,248,-161,-160,]),'CHAR':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[37,37,-61,-72,-71,-58,-54,-55,-33,-29,-59,37,-34,-53,-68,-63,-52,37,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,37,-67,37,-70,-74,37,-57,-82,-249,-81,37,-107,-30,37,-97,-96,37,-45,-46,37,-109,37,37,37,37,-88,37,37,-36,37,-47,37,37,-83,-89,-250,37,-110,37,37,-111,-113,-112,37,37,-98,-37,-39,-42,-38,-40,37,-148,-147,-43,-149,-41,-85,-84,-90,37,37,-100,-99,-167,-166,37,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'WHILE':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,343,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,249,-250,-39,-42,-38,-40,249,-148,-147,-43,-149,249,-41,-167,-166,-164,249,-150,-163,381,-151,249,-162,-165,-154,249,-152,249,-153,249,249,-158,-157,-155,249,249,-159,-156,249,-161,-160,]),'DIVEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[162,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'EXTERN':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[10,10,-61,-72,-71,-58,-54,-55,-33,-29,-59,10,-34,-53,-68,-63,-52,10,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,10,-67,10,-70,-74,10,-57,-82,-249,-81,-107,-30,10,-97,-96,10,-45,-46,10,-109,-36,10,-47,-83,-250,-110,-111,-113,-112,10,10,-98,-37,-39,-42,-38,-40,10,-148,-147,-43,-149,-41,-85,-84,10,10,-100,-99,-167,-166,10,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'CASE':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,250,-250,-39,-42,-38,-40,250,-148,-147,-43,-149,250,-41,-167,-166,-164,250,-150,-163,-151,250,-162,-165,-154,250,-152,250,-153,250,250,-158,-157,-155,250,250,-159,-156,250,-161,-160,]),'LAND':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,210,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,210,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-213,-221,-222,-207,-228,-229,]),'REGISTER':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[17,17,-61,-72,-71,-58,-54,-55,-33,-29,-59,17,-34,-53,-68,-63,-52,17,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,17,-67,17,-70,-74,17,-57,-82,-249,-81,-107,-30,17,-97,-96,17,-45,-46,17,-109,-36,17,-47,-83,-250,-110,-111,-113,-112,17,17,-98,-37,-39,-42,-38,-40,17,-148,-147,-43,-149,-41,-85,-84,17,17,-100,-99,-167,-166,17,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'MODEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[164,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'NE':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,202,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,202,-194,-192,-196,-200,-195,-191,-198,202,-189,-188,-197,202,-199,202,202,-190,-213,-221,-222,-207,-228,-229,]),'SWITCH':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,252,-250,-39,-42,-38,-40,252,-148,-147,-43,-149,252,-41,-167,-166,-164,252,-150,-163,-151,252,-162,-165,-154,252,-152,252,-153,252,252,-158,-157,-155,252,252,-159,-156,252,-161,-160,]),'INT_CONST_HEX':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,109,-45,-219,109,-217,109,-216,109,-215,109,109,-214,-218,109,109,-250,109,-176,-179,-177,-173,-174,-178,-180,109,-182,-183,-175,-181,109,-215,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,-251,-39,-42,-38,109,-40,109,109,-148,-147,-43,-149,109,-41,109,109,109,-215,109,-12,109,109,-11,-167,-166,109,-164,109,109,-150,109,-163,-151,109,109,109,109,-251,109,-215,-251,-131,-162,-165,109,-154,109,-152,109,109,109,-153,109,109,109,-251,109,-158,-157,-155,109,109,109,-159,-156,109,-161,-160,]),'_COMPLEX':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[27,27,-61,-72,-71,-58,-54,-55,-33,-29,-59,27,-34,-53,-68,-63,-52,27,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,27,-67,27,-70,-74,27,-57,-82,-249,-81,27,-107,-30,27,-97,-96,27,-45,-46,27,-109,27,27,27,27,-88,27,27,-36,27,-47,27,27,-83,-89,-250,27,-110,27,27,-111,-113,-112,27,27,-98,-37,-39,-42,-38,-40,27,-148,-147,-43,-149,-41,-85,-84,-90,27,27,-100,-99,-167,-166,27,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'PLUSEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[167,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'STRUCT':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[34,34,-61,-72,-71,-58,-54,-55,-33,-29,-59,34,-34,-53,-68,-63,-52,34,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,34,-67,34,-70,-74,34,-57,-82,-249,-81,34,-107,-30,34,-97,-96,34,-45,-46,34,-109,34,34,34,34,-88,34,34,-36,34,-47,34,34,-83,-89,-250,34,-110,34,34,-111,-113,-112,34,34,-98,-37,-39,-42,-38,-40,34,-148,-147,-43,-149,-41,-85,-84,-90,34,34,-100,-99,-167,-166,34,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'CONDOP':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,213,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-213,-221,-222,-207,-228,-229,]),'BREAK':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,256,-250,-39,-42,-38,-40,256,-148,-147,-43,-149,256,-41,-167,-166,-164,256,-150,-163,-151,256,-162,-165,-154,256,-152,256,-153,256,256,-158,-157,-155,256,256,-159,-156,256,-161,-160,]),'VOLATILE':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,28,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,66,68,73,75,80,82,83,84,85,86,87,88,89,112,139,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[46,46,-61,-72,-71,-58,-54,-55,-33,-29,-59,46,-34,-53,-68,-63,-52,46,-56,-170,-106,-66,46,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,46,-67,46,-70,-74,46,-57,-82,-249,-81,46,-107,-30,46,-97,-96,-116,46,46,-45,-46,46,-109,46,46,46,46,-88,46,46,-117,-36,46,-47,46,46,-83,-89,-250,46,-110,46,46,-111,-113,-112,46,46,-98,-37,-39,-42,-38,-40,46,-148,-147,-43,-149,-41,-85,-84,-90,46,46,-100,-99,-167,-166,46,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'INLINE':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[49,49,-61,-72,-71,-58,-54,-55,-33,-29,-59,49,-34,-53,-68,-63,-52,49,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,49,-67,49,-70,-74,49,-57,-82,-249,-81,-107,-30,49,-97,-96,49,-45,-46,49,-109,-36,49,-47,-83,-250,-110,-111,-113,-112,49,49,-98,-37,-39,-42,-38,-40,49,-148,-147,-43,-149,-41,-85,-84,49,49,-100,-99,-167,-166,49,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'DO':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,259,-250,-39,-42,-38,-40,259,-148,-147,-43,-149,259,-41,-167,-166,-164,259,-150,-163,-151,259,-162,-165,-154,259,-152,259,-153,259,259,-158,-157,-155,259,259,-159,-156,259,-161,-160,]),'LNOT':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,91,-45,-219,91,-217,91,-216,91,-215,91,91,-214,-218,91,91,-250,91,-176,-179,-177,-173,-174,-178,-180,91,-182,-183,-175,-181,91,-215,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,-251,-39,-42,-38,91,-40,91,91,-148,-147,-43,-149,91,-41,91,91,91,-215,91,-12,91,91,-11,-167,-166,91,-164,91,91,-150,91,-163,-151,91,91,91,91,-251,91,-215,-251,-131,-162,-165,91,-154,91,-152,91,91,91,-153,91,91,91,-251,91,-158,-157,-155,91,91,91,-159,-156,91,-161,-160,]),'CONST':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,28,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,66,68,73,75,80,82,83,84,85,86,87,88,89,112,139,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[3,3,-61,-72,-71,-58,-54,-55,-33,-29,-59,3,-34,-53,-68,-63,-52,3,-56,-170,-106,-66,3,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,3,-67,3,-70,-74,3,-57,-82,-249,-81,3,-107,-30,3,-97,-96,-116,3,3,-45,-46,3,-109,3,3,3,3,-88,3,3,-117,-36,3,-47,3,3,-83,-89,-250,3,-110,3,3,-111,-113,-112,3,3,-98,-37,-39,-42,-38,-40,3,-148,-147,-43,-149,-41,-85,-84,-90,3,3,-100,-99,-167,-166,3,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'LOR':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,198,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-213,-221,-222,-207,-228,-229,]),'CHAR_CONST':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,94,-45,-219,94,-217,94,-216,94,-215,94,94,-214,-218,94,94,-250,94,-176,-179,-177,-173,-174,-178,-180,94,-182,-183,-175,-181,94,-215,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,-251,-39,-42,-38,94,-40,94,94,-148,-147,-43,-149,94,-41,94,94,94,-215,94,-12,94,94,-11,-167,-166,94,-164,94,94,-150,94,-163,-151,94,94,94,94,-251,94,-215,-251,-131,-162,-165,94,-154,94,-152,94,94,94,-153,94,94,94,-251,94,-158,-157,-155,94,94,94,-159,-156,94,-161,-160,]),'LSHIFT':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,199,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,199,-194,-192,199,199,199,-191,199,199,-189,-188,199,199,199,199,199,-190,-213,-221,-222,-207,-228,-229,]),'RBRACE':([55,75,86,88,92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,122,124,135,136,137,145,147,148,150,151,174,176,178,180,184,187,188,190,196,228,229,230,236,238,239,242,244,251,253,254,255,257,258,260,261,267,269,271,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,320,321,328,331,332,335,340,342,344,349,350,351,356,368,369,370,373,374,377,382,385,386,392,396,400,401,402,405,406,408,409,416,417,419,420,],[-249,-45,151,-88,-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,-185,-242,-239,-171,-230,-101,151,-104,-251,151,151,-89,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,151,151,-102,-126,-39,-42,-38,-40,-6,-148,-147,-43,-149,-5,-41,151,-184,-90,-172,-225,-224,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-103,-105,151,-167,-166,-164,-150,-163,-151,-213,-221,-222,-207,-129,151,-127,-162,-165,-154,-152,151,-186,-128,-153,151,-228,-130,-158,-157,-155,-229,-159,-156,-161,-160,]),'_BOOL':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[13,13,-61,-72,-71,-58,-54,-55,-33,-29,-59,13,-34,-53,-68,-63,-52,13,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,13,-67,13,-70,-74,13,-57,-82,-249,-81,13,-107,-30,13,-97,-96,13,-45,-46,13,-109,13,13,13,13,-88,13,13,-36,13,-47,13,13,-83,-89,-250,13,-110,13,13,-111,-113,-112,13,13,-98,-37,-39,-42,-38,-40,13,-148,-147,-43,-149,-41,-85,-84,-90,13,13,-100,-99,-167,-166,13,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'LE':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,201,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,201,-194,-192,-196,201,-195,-191,-198,201,-189,-188,-197,201,201,201,201,-190,-213,-221,-222,-207,-228,-229,]),'SEMI':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,30,31,32,33,35,36,37,38,39,40,41,42,43,44,45,46,49,50,51,52,54,55,56,58,59,60,63,64,70,71,72,73,74,75,76,77,79,83,87,89,90,92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,122,124,143,144,145,149,151,152,153,154,155,157,158,159,160,161,174,176,178,180,184,185,187,188,190,191,194,196,216,217,231,233,234,236,237,238,239,241,242,243,244,246,247,251,253,254,255,256,257,258,259,260,262,264,265,266,267,271,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,318,319,330,331,332,333,334,335,336,339,340,342,344,345,347,348,349,350,351,355,356,370,373,374,375,376,377,379,382,386,392,393,394,395,396,397,399,401,403,405,406,408,409,412,413,415,416,417,418,419,420,],[15,-251,-61,-72,-71,-58,-54,-55,-33,-29,-59,-251,-34,-53,-68,-63,-52,15,-56,-170,-106,-66,-69,-251,-32,-73,-108,-64,-31,-60,-35,-62,-65,75,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-249,-81,-49,-107,-30,-97,-96,-18,-44,-17,-77,-75,-45,-48,-51,-251,-109,-251,-251,-251,-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,-185,-242,-239,-171,-230,-77,-36,-251,-83,-250,-21,-80,-22,-79,-24,269,-91,-23,-93,-248,-212,-246,-226,-227,-110,-206,-211,-209,-111,-168,-210,-113,-112,-98,-76,-78,-126,-37,-39,-42,331,-38,332,-40,335,-14,-251,-148,-147,-43,342,-149,-13,-251,-41,-237,-85,-84,-95,-184,-172,-225,-224,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-100,-99,373,-167,-166,374,-251,-164,-251,-13,-150,-163,-151,-251,-92,-94,-213,-221,-222,-169,-207,-127,-162,-165,393,-251,-154,-251,-152,-186,-128,-251,404,-251,-153,-251,-251,-228,410,-158,-157,-155,-229,416,-251,-251,-159,-156,-251,-161,-160,]),'LT':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,203,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,203,-194,-192,-196,203,-195,-191,-198,203,-189,-188,-197,203,203,203,203,-190,-213,-221,-222,-207,-228,-229,]),'COMMA':([1,2,3,5,6,9,10,13,14,17,18,19,21,23,24,25,27,28,29,32,33,35,37,39,40,42,43,44,45,46,49,50,51,52,54,56,58,59,63,64,66,67,68,69,70,73,74,76,77,83,92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,122,124,128,129,130,131,132,135,136,137,138,139,143,149,151,157,159,161,174,176,178,180,184,185,187,188,190,191,192,194,196,216,217,219,220,222,223,224,225,228,229,230,231,233,234,236,247,262,264,265,266,267,271,273,274,275,276,277,278,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,314,315,317,318,319,320,321,328,333,347,348,349,350,351,355,356,359,360,361,362,368,370,378,380,383,384,385,386,387,388,389,392,401,402,407,409,],[-251,-61,-72,-71,-58,-54,-55,-59,-251,-53,-68,-63,-52,-56,-170,-106,-66,-251,-69,-73,-108,-64,-60,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-81,-49,-107,-97,-96,-116,-114,-26,-25,140,-77,-75,-48,-51,-109,-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,-185,-242,-239,-171,-230,-120,-251,226,227,-124,-101,230,-104,-115,-117,-77,-83,-250,268,-91,-93,-248,-212,-246,-226,-227,-110,-206,-211,-209,-111,282,-168,-210,-113,-112,-123,-2,-122,-139,-137,-1,230,230,-102,-98,-76,-78,-126,282,-237,-85,-84,-95,-184,-172,-225,-224,282,-235,-223,352,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,282,-202,-190,-138,-125,-121,-100,-99,-103,-105,369,282,-92,-94,-213,-221,-222,-169,-207,-146,-140,-142,-144,-129,-127,282,282,282,-236,400,-186,-141,-143,-145,-128,-228,-130,282,-229,]),'TYPEDEF':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[23,23,-61,-72,-71,-58,-54,-55,-33,-29,-59,23,-34,-53,-68,-63,-52,23,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,23,-67,23,-70,-74,23,-57,-82,-249,-81,-107,-30,23,-97,-96,23,-45,-46,23,-109,-36,23,-47,-83,-250,-110,-111,-113,-112,23,23,-98,-37,-39,-42,-38,-40,23,-148,-147,-43,-149,-41,-85,-84,23,23,-100,-99,-167,-166,23,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'XOR':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,206,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,206,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,206,-199,-201,206,-190,-213,-221,-222,-207,-228,-229,]),'AUTO':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[21,21,-61,-72,-71,-58,-54,-55,-33,-29,-59,21,-34,-53,-68,-63,-52,21,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,21,-67,21,-70,-74,21,-57,-82,-249,-81,-107,-30,21,-97,-96,21,-45,-46,21,-109,-36,21,-47,-83,-250,-110,-111,-113,-112,21,21,-98,-37,-39,-42,-38,-40,21,-148,-147,-43,-149,-41,-85,-84,21,21,-100,-99,-167,-166,21,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'TIMES':([0,1,2,3,4,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,27,28,29,30,31,32,35,36,37,38,39,40,42,43,44,45,46,49,50,51,52,54,55,56,58,60,61,63,64,66,67,68,69,75,76,77,79,87,89,90,91,92,93,94,95,96,97,98,99,100,101,102,104,105,106,108,109,110,111,112,113,114,115,116,117,118,119,120,123,124,129,139,140,141,144,145,149,151,152,153,154,155,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,180,182,183,184,186,187,188,189,190,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,218,221,231,232,235,237,238,239,242,243,244,250,251,253,254,255,257,259,260,262,264,265,268,270,273,274,277,281,282,283,285,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,311,312,318,319,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,349,350,351,352,353,356,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[28,-251,-61,-72,28,-71,-58,-54,-55,-33,-29,-59,-251,-34,-53,-68,-63,-52,28,-56,-170,-66,-251,-69,28,-32,-73,-64,-31,-60,-35,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-249,-81,-49,-30,110,-97,-96,-116,28,-26,-25,-45,-48,-51,28,-251,-251,28,-219,-206,-233,-243,-247,-244,-241,-231,177,-217,-232,-208,-187,177,-216,177,-240,-215,-220,177,177,-237,-245,-214,-238,208,-242,-239,-218,-230,28,-117,28,177,-36,177,-83,-250,-21,-80,-22,-79,177,-176,-179,-177,-173,-174,-178,-180,177,-182,-183,-175,-181,-248,177,-212,-215,-246,-226,177,177,-227,177,-206,-211,177,-209,28,-210,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,28,311,-98,177,-251,-37,-39,-42,-38,177,-40,177,177,-148,-147,-43,-149,177,-41,-237,-85,-84,28,177,-225,-224,-223,-234,177,177,28,208,208,208,208,208,208,208,208,208,208,-189,-188,208,208,208,208,208,-190,-215,364,-100,-99,-12,177,177,-11,-167,-166,177,-164,177,177,-150,177,-163,-151,177,177,-213,-221,-222,177,177,-207,-251,177,-215,-251,-131,-162,-165,177,-154,177,-152,177,177,177,-153,177,177,177,-251,-228,177,-158,-157,-155,-229,177,177,177,-159,-156,177,-161,-160,]),'LPAREN':([0,1,2,3,4,5,6,9,10,11,12,13,14,15,16,17,18,19,21,22,23,24,25,27,28,29,30,31,32,33,35,36,37,38,39,40,42,43,44,45,46,49,50,51,52,54,55,56,58,59,60,61,63,64,66,67,68,69,75,76,77,79,83,87,89,90,91,93,94,95,96,97,98,99,100,101,102,105,106,108,109,110,111,112,113,114,115,116,117,119,120,123,124,129,138,139,140,141,144,145,149,151,152,153,154,155,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,177,178,180,182,183,184,185,186,189,191,195,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,221,223,224,231,232,235,237,238,239,242,243,244,245,249,250,251,252,253,254,255,257,259,260,262,263,264,265,268,270,273,274,277,281,282,283,285,286,311,312,314,318,319,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,350,351,352,353,357,358,359,360,361,362,364,369,372,373,374,376,377,379,381,382,387,388,389,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[4,-251,-61,-72,4,-71,-58,-54,-55,-33,-29,-59,-251,-34,4,-53,-68,-63,-52,4,-56,-170,62,-66,-251,-69,4,-32,-73,-108,-64,-31,-60,-35,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-249,-81,-49,62,-30,112,-97,-96,-116,-114,-26,-25,-45,-48,-51,4,-109,-251,-251,4,-219,-233,-243,-247,-244,-241,-231,175,-217,-232,183,186,-216,189,-240,-215,-220,112,189,-237,-245,-214,-238,-242,-239,-218,-230,218,-115,-117,4,112,-36,112,-83,-250,-21,-80,-22,-79,186,-176,-179,-177,-173,-174,-178,-180,112,-182,-183,-175,-181,-248,112,-215,-246,-226,112,112,-227,-110,112,112,-111,285,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,112,186,186,-113,-112,218,112,313,218,-98,186,-251,-37,-39,-42,-38,112,-40,334,337,186,112,341,-148,-147,-43,-149,112,-41,-237,346,-85,-84,4,186,-225,-224,-223,-234,112,186,285,285,-215,112,313,-100,-99,-12,186,112,-11,-167,-166,112,-164,112,112,-150,112,-163,-151,112,112,-221,-222,112,186,-251,186,-146,-140,-142,-144,-215,-251,-131,-162,-165,112,-154,112,398,-152,-141,-143,-145,112,112,112,-153,112,112,112,-251,-228,112,-158,-157,-155,-229,112,112,112,-159,-156,112,-161,-160,]),'MINUSMINUS':([55,61,75,91,93,94,95,96,97,98,99,100,101,102,105,106,108,109,110,111,112,113,114,115,116,117,119,120,123,124,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,177,178,180,182,183,184,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,262,270,273,274,277,281,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,350,351,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[-249,113,-45,-219,-233,-243,-247,-244,-241,-231,113,-217,-232,184,113,-216,113,-240,-215,-220,113,113,-237,-245,-214,-238,-242,-239,-218,-230,113,113,-250,113,-176,-179,-177,-173,-174,-178,-180,113,-182,-183,-175,-181,-248,113,-215,-246,-226,113,113,-227,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,-251,-39,-42,-38,113,-40,113,113,-148,-147,-43,-149,113,-41,-237,113,-225,-224,-223,-234,113,113,-215,113,-12,113,113,-11,-167,-166,113,-164,113,113,-150,113,-163,-151,113,113,-221,-222,113,113,-251,113,-215,-251,-131,-162,-165,113,-154,113,-152,113,113,113,-153,113,113,113,-251,-228,113,-158,-157,-155,-229,113,113,113,-159,-156,113,-161,-160,]),'ID':([0,1,2,3,4,5,6,7,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,39,40,42,43,44,45,46,49,50,51,52,54,55,56,58,60,61,62,63,64,65,66,67,68,69,75,76,77,79,87,89,90,91,99,100,105,106,108,110,112,113,116,123,129,133,134,138,139,140,141,144,145,149,151,152,153,154,155,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,179,181,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,218,221,224,226,230,231,232,235,237,238,239,240,242,243,244,250,251,253,254,255,257,259,260,264,265,268,270,282,283,311,312,318,319,322,324,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[33,-251,-61,-72,33,-71,-58,56,-54,-55,-33,-29,-59,-251,-34,33,-53,-68,-63,-87,-52,33,-56,-170,64,-66,-251,-69,33,-32,-73,-86,-64,-31,-60,-35,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-249,-81,-49,-30,114,114,-97,-96,137,-116,-114,-26,-25,-45,-48,-51,33,-251,-251,33,-219,114,-217,114,-216,114,-215,114,114,-214,-218,33,137,137,-115,-117,33,114,-36,262,-83,-250,-21,-80,-22,-79,114,-176,-179,-177,-173,-174,-178,-180,114,-182,-183,-175,-181,114,-215,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,33,114,33,114,137,-98,114,-251,-37,-39,-42,330,-38,114,-40,114,262,-148,-147,-43,-149,262,-41,-85,-84,33,114,114,114,-215,114,-100,-99,-12,114,114,114,-11,-167,-166,114,-164,262,114,-150,114,-163,-151,262,114,114,114,-251,114,-215,-251,-131,-162,-165,114,-154,262,-152,114,114,262,-153,262,114,262,-251,114,-158,-157,-155,114,262,262,-159,-156,262,-161,-160,]),'IF':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,263,-250,-39,-42,-38,-40,263,-148,-147,-43,-149,263,-41,-167,-166,-164,263,-150,-163,-151,263,-162,-165,-154,263,-152,263,-153,263,263,-158,-157,-155,263,263,-159,-156,263,-161,-160,]),'STRING_LITERAL':([55,61,75,91,99,100,101,105,106,108,110,112,113,115,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,178,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,115,-45,-219,115,-217,178,115,-216,115,-215,115,115,-245,-214,-218,115,115,-250,115,-176,-179,-177,-173,-174,-178,-180,115,-182,-183,-175,-181,115,-215,-246,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,-251,-39,-42,-38,115,-40,115,115,-148,-147,-43,-149,115,-41,115,115,115,-215,115,-12,115,115,-11,-167,-166,115,-164,115,115,-150,115,-163,-151,115,115,115,115,-251,115,-215,-251,-131,-162,-165,115,-154,115,-152,115,115,115,-153,115,115,115,-251,115,-158,-157,-155,115,115,115,-159,-156,115,-161,-160,]),'FLOAT':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[35,35,-61,-72,-71,-58,-54,-55,-33,-29,-59,35,-34,-53,-68,-63,-52,35,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,35,-67,35,-70,-74,35,-57,-82,-249,-81,35,-107,-30,35,-97,-96,35,-45,-46,35,-109,35,35,35,35,-88,35,35,-36,35,-47,35,35,-83,-89,-250,35,-110,35,35,-111,-113,-112,35,35,-98,-37,-39,-42,-38,-40,35,-148,-147,-43,-149,-41,-85,-84,-90,35,35,-100,-99,-167,-166,35,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'XOREQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[166,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'LSHIFTEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[168,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'RBRACKET':([61,92,93,94,95,96,97,98,101,102,103,104,107,109,110,111,114,115,117,118,119,120,121,122,124,151,174,176,178,180,184,187,188,190,194,196,221,267,271,273,274,275,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,310,311,312,349,350,351,355,356,363,364,367,386,401,409,],[-251,-206,-233,-243,-247,-244,-241,-231,-232,-208,185,-187,-4,-240,191,-220,-237,-245,-238,-185,-242,-239,-3,-171,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-168,-210,-251,-184,-172,-225,-224,350,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,361,362,-251,-213,-221,-222,-169,-207,387,388,390,-186,-228,-229,]),} - -_lr_action = { } -for _k, _v in _lr_action_items.items(): - for _x,_y in zip(_v[0],_v[1]): - if not _x in _lr_action: _lr_action[_x] = { } - _lr_action[_x][_k] = _y -del _lr_action_items - -_lr_goto_items = {'storage_class_specifier':([0,1,14,22,42,44,48,62,73,82,145,218,227,251,285,313,334,],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,]),'identifier_list_opt':([62,],[125,]),'selection_statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[260,260,260,260,260,260,260,260,260,260,260,260,]),'constant':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,]),'unary_expression':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[92,176,187,190,92,196,92,92,187,92,92,92,92,92,92,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,92,187,187,92,187,92,187,92,92,187,92,187,92,187,92,92,92,92,92,92,92,92,187,187,92,92,92,92,92,92,92,92,92,92,92,92,92,]),'conditional_expression':([61,112,141,145,156,169,175,182,183,186,189,213,221,232,243,250,251,259,270,282,312,325,326,334,336,337,341,345,346,352,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[122,122,122,122,267,122,122,122,122,122,122,122,122,267,122,267,122,122,267,122,122,267,122,122,122,122,122,122,122,122,386,122,122,122,122,122,122,122,122,122,122,122,122,122,]),'brace_close':([86,136,147,148,228,229,261,328,369,385,400,],[149,231,264,265,318,319,344,370,392,401,409,]),'struct_or_union_specifier':([0,1,14,22,42,44,48,57,62,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,]),'unified_wstring_literal':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,]),'abstract_declarator_opt':([129,195,],[219,284,]),'iteration_statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[239,239,239,239,239,239,239,239,239,239,239,239,]),'init_declarator_list':([30,79,],[70,70,]),'translation_unit_or_empty':([0,],[8,]),'struct_declaration_list':([57,84,85,],[86,147,148,]),'enumerator':([65,133,134,230,],[135,135,135,320,]),'pp_directive':([0,22,],[11,11,]),'declaration_list':([48,73,],[82,82,]),'declaration_specifiers_opt':([1,14,42,44,],[50,58,76,77,]),'abstract_declarator':([129,195,218,285,],[220,220,309,309,]),'external_declaration':([0,22,],[12,60,]),'type_specifier':([0,1,14,22,42,44,48,57,62,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[14,14,14,14,14,14,14,87,14,14,14,87,87,87,87,87,87,14,87,87,87,87,87,14,14,14,14,14,14,]),'designation':([235,357,369,400,],[322,322,322,322,]),'compound_statement':([81,142,145,251,259,336,345,379,395,397,399,413,415,418,],[144,237,244,244,244,244,244,244,244,244,244,244,244,244,]),'pointer':([0,4,22,30,67,79,90,129,140,195,218,268,285,],[16,16,16,16,138,16,16,224,16,286,224,16,286,]),'type_name':([112,175,186,189,],[193,272,279,280,]),'unified_string_literal':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,]),'postfix_expression':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,]),'assignment_expression_opt':([61,221,312,],[103,310,363,]),'designation_opt':([235,357,369,400,],[326,326,391,391,]),'expression_statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[238,238,238,238,238,238,238,238,238,238,238,238,]),'unary_operator':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,]),'cast_expression':([61,105,112,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[104,188,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,356,104,104,104,104,104,104,104,104,104,104,356,104,104,104,104,104,104,104,104,104,104,104,104,104,104,]),'brace_open':([7,26,54,56,63,64,81,141,142,145,251,259,283,326,336,345,349,353,354,379,391,395,397,399,413,415,418,],[57,65,84,85,133,134,145,235,145,145,145,145,357,235,145,145,357,357,357,145,235,145,145,145,145,145,145,]),'init_declarator':([30,79,140,],[74,74,233,]),'translation_unit':([0,],[22,]),'assignment_operator':([92,],[169,]),'struct_or_union':([0,1,14,22,42,44,48,57,62,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,]),'block_item_list_opt':([145,],[261,]),'struct_declaration':([57,84,85,86,147,148,],[88,88,88,150,150,150,]),'assignment_expression':([61,112,141,145,169,175,182,183,186,189,213,221,243,251,259,282,312,326,334,336,337,341,345,346,352,376,379,391,393,395,397,398,399,404,410,413,415,418,],[107,194,236,194,271,194,194,276,194,194,194,107,194,194,194,355,107,236,194,194,194,194,194,194,384,194,194,236,194,194,194,194,194,194,194,194,194,194,]),'parameter_type_list':([62,218,285,313,],[127,307,307,307,]),'type_qualifier_list_opt':([28,],[67,]),'direct_declarator':([0,4,16,22,30,79,90,129,140,218,224,268,],[25,25,59,25,25,25,25,25,25,25,59,25,]),'type_qualifier_list':([28,],[68,]),'designator':([235,329,357,369,400,],[323,371,323,323,323,]),'argument_expression_list':([183,],[278,]),'initializer':([141,326,391,],[234,368,402,]),'direct_abstract_declarator':([129,195,218,224,285,286,],[223,223,223,314,223,314,]),'specifier_qualifier_list_opt':([87,89,],[153,155,]),'constant_expression':([156,232,250,270,325,],[266,321,338,348,367,]),'expression_opt':([145,251,259,334,336,345,376,379,393,395,397,399,404,410,413,415,418,],[241,241,241,375,241,241,394,241,403,241,241,241,411,414,241,241,241,]),'primary_expression':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,]),'declaration_specifiers':([0,1,14,22,42,44,48,62,73,82,145,218,227,251,285,313,334,],[30,52,52,30,52,52,79,129,79,79,79,129,129,79,129,129,79,]),'declaration':([0,22,48,73,82,145,251,334,],[31,31,80,80,146,254,254,376,]),'struct_declarator_list_opt':([90,],[158,]),'identifier_list':([62,],[130,]),'typedef_name':([0,1,14,22,42,44,48,57,62,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,]),'parameter_type_list_opt':([218,285,313,],[308,308,365,]),'jump_statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[255,255,255,255,255,255,255,255,255,255,255,255,]),'declaration_list_opt':([48,73,],[81,142,]),'struct_declarator':([90,268,],[159,347,]),'function_definition':([0,22,],[36,36,]),'binary_expression':([61,112,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,312,325,326,334,336,337,341,345,346,352,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[118,118,118,118,118,118,118,118,118,118,118,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,118,304,305,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,]),'parameter_list':([62,218,285,313,],[131,131,131,131,]),'init_declarator_list_opt':([30,79,],[71,71,]),'enum_specifier':([0,1,14,22,42,44,48,57,62,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,]),'struct_declarator_list':([90,],[157,]),'decl_body':([0,22,48,73,82,145,251,334,],[41,41,41,41,41,41,41,41,]),'type_qualifier':([0,1,14,22,28,42,44,48,57,62,68,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[42,42,42,42,66,42,42,42,89,42,139,42,42,89,89,89,89,89,89,42,89,89,89,89,89,42,42,42,42,42,42,]),'enumerator_list':([65,133,134,],[136,228,229,]),'labeled_statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[242,242,242,242,242,242,242,242,242,242,242,242,]),'function_specifier':([0,1,14,22,42,44,48,62,73,82,145,218,227,251,285,313,334,],[44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,]),'specifier_qualifier_list':([57,84,85,86,87,89,112,147,148,175,186,189,],[90,90,90,90,154,154,195,90,90,195,195,195,]),'block_item':([145,251,],[257,340,]),'block_item_list':([145,],[251,]),'statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[253,253,343,377,382,396,405,406,408,417,419,420,]),'empty':([0,1,14,28,30,42,44,48,61,62,73,79,87,89,90,129,145,195,218,221,235,251,259,285,312,313,334,336,345,357,369,376,379,393,395,397,399,400,404,410,413,415,418,],[47,51,51,69,72,51,51,78,121,126,78,72,152,152,160,225,258,225,306,121,327,339,339,306,121,306,339,339,339,327,327,339,339,339,339,339,339,327,339,339,339,339,339,]),'initializer_list':([235,357,],[328,385,]),'declarator':([0,4,22,30,79,90,129,140,218,268,],[48,53,48,73,143,161,222,143,53,161,]),'parameter_declaration':([62,218,227,285,313,],[128,128,317,128,128,]),'designator_list':([235,357,369,400,],[329,329,329,329,]),'identifier':([61,62,99,105,108,112,113,141,145,156,169,175,179,181,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,226,232,243,250,251,259,270,282,283,312,324,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[124,132,124,124,124,124,124,124,124,124,124,124,273,274,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,315,124,124,124,124,124,124,124,124,124,366,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,]),'expression':([112,145,175,182,186,189,213,243,251,259,334,336,337,341,345,346,376,379,393,395,397,398,399,404,410,413,415,418,],[192,247,192,275,192,192,303,333,247,247,247,247,378,380,247,383,247,247,247,247,247,407,247,247,247,247,247,247,]),} - -_lr_goto = { } -for _k, _v in _lr_goto_items.items(): - for _x,_y in zip(_v[0],_v[1]): - if not _x in _lr_goto: _lr_goto[_x] = { } - _lr_goto[_x][_k] = _y -del _lr_goto_items -_lr_productions = [ - ("S' -> translation_unit_or_empty","S'",1,None,None,None), - ('abstract_declarator_opt -> empty','abstract_declarator_opt',1,'p_abstract_declarator_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('abstract_declarator_opt -> abstract_declarator','abstract_declarator_opt',1,'p_abstract_declarator_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('assignment_expression_opt -> empty','assignment_expression_opt',1,'p_assignment_expression_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('assignment_expression_opt -> assignment_expression','assignment_expression_opt',1,'p_assignment_expression_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('block_item_list_opt -> empty','block_item_list_opt',1,'p_block_item_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('block_item_list_opt -> block_item_list','block_item_list_opt',1,'p_block_item_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('declaration_list_opt -> empty','declaration_list_opt',1,'p_declaration_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('declaration_list_opt -> declaration_list','declaration_list_opt',1,'p_declaration_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('declaration_specifiers_opt -> empty','declaration_specifiers_opt',1,'p_declaration_specifiers_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('declaration_specifiers_opt -> declaration_specifiers','declaration_specifiers_opt',1,'p_declaration_specifiers_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('designation_opt -> empty','designation_opt',1,'p_designation_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('designation_opt -> designation','designation_opt',1,'p_designation_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('expression_opt -> empty','expression_opt',1,'p_expression_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('expression_opt -> expression','expression_opt',1,'p_expression_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('identifier_list_opt -> empty','identifier_list_opt',1,'p_identifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('identifier_list_opt -> identifier_list','identifier_list_opt',1,'p_identifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('init_declarator_list_opt -> empty','init_declarator_list_opt',1,'p_init_declarator_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('init_declarator_list_opt -> init_declarator_list','init_declarator_list_opt',1,'p_init_declarator_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('parameter_type_list_opt -> empty','parameter_type_list_opt',1,'p_parameter_type_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('parameter_type_list_opt -> parameter_type_list','parameter_type_list_opt',1,'p_parameter_type_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('specifier_qualifier_list_opt -> empty','specifier_qualifier_list_opt',1,'p_specifier_qualifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('specifier_qualifier_list_opt -> specifier_qualifier_list','specifier_qualifier_list_opt',1,'p_specifier_qualifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('struct_declarator_list_opt -> empty','struct_declarator_list_opt',1,'p_struct_declarator_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('struct_declarator_list_opt -> struct_declarator_list','struct_declarator_list_opt',1,'p_struct_declarator_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('type_qualifier_list_opt -> empty','type_qualifier_list_opt',1,'p_type_qualifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('type_qualifier_list_opt -> type_qualifier_list','type_qualifier_list_opt',1,'p_type_qualifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('translation_unit_or_empty -> translation_unit','translation_unit_or_empty',1,'p_translation_unit_or_empty','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',355), - ('translation_unit_or_empty -> empty','translation_unit_or_empty',1,'p_translation_unit_or_empty','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',356), - ('translation_unit -> external_declaration','translation_unit',1,'p_translation_unit_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',364), - ('translation_unit -> translation_unit external_declaration','translation_unit',2,'p_translation_unit_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',371), - ('external_declaration -> function_definition','external_declaration',1,'p_external_declaration_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',383), - ('external_declaration -> declaration','external_declaration',1,'p_external_declaration_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',388), - ('external_declaration -> pp_directive','external_declaration',1,'p_external_declaration_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',393), - ('external_declaration -> SEMI','external_declaration',1,'p_external_declaration_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',398), - ('pp_directive -> PPHASH','pp_directive',1,'p_pp_directive','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',403), - ('function_definition -> declarator declaration_list_opt compound_statement','function_definition',3,'p_function_definition_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',412), - ('function_definition -> declaration_specifiers declarator declaration_list_opt compound_statement','function_definition',4,'p_function_definition_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',424), - ('statement -> labeled_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',435), - ('statement -> expression_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',436), - ('statement -> compound_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',437), - ('statement -> selection_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',438), - ('statement -> iteration_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',439), - ('statement -> jump_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',440), - ('decl_body -> declaration_specifiers init_declarator_list_opt','decl_body',2,'p_decl_body','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',454), - ('declaration -> decl_body SEMI','declaration',2,'p_declaration','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',537), - ('declaration_list -> declaration','declaration_list',1,'p_declaration_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',546), - ('declaration_list -> declaration_list declaration','declaration_list',2,'p_declaration_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',547), - ('declaration_specifiers -> type_qualifier declaration_specifiers_opt','declaration_specifiers',2,'p_declaration_specifiers_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',552), - ('declaration_specifiers -> type_specifier declaration_specifiers_opt','declaration_specifiers',2,'p_declaration_specifiers_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',557), - ('declaration_specifiers -> storage_class_specifier declaration_specifiers_opt','declaration_specifiers',2,'p_declaration_specifiers_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',562), - ('declaration_specifiers -> function_specifier declaration_specifiers_opt','declaration_specifiers',2,'p_declaration_specifiers_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',567), - ('storage_class_specifier -> AUTO','storage_class_specifier',1,'p_storage_class_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',572), - ('storage_class_specifier -> REGISTER','storage_class_specifier',1,'p_storage_class_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',573), - ('storage_class_specifier -> STATIC','storage_class_specifier',1,'p_storage_class_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',574), - ('storage_class_specifier -> EXTERN','storage_class_specifier',1,'p_storage_class_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',575), - ('storage_class_specifier -> TYPEDEF','storage_class_specifier',1,'p_storage_class_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',576), - ('function_specifier -> INLINE','function_specifier',1,'p_function_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',581), - ('type_specifier -> VOID','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',586), - ('type_specifier -> _BOOL','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',587), - ('type_specifier -> CHAR','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',588), - ('type_specifier -> SHORT','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',589), - ('type_specifier -> INT','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',590), - ('type_specifier -> LONG','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',591), - ('type_specifier -> FLOAT','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',592), - ('type_specifier -> DOUBLE','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',593), - ('type_specifier -> _COMPLEX','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',594), - ('type_specifier -> SIGNED','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',595), - ('type_specifier -> UNSIGNED','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',596), - ('type_specifier -> typedef_name','type_specifier',1,'p_type_specifier_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',601), - ('type_specifier -> enum_specifier','type_specifier',1,'p_type_specifier_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',602), - ('type_specifier -> struct_or_union_specifier','type_specifier',1,'p_type_specifier_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',603), - ('type_qualifier -> CONST','type_qualifier',1,'p_type_qualifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',608), - ('type_qualifier -> RESTRICT','type_qualifier',1,'p_type_qualifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',609), - ('type_qualifier -> VOLATILE','type_qualifier',1,'p_type_qualifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',610), - ('init_declarator_list -> init_declarator','init_declarator_list',1,'p_init_declarator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',615), - ('init_declarator_list -> init_declarator_list COMMA init_declarator','init_declarator_list',3,'p_init_declarator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',616), - ('init_declarator -> declarator','init_declarator',1,'p_init_declarator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',624), - ('init_declarator -> declarator EQUALS initializer','init_declarator',3,'p_init_declarator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',625), - ('specifier_qualifier_list -> type_qualifier specifier_qualifier_list_opt','specifier_qualifier_list',2,'p_specifier_qualifier_list_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',630), - ('specifier_qualifier_list -> type_specifier specifier_qualifier_list_opt','specifier_qualifier_list',2,'p_specifier_qualifier_list_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',635), - ('struct_or_union_specifier -> struct_or_union ID','struct_or_union_specifier',2,'p_struct_or_union_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',643), - ('struct_or_union_specifier -> struct_or_union TYPEID','struct_or_union_specifier',2,'p_struct_or_union_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',644), - ('struct_or_union_specifier -> struct_or_union brace_open struct_declaration_list brace_close','struct_or_union_specifier',4,'p_struct_or_union_specifier_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',653), - ('struct_or_union_specifier -> struct_or_union ID brace_open struct_declaration_list brace_close','struct_or_union_specifier',5,'p_struct_or_union_specifier_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',662), - ('struct_or_union_specifier -> struct_or_union TYPEID brace_open struct_declaration_list brace_close','struct_or_union_specifier',5,'p_struct_or_union_specifier_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',663), - ('struct_or_union -> STRUCT','struct_or_union',1,'p_struct_or_union','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',672), - ('struct_or_union -> UNION','struct_or_union',1,'p_struct_or_union','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',673), - ('struct_declaration_list -> struct_declaration','struct_declaration_list',1,'p_struct_declaration_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',680), - ('struct_declaration_list -> struct_declaration_list struct_declaration','struct_declaration_list',2,'p_struct_declaration_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',681), - ('struct_declaration -> specifier_qualifier_list struct_declarator_list_opt SEMI','struct_declaration',3,'p_struct_declaration_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',686), - ('struct_declarator_list -> struct_declarator','struct_declarator_list',1,'p_struct_declarator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',737), - ('struct_declarator_list -> struct_declarator_list COMMA struct_declarator','struct_declarator_list',3,'p_struct_declarator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',738), - ('struct_declarator -> declarator','struct_declarator',1,'p_struct_declarator_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',746), - ('struct_declarator -> declarator COLON constant_expression','struct_declarator',3,'p_struct_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',751), - ('struct_declarator -> COLON constant_expression','struct_declarator',2,'p_struct_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',752), - ('enum_specifier -> ENUM ID','enum_specifier',2,'p_enum_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',760), - ('enum_specifier -> ENUM TYPEID','enum_specifier',2,'p_enum_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',761), - ('enum_specifier -> ENUM brace_open enumerator_list brace_close','enum_specifier',4,'p_enum_specifier_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',766), - ('enum_specifier -> ENUM ID brace_open enumerator_list brace_close','enum_specifier',5,'p_enum_specifier_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',771), - ('enum_specifier -> ENUM TYPEID brace_open enumerator_list brace_close','enum_specifier',5,'p_enum_specifier_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',772), - ('enumerator_list -> enumerator','enumerator_list',1,'p_enumerator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',777), - ('enumerator_list -> enumerator_list COMMA','enumerator_list',2,'p_enumerator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',778), - ('enumerator_list -> enumerator_list COMMA enumerator','enumerator_list',3,'p_enumerator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',779), - ('enumerator -> ID','enumerator',1,'p_enumerator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',790), - ('enumerator -> ID EQUALS constant_expression','enumerator',3,'p_enumerator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',791), - ('declarator -> direct_declarator','declarator',1,'p_declarator_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',803), - ('declarator -> pointer direct_declarator','declarator',2,'p_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',808), - ('direct_declarator -> ID','direct_declarator',1,'p_direct_declarator_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',813), - ('direct_declarator -> LPAREN declarator RPAREN','direct_declarator',3,'p_direct_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',822), - ('direct_declarator -> direct_declarator LBRACKET assignment_expression_opt RBRACKET','direct_declarator',4,'p_direct_declarator_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',827), - ('direct_declarator -> direct_declarator LBRACKET TIMES RBRACKET','direct_declarator',4,'p_direct_declarator_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',839), - ('direct_declarator -> direct_declarator LPAREN parameter_type_list RPAREN','direct_declarator',4,'p_direct_declarator_5','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',849), - ('direct_declarator -> direct_declarator LPAREN identifier_list_opt RPAREN','direct_declarator',4,'p_direct_declarator_5','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',850), - ('pointer -> TIMES type_qualifier_list_opt','pointer',2,'p_pointer','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',860), - ('pointer -> TIMES type_qualifier_list_opt pointer','pointer',3,'p_pointer','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',861), - ('type_qualifier_list -> type_qualifier','type_qualifier_list',1,'p_type_qualifier_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',871), - ('type_qualifier_list -> type_qualifier_list type_qualifier','type_qualifier_list',2,'p_type_qualifier_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',872), - ('parameter_type_list -> parameter_list','parameter_type_list',1,'p_parameter_type_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',877), - ('parameter_type_list -> parameter_list COMMA ELLIPSIS','parameter_type_list',3,'p_parameter_type_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',878), - ('parameter_list -> parameter_declaration','parameter_list',1,'p_parameter_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',886), - ('parameter_list -> parameter_list COMMA parameter_declaration','parameter_list',3,'p_parameter_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',887), - ('parameter_declaration -> declaration_specifiers declarator','parameter_declaration',2,'p_parameter_declaration_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',896), - ('parameter_declaration -> declaration_specifiers abstract_declarator_opt','parameter_declaration',2,'p_parameter_declaration_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',915), - ('identifier_list -> identifier','identifier_list',1,'p_identifier_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',927), - ('identifier_list -> identifier_list COMMA identifier','identifier_list',3,'p_identifier_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',928), - ('initializer -> assignment_expression','initializer',1,'p_initializer_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',937), - ('initializer -> brace_open initializer_list brace_close','initializer',3,'p_initializer_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',942), - ('initializer -> brace_open initializer_list COMMA brace_close','initializer',4,'p_initializer_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',943), - ('initializer_list -> designation_opt initializer','initializer_list',2,'p_initializer_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',948), - ('initializer_list -> initializer_list COMMA designation_opt initializer','initializer_list',4,'p_initializer_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',949), - ('designation -> designator_list EQUALS','designation',2,'p_designation','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',960), - ('designator_list -> designator','designator_list',1,'p_designator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',968), - ('designator_list -> designator_list designator','designator_list',2,'p_designator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',969), - ('designator -> LBRACKET constant_expression RBRACKET','designator',3,'p_designator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',974), - ('designator -> PERIOD identifier','designator',2,'p_designator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',975), - ('type_name -> specifier_qualifier_list abstract_declarator_opt','type_name',2,'p_type_name','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',980), - ('abstract_declarator -> pointer','abstract_declarator',1,'p_abstract_declarator_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',996), - ('abstract_declarator -> pointer direct_abstract_declarator','abstract_declarator',2,'p_abstract_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1004), - ('abstract_declarator -> direct_abstract_declarator','abstract_declarator',1,'p_abstract_declarator_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1009), - ('direct_abstract_declarator -> LPAREN abstract_declarator RPAREN','direct_abstract_declarator',3,'p_direct_abstract_declarator_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1019), - ('direct_abstract_declarator -> direct_abstract_declarator LBRACKET assignment_expression_opt RBRACKET','direct_abstract_declarator',4,'p_direct_abstract_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1023), - ('direct_abstract_declarator -> LBRACKET assignment_expression_opt RBRACKET','direct_abstract_declarator',3,'p_direct_abstract_declarator_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1033), - ('direct_abstract_declarator -> direct_abstract_declarator LBRACKET TIMES RBRACKET','direct_abstract_declarator',4,'p_direct_abstract_declarator_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1041), - ('direct_abstract_declarator -> LBRACKET TIMES RBRACKET','direct_abstract_declarator',3,'p_direct_abstract_declarator_5','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1051), - ('direct_abstract_declarator -> direct_abstract_declarator LPAREN parameter_type_list_opt RPAREN','direct_abstract_declarator',4,'p_direct_abstract_declarator_6','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1059), - ('direct_abstract_declarator -> LPAREN parameter_type_list_opt RPAREN','direct_abstract_declarator',3,'p_direct_abstract_declarator_7','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1069), - ('block_item -> declaration','block_item',1,'p_block_item','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1080), - ('block_item -> statement','block_item',1,'p_block_item','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1081), - ('block_item_list -> block_item','block_item_list',1,'p_block_item_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1088), - ('block_item_list -> block_item_list block_item','block_item_list',2,'p_block_item_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1089), - ('compound_statement -> brace_open block_item_list_opt brace_close','compound_statement',3,'p_compound_statement_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1095), - ('labeled_statement -> ID COLON statement','labeled_statement',3,'p_labeled_statement_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1101), - ('labeled_statement -> CASE constant_expression COLON statement','labeled_statement',4,'p_labeled_statement_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1105), - ('labeled_statement -> DEFAULT COLON statement','labeled_statement',3,'p_labeled_statement_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1109), - ('selection_statement -> IF LPAREN expression RPAREN statement','selection_statement',5,'p_selection_statement_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1113), - ('selection_statement -> IF LPAREN expression RPAREN statement ELSE statement','selection_statement',7,'p_selection_statement_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1117), - ('selection_statement -> SWITCH LPAREN expression RPAREN statement','selection_statement',5,'p_selection_statement_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1121), - ('iteration_statement -> WHILE LPAREN expression RPAREN statement','iteration_statement',5,'p_iteration_statement_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1126), - ('iteration_statement -> DO statement WHILE LPAREN expression RPAREN SEMI','iteration_statement',7,'p_iteration_statement_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1130), - ('iteration_statement -> FOR LPAREN expression_opt SEMI expression_opt SEMI expression_opt RPAREN statement','iteration_statement',9,'p_iteration_statement_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1134), - ('iteration_statement -> FOR LPAREN declaration expression_opt SEMI expression_opt RPAREN statement','iteration_statement',8,'p_iteration_statement_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1138), - ('jump_statement -> GOTO ID SEMI','jump_statement',3,'p_jump_statement_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1142), - ('jump_statement -> BREAK SEMI','jump_statement',2,'p_jump_statement_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1146), - ('jump_statement -> CONTINUE SEMI','jump_statement',2,'p_jump_statement_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1150), - ('jump_statement -> RETURN expression SEMI','jump_statement',3,'p_jump_statement_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1154), - ('jump_statement -> RETURN SEMI','jump_statement',2,'p_jump_statement_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1155), - ('expression_statement -> expression_opt SEMI','expression_statement',2,'p_expression_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1160), - ('expression -> assignment_expression','expression',1,'p_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1167), - ('expression -> expression COMMA assignment_expression','expression',3,'p_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1168), - ('typedef_name -> TYPEID','typedef_name',1,'p_typedef_name','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1180), - ('assignment_expression -> conditional_expression','assignment_expression',1,'p_assignment_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1184), - ('assignment_expression -> unary_expression assignment_operator assignment_expression','assignment_expression',3,'p_assignment_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1185), - ('assignment_operator -> EQUALS','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1198), - ('assignment_operator -> XOREQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1199), - ('assignment_operator -> TIMESEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1200), - ('assignment_operator -> DIVEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1201), - ('assignment_operator -> MODEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1202), - ('assignment_operator -> PLUSEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1203), - ('assignment_operator -> MINUSEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1204), - ('assignment_operator -> LSHIFTEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1205), - ('assignment_operator -> RSHIFTEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1206), - ('assignment_operator -> ANDEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1207), - ('assignment_operator -> OREQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1208), - ('constant_expression -> conditional_expression','constant_expression',1,'p_constant_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1213), - ('conditional_expression -> binary_expression','conditional_expression',1,'p_conditional_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1217), - ('conditional_expression -> binary_expression CONDOP expression COLON conditional_expression','conditional_expression',5,'p_conditional_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1218), - ('binary_expression -> cast_expression','binary_expression',1,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1226), - ('binary_expression -> binary_expression TIMES binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1227), - ('binary_expression -> binary_expression DIVIDE binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1228), - ('binary_expression -> binary_expression MOD binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1229), - ('binary_expression -> binary_expression PLUS binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1230), - ('binary_expression -> binary_expression MINUS binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1231), - ('binary_expression -> binary_expression RSHIFT binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1232), - ('binary_expression -> binary_expression LSHIFT binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1233), - ('binary_expression -> binary_expression LT binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1234), - ('binary_expression -> binary_expression LE binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1235), - ('binary_expression -> binary_expression GE binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1236), - ('binary_expression -> binary_expression GT binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1237), - ('binary_expression -> binary_expression EQ binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1238), - ('binary_expression -> binary_expression NE binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1239), - ('binary_expression -> binary_expression AND binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1240), - ('binary_expression -> binary_expression OR binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1241), - ('binary_expression -> binary_expression XOR binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1242), - ('binary_expression -> binary_expression LAND binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1243), - ('binary_expression -> binary_expression LOR binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1244), - ('cast_expression -> unary_expression','cast_expression',1,'p_cast_expression_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1252), - ('cast_expression -> LPAREN type_name RPAREN cast_expression','cast_expression',4,'p_cast_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1256), - ('unary_expression -> postfix_expression','unary_expression',1,'p_unary_expression_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1260), - ('unary_expression -> PLUSPLUS unary_expression','unary_expression',2,'p_unary_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1264), - ('unary_expression -> MINUSMINUS unary_expression','unary_expression',2,'p_unary_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1265), - ('unary_expression -> unary_operator cast_expression','unary_expression',2,'p_unary_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1266), - ('unary_expression -> SIZEOF unary_expression','unary_expression',2,'p_unary_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1271), - ('unary_expression -> SIZEOF LPAREN type_name RPAREN','unary_expression',4,'p_unary_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1272), - ('unary_operator -> AND','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1280), - ('unary_operator -> TIMES','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1281), - ('unary_operator -> PLUS','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1282), - ('unary_operator -> MINUS','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1283), - ('unary_operator -> NOT','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1284), - ('unary_operator -> LNOT','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1285), - ('postfix_expression -> primary_expression','postfix_expression',1,'p_postfix_expression_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1290), - ('postfix_expression -> postfix_expression LBRACKET expression RBRACKET','postfix_expression',4,'p_postfix_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1294), - ('postfix_expression -> postfix_expression LPAREN argument_expression_list RPAREN','postfix_expression',4,'p_postfix_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1298), - ('postfix_expression -> postfix_expression LPAREN RPAREN','postfix_expression',3,'p_postfix_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1299), - ('postfix_expression -> postfix_expression PERIOD identifier','postfix_expression',3,'p_postfix_expression_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1304), - ('postfix_expression -> postfix_expression ARROW identifier','postfix_expression',3,'p_postfix_expression_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1305), - ('postfix_expression -> postfix_expression PLUSPLUS','postfix_expression',2,'p_postfix_expression_5','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1310), - ('postfix_expression -> postfix_expression MINUSMINUS','postfix_expression',2,'p_postfix_expression_5','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1311), - ('postfix_expression -> LPAREN type_name RPAREN brace_open initializer_list brace_close','postfix_expression',6,'p_postfix_expression_6','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1316), - ('postfix_expression -> LPAREN type_name RPAREN brace_open initializer_list COMMA brace_close','postfix_expression',7,'p_postfix_expression_6','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1317), - ('primary_expression -> identifier','primary_expression',1,'p_primary_expression_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1322), - ('primary_expression -> constant','primary_expression',1,'p_primary_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1326), - ('primary_expression -> unified_string_literal','primary_expression',1,'p_primary_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1330), - ('primary_expression -> unified_wstring_literal','primary_expression',1,'p_primary_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1331), - ('primary_expression -> LPAREN expression RPAREN','primary_expression',3,'p_primary_expression_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1336), - ('argument_expression_list -> assignment_expression','argument_expression_list',1,'p_argument_expression_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1340), - ('argument_expression_list -> argument_expression_list COMMA assignment_expression','argument_expression_list',3,'p_argument_expression_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1341), - ('identifier -> ID','identifier',1,'p_identifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1350), - ('constant -> INT_CONST_DEC','constant',1,'p_constant_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1354), - ('constant -> INT_CONST_OCT','constant',1,'p_constant_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1355), - ('constant -> INT_CONST_HEX','constant',1,'p_constant_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1356), - ('constant -> FLOAT_CONST','constant',1,'p_constant_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1362), - ('constant -> HEX_FLOAT_CONST','constant',1,'p_constant_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1363), - ('constant -> CHAR_CONST','constant',1,'p_constant_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1369), - ('constant -> WCHAR_CONST','constant',1,'p_constant_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1370), - ('unified_string_literal -> STRING_LITERAL','unified_string_literal',1,'p_unified_string_literal','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1381), - ('unified_string_literal -> unified_string_literal STRING_LITERAL','unified_string_literal',2,'p_unified_string_literal','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1382), - ('unified_wstring_literal -> WSTRING_LITERAL','unified_wstring_literal',1,'p_unified_wstring_literal','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1392), - ('unified_wstring_literal -> unified_wstring_literal WSTRING_LITERAL','unified_wstring_literal',2,'p_unified_wstring_literal','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1393), - ('brace_open -> LBRACE','brace_open',1,'p_brace_open','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1403), - ('brace_close -> RBRACE','brace_close',1,'p_brace_close','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1409), - ('empty -> ','empty',0,'p_empty','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1415), -] diff --git a/pypy/tool/release/package.py b/pypy/tool/release/package.py --- a/pypy/tool/release/package.py +++ b/pypy/tool/release/package.py @@ -17,6 +17,7 @@ import py import fnmatch from rpython.tool.udir import udir +import subprocess if sys.version_info < (2,6): py.test.skip("requires 2.6 so far") @@ -64,6 +65,8 @@ raise PyPyCNotFound( 'Bogus path: %r does not exist (see docstring for more info)' % (os.path.dirname(str(pypy_c)),)) + subprocess.check_call([str(pypy_c), '-c', 'import _sqlite3']) + subprocess.check_call([str(pypy_c), '-c', 'import _curses']) if sys.platform == 'win32' and not rename_pypy_c.lower().endswith('.exe'): rename_pypy_c += '.exe' binaries = [(pypy_c, rename_pypy_c)] @@ -73,9 +76,9 @@ #Instructions are provided on the website. # Can't rename a DLL: it is always called 'libpypy-c.dll' - + for extra in ['libpypy-c.dll', - 'libexpat.dll', 'sqlite3.dll', + 'libexpat.dll', 'sqlite3.dll', 'libeay32.dll', 'ssleay32.dll']: p = pypy_c.dirpath().join(extra) if not p.check(): @@ -93,7 +96,8 @@ ignore=ignore_patterns('.svn', 'py', '*.pyc', '*~')) shutil.copytree(str(basedir.join('lib_pypy')), str(pypydir.join('lib_pypy')), - ignore=ignore_patterns('.svn', 'py', '*.pyc', '*~')) + ignore=ignore_patterns('.svn', 'py', '*.pyc', '*~', + '*.c', '*.o')) for file in ['LICENSE', 'README.rst']: shutil.copy(str(basedir.join(file)), str(pypydir)) pypydir.ensure('include', dir=True) diff --git a/rpython/jit/backend/x86/test/test_zrpy_releasegil.py b/rpython/jit/backend/x86/test/test_zrpy_releasegil.py --- a/rpython/jit/backend/x86/test/test_zrpy_releasegil.py +++ b/rpython/jit/backend/x86/test/test_zrpy_releasegil.py @@ -68,10 +68,12 @@ c_qsort = rffi.llexternal('qsort', [rffi.VOIDP, rffi.SIZE_T, rffi.SIZE_T, CALLBACK], lltype.Void) # - def f42(): + def f42(n): length = len(glob.lst) raw = alloc1() fn = llhelper(CALLBACK, rffi._make_wrapper_for(CALLBACK, callback)) + if n & 1: # to create a loop and a bridge, and also + pass # to run the qsort() call in the blackhole interp c_qsort(rffi.cast(rffi.VOIDP, raw), rffi.cast(rffi.SIZE_T, 2), rffi.cast(rffi.SIZE_T, 8), fn) free1(raw) @@ -85,7 +87,7 @@ None, None, None, None, None, None) # def f(n, x, *args): - f42() + f42(n) n -= 1 return (n, x) + args return before, f, None diff --git a/rpython/memory/gctransform/asmgcroot.py b/rpython/memory/gctransform/asmgcroot.py --- a/rpython/memory/gctransform/asmgcroot.py +++ b/rpython/memory/gctransform/asmgcroot.py @@ -1,13 +1,15 @@ from rpython.flowspace.model import (Constant, Variable, Block, Link, - copygraph, SpaceOperation) + copygraph, SpaceOperation, checkgraph) from rpython.rlib.debug import ll_assert +from rpython.rlib.nonconst import NonConstant from rpython.rtyper.annlowlevel import llhelper from rpython.rtyper.lltypesystem import lltype, llmemory, rffi from rpython.rtyper.lltypesystem.lloperation import llop from rpython.memory.gctransform.framework import ( BaseFrameworkGCTransformer, BaseRootWalker) from rpython.rtyper.rbuiltin import gen_cast -from rpython.translator.unsimplify import copyvar +from rpython.translator.unsimplify import copyvar, varoftype +from rpython.translator.tool.cbuild import ExternalCompilationInfo import sys @@ -22,6 +24,7 @@ class AsmGcRootFrameworkGCTransformer(BaseFrameworkGCTransformer): _asmgcc_save_restore_arguments = None + _seen_gctransformer_hint_close_stack = None def push_roots(self, hop, keep_current_args=False): livevars = self.get_livevars_for_roots(hop, keep_current_args) @@ -57,10 +60,22 @@ def handle_call_with_close_stack(self, hop): fnptr = hop.spaceop.args[0].value + if self._seen_gctransformer_hint_close_stack is None: + self._seen_gctransformer_hint_close_stack = {} + if fnptr._obj.graph not in self._seen_gctransformer_hint_close_stack: + self._transform_hint_close_stack(fnptr) + self._seen_gctransformer_hint_close_stack[fnptr._obj.graph] = True + # + livevars = self.push_roots(hop) + self.default(hop) + self.pop_roots(hop, livevars) + + def _transform_hint_close_stack(self, fnptr): # We cannot easily pass variable amount of arguments of the call # across the call to the pypy_asm_stackwalk helper. So we store - # them away and restore them. We need to make a new graph - # that starts with restoring the arguments. + # them away and restore them. More precisely, we need to + # replace 'graph' with code that saves the arguments, and make + # a new graph that starts with restoring the arguments. if self._asmgcc_save_restore_arguments is None: self._asmgcc_save_restore_arguments = {} sradict = self._asmgcc_save_restore_arguments @@ -80,25 +95,52 @@ sradict[key] = Constant(p, lltype.Ptr(CONTAINER)) sra.append(sradict[key]) # - # store the value of the arguments - livevars = self.push_roots(hop) + # make a copy of the graph that will reload the values + graph = fnptr._obj.graph + graph2 = copygraph(graph) + # + # edit the original graph to only store the value of the arguments + block = Block(graph.startblock.inputargs) c_item0 = Constant('item0', lltype.Void) - for v_arg, c_p in zip(hop.spaceop.args[1:], sra): + assert len(block.inputargs) == len(sra) + for v_arg, c_p in zip(block.inputargs, sra): if isinstance(v_arg.concretetype, lltype.Ptr): - v_arg = hop.genop("cast_ptr_to_adr", [v_arg], - resulttype=llmemory.Address) - hop.genop("bare_setfield", [c_p, c_item0, v_arg]) + v_adr = varoftype(llmemory.Address) + block.operations.append( + SpaceOperation("cast_ptr_to_adr", [v_arg], v_adr)) + v_arg = v_adr + v_void = varoftype(lltype.Void) + block.operations.append( + SpaceOperation("bare_setfield", [c_p, c_item0, v_arg], v_void)) # - # make a copy of the graph that will reload the values - graph2 = copygraph(fnptr._obj.graph) + # call asm_stackwalk(graph2) + FUNC2 = lltype.FuncType([], FUNC1.RESULT) + fnptr2 = lltype.functionptr(FUNC2, + fnptr._obj._name + '_reload', + graph=graph2) + c_fnptr2 = Constant(fnptr2, lltype.Ptr(FUNC2)) + HELPERFUNC = lltype.FuncType([lltype.Ptr(FUNC2), + ASM_FRAMEDATA_HEAD_PTR], FUNC1.RESULT) + v_asm_stackwalk = varoftype(lltype.Ptr(HELPERFUNC), "asm_stackwalk") + block.operations.append( + SpaceOperation("cast_pointer", [c_asm_stackwalk], v_asm_stackwalk)) + v_result = varoftype(FUNC1.RESULT) + block.operations.append( + SpaceOperation("indirect_call", [v_asm_stackwalk, c_fnptr2, + c_gcrootanchor, + Constant(None, lltype.Void)], + v_result)) + block.closeblock(Link([v_result], graph.returnblock)) + graph.startblock = block + # + # edit the copy of the graph to reload the values block2 = graph2.startblock block1 = Block([]) reloadedvars = [] for v, c_p in zip(block2.inputargs, sra): v = copyvar(None, v) if isinstance(v.concretetype, lltype.Ptr): - w = Variable('tmp') - w.concretetype = llmemory.Address + w = varoftype(llmemory.Address) else: w = v block1.operations.append(SpaceOperation('getfield', @@ -109,21 +151,9 @@ reloadedvars.append(v) block1.closeblock(Link(reloadedvars, block2)) graph2.startblock = block1 - FUNC2 = lltype.FuncType([], FUNC1.RESULT) - fnptr2 = lltype.functionptr(FUNC2, - fnptr._obj._name + '_reload', - graph=graph2) - c_fnptr2 = Constant(fnptr2, lltype.Ptr(FUNC2)) - HELPERFUNC = lltype.FuncType([lltype.Ptr(FUNC2), - ASM_FRAMEDATA_HEAD_PTR], FUNC1.RESULT) # - v_asm_stackwalk = hop.genop("cast_pointer", [c_asm_stackwalk], - resulttype=lltype.Ptr(HELPERFUNC)) - hop.genop("indirect_call", - [v_asm_stackwalk, c_fnptr2, c_gcrootanchor, - Constant(None, lltype.Void)], - resultvar=hop.spaceop.result) - self.pop_roots(hop, livevars) + checkgraph(graph) + checkgraph(graph2) class AsmStackRootWalker(BaseRootWalker): @@ -284,6 +314,8 @@ stackscount += 1 # expected = rffi.stackcounter.stacks_counter + if NonConstant(0): + rffi.stackcounter.stacks_counter += 42 # hack to force it ll_assert(not (stackscount < expected), "non-closed stacks around") ll_assert(not (stackscount > expected), "stacks counter corruption?") lltype.free(otherframe, flavor='raw') @@ -681,13 +713,16 @@ gcrootanchor.next = gcrootanchor c_gcrootanchor = Constant(gcrootanchor, ASM_FRAMEDATA_HEAD_PTR) +eci = ExternalCompilationInfo(pre_include_bits=['#define PYPY_USE_ASMGCC']) + pypy_asm_stackwalk = rffi.llexternal('pypy_asm_stackwalk', [ASM_CALLBACK_PTR, ASM_FRAMEDATA_HEAD_PTR], lltype.Signed, sandboxsafe=True, _nowrapper=True, - random_effects_on_gcobjs=True) + random_effects_on_gcobjs=True, + compilation_info=eci) c_asm_stackwalk = Constant(pypy_asm_stackwalk, lltype.typeOf(pypy_asm_stackwalk)) diff --git a/rpython/rtyper/lltypesystem/rffi.py b/rpython/rtyper/lltypesystem/rffi.py --- a/rpython/rtyper/lltypesystem/rffi.py +++ b/rpython/rtyper/lltypesystem/rffi.py @@ -282,13 +282,13 @@ args = ', '.join(['a%d' % i for i in range(len(TP.TO.ARGS))]) source = py.code.Source(r""" def wrapper(%(args)s): # no *args - no GIL for mallocing the tuple - llop.gc_stack_bottom(lltype.Void) # marker for trackgcroot.py if aroundstate is not None: after = aroundstate.after if after: after() # from now on we hold the GIL stackcounter.stacks_counter += 1 + llop.gc_stack_bottom(lltype.Void) # marker for trackgcroot.py try: result = callable(%(args)s) except Exception, e: diff --git a/rpython/translator/c/gcc/test/test_asmgcroot.py b/rpython/translator/c/gcc/test/test_asmgcroot.py --- a/rpython/translator/c/gcc/test/test_asmgcroot.py +++ b/rpython/translator/c/gcc/test/test_asmgcroot.py @@ -195,8 +195,8 @@ @entrypoint("x42", [lltype.Signed, lltype.Signed], c_name='callback') def mycallback(a, b): + rffi.stackcounter.stacks_counter += 1 llop.gc_stack_bottom(lltype.Void) - rffi.stackcounter.stacks_counter += 1 gc.collect() rffi.stackcounter.stacks_counter -= 1 return a + b diff --git a/rpython/translator/c/src/mem.c b/rpython/translator/c/src/mem.c --- a/rpython/translator/c/src/mem.c +++ b/rpython/translator/c/src/mem.c @@ -96,3 +96,27 @@ GC_set_warn_proc(mem_boehm_ignore); } #endif /* BOEHM GC */ + + +#ifdef RPY_ASSERT +# ifdef PYPY_USE_ASMGCC +# include "structdef.h" +# include "forwarddecl.h" +# endif +void pypy_check_stack_count(void) +{ +# ifdef PYPY_USE_ASMGCC + void *anchor = (void*)&pypy_g_ASM_FRAMEDATA_HEAD; + void *fd = ((void* *) (((char *)anchor) + sizeof(void*)))[0]; + long got = 0; + long stacks_counter = + pypy_g_rpython_rtyper_lltypesystem_rffi_StackCounter.sc_inst_stacks_counter; + while (fd != anchor) { + got += 1; + fd = ((void* *) (((char *)fd) + sizeof(void*)))[0]; + } + RPyAssert(got == stacks_counter - 1, + "bad stacks_counter or non-closed stacks around"); +# endif +} +#endif diff --git a/rpython/translator/c/src/mem.h b/rpython/translator/c/src/mem.h --- a/rpython/translator/c/src/mem.h +++ b/rpython/translator/c/src/mem.h @@ -195,8 +195,14 @@ "g" (v)) /* marker for trackgcroot.py, and inhibits tail calls */ -#define pypy_asm_stack_bottom() asm volatile ("/* GC_STACK_BOTTOM */" : : : \ - "memory") +#define pypy_asm_stack_bottom() { asm volatile ("/* GC_STACK_BOTTOM */" : : : \ + "memory"); pypy_check_stack_count(); } +#ifdef RPY_ASSERT +void pypy_check_stack_count(void); +#else +static void pypy_check_stack_count(void) { } +#endif + #define OP_GC_ASMGCROOT_STATIC(i, r) r = \ i == 0 ? (void*)&__gcmapstart : \ From noreply at buildbot.pypy.org Thu Apr 4 23:30:26 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Thu, 4 Apr 2013 23:30:26 +0200 (CEST) Subject: [pypy-commit] pypy default: this is technically bytes (matters for py3) Message-ID: <20130404213026.E5CCE1C301F@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63028:c2b2e1588571 Date: 2013-04-04 17:29 -0400 http://bitbucket.org/pypy/pypy/changeset/c2b2e1588571/ Log: this is technically bytes (matters for py3) diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -1167,7 +1167,7 @@ if ret == _lib.SQLITE_OK and not self._statement: # an empty statement, work around that, as it's the least trouble - c_sql = _ffi.new("char[]", "select 42") + c_sql = _ffi.new("char[]", b"select 42") ret = _lib.sqlite3_prepare_v2(self.__con._db, c_sql, -1, statement_star, next_char) self._statement = statement_star[0] From noreply at buildbot.pypy.org Thu Apr 4 23:30:28 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Thu, 4 Apr 2013 23:30:28 +0200 (CEST) Subject: [pypy-commit] pypy py3k: merge default Message-ID: <20130404213028.4F00D1C301F@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: py3k Changeset: r63029:0a500b88c375 Date: 2013-04-04 17:30 -0400 http://bitbucket.org/pypy/pypy/changeset/0a500b88c375/ Log: merge default diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -30,6 +30,11 @@ import sys import weakref from threading import _get_ident as _thread_get_ident +try: + from __pypy__ import newlist_hint +except ImportError: + assert '__pypy__' not in sys.builtin_module_names + newlist_hint = lambda sizehint: [] if sys.version_info[0] >= 3: StandardError = Exception @@ -377,7 +382,7 @@ self.maxcount = maxcount self.cache = OrderedDict() - def get(self, sql, row_factory): + def get(self, sql): try: stat = self.cache[sql] except KeyError: @@ -385,10 +390,10 @@ self.cache[sql] = stat if len(self.cache) > self.maxcount: self.cache.popitem(0) - - if stat._in_use: - stat = Statement(self.connection, sql) - stat._row_factory = row_factory + else: + if stat._in_use: + stat = Statement(self.connection, sql) + self.cache[sql] = stat return stat @@ -551,7 +556,7 @@ @_check_thread_wrap @_check_closed_wrap def __call__(self, sql): - return self._statement_cache.get(sql, self.row_factory) + return self._statement_cache.get(sql) def cursor(self, factory=None): self._check_thread() @@ -855,10 +860,6 @@ self.__initialized = True - def __del__(self): - if self.__statement: - self.__statement._reset() - def close(self): self.__connection._check_thread() self.__connection._check_closed() @@ -884,16 +885,96 @@ return func(self, *args, **kwargs) return wrapper + def __check_reset(self): + if self._reset: + raise InterfaceError( + "Cursor needed to be reset because of commit/rollback " + "and can no longer be fetched from.") + + def __build_row_cast_map(self): + if not self.__connection._detect_types: + return + self.__row_cast_map = [] + for i in xrange(_lib.sqlite3_column_count(self.__statement._statement)): + converter = None + + if self.__connection._detect_types & PARSE_COLNAMES: + colname = _lib.sqlite3_column_name(self.__statement._statement, i) + if colname: + colname = _ffi.string(colname).decode('utf-8') + type_start = -1 + key = None + for pos in range(len(colname)): + if colname[pos] == '[': + type_start = pos + 1 + elif colname[pos] == ']' and type_start != -1: + key = colname[type_start:pos] + converter = converters[key.upper()] + + if converter is None and self.__connection._detect_types & PARSE_DECLTYPES: + decltype = _lib.sqlite3_column_decltype(self.__statement._statement, i) + if decltype: + decltype = _ffi.string(decltype).decode('utf-8') + # if multiple words, use first, eg. + # "INTEGER NOT NULL" => "INTEGER" + decltype = decltype.split()[0] + if '(' in decltype: + decltype = decltype[:decltype.index('(')] + converter = converters.get(decltype.upper(), None) + + self.__row_cast_map.append(converter) + + def __fetch_one_row(self): + num_cols = _lib.sqlite3_data_count(self.__statement._statement) + row = newlist_hint(num_cols) + for i in xrange(num_cols): + if self.__connection._detect_types: + converter = self.__row_cast_map[i] + else: + converter = None + + if converter is not None: + blob = _lib.sqlite3_column_blob(self.__statement._statement, i) + if not blob: + val = None + else: + blob_len = _lib.sqlite3_column_bytes(self.__statement._statement, i) + val = _ffi.buffer(blob, blob_len)[:] + val = converter(val) + else: + typ = _lib.sqlite3_column_type(self.__statement._statement, i) + if typ == _lib.SQLITE_NULL: + val = None + elif typ == _lib.SQLITE_INTEGER: + val = _lib.sqlite3_column_int64(self.__statement._statement, i) + val = int(val) + elif typ == _lib.SQLITE_FLOAT: + val = _lib.sqlite3_column_double(self.__statement._statement, i) + elif typ == _lib.SQLITE_TEXT: + text = _lib.sqlite3_column_text(self.__statement._statement, i) + text_len = _lib.sqlite3_column_bytes(self.__statement._statement, i) + val = _ffi.buffer(text, text_len)[:] + val = self.__connection.text_factory(val) + elif typ == _lib.SQLITE_BLOB: + blob = _lib.sqlite3_column_blob(self.__statement._statement, i) + blob_len = _lib.sqlite3_column_bytes(self.__statement._statement, i) + val = _BLOB_TYPE(_ffi.buffer(blob, blob_len)) + row.append(val) + return tuple(row) + def __execute(self, multiple, sql, many_params): self.__locked = True + self._reset = False try: - self._reset = False + del self.__next_row + except AttributeError: + pass + try: if not isinstance(sql, basestring): raise ValueError("operation parameter must be str or unicode") self.__description = None self.__rowcount = -1 - self.__statement = self.__connection._statement_cache.get( - sql, self.row_factory) + self.__statement = self.__connection._statement_cache.get(sql) if self.__connection._isolation_level is not None: if self.__statement._kind == Statement._DDL: @@ -918,9 +999,9 @@ if self.__statement._kind == Statement._DML: self.__statement._reset() - if self.__statement._kind == Statement._DQL and ret == _lib.SQLITE_ROW: - self.__statement._build_row_cast_map() - self.__statement._readahead(self) + if ret == _lib.SQLITE_ROW: + self.__build_row_cast_map() + self.__next_row = self.__fetch_one_row() if self.__statement._kind == Statement._DML: if self.__rowcount == -1: @@ -981,12 +1062,6 @@ break return self - def __check_reset(self): - if self._reset: - raise self.__connection.InterfaceError( - "Cursor needed to be reset because of commit/rollback " - "and can no longer be fetched from.") - def __iter__(self): return self @@ -995,7 +1070,25 @@ self.__check_reset() if not self.__statement: raise StopIteration - return self.__statement._next(self) + + try: + next_row = self.__next_row + except AttributeError: + self.__statement._reset() + self.__statement = None + raise StopIteration + del self.__next_row + + if self.row_factory is not None: + next_row = self.row_factory(self, next_row) + + ret = _lib.sqlite3_step(self.__statement._statement) + if ret not in (_lib.SQLITE_DONE, _lib.SQLITE_ROW): + self.__statement._reset() + raise self.__connection._get_exception(ret) + elif ret == _lib.SQLITE_ROW: + self.__next_row = self.__fetch_one_row() + return next_row if sys.version_info[0] < 3: next = __next__ @@ -1052,7 +1145,6 @@ self.__con._remember_statement(self) self._in_use = False - self._row_factory = None if not isinstance(sql, basestring): raise Warning("SQL is of wrong type. Must be string or unicode.") @@ -1075,7 +1167,7 @@ if ret == _lib.SQLITE_OK and not self._statement: # an empty statement, work around that, as it's the least trouble - c_sql = _ffi.new("char[]", "select 42") + c_sql = _ffi.new("char[]", b"select 42") ret = _lib.sqlite3_prepare_v2(self.__con._db, c_sql, -1, statement_star, next_char) self._statement = statement_star[0] @@ -1189,98 +1281,6 @@ else: raise ValueError("parameters are of unsupported type") - def _build_row_cast_map(self): - if not self.__con._detect_types: - return - self.__row_cast_map = [] - for i in xrange(_lib.sqlite3_column_count(self._statement)): - converter = None - - if self.__con._detect_types & PARSE_COLNAMES: - colname = _lib.sqlite3_column_name(self._statement, i) - if colname: - colname = _ffi.string(colname).decode('utf-8') - type_start = -1 - key = None - for pos in range(len(colname)): - if colname[pos] == '[': - type_start = pos + 1 - elif colname[pos] == ']' and type_start != -1: - key = colname[type_start:pos] - converter = converters[key.upper()] - - if converter is None and self.__con._detect_types & PARSE_DECLTYPES: - decltype = _lib.sqlite3_column_decltype(self._statement, i) - if decltype: - decltype = _ffi.string(decltype).decode('utf-8') - # if multiple words, use first, eg. - # "INTEGER NOT NULL" => "INTEGER" - decltype = decltype.split()[0] - if '(' in decltype: - decltype = decltype[:decltype.index('(')] - converter = converters.get(decltype.upper(), None) - - self.__row_cast_map.append(converter) - - def _readahead(self, cursor): - row = [] - num_cols = _lib.sqlite3_data_count(self._statement) - for i in xrange(num_cols): - if self.__con._detect_types: - converter = self.__row_cast_map[i] - else: - converter = None - - if converter is not None: - blob = _lib.sqlite3_column_blob(self._statement, i) - if not blob: - val = None - else: - blob_len = _lib.sqlite3_column_bytes(self._statement, i) - val = _ffi.buffer(blob, blob_len)[:] - val = converter(val) - else: - typ = _lib.sqlite3_column_type(self._statement, i) - if typ == _lib.SQLITE_NULL: - val = None - elif typ == _lib.SQLITE_INTEGER: - val = _lib.sqlite3_column_int64(self._statement, i) - val = int(val) - elif typ == _lib.SQLITE_FLOAT: - val = _lib.sqlite3_column_double(self._statement, i) - elif typ == _lib.SQLITE_TEXT: - text = _lib.sqlite3_column_text(self._statement, i) - text_len = _lib.sqlite3_column_bytes(self._statement, i) - val = _ffi.buffer(text, text_len)[:] - val = self.__con.text_factory(val) - elif typ == _lib.SQLITE_BLOB: - blob = _lib.sqlite3_column_blob(self._statement, i) - blob_len = _lib.sqlite3_column_bytes(self._statement, i) - val = _BLOB_TYPE(_ffi.buffer(blob, blob_len)) - row.append(val) - - row = tuple(row) - if self._row_factory is not None: - row = self._row_factory(cursor, row) - self._item = row - - def _next(self, cursor): - try: - item = self._item - except AttributeError: - self._reset() - raise StopIteration - del self._item - - ret = _lib.sqlite3_step(self._statement) - if ret not in (_lib.SQLITE_DONE, _lib.SQLITE_ROW): - _lib.sqlite3_reset(self._statement) - raise self.__con._get_exception(ret) - elif ret == _lib.SQLITE_ROW: - self._readahead(cursor) - - return item - def _get_description(self): if self._kind == Statement._DML: return None diff --git a/lib_pypy/cffi/api.py b/lib_pypy/cffi/api.py --- a/lib_pypy/cffi/api.py +++ b/lib_pypy/cffi/api.py @@ -25,7 +25,6 @@ line = '' return '%s%s' % (line, self.args[0]) - class FFI(object): r''' The main top-level class that you instantiate once, or once per module. diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py --- a/pypy/module/cpyext/api.py +++ b/pypy/module/cpyext/api.py @@ -555,8 +555,8 @@ from pypy.module.cpyext.pyobject import Reference # we hope that malloc removal removes the newtuple() that is # inserted exactly here by the varargs specializer + rffi.stackcounter.stacks_counter += 1 llop.gc_stack_bottom(lltype.Void) # marker for trackgcroot.py - rffi.stackcounter.stacks_counter += 1 retval = fatal_value boxed_args = () try: diff --git a/pypy/module/micronumpy/arrayimpl/concrete.py b/pypy/module/micronumpy/arrayimpl/concrete.py --- a/pypy/module/micronumpy/arrayimpl/concrete.py +++ b/pypy/module/micronumpy/arrayimpl/concrete.py @@ -281,7 +281,7 @@ def astype(self, space, dtype): new_arr = W_NDimArray.from_shape(self.get_shape(), dtype) - if dtype.is_str_or_unicode(): + if self.dtype.is_str_or_unicode() and not dtype.is_str_or_unicode(): raise OperationError(space.w_NotImplementedError, space.wrap( "astype(%s) not implemented yet" % self.dtype)) else: diff --git a/pypy/module/micronumpy/interp_support.py b/pypy/module/micronumpy/interp_support.py --- a/pypy/module/micronumpy/interp_support.py +++ b/pypy/module/micronumpy/interp_support.py @@ -15,7 +15,7 @@ items = [] num_items = 0 idx = 0 - + while (num_items < count or count == -1) and idx < len(s): nextidx = s.find(sep, idx) if nextidx < 0: @@ -45,7 +45,7 @@ items.append(val) num_items += 1 idx = nextidx + 1 - + if count > num_items: raise OperationError(space.w_ValueError, space.wrap( "string is smaller than requested size")) @@ -70,7 +70,7 @@ if count * itemsize > length: raise OperationError(space.w_ValueError, space.wrap( "string is smaller than requested size")) - + a = W_NDimArray.from_shape([count], dtype=dtype) loop.fromstring_loop(a, dtype, itemsize, s) return space.wrap(a) diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py --- a/pypy/module/micronumpy/test/test_numarray.py +++ b/pypy/module/micronumpy/test/test_numarray.py @@ -1487,14 +1487,14 @@ a = concatenate((['abcdef'], ['abc'])) assert a[0] == 'abcdef' assert str(a.dtype) == '|S6' - + def test_record_concatenate(self): # only an exact match can succeed from numpypy import zeros, concatenate a = concatenate((zeros((2,),dtype=[('x', int), ('y', float)]), zeros((2,),dtype=[('x', int), ('y', float)]))) assert a.shape == (4,) - exc = raises(TypeError, concatenate, + exc = raises(TypeError, concatenate, (zeros((2,), dtype=[('x', int), ('y', float)]), (zeros((2,), dtype=[('x', float), ('y', float)])))) assert str(exc.value).startswith('record type mismatch') @@ -1677,11 +1677,15 @@ a = array('x').astype('S3').dtype assert a.itemsize == 3 # scalar vs. array + a = array([1, 2, 3.14156]).astype('S3').dtype + assert a.itemsize == 3 + a = array(3.1415).astype('S3').dtype + assert a.itemsize == 3 try: - a = array([1, 2, 3.14156]).astype('S3').dtype - assert a.itemsize == 3 + a = array(['1', '2','3']).astype(float) + assert a[2] == 3.0 except NotImplementedError: - skip('astype("S3") not implemented for numeric arrays') + skip('astype("float") not implemented for str arrays') def test_base(self): from numpypy import array diff --git a/pypy/module/test_lib_pypy/lextab.py b/pypy/module/test_lib_pypy/lextab.py deleted file mode 100644 --- a/pypy/module/test_lib_pypy/lextab.py +++ /dev/null @@ -1,9 +0,0 @@ -# pycparser.lextab.py. This file automatically created by PLY (version 3.4). Don't edit! -_tabversion = '3.4' -_lextokens = {'VOID': 1, 'LBRACKET': 1, 'WCHAR_CONST': 1, 'FLOAT_CONST': 1, 'MINUS': 1, 'RPAREN': 1, 'LONG': 1, 'PLUS': 1, 'ELLIPSIS': 1, 'GT': 1, 'GOTO': 1, 'ENUM': 1, 'PERIOD': 1, 'GE': 1, 'INT_CONST_DEC': 1, 'ARROW': 1, 'HEX_FLOAT_CONST': 1, 'DOUBLE': 1, 'MINUSEQUAL': 1, 'INT_CONST_OCT': 1, 'TIMESEQUAL': 1, 'OR': 1, 'SHORT': 1, 'RETURN': 1, 'RSHIFTEQUAL': 1, 'RESTRICT': 1, 'STATIC': 1, 'SIZEOF': 1, 'UNSIGNED': 1, 'UNION': 1, 'COLON': 1, 'WSTRING_LITERAL': 1, 'DIVIDE': 1, 'FOR': 1, 'PLUSPLUS': 1, 'EQUALS': 1, 'ELSE': 1, 'INLINE': 1, 'EQ': 1, 'AND': 1, 'TYPEID': 1, 'LBRACE': 1, 'PPHASH': 1, 'INT': 1, 'SIGNED': 1, 'CONTINUE': 1, 'NOT': 1, 'OREQUAL': 1, 'MOD': 1, 'RSHIFT': 1, 'DEFAULT': 1, 'CHAR': 1, 'WHILE': 1, 'DIVEQUAL': 1, 'EXTERN': 1, 'CASE': 1, 'LAND': 1, 'REGISTER': 1, 'MODEQUAL': 1, 'NE': 1, 'SWITCH': 1, 'INT_CONST_HEX': 1, '_COMPLEX': 1, 'PLUSEQUAL': 1, 'STRUCT': 1, 'CONDOP': 1, 'BREAK': 1, 'VOLATILE': 1, 'ANDEQUAL': 1, 'DO': 1, 'LNOT': 1, 'CONST': 1, 'LOR': 1, 'CHAR_CONST': 1, 'LSHIFT': 1, 'RBRACE': 1, '_BOOL': 1, 'LE': 1, 'SEMI': 1, 'LT': 1, 'COMMA': 1, 'TYPEDEF': 1, 'XOR': 1, 'AUTO': 1, 'TIMES': 1, 'LPAREN': 1, 'MINUSMINUS': 1, 'ID': 1, 'IF': 1, 'STRING_LITERAL': 1, 'FLOAT': 1, 'XOREQUAL': 1, 'LSHIFTEQUAL': 1, 'RBRACKET': 1} -_lexreflags = 0 -_lexliterals = '' -_lexstateinfo = {'ppline': 'exclusive', 'pppragma': 'exclusive', 'INITIAL': 'inclusive'} -_lexstatere = {'ppline': [('(?P"([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*")|(?P(0(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?)|([1-9][0-9]*(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?))|(?P\\n)|(?Pline)', [None, ('t_ppline_FILENAME', 'FILENAME'), None, None, None, None, None, None, ('t_ppline_LINE_NUMBER', 'LINE_NUMBER'), None, None, None, None, None, None, None, None, ('t_ppline_NEWLINE', 'NEWLINE'), ('t_ppline_PPLINE', 'PPLINE')])], 'pppragma': [('(?P\\n)|(?Ppragma)|(?P"([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*")|(?P[a-zA-Z_][0-9a-zA-Z_]*)', [None, ('t_pppragma_NEWLINE', 'NEWLINE'), ('t_pppragma_PPPRAGMA', 'PPPRAGMA'), ('t_pppragma_STR', 'STR'), None, None, None, None, None, None, ('t_pppragma_ID', 'ID')])], 'INITIAL': [('(?P[ \\t]*\\#)|(?P\\n+)|(?P((((([0-9]*\\.[0-9]+)|([0-9]+\\.))([eE][-+]?[0-9]+)?)|([0-9]+([eE][-+]?[0-9]+)))[FfLl]?))|(?P(0[xX]([0-9a-fA-F]+|((([0-9a-fA-F]+)?\\.[0-9a-fA-F]+)|([0-9a-fA-F]+\\.)))([pP][+-]?[0-9]+)[FfLl]?))|(?P0[xX][0-9a-fA-F]+(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?)|(?P0[0-7]*[89])|(?P0[0-7]*(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?)', [None, ('t_PPHASH', 'PPHASH'), ('t_NEWLINE', 'NEWLINE'), ('t_FLOAT_CONST', 'FLOAT_CONST'), None, None, None, None, None, None, None, None, None, ('t_HEX_FLOAT_CONST', 'HEX_FLOAT_CONST'), None, None, None, None, None, None, None, ('t_INT_CONST_HEX', 'INT_CONST_HEX'), None, None, None, ('t_BAD_CONST_OCT', 'BAD_CONST_OCT'), ('t_INT_CONST_OCT', 'INT_CONST_OCT')]), ('(?P(0(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?)|([1-9][0-9]*(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?))|(?P\'([^\'\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))\')|(?PL\'([^\'\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))\')|(?P(\'([^\'\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*\\n)|(\'([^\'\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*$))|(?P(\'([^\'\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))[^\'\n]+\')|(\'\')|(\'([\\\\][^a-zA-Z._~^!=&\\^\\-\\\\?\'"x0-7])[^\'\\n]*\'))|(?PL"([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*")|(?P"([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*([\\\\][^a-zA-Z._~^!=&\\^\\-\\\\?\'"x0-7])([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*")|(?P[a-zA-Z_][0-9a-zA-Z_]*)', [None, ('t_INT_CONST_DEC', 'INT_CONST_DEC'), None, None, None, None, None, None, None, None, ('t_CHAR_CONST', 'CHAR_CONST'), None, None, None, None, None, None, ('t_WCHAR_CONST', 'WCHAR_CONST'), None, None, None, None, None, None, ('t_UNMATCHED_QUOTE', 'UNMATCHED_QUOTE'), None, None, None, None, None, None, None, None, None, None, None, None, None, None, ('t_BAD_CHAR_CONST', 'BAD_CHAR_CONST'), None, None, None, None, None, None, None, None, None, None, ('t_WSTRING_LITERAL', 'WSTRING_LITERAL'), None, None, None, None, None, None, ('t_BAD_STRING_LITERAL', 'BAD_STRING_LITERAL'), None, None, None, None, None, None, None, None, None, None, None, None, None, ('t_ID', 'ID')]), ('(?P"([^"\\\\\\n]|(\\\\(([a-zA-Z._~!=&\\^\\-\\\\?\'"])|(\\d+)|(x[0-9a-fA-F]+))))*")|(?P\\.\\.\\.)|(?P\\+\\+)|(?P\\|\\|)|(?P\\^=)|(?P\\|=)|(?P<<=)|(?P>>=)|(?P\\+=)|(?P\\*=)|(?P\\+)|(?P%=)|(?P\\{)|(?P/=)|(?P\\])|(?P\\?)', [None, (None, 'STRING_LITERAL'), None, None, None, None, None, None, (None, 'ELLIPSIS'), (None, 'PLUSPLUS'), (None, 'LOR'), (None, 'XOREQUAL'), (None, 'OREQUAL'), (None, 'LSHIFTEQUAL'), (None, 'RSHIFTEQUAL'), (None, 'PLUSEQUAL'), (None, 'TIMESEQUAL'), (None, 'PLUS'), (None, 'MODEQUAL'), (None, 'LBRACE'), (None, 'DIVEQUAL'), (None, 'RBRACKET'), (None, 'CONDOP')]), ('(?P\\^)|(?P<<)|(?P<=)|(?P\\()|(?P->)|(?P==)|(?P\\})|(?P!=)|(?P--)|(?P\\|)|(?P\\*)|(?P\\[)|(?P>=)|(?P\\))|(?P&&)|(?P>>)|(?P&=)|(?P-=)|(?P\\.)|(?P=)|(?P<)|(?P,)|(?P/)|(?P&)|(?P%)|(?P;)|(?P-)|(?P>)|(?P:)|(?P~)|(?P!)', [None, (None, 'XOR'), (None, 'LSHIFT'), (None, 'LE'), (None, 'LPAREN'), (None, 'ARROW'), (None, 'EQ'), (None, 'RBRACE'), (None, 'NE'), (None, 'MINUSMINUS'), (None, 'OR'), (None, 'TIMES'), (None, 'LBRACKET'), (None, 'GE'), (None, 'RPAREN'), (None, 'LAND'), (None, 'RSHIFT'), (None, 'ANDEQUAL'), (None, 'MINUSEQUAL'), (None, 'PERIOD'), (None, 'EQUALS'), (None, 'LT'), (None, 'COMMA'), (None, 'DIVIDE'), (None, 'AND'), (None, 'MOD'), (None, 'SEMI'), (None, 'MINUS'), (None, 'GT'), (None, 'COLON'), (None, 'NOT'), (None, 'LNOT')])]} -_lexstateignore = {'ppline': ' \t', 'pppragma': ' \t<>.-{}();+-*/$%@&^~!?:,0123456789', 'INITIAL': ' \t'} -_lexstateerrorf = {'ppline': 't_ppline_error', 'pppragma': 't_pppragma_error', 'INITIAL': 't_error'} diff --git a/pypy/module/test_lib_pypy/pyrepl/test_bugs.py b/pypy/module/test_lib_pypy/pyrepl/test_bugs.py --- a/pypy/module/test_lib_pypy/pyrepl/test_bugs.py +++ b/pypy/module/test_lib_pypy/pyrepl/test_bugs.py @@ -24,7 +24,6 @@ # (applicable) bug reports import pytest -import os, sys class HistoricalTestReader(HistoricalReader, BaseTestReader): diff --git a/pypy/module/test_lib_pypy/pyrepl/test_readline.py b/pypy/module/test_lib_pypy/pyrepl/test_readline.py --- a/pypy/module/test_lib_pypy/pyrepl/test_readline.py +++ b/pypy/module/test_lib_pypy/pyrepl/test_readline.py @@ -1,5 +1,4 @@ import pytest -import os, sys @pytest.mark.skipif("os.name != 'posix' or 'darwin' in sys.platform") diff --git a/pypy/module/test_lib_pypy/test_sqlite3.py b/pypy/module/test_lib_pypy/test_sqlite3.py --- a/pypy/module/test_lib_pypy/test_sqlite3.py +++ b/pypy/module/test_lib_pypy/test_sqlite3.py @@ -96,18 +96,6 @@ pytest.raises(_sqlite3.ProgrammingError, "cur.executemany(1,2,3,4,5)") @pytest.mark.skipif("not hasattr(sys, 'pypy_translation_info')") -def test_cursor_del(): - con = _sqlite3.connect(':memory:') - cur = con.execute('select 1') - stmt = cur._Cursor__statement - cur.close() - cur = con.execute('select 1') - assert cur._Cursor__statement is stmt - del cur; import gc; gc.collect(); gc.collect() - cur = con.execute('select 1') - assert cur._Cursor__statement is stmt - - at pytest.mark.skipif("not hasattr(sys, 'pypy_translation_info')") def test_connection_del(tmpdir): """For issue1325.""" import os @@ -205,3 +193,8 @@ con.commit() con.execute('BEGIN') con.commit() + +def test_row_factory_use(): + con = _sqlite3.connect(':memory:') + con.row_factory = 42 + con.execute('select 1') diff --git a/pypy/module/test_lib_pypy/yacctab.py b/pypy/module/test_lib_pypy/yacctab.py deleted file mode 100644 --- a/pypy/module/test_lib_pypy/yacctab.py +++ /dev/null @@ -1,280 +0,0 @@ - -# yacctab.py -# This file is automatically generated. Do not edit. -_tabversion = '3.2' - -_lr_method = 'LALR' - -_lr_signature = '\x9er\xf1|P\xb6\xbb\x13\xed\xf52\xa1\xb1\xc3J\x12' - -_lr_action_items = {'VOID':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[6,6,-61,-72,-71,-58,-54,-55,-33,-29,-59,6,-34,-53,-68,-63,-52,6,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,6,-67,6,-70,-74,6,-57,-82,-249,-81,6,-107,-30,6,-97,-96,6,-45,-46,6,-109,6,6,6,6,-88,6,6,-36,6,-47,6,6,-83,-89,-250,6,-110,6,6,-111,-113,-112,6,6,-98,-37,-39,-42,-38,-40,6,-148,-147,-43,-149,-41,-85,-84,-90,6,6,-100,-99,-167,-166,6,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'LBRACKET':([1,2,3,5,6,9,10,13,14,17,18,19,21,23,24,25,27,28,29,32,33,35,37,39,40,42,43,44,45,46,49,50,51,52,54,55,56,58,59,63,64,66,67,68,69,76,77,83,87,89,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,129,138,139,149,151,152,153,154,155,174,178,180,184,185,191,195,216,217,218,223,224,231,235,262,264,265,273,274,277,281,285,286,314,318,319,323,329,350,351,357,359,360,361,362,366,369,371,387,388,389,390,400,401,409,],[-251,-61,-72,-71,-58,-54,-55,-59,-251,-53,-68,-63,-52,-56,-170,61,-66,-251,-69,-73,-108,-64,-60,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-249,-81,-49,61,-97,-96,-116,-114,-26,-25,-48,-51,-109,-251,-251,-233,-243,-247,-244,-241,-231,-232,182,-240,-220,-237,-245,-238,-242,-239,-230,221,-115,-117,-83,-250,-21,-80,-22,-79,-248,-246,-226,-227,-110,-111,221,-113,-112,221,312,221,-98,325,-237,-85,-84,-225,-224,-223,-234,221,221,312,-100,-99,-132,325,-221,-222,325,-146,-140,-142,-144,-135,325,-133,-141,-143,-145,-134,325,-228,-229,]),'WCHAR_CONST':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,96,-45,-219,96,-217,96,-216,96,-215,96,96,-214,-218,96,96,-250,96,-176,-179,-177,-173,-174,-178,-180,96,-182,-183,-175,-181,96,-215,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,-251,-39,-42,-38,96,-40,96,96,-148,-147,-43,-149,96,-41,96,96,96,-215,96,-12,96,96,-11,-167,-166,96,-164,96,96,-150,96,-163,-151,96,96,96,96,-251,96,-215,-251,-131,-162,-165,96,-154,96,-152,96,96,96,-153,96,96,96,-251,96,-158,-157,-155,96,96,96,-159,-156,96,-161,-160,]),'FLOAT_CONST':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,97,-45,-219,97,-217,97,-216,97,-215,97,97,-214,-218,97,97,-250,97,-176,-179,-177,-173,-174,-178,-180,97,-182,-183,-175,-181,97,-215,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,-251,-39,-42,-38,97,-40,97,97,-148,-147,-43,-149,97,-41,97,97,97,-215,97,-12,97,97,-11,-167,-166,97,-164,97,97,-150,97,-163,-151,97,97,97,97,-251,97,-215,-251,-131,-162,-165,97,-154,97,-152,97,97,97,-153,97,97,97,-251,97,-158,-157,-155,97,97,97,-159,-156,97,-161,-160,]),'MINUS':([55,61,75,91,92,93,94,95,96,97,98,99,100,101,102,104,105,106,108,109,110,111,112,113,114,115,116,117,118,119,120,123,124,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,180,182,183,184,186,187,188,189,190,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,262,270,273,274,277,281,282,283,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,349,350,351,352,353,356,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[-249,100,-45,-219,-206,-233,-243,-247,-244,-241,-231,100,-217,-232,-208,-187,100,-216,100,-240,-215,-220,100,100,-237,-245,-214,-238,200,-242,-239,-218,-230,100,100,-250,100,-176,-179,-177,-173,-174,-178,-180,100,-182,-183,-175,-181,-248,100,-212,-215,-246,-226,100,100,-227,100,-206,-211,100,-209,-210,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,-251,-39,-42,-38,100,-40,100,100,-148,-147,-43,-149,100,-41,-237,100,-225,-224,-223,-234,100,100,200,200,200,-192,200,200,200,-191,200,200,-189,-188,200,200,200,200,200,-190,-215,100,-12,100,100,-11,-167,-166,100,-164,100,100,-150,100,-163,-151,100,100,-213,-221,-222,100,100,-207,-251,100,-215,-251,-131,-162,-165,100,-154,100,-152,100,100,100,-153,100,100,100,-251,-228,100,-158,-157,-155,-229,100,100,100,-159,-156,100,-161,-160,]),'RPAREN':([1,2,3,5,6,9,10,13,14,17,18,19,21,23,24,25,27,28,29,32,33,35,37,39,40,42,43,44,45,46,49,50,51,52,53,54,56,58,59,62,63,64,66,67,68,69,76,77,83,87,89,92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,122,124,125,126,127,128,129,130,131,132,138,139,149,151,152,153,154,155,174,176,178,180,183,184,185,187,188,190,191,192,193,194,195,196,216,217,218,219,220,222,223,224,225,231,247,264,265,271,272,273,274,276,277,278,279,280,281,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,306,307,308,309,313,314,315,316,317,318,319,339,349,350,351,355,356,359,360,361,362,365,378,380,383,384,386,387,388,389,401,404,407,409,410,411,414,],[-251,-61,-72,-71,-58,-54,-55,-59,-251,-53,-68,-63,-52,-56,-170,-106,-66,-251,-69,-73,-108,-64,-60,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,83,-82,-81,-49,-107,-251,-97,-96,-116,-114,-26,-25,-48,-51,-109,-251,-251,-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,-185,-242,-239,-171,-230,216,-15,217,-120,-251,-16,-118,-124,-115,-117,-83,-250,-21,-80,-22,-79,-248,-212,-246,-226,277,-227,-110,-206,-211,-209,-111,281,283,-168,-251,-210,-113,-112,-251,-123,-2,-122,-139,-137,-1,-98,-14,-85,-84,-172,349,-225,-224,-235,-223,351,353,354,-234,-136,-251,-137,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-19,-20,359,360,-251,-138,-125,-119,-121,-100,-99,-13,-213,-221,-222,-169,-207,-146,-140,-142,-144,389,395,397,399,-236,-186,-141,-143,-145,-228,-251,412,-229,-251,415,418,]),'LONG':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[19,19,-61,-72,-71,-58,-54,-55,-33,-29,-59,19,-34,-53,-68,-63,-52,19,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,19,-67,19,-70,-74,19,-57,-82,-249,-81,19,-107,-30,19,-97,-96,19,-45,-46,19,-109,19,19,19,19,-88,19,19,-36,19,-47,19,19,-83,-89,-250,19,-110,19,19,-111,-113,-112,19,19,-98,-37,-39,-42,-38,-40,19,-148,-147,-43,-149,-41,-85,-84,-90,19,19,-100,-99,-167,-166,19,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'PLUS':([55,61,75,91,92,93,94,95,96,97,98,99,100,101,102,104,105,106,108,109,110,111,112,113,114,115,116,117,118,119,120,123,124,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,180,182,183,184,186,187,188,189,190,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,262,270,273,274,277,281,282,283,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,349,350,351,352,353,356,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[-249,106,-45,-219,-206,-233,-243,-247,-244,-241,-231,106,-217,-232,-208,-187,106,-216,106,-240,-215,-220,106,106,-237,-245,-214,-238,204,-242,-239,-218,-230,106,106,-250,106,-176,-179,-177,-173,-174,-178,-180,106,-182,-183,-175,-181,-248,106,-212,-215,-246,-226,106,106,-227,106,-206,-211,106,-209,-210,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,-251,-39,-42,-38,106,-40,106,106,-148,-147,-43,-149,106,-41,-237,106,-225,-224,-223,-234,106,106,204,204,204,-192,204,204,204,-191,204,204,-189,-188,204,204,204,204,204,-190,-215,106,-12,106,106,-11,-167,-166,106,-164,106,106,-150,106,-163,-151,106,106,-213,-221,-222,106,106,-207,-251,106,-215,-251,-131,-162,-165,106,-154,106,-152,106,106,106,-153,106,106,106,-251,-228,106,-158,-157,-155,-229,106,106,106,-159,-156,106,-161,-160,]),'ELLIPSIS':([227,],[316,]),'GT':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,205,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,205,-194,-192,-196,205,-195,-191,-198,205,-189,-188,-197,205,205,205,205,-190,-213,-221,-222,-207,-228,-229,]),'GOTO':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,240,-250,-39,-42,-38,-40,240,-148,-147,-43,-149,240,-41,-167,-166,-164,240,-150,-163,-151,240,-162,-165,-154,240,-152,240,-153,240,240,-158,-157,-155,240,240,-159,-156,240,-161,-160,]),'ENUM':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[26,26,-61,-72,-71,-58,-54,-55,-33,-29,-59,26,-34,-53,-68,-63,-52,26,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,26,-67,26,-70,-74,26,-57,-82,-249,-81,26,-107,-30,26,-97,-96,26,-45,-46,26,-109,26,26,26,26,-88,26,26,-36,26,-47,26,26,-83,-89,-250,26,-110,26,26,-111,-113,-112,26,26,-98,-37,-39,-42,-38,-40,26,-148,-147,-43,-149,-41,-85,-84,-90,26,26,-100,-99,-167,-166,26,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'PERIOD':([55,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,178,180,184,235,262,273,274,277,281,323,329,350,351,357,366,369,371,390,400,401,409,],[-249,-233,-243,-247,-244,-241,-231,-232,181,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-246,-226,-227,324,-237,-225,-224,-223,-234,-132,324,-221,-222,324,-135,324,-133,-134,324,-228,-229,]),'GE':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,209,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,209,-194,-192,-196,209,-195,-191,-198,209,-189,-188,-197,209,209,209,209,-190,-213,-221,-222,-207,-228,-229,]),'INT_CONST_DEC':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,117,-45,-219,117,-217,117,-216,117,-215,117,117,-214,-218,117,117,-250,117,-176,-179,-177,-173,-174,-178,-180,117,-182,-183,-175,-181,117,-215,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,-251,-39,-42,-38,117,-40,117,117,-148,-147,-43,-149,117,-41,117,117,117,-215,117,-12,117,117,-11,-167,-166,117,-164,117,117,-150,117,-163,-151,117,117,117,117,-251,117,-215,-251,-131,-162,-165,117,-154,117,-152,117,117,117,-153,117,117,117,-251,117,-158,-157,-155,117,117,117,-159,-156,117,-161,-160,]),'ARROW':([93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,178,180,184,262,273,274,277,281,350,351,401,409,],[-233,-243,-247,-244,-241,-231,-232,179,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-246,-226,-227,-237,-225,-224,-223,-234,-221,-222,-228,-229,]),'HEX_FLOAT_CONST':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,119,-45,-219,119,-217,119,-216,119,-215,119,119,-214,-218,119,119,-250,119,-176,-179,-177,-173,-174,-178,-180,119,-182,-183,-175,-181,119,-215,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,-251,-39,-42,-38,119,-40,119,119,-148,-147,-43,-149,119,-41,119,119,119,-215,119,-12,119,119,-11,-167,-166,119,-164,119,119,-150,119,-163,-151,119,119,119,119,-251,119,-215,-251,-131,-162,-165,119,-154,119,-152,119,119,119,-153,119,119,119,-251,119,-158,-157,-155,119,119,119,-159,-156,119,-161,-160,]),'DOUBLE':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[40,40,-61,-72,-71,-58,-54,-55,-33,-29,-59,40,-34,-53,-68,-63,-52,40,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,40,-67,40,-70,-74,40,-57,-82,-249,-81,40,-107,-30,40,-97,-96,40,-45,-46,40,-109,40,40,40,40,-88,40,40,-36,40,-47,40,40,-83,-89,-250,40,-110,40,40,-111,-113,-112,40,40,-98,-37,-39,-42,-38,-40,40,-148,-147,-43,-149,-41,-85,-84,-90,40,40,-100,-99,-167,-166,40,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'MINUSEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[163,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'INT_CONST_OCT':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,120,-45,-219,120,-217,120,-216,120,-215,120,120,-214,-218,120,120,-250,120,-176,-179,-177,-173,-174,-178,-180,120,-182,-183,-175,-181,120,-215,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,-251,-39,-42,-38,120,-40,120,120,-148,-147,-43,-149,120,-41,120,120,120,-215,120,-12,120,120,-11,-167,-166,120,-164,120,120,-150,120,-163,-151,120,120,120,120,-251,120,-215,-251,-131,-162,-165,120,-154,120,-152,120,120,120,-153,120,120,120,-251,120,-158,-157,-155,120,120,120,-159,-156,120,-161,-160,]),'TIMESEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[172,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'OR':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,214,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,214,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,214,-199,-201,-202,-190,-213,-221,-222,-207,-228,-229,]),'SHORT':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[2,2,-61,-72,-71,-58,-54,-55,-33,-29,-59,2,-34,-53,-68,-63,-52,2,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,2,-67,2,-70,-74,2,-57,-82,-249,-81,2,-107,-30,2,-97,-96,2,-45,-46,2,-109,2,2,2,2,-88,2,2,-36,2,-47,2,2,-83,-89,-250,2,-110,2,2,-111,-113,-112,2,2,-98,-37,-39,-42,-38,-40,2,-148,-147,-43,-149,-41,-85,-84,-90,2,2,-100,-99,-167,-166,2,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'RETURN':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,243,-250,-39,-42,-38,-40,243,-148,-147,-43,-149,243,-41,-167,-166,-164,243,-150,-163,-151,243,-162,-165,-154,243,-152,243,-153,243,243,-158,-157,-155,243,243,-159,-156,243,-161,-160,]),'RSHIFTEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[173,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'RESTRICT':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,28,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,66,68,73,75,80,82,83,84,85,86,87,88,89,112,139,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[32,32,-61,-72,-71,-58,-54,-55,-33,-29,-59,32,-34,-53,-68,-63,-52,32,-56,-170,-106,-66,32,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,32,-67,32,-70,-74,32,-57,-82,-249,-81,32,-107,-30,32,-97,-96,-116,32,32,-45,-46,32,-109,32,32,32,32,-88,32,32,-117,-36,32,-47,32,32,-83,-89,-250,32,-110,32,32,-111,-113,-112,32,32,-98,-37,-39,-42,-38,-40,32,-148,-147,-43,-149,-41,-85,-84,-90,32,32,-100,-99,-167,-166,32,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'STATIC':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[9,9,-61,-72,-71,-58,-54,-55,-33,-29,-59,9,-34,-53,-68,-63,-52,9,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,9,-67,9,-70,-74,9,-57,-82,-249,-81,-107,-30,9,-97,-96,9,-45,-46,9,-109,-36,9,-47,-83,-250,-110,-111,-113,-112,9,9,-98,-37,-39,-42,-38,-40,9,-148,-147,-43,-149,-41,-85,-84,9,9,-100,-99,-167,-166,9,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'SIZEOF':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,99,-45,-219,99,-217,99,-216,99,-215,99,99,-214,-218,99,99,-250,99,-176,-179,-177,-173,-174,-178,-180,99,-182,-183,-175,-181,99,-215,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,-251,-39,-42,-38,99,-40,99,99,-148,-147,-43,-149,99,-41,99,99,99,-215,99,-12,99,99,-11,-167,-166,99,-164,99,99,-150,99,-163,-151,99,99,99,99,-251,99,-215,-251,-131,-162,-165,99,-154,99,-152,99,99,99,-153,99,99,99,-251,99,-158,-157,-155,99,99,99,-159,-156,99,-161,-160,]),'UNSIGNED':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[18,18,-61,-72,-71,-58,-54,-55,-33,-29,-59,18,-34,-53,-68,-63,-52,18,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,18,-67,18,-70,-74,18,-57,-82,-249,-81,18,-107,-30,18,-97,-96,18,-45,-46,18,-109,18,18,18,18,-88,18,18,-36,18,-47,18,18,-83,-89,-250,18,-110,18,18,-111,-113,-112,18,18,-98,-37,-39,-42,-38,-40,18,-148,-147,-43,-149,-41,-85,-84,-90,18,18,-100,-99,-167,-166,18,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'UNION':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[20,20,-61,-72,-71,-58,-54,-55,-33,-29,-59,20,-34,-53,-68,-63,-52,20,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,20,-67,20,-70,-74,20,-57,-82,-249,-81,20,-107,-30,20,-97,-96,20,-45,-46,20,-109,20,20,20,20,-88,20,20,-36,20,-47,20,20,-83,-89,-250,20,-110,20,20,-111,-113,-112,20,20,-98,-37,-39,-42,-38,-40,20,-148,-147,-43,-149,-41,-85,-84,-90,20,20,-100,-99,-167,-166,20,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'COLON':([2,3,5,6,13,18,19,24,25,27,29,32,33,35,37,39,40,43,45,46,54,56,59,63,64,83,87,89,90,92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,122,124,149,151,152,153,154,155,161,174,176,178,180,184,185,187,188,190,191,194,196,216,217,231,248,262,264,265,267,268,271,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,318,319,338,349,350,351,355,356,386,401,409,],[-61,-72,-71,-58,-59,-68,-63,-170,-106,-66,-69,-73,-108,-64,-60,-62,-65,-67,-70,-74,-82,-81,-107,-97,-96,-109,-251,-251,156,-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,-185,-242,-239,-171,-230,-83,-250,-21,-80,-22,-79,270,-248,-212,-246,-226,-227,-110,-206,-211,-209,-111,-168,-210,-113,-112,-98,336,345,-85,-84,-184,156,-172,-225,-224,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,358,-202,-190,-100,-99,379,-213,-221,-222,-169,-207,-186,-228,-229,]),'$end':([0,8,11,12,15,22,31,36,38,47,60,75,144,151,237,344,],[-251,0,-33,-29,-34,-27,-32,-31,-35,-28,-30,-45,-36,-250,-37,-151,]),'WSTRING_LITERAL':([55,61,75,91,93,95,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,95,-45,-219,174,-247,95,-217,95,-216,95,-215,95,95,-214,-218,95,95,-250,95,-176,-179,-177,-173,-174,-178,-180,95,-182,-183,-175,-181,-248,95,-215,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,-251,-39,-42,-38,95,-40,95,95,-148,-147,-43,-149,95,-41,95,95,95,-215,95,-12,95,95,-11,-167,-166,95,-164,95,95,-150,95,-163,-151,95,95,95,95,-251,95,-215,-251,-131,-162,-165,95,-154,95,-152,95,95,95,-153,95,95,95,-251,95,-158,-157,-155,95,95,95,-159,-156,95,-161,-160,]),'DIVIDE':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,207,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,207,207,207,207,207,207,207,207,207,207,-189,-188,207,207,207,207,207,-190,-213,-221,-222,-207,-228,-229,]),'FOR':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,245,-250,-39,-42,-38,-40,245,-148,-147,-43,-149,245,-41,-167,-166,-164,245,-150,-163,-151,245,-162,-165,-154,245,-152,245,-153,245,245,-158,-157,-155,245,245,-159,-156,245,-161,-160,]),'PLUSPLUS':([55,61,75,91,93,94,95,96,97,98,99,100,101,102,105,106,108,109,110,111,112,113,114,115,116,117,119,120,123,124,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,177,178,180,182,183,184,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,262,270,273,274,277,281,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,350,351,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[-249,108,-45,-219,-233,-243,-247,-244,-241,-231,108,-217,-232,180,108,-216,108,-240,-215,-220,108,108,-237,-245,-214,-238,-242,-239,-218,-230,108,108,-250,108,-176,-179,-177,-173,-174,-178,-180,108,-182,-183,-175,-181,-248,108,-215,-246,-226,108,108,-227,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,-251,-39,-42,-38,108,-40,108,108,-148,-147,-43,-149,108,-41,-237,108,-225,-224,-223,-234,108,108,-215,108,-12,108,108,-11,-167,-166,108,-164,108,108,-150,108,-163,-151,108,108,-221,-222,108,108,-251,108,-215,-251,-131,-162,-165,108,-154,108,-152,108,108,108,-153,108,108,108,-251,-228,108,-158,-157,-155,-229,108,108,108,-159,-156,108,-161,-160,]),'EQUALS':([25,33,59,73,83,92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,137,143,151,174,176,178,180,184,185,187,188,190,191,196,216,217,262,273,274,277,281,323,329,349,350,351,356,366,371,390,401,409,],[-106,-108,-107,141,-109,165,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,232,141,-250,-248,-212,-246,-226,-227,-110,-206,-211,-209,-111,-210,-113,-112,-237,-225,-224,-223,-234,-132,372,-213,-221,-222,-207,-135,-133,-134,-228,-229,]),'ELSE':([151,238,239,242,244,255,260,331,332,335,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[-250,-39,-42,-38,-40,-43,-41,-167,-166,-164,-163,-151,-162,-165,-154,-152,-153,-158,-157,413,-159,-156,-161,-160,]),'ANDEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[170,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'EQ':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,211,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,211,-194,-192,-196,-200,-195,-191,-198,211,-189,-188,-197,211,-199,211,211,-190,-213,-221,-222,-207,-228,-229,]),'AND':([55,61,75,91,92,93,94,95,96,97,98,99,100,101,102,104,105,106,108,109,110,111,112,113,114,115,116,117,118,119,120,123,124,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,180,182,183,184,186,187,188,189,190,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,262,270,273,274,277,281,282,283,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,349,350,351,352,353,356,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[-249,116,-45,-219,-206,-233,-243,-247,-244,-241,-231,116,-217,-232,-208,-187,116,-216,116,-240,-215,-220,116,116,-237,-245,-214,-238,212,-242,-239,-218,-230,116,116,-250,116,-176,-179,-177,-173,-174,-178,-180,116,-182,-183,-175,-181,-248,116,-212,-215,-246,-226,116,116,-227,116,-206,-211,116,-209,-210,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,-251,-39,-42,-38,116,-40,116,116,-148,-147,-43,-149,116,-41,-237,116,-225,-224,-223,-234,116,116,-193,212,-194,-192,-196,-200,-195,-191,-198,212,-189,-188,-197,212,-199,-201,212,-190,-215,116,-12,116,116,-11,-167,-166,116,-164,116,116,-150,116,-163,-151,116,116,-213,-221,-222,116,116,-207,-251,116,-215,-251,-131,-162,-165,116,-154,116,-152,116,116,116,-153,116,116,116,-251,-228,116,-158,-157,-155,-229,116,116,116,-159,-156,116,-161,-160,]),'TYPEID':([0,1,2,3,5,6,7,9,10,11,12,13,14,15,17,18,19,20,21,22,23,24,25,26,27,29,31,32,33,34,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[24,24,-61,-72,-71,-58,54,-54,-55,-33,-29,-59,24,-34,-53,-68,-63,-87,-52,24,-56,-170,-106,63,-66,-69,-32,-73,-108,-86,-64,-31,-60,-35,-62,-65,24,-67,24,-70,-74,24,-57,-82,-249,-81,24,-107,-30,24,-97,-96,24,-45,-46,24,-109,24,24,24,24,-88,24,24,-36,24,-47,24,24,-83,-89,-250,24,-110,24,24,-111,-113,-112,24,24,-98,-37,-39,-42,-38,-40,24,-148,-147,-43,-149,-41,-85,-84,-90,24,24,-100,-99,-167,-166,24,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'LBRACE':([7,20,25,26,33,34,48,54,55,56,59,63,64,73,75,78,80,81,82,83,141,142,145,146,151,185,191,216,217,235,238,239,242,244,251,253,254,255,257,259,260,283,322,326,327,331,332,335,336,340,342,344,345,349,353,354,357,369,372,373,374,377,379,382,391,395,396,397,399,400,405,406,408,413,415,416,417,418,419,420,],[55,-87,-106,55,-108,-86,-251,55,-249,55,-107,55,55,-251,-45,-7,-46,55,-8,-109,55,55,55,-47,-250,-110,-111,-113,-112,-251,-39,-42,-38,-40,55,-148,-147,-43,-149,55,-41,55,-12,55,-11,-167,-166,-164,55,-150,-163,-151,55,55,55,55,-251,-251,-131,-162,-165,-154,55,-152,55,55,-153,55,55,-251,-158,-157,-155,55,55,-159,-156,55,-161,-160,]),'PPHASH':([0,11,12,15,22,31,36,38,60,75,144,151,237,344,],[38,-33,-29,-34,38,-32,-31,-35,-30,-45,-36,-250,-37,-151,]),'INT':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[39,39,-61,-72,-71,-58,-54,-55,-33,-29,-59,39,-34,-53,-68,-63,-52,39,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,39,-67,39,-70,-74,39,-57,-82,-249,-81,39,-107,-30,39,-97,-96,39,-45,-46,39,-109,39,39,39,39,-88,39,39,-36,39,-47,39,39,-83,-89,-250,39,-110,39,39,-111,-113,-112,39,39,-98,-37,-39,-42,-38,-40,39,-148,-147,-43,-149,-41,-85,-84,-90,39,39,-100,-99,-167,-166,39,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'SIGNED':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[43,43,-61,-72,-71,-58,-54,-55,-33,-29,-59,43,-34,-53,-68,-63,-52,43,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,43,-67,43,-70,-74,43,-57,-82,-249,-81,43,-107,-30,43,-97,-96,43,-45,-46,43,-109,43,43,43,43,-88,43,43,-36,43,-47,43,43,-83,-89,-250,43,-110,43,43,-111,-113,-112,43,43,-98,-37,-39,-42,-38,-40,43,-148,-147,-43,-149,-41,-85,-84,-90,43,43,-100,-99,-167,-166,43,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'CONTINUE':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,246,-250,-39,-42,-38,-40,246,-148,-147,-43,-149,246,-41,-167,-166,-164,246,-150,-163,-151,246,-162,-165,-154,246,-152,246,-153,246,246,-158,-157,-155,246,246,-159,-156,246,-161,-160,]),'NOT':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,123,-45,-219,123,-217,123,-216,123,-215,123,123,-214,-218,123,123,-250,123,-176,-179,-177,-173,-174,-178,-180,123,-182,-183,-175,-181,123,-215,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,-251,-39,-42,-38,123,-40,123,123,-148,-147,-43,-149,123,-41,123,123,123,-215,123,-12,123,123,-11,-167,-166,123,-164,123,123,-150,123,-163,-151,123,123,123,123,-251,123,-215,-251,-131,-162,-165,123,-154,123,-152,123,123,123,-153,123,123,123,-251,123,-158,-157,-155,123,123,123,-159,-156,123,-161,-160,]),'OREQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[171,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'MOD':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,215,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,215,215,215,215,215,215,215,215,215,215,-189,-188,215,215,215,215,215,-190,-213,-221,-222,-207,-228,-229,]),'RSHIFT':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,197,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,197,-194,-192,197,197,197,-191,197,197,-189,-188,197,197,197,197,197,-190,-213,-221,-222,-207,-228,-229,]),'DEFAULT':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,248,-250,-39,-42,-38,-40,248,-148,-147,-43,-149,248,-41,-167,-166,-164,248,-150,-163,-151,248,-162,-165,-154,248,-152,248,-153,248,248,-158,-157,-155,248,248,-159,-156,248,-161,-160,]),'CHAR':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[37,37,-61,-72,-71,-58,-54,-55,-33,-29,-59,37,-34,-53,-68,-63,-52,37,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,37,-67,37,-70,-74,37,-57,-82,-249,-81,37,-107,-30,37,-97,-96,37,-45,-46,37,-109,37,37,37,37,-88,37,37,-36,37,-47,37,37,-83,-89,-250,37,-110,37,37,-111,-113,-112,37,37,-98,-37,-39,-42,-38,-40,37,-148,-147,-43,-149,-41,-85,-84,-90,37,37,-100,-99,-167,-166,37,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'WHILE':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,343,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,249,-250,-39,-42,-38,-40,249,-148,-147,-43,-149,249,-41,-167,-166,-164,249,-150,-163,381,-151,249,-162,-165,-154,249,-152,249,-153,249,249,-158,-157,-155,249,249,-159,-156,249,-161,-160,]),'DIVEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[162,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'EXTERN':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[10,10,-61,-72,-71,-58,-54,-55,-33,-29,-59,10,-34,-53,-68,-63,-52,10,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,10,-67,10,-70,-74,10,-57,-82,-249,-81,-107,-30,10,-97,-96,10,-45,-46,10,-109,-36,10,-47,-83,-250,-110,-111,-113,-112,10,10,-98,-37,-39,-42,-38,-40,10,-148,-147,-43,-149,-41,-85,-84,10,10,-100,-99,-167,-166,10,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'CASE':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,250,-250,-39,-42,-38,-40,250,-148,-147,-43,-149,250,-41,-167,-166,-164,250,-150,-163,-151,250,-162,-165,-154,250,-152,250,-153,250,250,-158,-157,-155,250,250,-159,-156,250,-161,-160,]),'LAND':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,210,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,210,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-213,-221,-222,-207,-228,-229,]),'REGISTER':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[17,17,-61,-72,-71,-58,-54,-55,-33,-29,-59,17,-34,-53,-68,-63,-52,17,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,17,-67,17,-70,-74,17,-57,-82,-249,-81,-107,-30,17,-97,-96,17,-45,-46,17,-109,-36,17,-47,-83,-250,-110,-111,-113,-112,17,17,-98,-37,-39,-42,-38,-40,17,-148,-147,-43,-149,-41,-85,-84,17,17,-100,-99,-167,-166,17,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'MODEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[164,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'NE':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,202,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,202,-194,-192,-196,-200,-195,-191,-198,202,-189,-188,-197,202,-199,202,202,-190,-213,-221,-222,-207,-228,-229,]),'SWITCH':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,252,-250,-39,-42,-38,-40,252,-148,-147,-43,-149,252,-41,-167,-166,-164,252,-150,-163,-151,252,-162,-165,-154,252,-152,252,-153,252,252,-158,-157,-155,252,252,-159,-156,252,-161,-160,]),'INT_CONST_HEX':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,109,-45,-219,109,-217,109,-216,109,-215,109,109,-214,-218,109,109,-250,109,-176,-179,-177,-173,-174,-178,-180,109,-182,-183,-175,-181,109,-215,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,-251,-39,-42,-38,109,-40,109,109,-148,-147,-43,-149,109,-41,109,109,109,-215,109,-12,109,109,-11,-167,-166,109,-164,109,109,-150,109,-163,-151,109,109,109,109,-251,109,-215,-251,-131,-162,-165,109,-154,109,-152,109,109,109,-153,109,109,109,-251,109,-158,-157,-155,109,109,109,-159,-156,109,-161,-160,]),'_COMPLEX':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[27,27,-61,-72,-71,-58,-54,-55,-33,-29,-59,27,-34,-53,-68,-63,-52,27,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,27,-67,27,-70,-74,27,-57,-82,-249,-81,27,-107,-30,27,-97,-96,27,-45,-46,27,-109,27,27,27,27,-88,27,27,-36,27,-47,27,27,-83,-89,-250,27,-110,27,27,-111,-113,-112,27,27,-98,-37,-39,-42,-38,-40,27,-148,-147,-43,-149,-41,-85,-84,-90,27,27,-100,-99,-167,-166,27,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'PLUSEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[167,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'STRUCT':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[34,34,-61,-72,-71,-58,-54,-55,-33,-29,-59,34,-34,-53,-68,-63,-52,34,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,34,-67,34,-70,-74,34,-57,-82,-249,-81,34,-107,-30,34,-97,-96,34,-45,-46,34,-109,34,34,34,34,-88,34,34,-36,34,-47,34,34,-83,-89,-250,34,-110,34,34,-111,-113,-112,34,34,-98,-37,-39,-42,-38,-40,34,-148,-147,-43,-149,-41,-85,-84,-90,34,34,-100,-99,-167,-166,34,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'CONDOP':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,213,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-213,-221,-222,-207,-228,-229,]),'BREAK':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,256,-250,-39,-42,-38,-40,256,-148,-147,-43,-149,256,-41,-167,-166,-164,256,-150,-163,-151,256,-162,-165,-154,256,-152,256,-153,256,256,-158,-157,-155,256,256,-159,-156,256,-161,-160,]),'VOLATILE':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,28,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,66,68,73,75,80,82,83,84,85,86,87,88,89,112,139,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[46,46,-61,-72,-71,-58,-54,-55,-33,-29,-59,46,-34,-53,-68,-63,-52,46,-56,-170,-106,-66,46,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,46,-67,46,-70,-74,46,-57,-82,-249,-81,46,-107,-30,46,-97,-96,-116,46,46,-45,-46,46,-109,46,46,46,46,-88,46,46,-117,-36,46,-47,46,46,-83,-89,-250,46,-110,46,46,-111,-113,-112,46,46,-98,-37,-39,-42,-38,-40,46,-148,-147,-43,-149,-41,-85,-84,-90,46,46,-100,-99,-167,-166,46,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'INLINE':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[49,49,-61,-72,-71,-58,-54,-55,-33,-29,-59,49,-34,-53,-68,-63,-52,49,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,49,-67,49,-70,-74,49,-57,-82,-249,-81,-107,-30,49,-97,-96,49,-45,-46,49,-109,-36,49,-47,-83,-250,-110,-111,-113,-112,49,49,-98,-37,-39,-42,-38,-40,49,-148,-147,-43,-149,-41,-85,-84,49,49,-100,-99,-167,-166,49,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'DO':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,259,-250,-39,-42,-38,-40,259,-148,-147,-43,-149,259,-41,-167,-166,-164,259,-150,-163,-151,259,-162,-165,-154,259,-152,259,-153,259,259,-158,-157,-155,259,259,-159,-156,259,-161,-160,]),'LNOT':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,91,-45,-219,91,-217,91,-216,91,-215,91,91,-214,-218,91,91,-250,91,-176,-179,-177,-173,-174,-178,-180,91,-182,-183,-175,-181,91,-215,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,-251,-39,-42,-38,91,-40,91,91,-148,-147,-43,-149,91,-41,91,91,91,-215,91,-12,91,91,-11,-167,-166,91,-164,91,91,-150,91,-163,-151,91,91,91,91,-251,91,-215,-251,-131,-162,-165,91,-154,91,-152,91,91,91,-153,91,91,91,-251,91,-158,-157,-155,91,91,91,-159,-156,91,-161,-160,]),'CONST':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,28,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,66,68,73,75,80,82,83,84,85,86,87,88,89,112,139,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[3,3,-61,-72,-71,-58,-54,-55,-33,-29,-59,3,-34,-53,-68,-63,-52,3,-56,-170,-106,-66,3,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,3,-67,3,-70,-74,3,-57,-82,-249,-81,3,-107,-30,3,-97,-96,-116,3,3,-45,-46,3,-109,3,3,3,3,-88,3,3,-117,-36,3,-47,3,3,-83,-89,-250,3,-110,3,3,-111,-113,-112,3,3,-98,-37,-39,-42,-38,-40,3,-148,-147,-43,-149,-41,-85,-84,-90,3,3,-100,-99,-167,-166,3,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'LOR':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,198,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-213,-221,-222,-207,-228,-229,]),'CHAR_CONST':([55,61,75,91,99,100,105,106,108,110,112,113,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,94,-45,-219,94,-217,94,-216,94,-215,94,94,-214,-218,94,94,-250,94,-176,-179,-177,-173,-174,-178,-180,94,-182,-183,-175,-181,94,-215,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,-251,-39,-42,-38,94,-40,94,94,-148,-147,-43,-149,94,-41,94,94,94,-215,94,-12,94,94,-11,-167,-166,94,-164,94,94,-150,94,-163,-151,94,94,94,94,-251,94,-215,-251,-131,-162,-165,94,-154,94,-152,94,94,94,-153,94,94,94,-251,94,-158,-157,-155,94,94,94,-159,-156,94,-161,-160,]),'LSHIFT':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,199,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,199,-194,-192,199,199,199,-191,199,199,-189,-188,199,199,199,199,199,-190,-213,-221,-222,-207,-228,-229,]),'RBRACE':([55,75,86,88,92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,122,124,135,136,137,145,147,148,150,151,174,176,178,180,184,187,188,190,196,228,229,230,236,238,239,242,244,251,253,254,255,257,258,260,261,267,269,271,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,320,321,328,331,332,335,340,342,344,349,350,351,356,368,369,370,373,374,377,382,385,386,392,396,400,401,402,405,406,408,409,416,417,419,420,],[-249,-45,151,-88,-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,-185,-242,-239,-171,-230,-101,151,-104,-251,151,151,-89,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,151,151,-102,-126,-39,-42,-38,-40,-6,-148,-147,-43,-149,-5,-41,151,-184,-90,-172,-225,-224,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-103,-105,151,-167,-166,-164,-150,-163,-151,-213,-221,-222,-207,-129,151,-127,-162,-165,-154,-152,151,-186,-128,-153,151,-228,-130,-158,-157,-155,-229,-159,-156,-161,-160,]),'_BOOL':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[13,13,-61,-72,-71,-58,-54,-55,-33,-29,-59,13,-34,-53,-68,-63,-52,13,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,13,-67,13,-70,-74,13,-57,-82,-249,-81,13,-107,-30,13,-97,-96,13,-45,-46,13,-109,13,13,13,13,-88,13,13,-36,13,-47,13,13,-83,-89,-250,13,-110,13,13,-111,-113,-112,13,13,-98,-37,-39,-42,-38,-40,13,-148,-147,-43,-149,-41,-85,-84,-90,13,13,-100,-99,-167,-166,13,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'LE':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,201,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,201,-194,-192,-196,201,-195,-191,-198,201,-189,-188,-197,201,201,201,201,-190,-213,-221,-222,-207,-228,-229,]),'SEMI':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,30,31,32,33,35,36,37,38,39,40,41,42,43,44,45,46,49,50,51,52,54,55,56,58,59,60,63,64,70,71,72,73,74,75,76,77,79,83,87,89,90,92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,122,124,143,144,145,149,151,152,153,154,155,157,158,159,160,161,174,176,178,180,184,185,187,188,190,191,194,196,216,217,231,233,234,236,237,238,239,241,242,243,244,246,247,251,253,254,255,256,257,258,259,260,262,264,265,266,267,271,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,318,319,330,331,332,333,334,335,336,339,340,342,344,345,347,348,349,350,351,355,356,370,373,374,375,376,377,379,382,386,392,393,394,395,396,397,399,401,403,405,406,408,409,412,413,415,416,417,418,419,420,],[15,-251,-61,-72,-71,-58,-54,-55,-33,-29,-59,-251,-34,-53,-68,-63,-52,15,-56,-170,-106,-66,-69,-251,-32,-73,-108,-64,-31,-60,-35,-62,-65,75,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-249,-81,-49,-107,-30,-97,-96,-18,-44,-17,-77,-75,-45,-48,-51,-251,-109,-251,-251,-251,-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,-185,-242,-239,-171,-230,-77,-36,-251,-83,-250,-21,-80,-22,-79,-24,269,-91,-23,-93,-248,-212,-246,-226,-227,-110,-206,-211,-209,-111,-168,-210,-113,-112,-98,-76,-78,-126,-37,-39,-42,331,-38,332,-40,335,-14,-251,-148,-147,-43,342,-149,-13,-251,-41,-237,-85,-84,-95,-184,-172,-225,-224,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,-100,-99,373,-167,-166,374,-251,-164,-251,-13,-150,-163,-151,-251,-92,-94,-213,-221,-222,-169,-207,-127,-162,-165,393,-251,-154,-251,-152,-186,-128,-251,404,-251,-153,-251,-251,-228,410,-158,-157,-155,-229,416,-251,-251,-159,-156,-251,-161,-160,]),'LT':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,203,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,203,-194,-192,-196,203,-195,-191,-198,203,-189,-188,-197,203,203,203,203,-190,-213,-221,-222,-207,-228,-229,]),'COMMA':([1,2,3,5,6,9,10,13,14,17,18,19,21,23,24,25,27,28,29,32,33,35,37,39,40,42,43,44,45,46,49,50,51,52,54,56,58,59,63,64,66,67,68,69,70,73,74,76,77,83,92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,122,124,128,129,130,131,132,135,136,137,138,139,143,149,151,157,159,161,174,176,178,180,184,185,187,188,190,191,192,194,196,216,217,219,220,222,223,224,225,228,229,230,231,233,234,236,247,262,264,265,266,267,271,273,274,275,276,277,278,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,314,315,317,318,319,320,321,328,333,347,348,349,350,351,355,356,359,360,361,362,368,370,378,380,383,384,385,386,387,388,389,392,401,402,407,409,],[-251,-61,-72,-71,-58,-54,-55,-59,-251,-53,-68,-63,-52,-56,-170,-106,-66,-251,-69,-73,-108,-64,-60,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-81,-49,-107,-97,-96,-116,-114,-26,-25,140,-77,-75,-48,-51,-109,-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,-185,-242,-239,-171,-230,-120,-251,226,227,-124,-101,230,-104,-115,-117,-77,-83,-250,268,-91,-93,-248,-212,-246,-226,-227,-110,-206,-211,-209,-111,282,-168,-210,-113,-112,-123,-2,-122,-139,-137,-1,230,230,-102,-98,-76,-78,-126,282,-237,-85,-84,-95,-184,-172,-225,-224,282,-235,-223,352,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,282,-202,-190,-138,-125,-121,-100,-99,-103,-105,369,282,-92,-94,-213,-221,-222,-169,-207,-146,-140,-142,-144,-129,-127,282,282,282,-236,400,-186,-141,-143,-145,-128,-228,-130,282,-229,]),'TYPEDEF':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[23,23,-61,-72,-71,-58,-54,-55,-33,-29,-59,23,-34,-53,-68,-63,-52,23,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,23,-67,23,-70,-74,23,-57,-82,-249,-81,-107,-30,23,-97,-96,23,-45,-46,23,-109,-36,23,-47,-83,-250,-110,-111,-113,-112,23,23,-98,-37,-39,-42,-38,-40,23,-148,-147,-43,-149,-41,-85,-84,23,23,-100,-99,-167,-166,23,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'XOR':([92,93,94,95,96,97,98,101,102,104,109,111,114,115,117,118,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,349,350,351,356,401,409,],[-206,-233,-243,-247,-244,-241,-231,-232,-208,-187,-240,-220,-237,-245,-238,206,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-193,206,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,206,-199,-201,206,-190,-213,-221,-222,-207,-228,-229,]),'AUTO':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,59,60,62,63,64,73,75,80,82,83,144,145,146,149,151,185,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[21,21,-61,-72,-71,-58,-54,-55,-33,-29,-59,21,-34,-53,-68,-63,-52,21,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,21,-67,21,-70,-74,21,-57,-82,-249,-81,-107,-30,21,-97,-96,21,-45,-46,21,-109,-36,21,-47,-83,-250,-110,-111,-113,-112,21,21,-98,-37,-39,-42,-38,-40,21,-148,-147,-43,-149,-41,-85,-84,21,21,-100,-99,-167,-166,21,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'TIMES':([0,1,2,3,4,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,27,28,29,30,31,32,35,36,37,38,39,40,42,43,44,45,46,49,50,51,52,54,55,56,58,60,61,63,64,66,67,68,69,75,76,77,79,87,89,90,91,92,93,94,95,96,97,98,99,100,101,102,104,105,106,108,109,110,111,112,113,114,115,116,117,118,119,120,123,124,129,139,140,141,144,145,149,151,152,153,154,155,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,180,182,183,184,186,187,188,189,190,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,218,221,231,232,235,237,238,239,242,243,244,250,251,253,254,255,257,259,260,262,264,265,268,270,273,274,277,281,282,283,285,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,311,312,318,319,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,349,350,351,352,353,356,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[28,-251,-61,-72,28,-71,-58,-54,-55,-33,-29,-59,-251,-34,-53,-68,-63,-52,28,-56,-170,-66,-251,-69,28,-32,-73,-64,-31,-60,-35,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-249,-81,-49,-30,110,-97,-96,-116,28,-26,-25,-45,-48,-51,28,-251,-251,28,-219,-206,-233,-243,-247,-244,-241,-231,177,-217,-232,-208,-187,177,-216,177,-240,-215,-220,177,177,-237,-245,-214,-238,208,-242,-239,-218,-230,28,-117,28,177,-36,177,-83,-250,-21,-80,-22,-79,177,-176,-179,-177,-173,-174,-178,-180,177,-182,-183,-175,-181,-248,177,-212,-215,-246,-226,177,177,-227,177,-206,-211,177,-209,28,-210,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,28,311,-98,177,-251,-37,-39,-42,-38,177,-40,177,177,-148,-147,-43,-149,177,-41,-237,-85,-84,28,177,-225,-224,-223,-234,177,177,28,208,208,208,208,208,208,208,208,208,208,-189,-188,208,208,208,208,208,-190,-215,364,-100,-99,-12,177,177,-11,-167,-166,177,-164,177,177,-150,177,-163,-151,177,177,-213,-221,-222,177,177,-207,-251,177,-215,-251,-131,-162,-165,177,-154,177,-152,177,177,177,-153,177,177,177,-251,-228,177,-158,-157,-155,-229,177,177,177,-159,-156,177,-161,-160,]),'LPAREN':([0,1,2,3,4,5,6,9,10,11,12,13,14,15,16,17,18,19,21,22,23,24,25,27,28,29,30,31,32,33,35,36,37,38,39,40,42,43,44,45,46,49,50,51,52,54,55,56,58,59,60,61,63,64,66,67,68,69,75,76,77,79,83,87,89,90,91,93,94,95,96,97,98,99,100,101,102,105,106,108,109,110,111,112,113,114,115,116,117,119,120,123,124,129,138,139,140,141,144,145,149,151,152,153,154,155,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,177,178,180,182,183,184,185,186,189,191,195,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,221,223,224,231,232,235,237,238,239,242,243,244,245,249,250,251,252,253,254,255,257,259,260,262,263,264,265,268,270,273,274,277,281,282,283,285,286,311,312,314,318,319,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,350,351,352,353,357,358,359,360,361,362,364,369,372,373,374,376,377,379,381,382,387,388,389,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[4,-251,-61,-72,4,-71,-58,-54,-55,-33,-29,-59,-251,-34,4,-53,-68,-63,-52,4,-56,-170,62,-66,-251,-69,4,-32,-73,-108,-64,-31,-60,-35,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-249,-81,-49,62,-30,112,-97,-96,-116,-114,-26,-25,-45,-48,-51,4,-109,-251,-251,4,-219,-233,-243,-247,-244,-241,-231,175,-217,-232,183,186,-216,189,-240,-215,-220,112,189,-237,-245,-214,-238,-242,-239,-218,-230,218,-115,-117,4,112,-36,112,-83,-250,-21,-80,-22,-79,186,-176,-179,-177,-173,-174,-178,-180,112,-182,-183,-175,-181,-248,112,-215,-246,-226,112,112,-227,-110,112,112,-111,285,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,112,186,186,-113,-112,218,112,313,218,-98,186,-251,-37,-39,-42,-38,112,-40,334,337,186,112,341,-148,-147,-43,-149,112,-41,-237,346,-85,-84,4,186,-225,-224,-223,-234,112,186,285,285,-215,112,313,-100,-99,-12,186,112,-11,-167,-166,112,-164,112,112,-150,112,-163,-151,112,112,-221,-222,112,186,-251,186,-146,-140,-142,-144,-215,-251,-131,-162,-165,112,-154,112,398,-152,-141,-143,-145,112,112,112,-153,112,112,112,-251,-228,112,-158,-157,-155,-229,112,112,112,-159,-156,112,-161,-160,]),'MINUSMINUS':([55,61,75,91,93,94,95,96,97,98,99,100,101,102,105,106,108,109,110,111,112,113,114,115,116,117,119,120,123,124,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,174,175,177,178,180,182,183,184,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,262,270,273,274,277,281,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,350,351,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,401,404,405,406,408,409,410,413,415,416,417,418,419,420,],[-249,113,-45,-219,-233,-243,-247,-244,-241,-231,113,-217,-232,184,113,-216,113,-240,-215,-220,113,113,-237,-245,-214,-238,-242,-239,-218,-230,113,113,-250,113,-176,-179,-177,-173,-174,-178,-180,113,-182,-183,-175,-181,-248,113,-215,-246,-226,113,113,-227,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,-251,-39,-42,-38,113,-40,113,113,-148,-147,-43,-149,113,-41,-237,113,-225,-224,-223,-234,113,113,-215,113,-12,113,113,-11,-167,-166,113,-164,113,113,-150,113,-163,-151,113,113,-221,-222,113,113,-251,113,-215,-251,-131,-162,-165,113,-154,113,-152,113,113,113,-153,113,113,113,-251,-228,113,-158,-157,-155,-229,113,113,113,-159,-156,113,-161,-160,]),'ID':([0,1,2,3,4,5,6,7,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,26,27,28,29,30,31,32,34,35,36,37,38,39,40,42,43,44,45,46,49,50,51,52,54,55,56,58,60,61,62,63,64,65,66,67,68,69,75,76,77,79,87,89,90,91,99,100,105,106,108,110,112,113,116,123,129,133,134,138,139,140,141,144,145,149,151,152,153,154,155,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,179,181,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,218,221,224,226,230,231,232,235,237,238,239,240,242,243,244,250,251,253,254,255,257,259,260,264,265,268,270,282,283,311,312,318,319,322,324,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[33,-251,-61,-72,33,-71,-58,56,-54,-55,-33,-29,-59,-251,-34,33,-53,-68,-63,-87,-52,33,-56,-170,64,-66,-251,-69,33,-32,-73,-86,-64,-31,-60,-35,-62,-65,-251,-67,-251,-70,-74,-57,-50,-9,-10,-82,-249,-81,-49,-30,114,114,-97,-96,137,-116,-114,-26,-25,-45,-48,-51,33,-251,-251,33,-219,114,-217,114,-216,114,-215,114,114,-214,-218,33,137,137,-115,-117,33,114,-36,262,-83,-250,-21,-80,-22,-79,114,-176,-179,-177,-173,-174,-178,-180,114,-182,-183,-175,-181,114,-215,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,33,114,33,114,137,-98,114,-251,-37,-39,-42,330,-38,114,-40,114,262,-148,-147,-43,-149,262,-41,-85,-84,33,114,114,114,-215,114,-100,-99,-12,114,114,114,-11,-167,-166,114,-164,262,114,-150,114,-163,-151,262,114,114,114,-251,114,-215,-251,-131,-162,-165,114,-154,262,-152,114,114,262,-153,262,114,262,-251,114,-158,-157,-155,114,262,262,-159,-156,262,-161,-160,]),'IF':([55,75,145,151,238,239,242,244,251,253,254,255,257,259,260,331,332,335,336,340,342,344,345,373,374,377,379,382,395,396,397,399,405,406,408,413,415,416,417,418,419,420,],[-249,-45,263,-250,-39,-42,-38,-40,263,-148,-147,-43,-149,263,-41,-167,-166,-164,263,-150,-163,-151,263,-162,-165,-154,263,-152,263,-153,263,263,-158,-157,-155,263,263,-159,-156,263,-161,-160,]),'STRING_LITERAL':([55,61,75,91,99,100,101,105,106,108,110,112,113,115,116,123,141,145,151,156,162,163,164,165,166,167,168,169,170,171,172,173,175,177,178,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,235,238,239,242,243,244,250,251,253,254,255,257,259,260,270,282,283,311,312,322,325,326,327,331,332,334,335,336,337,340,341,342,344,345,346,352,353,357,358,364,369,372,373,374,376,377,379,382,391,393,395,396,397,398,399,400,404,405,406,408,410,413,415,416,417,418,419,420,],[-249,115,-45,-219,115,-217,178,115,-216,115,-215,115,115,-245,-214,-218,115,115,-250,115,-176,-179,-177,-173,-174,-178,-180,115,-182,-183,-175,-181,115,-215,-246,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,-251,-39,-42,-38,115,-40,115,115,-148,-147,-43,-149,115,-41,115,115,115,-215,115,-12,115,115,-11,-167,-166,115,-164,115,115,-150,115,-163,-151,115,115,115,115,-251,115,-215,-251,-131,-162,-165,115,-154,115,-152,115,115,115,-153,115,115,115,-251,115,-158,-157,-155,115,115,115,-159,-156,115,-161,-160,]),'FLOAT':([0,1,2,3,5,6,9,10,11,12,13,14,15,17,18,19,21,22,23,24,25,27,29,31,32,33,35,36,37,38,39,40,42,43,44,45,46,48,49,54,55,56,57,59,60,62,63,64,73,75,80,82,83,84,85,86,87,88,89,112,144,145,146,147,148,149,150,151,175,185,186,189,191,216,217,218,227,231,237,238,239,242,244,251,253,254,255,257,260,264,265,269,285,313,318,319,331,332,334,335,340,342,344,373,374,377,382,396,405,406,408,416,417,419,420,],[35,35,-61,-72,-71,-58,-54,-55,-33,-29,-59,35,-34,-53,-68,-63,-52,35,-56,-170,-106,-66,-69,-32,-73,-108,-64,-31,-60,-35,-62,-65,35,-67,35,-70,-74,35,-57,-82,-249,-81,35,-107,-30,35,-97,-96,35,-45,-46,35,-109,35,35,35,35,-88,35,35,-36,35,-47,35,35,-83,-89,-250,35,-110,35,35,-111,-113,-112,35,35,-98,-37,-39,-42,-38,-40,35,-148,-147,-43,-149,-41,-85,-84,-90,35,35,-100,-99,-167,-166,35,-164,-150,-163,-151,-162,-165,-154,-152,-153,-158,-157,-155,-159,-156,-161,-160,]),'XOREQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[166,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'LSHIFTEQUAL':([92,93,94,95,96,97,98,101,102,109,111,114,115,117,119,120,124,151,174,176,178,180,184,187,188,190,196,262,273,274,277,281,349,350,351,356,401,409,],[168,-233,-243,-247,-244,-241,-231,-232,-208,-240,-220,-237,-245,-238,-242,-239,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-210,-237,-225,-224,-223,-234,-213,-221,-222,-207,-228,-229,]),'RBRACKET':([61,92,93,94,95,96,97,98,101,102,103,104,107,109,110,111,114,115,117,118,119,120,121,122,124,151,174,176,178,180,184,187,188,190,194,196,221,267,271,273,274,275,277,281,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,310,311,312,349,350,351,355,356,363,364,367,386,401,409,],[-251,-206,-233,-243,-247,-244,-241,-231,-232,-208,185,-187,-4,-240,191,-220,-237,-245,-238,-185,-242,-239,-3,-171,-230,-250,-248,-212,-246,-226,-227,-206,-211,-209,-168,-210,-251,-184,-172,-225,-224,350,-223,-234,-193,-205,-194,-192,-196,-200,-195,-191,-198,-203,-189,-188,-197,-204,-199,-201,-202,-190,361,362,-251,-213,-221,-222,-169,-207,387,388,390,-186,-228,-229,]),} - -_lr_action = { } -for _k, _v in _lr_action_items.items(): - for _x,_y in zip(_v[0],_v[1]): - if not _x in _lr_action: _lr_action[_x] = { } - _lr_action[_x][_k] = _y -del _lr_action_items - -_lr_goto_items = {'storage_class_specifier':([0,1,14,22,42,44,48,62,73,82,145,218,227,251,285,313,334,],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,]),'identifier_list_opt':([62,],[125,]),'selection_statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[260,260,260,260,260,260,260,260,260,260,260,260,]),'constant':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,]),'unary_expression':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[92,176,187,190,92,196,92,92,187,92,92,92,92,92,92,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,92,187,187,92,187,92,187,92,92,187,92,187,92,187,92,92,92,92,92,92,92,92,187,187,92,92,92,92,92,92,92,92,92,92,92,92,92,]),'conditional_expression':([61,112,141,145,156,169,175,182,183,186,189,213,221,232,243,250,251,259,270,282,312,325,326,334,336,337,341,345,346,352,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[122,122,122,122,267,122,122,122,122,122,122,122,122,267,122,267,122,122,267,122,122,267,122,122,122,122,122,122,122,122,386,122,122,122,122,122,122,122,122,122,122,122,122,122,]),'brace_close':([86,136,147,148,228,229,261,328,369,385,400,],[149,231,264,265,318,319,344,370,392,401,409,]),'struct_or_union_specifier':([0,1,14,22,42,44,48,57,62,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,]),'unified_wstring_literal':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,]),'abstract_declarator_opt':([129,195,],[219,284,]),'iteration_statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[239,239,239,239,239,239,239,239,239,239,239,239,]),'init_declarator_list':([30,79,],[70,70,]),'translation_unit_or_empty':([0,],[8,]),'struct_declaration_list':([57,84,85,],[86,147,148,]),'enumerator':([65,133,134,230,],[135,135,135,320,]),'pp_directive':([0,22,],[11,11,]),'declaration_list':([48,73,],[82,82,]),'declaration_specifiers_opt':([1,14,42,44,],[50,58,76,77,]),'abstract_declarator':([129,195,218,285,],[220,220,309,309,]),'external_declaration':([0,22,],[12,60,]),'type_specifier':([0,1,14,22,42,44,48,57,62,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[14,14,14,14,14,14,14,87,14,14,14,87,87,87,87,87,87,14,87,87,87,87,87,14,14,14,14,14,14,]),'designation':([235,357,369,400,],[322,322,322,322,]),'compound_statement':([81,142,145,251,259,336,345,379,395,397,399,413,415,418,],[144,237,244,244,244,244,244,244,244,244,244,244,244,244,]),'pointer':([0,4,22,30,67,79,90,129,140,195,218,268,285,],[16,16,16,16,138,16,16,224,16,286,224,16,286,]),'type_name':([112,175,186,189,],[193,272,279,280,]),'unified_string_literal':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,]),'postfix_expression':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,]),'assignment_expression_opt':([61,221,312,],[103,310,363,]),'designation_opt':([235,357,369,400,],[326,326,391,391,]),'expression_statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[238,238,238,238,238,238,238,238,238,238,238,238,]),'unary_operator':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,]),'cast_expression':([61,105,112,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[104,188,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,356,104,104,104,104,104,104,104,104,104,104,356,104,104,104,104,104,104,104,104,104,104,104,104,104,104,]),'brace_open':([7,26,54,56,63,64,81,141,142,145,251,259,283,326,336,345,349,353,354,379,391,395,397,399,413,415,418,],[57,65,84,85,133,134,145,235,145,145,145,145,357,235,145,145,357,357,357,145,235,145,145,145,145,145,145,]),'init_declarator':([30,79,140,],[74,74,233,]),'translation_unit':([0,],[22,]),'assignment_operator':([92,],[169,]),'struct_or_union':([0,1,14,22,42,44,48,57,62,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,]),'block_item_list_opt':([145,],[261,]),'struct_declaration':([57,84,85,86,147,148,],[88,88,88,150,150,150,]),'assignment_expression':([61,112,141,145,169,175,182,183,186,189,213,221,243,251,259,282,312,326,334,336,337,341,345,346,352,376,379,391,393,395,397,398,399,404,410,413,415,418,],[107,194,236,194,271,194,194,276,194,194,194,107,194,194,194,355,107,236,194,194,194,194,194,194,384,194,194,236,194,194,194,194,194,194,194,194,194,194,]),'parameter_type_list':([62,218,285,313,],[127,307,307,307,]),'type_qualifier_list_opt':([28,],[67,]),'direct_declarator':([0,4,16,22,30,79,90,129,140,218,224,268,],[25,25,59,25,25,25,25,25,25,25,59,25,]),'type_qualifier_list':([28,],[68,]),'designator':([235,329,357,369,400,],[323,371,323,323,323,]),'argument_expression_list':([183,],[278,]),'initializer':([141,326,391,],[234,368,402,]),'direct_abstract_declarator':([129,195,218,224,285,286,],[223,223,223,314,223,314,]),'specifier_qualifier_list_opt':([87,89,],[153,155,]),'constant_expression':([156,232,250,270,325,],[266,321,338,348,367,]),'expression_opt':([145,251,259,334,336,345,376,379,393,395,397,399,404,410,413,415,418,],[241,241,241,375,241,241,394,241,403,241,241,241,411,414,241,241,241,]),'primary_expression':([61,99,105,108,112,113,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,283,312,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,]),'declaration_specifiers':([0,1,14,22,42,44,48,62,73,82,145,218,227,251,285,313,334,],[30,52,52,30,52,52,79,129,79,79,79,129,129,79,129,129,79,]),'declaration':([0,22,48,73,82,145,251,334,],[31,31,80,80,146,254,254,376,]),'struct_declarator_list_opt':([90,],[158,]),'identifier_list':([62,],[130,]),'typedef_name':([0,1,14,22,42,44,48,57,62,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,]),'parameter_type_list_opt':([218,285,313,],[308,308,365,]),'jump_statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[255,255,255,255,255,255,255,255,255,255,255,255,]),'declaration_list_opt':([48,73,],[81,142,]),'struct_declarator':([90,268,],[159,347,]),'function_definition':([0,22,],[36,36,]),'binary_expression':([61,112,141,145,156,169,175,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,232,243,250,251,259,270,282,312,325,326,334,336,337,341,345,346,352,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[118,118,118,118,118,118,118,118,118,118,118,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,118,304,305,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,]),'parameter_list':([62,218,285,313,],[131,131,131,131,]),'init_declarator_list_opt':([30,79,],[71,71,]),'enum_specifier':([0,1,14,22,42,44,48,57,62,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,]),'struct_declarator_list':([90,],[157,]),'decl_body':([0,22,48,73,82,145,251,334,],[41,41,41,41,41,41,41,41,]),'type_qualifier':([0,1,14,22,28,42,44,48,57,62,68,73,82,84,85,86,87,89,112,145,147,148,175,186,189,218,227,251,285,313,334,],[42,42,42,42,66,42,42,42,89,42,139,42,42,89,89,89,89,89,89,42,89,89,89,89,89,42,42,42,42,42,42,]),'enumerator_list':([65,133,134,],[136,228,229,]),'labeled_statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[242,242,242,242,242,242,242,242,242,242,242,242,]),'function_specifier':([0,1,14,22,42,44,48,62,73,82,145,218,227,251,285,313,334,],[44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,]),'specifier_qualifier_list':([57,84,85,86,87,89,112,147,148,175,186,189,],[90,90,90,90,154,154,195,90,90,195,195,195,]),'block_item':([145,251,],[257,340,]),'block_item_list':([145,],[251,]),'statement':([145,251,259,336,345,379,395,397,399,413,415,418,],[253,253,343,377,382,396,405,406,408,417,419,420,]),'empty':([0,1,14,28,30,42,44,48,61,62,73,79,87,89,90,129,145,195,218,221,235,251,259,285,312,313,334,336,345,357,369,376,379,393,395,397,399,400,404,410,413,415,418,],[47,51,51,69,72,51,51,78,121,126,78,72,152,152,160,225,258,225,306,121,327,339,339,306,121,306,339,339,339,327,327,339,339,339,339,339,339,327,339,339,339,339,339,]),'initializer_list':([235,357,],[328,385,]),'declarator':([0,4,22,30,79,90,129,140,218,268,],[48,53,48,73,143,161,222,143,53,161,]),'parameter_declaration':([62,218,227,285,313,],[128,128,317,128,128,]),'designator_list':([235,357,369,400,],[329,329,329,329,]),'identifier':([61,62,99,105,108,112,113,141,145,156,169,175,179,181,182,183,186,189,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,221,226,232,243,250,251,259,270,282,283,312,324,325,326,334,336,337,341,345,346,352,353,358,376,379,391,393,395,397,398,399,404,410,413,415,418,],[124,132,124,124,124,124,124,124,124,124,124,124,273,274,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,315,124,124,124,124,124,124,124,124,124,366,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,]),'expression':([112,145,175,182,186,189,213,243,251,259,334,336,337,341,345,346,376,379,393,395,397,398,399,404,410,413,415,418,],[192,247,192,275,192,192,303,333,247,247,247,247,378,380,247,383,247,247,247,247,247,407,247,247,247,247,247,247,]),} - -_lr_goto = { } -for _k, _v in _lr_goto_items.items(): - for _x,_y in zip(_v[0],_v[1]): - if not _x in _lr_goto: _lr_goto[_x] = { } - _lr_goto[_x][_k] = _y -del _lr_goto_items -_lr_productions = [ - ("S' -> translation_unit_or_empty","S'",1,None,None,None), - ('abstract_declarator_opt -> empty','abstract_declarator_opt',1,'p_abstract_declarator_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('abstract_declarator_opt -> abstract_declarator','abstract_declarator_opt',1,'p_abstract_declarator_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('assignment_expression_opt -> empty','assignment_expression_opt',1,'p_assignment_expression_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('assignment_expression_opt -> assignment_expression','assignment_expression_opt',1,'p_assignment_expression_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('block_item_list_opt -> empty','block_item_list_opt',1,'p_block_item_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('block_item_list_opt -> block_item_list','block_item_list_opt',1,'p_block_item_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('declaration_list_opt -> empty','declaration_list_opt',1,'p_declaration_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('declaration_list_opt -> declaration_list','declaration_list_opt',1,'p_declaration_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('declaration_specifiers_opt -> empty','declaration_specifiers_opt',1,'p_declaration_specifiers_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('declaration_specifiers_opt -> declaration_specifiers','declaration_specifiers_opt',1,'p_declaration_specifiers_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('designation_opt -> empty','designation_opt',1,'p_designation_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('designation_opt -> designation','designation_opt',1,'p_designation_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('expression_opt -> empty','expression_opt',1,'p_expression_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('expression_opt -> expression','expression_opt',1,'p_expression_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('identifier_list_opt -> empty','identifier_list_opt',1,'p_identifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('identifier_list_opt -> identifier_list','identifier_list_opt',1,'p_identifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('init_declarator_list_opt -> empty','init_declarator_list_opt',1,'p_init_declarator_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('init_declarator_list_opt -> init_declarator_list','init_declarator_list_opt',1,'p_init_declarator_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('parameter_type_list_opt -> empty','parameter_type_list_opt',1,'p_parameter_type_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('parameter_type_list_opt -> parameter_type_list','parameter_type_list_opt',1,'p_parameter_type_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('specifier_qualifier_list_opt -> empty','specifier_qualifier_list_opt',1,'p_specifier_qualifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('specifier_qualifier_list_opt -> specifier_qualifier_list','specifier_qualifier_list_opt',1,'p_specifier_qualifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('struct_declarator_list_opt -> empty','struct_declarator_list_opt',1,'p_struct_declarator_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('struct_declarator_list_opt -> struct_declarator_list','struct_declarator_list_opt',1,'p_struct_declarator_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('type_qualifier_list_opt -> empty','type_qualifier_list_opt',1,'p_type_qualifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',41), - ('type_qualifier_list_opt -> type_qualifier_list','type_qualifier_list_opt',1,'p_type_qualifier_list_opt','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/plyparser.py',42), - ('translation_unit_or_empty -> translation_unit','translation_unit_or_empty',1,'p_translation_unit_or_empty','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',355), - ('translation_unit_or_empty -> empty','translation_unit_or_empty',1,'p_translation_unit_or_empty','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',356), - ('translation_unit -> external_declaration','translation_unit',1,'p_translation_unit_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',364), - ('translation_unit -> translation_unit external_declaration','translation_unit',2,'p_translation_unit_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',371), - ('external_declaration -> function_definition','external_declaration',1,'p_external_declaration_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',383), - ('external_declaration -> declaration','external_declaration',1,'p_external_declaration_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',388), - ('external_declaration -> pp_directive','external_declaration',1,'p_external_declaration_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',393), - ('external_declaration -> SEMI','external_declaration',1,'p_external_declaration_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',398), - ('pp_directive -> PPHASH','pp_directive',1,'p_pp_directive','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',403), - ('function_definition -> declarator declaration_list_opt compound_statement','function_definition',3,'p_function_definition_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',412), - ('function_definition -> declaration_specifiers declarator declaration_list_opt compound_statement','function_definition',4,'p_function_definition_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',424), - ('statement -> labeled_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',435), - ('statement -> expression_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',436), - ('statement -> compound_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',437), - ('statement -> selection_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',438), - ('statement -> iteration_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',439), - ('statement -> jump_statement','statement',1,'p_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',440), - ('decl_body -> declaration_specifiers init_declarator_list_opt','decl_body',2,'p_decl_body','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',454), - ('declaration -> decl_body SEMI','declaration',2,'p_declaration','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',537), - ('declaration_list -> declaration','declaration_list',1,'p_declaration_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',546), - ('declaration_list -> declaration_list declaration','declaration_list',2,'p_declaration_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',547), - ('declaration_specifiers -> type_qualifier declaration_specifiers_opt','declaration_specifiers',2,'p_declaration_specifiers_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',552), - ('declaration_specifiers -> type_specifier declaration_specifiers_opt','declaration_specifiers',2,'p_declaration_specifiers_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',557), - ('declaration_specifiers -> storage_class_specifier declaration_specifiers_opt','declaration_specifiers',2,'p_declaration_specifiers_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',562), - ('declaration_specifiers -> function_specifier declaration_specifiers_opt','declaration_specifiers',2,'p_declaration_specifiers_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',567), - ('storage_class_specifier -> AUTO','storage_class_specifier',1,'p_storage_class_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',572), - ('storage_class_specifier -> REGISTER','storage_class_specifier',1,'p_storage_class_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',573), - ('storage_class_specifier -> STATIC','storage_class_specifier',1,'p_storage_class_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',574), - ('storage_class_specifier -> EXTERN','storage_class_specifier',1,'p_storage_class_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',575), - ('storage_class_specifier -> TYPEDEF','storage_class_specifier',1,'p_storage_class_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',576), - ('function_specifier -> INLINE','function_specifier',1,'p_function_specifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',581), - ('type_specifier -> VOID','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',586), - ('type_specifier -> _BOOL','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',587), - ('type_specifier -> CHAR','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',588), - ('type_specifier -> SHORT','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',589), - ('type_specifier -> INT','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',590), - ('type_specifier -> LONG','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',591), - ('type_specifier -> FLOAT','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',592), - ('type_specifier -> DOUBLE','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',593), - ('type_specifier -> _COMPLEX','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',594), - ('type_specifier -> SIGNED','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',595), - ('type_specifier -> UNSIGNED','type_specifier',1,'p_type_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',596), - ('type_specifier -> typedef_name','type_specifier',1,'p_type_specifier_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',601), - ('type_specifier -> enum_specifier','type_specifier',1,'p_type_specifier_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',602), - ('type_specifier -> struct_or_union_specifier','type_specifier',1,'p_type_specifier_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',603), - ('type_qualifier -> CONST','type_qualifier',1,'p_type_qualifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',608), - ('type_qualifier -> RESTRICT','type_qualifier',1,'p_type_qualifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',609), - ('type_qualifier -> VOLATILE','type_qualifier',1,'p_type_qualifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',610), - ('init_declarator_list -> init_declarator','init_declarator_list',1,'p_init_declarator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',615), - ('init_declarator_list -> init_declarator_list COMMA init_declarator','init_declarator_list',3,'p_init_declarator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',616), - ('init_declarator -> declarator','init_declarator',1,'p_init_declarator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',624), - ('init_declarator -> declarator EQUALS initializer','init_declarator',3,'p_init_declarator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',625), - ('specifier_qualifier_list -> type_qualifier specifier_qualifier_list_opt','specifier_qualifier_list',2,'p_specifier_qualifier_list_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',630), - ('specifier_qualifier_list -> type_specifier specifier_qualifier_list_opt','specifier_qualifier_list',2,'p_specifier_qualifier_list_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',635), - ('struct_or_union_specifier -> struct_or_union ID','struct_or_union_specifier',2,'p_struct_or_union_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',643), - ('struct_or_union_specifier -> struct_or_union TYPEID','struct_or_union_specifier',2,'p_struct_or_union_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',644), - ('struct_or_union_specifier -> struct_or_union brace_open struct_declaration_list brace_close','struct_or_union_specifier',4,'p_struct_or_union_specifier_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',653), - ('struct_or_union_specifier -> struct_or_union ID brace_open struct_declaration_list brace_close','struct_or_union_specifier',5,'p_struct_or_union_specifier_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',662), - ('struct_or_union_specifier -> struct_or_union TYPEID brace_open struct_declaration_list brace_close','struct_or_union_specifier',5,'p_struct_or_union_specifier_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',663), - ('struct_or_union -> STRUCT','struct_or_union',1,'p_struct_or_union','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',672), - ('struct_or_union -> UNION','struct_or_union',1,'p_struct_or_union','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',673), - ('struct_declaration_list -> struct_declaration','struct_declaration_list',1,'p_struct_declaration_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',680), - ('struct_declaration_list -> struct_declaration_list struct_declaration','struct_declaration_list',2,'p_struct_declaration_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',681), - ('struct_declaration -> specifier_qualifier_list struct_declarator_list_opt SEMI','struct_declaration',3,'p_struct_declaration_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',686), - ('struct_declarator_list -> struct_declarator','struct_declarator_list',1,'p_struct_declarator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',737), - ('struct_declarator_list -> struct_declarator_list COMMA struct_declarator','struct_declarator_list',3,'p_struct_declarator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',738), - ('struct_declarator -> declarator','struct_declarator',1,'p_struct_declarator_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',746), - ('struct_declarator -> declarator COLON constant_expression','struct_declarator',3,'p_struct_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',751), - ('struct_declarator -> COLON constant_expression','struct_declarator',2,'p_struct_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',752), - ('enum_specifier -> ENUM ID','enum_specifier',2,'p_enum_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',760), - ('enum_specifier -> ENUM TYPEID','enum_specifier',2,'p_enum_specifier_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',761), - ('enum_specifier -> ENUM brace_open enumerator_list brace_close','enum_specifier',4,'p_enum_specifier_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',766), - ('enum_specifier -> ENUM ID brace_open enumerator_list brace_close','enum_specifier',5,'p_enum_specifier_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',771), - ('enum_specifier -> ENUM TYPEID brace_open enumerator_list brace_close','enum_specifier',5,'p_enum_specifier_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',772), - ('enumerator_list -> enumerator','enumerator_list',1,'p_enumerator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',777), - ('enumerator_list -> enumerator_list COMMA','enumerator_list',2,'p_enumerator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',778), - ('enumerator_list -> enumerator_list COMMA enumerator','enumerator_list',3,'p_enumerator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',779), - ('enumerator -> ID','enumerator',1,'p_enumerator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',790), - ('enumerator -> ID EQUALS constant_expression','enumerator',3,'p_enumerator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',791), - ('declarator -> direct_declarator','declarator',1,'p_declarator_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',803), - ('declarator -> pointer direct_declarator','declarator',2,'p_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',808), - ('direct_declarator -> ID','direct_declarator',1,'p_direct_declarator_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',813), - ('direct_declarator -> LPAREN declarator RPAREN','direct_declarator',3,'p_direct_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',822), - ('direct_declarator -> direct_declarator LBRACKET assignment_expression_opt RBRACKET','direct_declarator',4,'p_direct_declarator_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',827), - ('direct_declarator -> direct_declarator LBRACKET TIMES RBRACKET','direct_declarator',4,'p_direct_declarator_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',839), - ('direct_declarator -> direct_declarator LPAREN parameter_type_list RPAREN','direct_declarator',4,'p_direct_declarator_5','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',849), - ('direct_declarator -> direct_declarator LPAREN identifier_list_opt RPAREN','direct_declarator',4,'p_direct_declarator_5','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',850), - ('pointer -> TIMES type_qualifier_list_opt','pointer',2,'p_pointer','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',860), - ('pointer -> TIMES type_qualifier_list_opt pointer','pointer',3,'p_pointer','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',861), - ('type_qualifier_list -> type_qualifier','type_qualifier_list',1,'p_type_qualifier_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',871), - ('type_qualifier_list -> type_qualifier_list type_qualifier','type_qualifier_list',2,'p_type_qualifier_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',872), - ('parameter_type_list -> parameter_list','parameter_type_list',1,'p_parameter_type_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',877), - ('parameter_type_list -> parameter_list COMMA ELLIPSIS','parameter_type_list',3,'p_parameter_type_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',878), - ('parameter_list -> parameter_declaration','parameter_list',1,'p_parameter_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',886), - ('parameter_list -> parameter_list COMMA parameter_declaration','parameter_list',3,'p_parameter_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',887), - ('parameter_declaration -> declaration_specifiers declarator','parameter_declaration',2,'p_parameter_declaration_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',896), - ('parameter_declaration -> declaration_specifiers abstract_declarator_opt','parameter_declaration',2,'p_parameter_declaration_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',915), - ('identifier_list -> identifier','identifier_list',1,'p_identifier_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',927), - ('identifier_list -> identifier_list COMMA identifier','identifier_list',3,'p_identifier_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',928), - ('initializer -> assignment_expression','initializer',1,'p_initializer_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',937), - ('initializer -> brace_open initializer_list brace_close','initializer',3,'p_initializer_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',942), - ('initializer -> brace_open initializer_list COMMA brace_close','initializer',4,'p_initializer_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',943), - ('initializer_list -> designation_opt initializer','initializer_list',2,'p_initializer_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',948), - ('initializer_list -> initializer_list COMMA designation_opt initializer','initializer_list',4,'p_initializer_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',949), - ('designation -> designator_list EQUALS','designation',2,'p_designation','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',960), - ('designator_list -> designator','designator_list',1,'p_designator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',968), - ('designator_list -> designator_list designator','designator_list',2,'p_designator_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',969), - ('designator -> LBRACKET constant_expression RBRACKET','designator',3,'p_designator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',974), - ('designator -> PERIOD identifier','designator',2,'p_designator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',975), - ('type_name -> specifier_qualifier_list abstract_declarator_opt','type_name',2,'p_type_name','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',980), - ('abstract_declarator -> pointer','abstract_declarator',1,'p_abstract_declarator_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',996), - ('abstract_declarator -> pointer direct_abstract_declarator','abstract_declarator',2,'p_abstract_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1004), - ('abstract_declarator -> direct_abstract_declarator','abstract_declarator',1,'p_abstract_declarator_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1009), - ('direct_abstract_declarator -> LPAREN abstract_declarator RPAREN','direct_abstract_declarator',3,'p_direct_abstract_declarator_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1019), - ('direct_abstract_declarator -> direct_abstract_declarator LBRACKET assignment_expression_opt RBRACKET','direct_abstract_declarator',4,'p_direct_abstract_declarator_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1023), - ('direct_abstract_declarator -> LBRACKET assignment_expression_opt RBRACKET','direct_abstract_declarator',3,'p_direct_abstract_declarator_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1033), - ('direct_abstract_declarator -> direct_abstract_declarator LBRACKET TIMES RBRACKET','direct_abstract_declarator',4,'p_direct_abstract_declarator_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1041), - ('direct_abstract_declarator -> LBRACKET TIMES RBRACKET','direct_abstract_declarator',3,'p_direct_abstract_declarator_5','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1051), - ('direct_abstract_declarator -> direct_abstract_declarator LPAREN parameter_type_list_opt RPAREN','direct_abstract_declarator',4,'p_direct_abstract_declarator_6','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1059), - ('direct_abstract_declarator -> LPAREN parameter_type_list_opt RPAREN','direct_abstract_declarator',3,'p_direct_abstract_declarator_7','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1069), - ('block_item -> declaration','block_item',1,'p_block_item','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1080), - ('block_item -> statement','block_item',1,'p_block_item','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1081), - ('block_item_list -> block_item','block_item_list',1,'p_block_item_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1088), - ('block_item_list -> block_item_list block_item','block_item_list',2,'p_block_item_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1089), - ('compound_statement -> brace_open block_item_list_opt brace_close','compound_statement',3,'p_compound_statement_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1095), - ('labeled_statement -> ID COLON statement','labeled_statement',3,'p_labeled_statement_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1101), - ('labeled_statement -> CASE constant_expression COLON statement','labeled_statement',4,'p_labeled_statement_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1105), - ('labeled_statement -> DEFAULT COLON statement','labeled_statement',3,'p_labeled_statement_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1109), - ('selection_statement -> IF LPAREN expression RPAREN statement','selection_statement',5,'p_selection_statement_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1113), - ('selection_statement -> IF LPAREN expression RPAREN statement ELSE statement','selection_statement',7,'p_selection_statement_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1117), - ('selection_statement -> SWITCH LPAREN expression RPAREN statement','selection_statement',5,'p_selection_statement_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1121), - ('iteration_statement -> WHILE LPAREN expression RPAREN statement','iteration_statement',5,'p_iteration_statement_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1126), - ('iteration_statement -> DO statement WHILE LPAREN expression RPAREN SEMI','iteration_statement',7,'p_iteration_statement_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1130), - ('iteration_statement -> FOR LPAREN expression_opt SEMI expression_opt SEMI expression_opt RPAREN statement','iteration_statement',9,'p_iteration_statement_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1134), - ('iteration_statement -> FOR LPAREN declaration expression_opt SEMI expression_opt RPAREN statement','iteration_statement',8,'p_iteration_statement_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1138), - ('jump_statement -> GOTO ID SEMI','jump_statement',3,'p_jump_statement_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1142), - ('jump_statement -> BREAK SEMI','jump_statement',2,'p_jump_statement_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1146), - ('jump_statement -> CONTINUE SEMI','jump_statement',2,'p_jump_statement_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1150), - ('jump_statement -> RETURN expression SEMI','jump_statement',3,'p_jump_statement_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1154), - ('jump_statement -> RETURN SEMI','jump_statement',2,'p_jump_statement_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1155), - ('expression_statement -> expression_opt SEMI','expression_statement',2,'p_expression_statement','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1160), - ('expression -> assignment_expression','expression',1,'p_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1167), - ('expression -> expression COMMA assignment_expression','expression',3,'p_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1168), - ('typedef_name -> TYPEID','typedef_name',1,'p_typedef_name','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1180), - ('assignment_expression -> conditional_expression','assignment_expression',1,'p_assignment_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1184), - ('assignment_expression -> unary_expression assignment_operator assignment_expression','assignment_expression',3,'p_assignment_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1185), - ('assignment_operator -> EQUALS','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1198), - ('assignment_operator -> XOREQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1199), - ('assignment_operator -> TIMESEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1200), - ('assignment_operator -> DIVEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1201), - ('assignment_operator -> MODEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1202), - ('assignment_operator -> PLUSEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1203), - ('assignment_operator -> MINUSEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1204), - ('assignment_operator -> LSHIFTEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1205), - ('assignment_operator -> RSHIFTEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1206), - ('assignment_operator -> ANDEQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1207), - ('assignment_operator -> OREQUAL','assignment_operator',1,'p_assignment_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1208), - ('constant_expression -> conditional_expression','constant_expression',1,'p_constant_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1213), - ('conditional_expression -> binary_expression','conditional_expression',1,'p_conditional_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1217), - ('conditional_expression -> binary_expression CONDOP expression COLON conditional_expression','conditional_expression',5,'p_conditional_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1218), - ('binary_expression -> cast_expression','binary_expression',1,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1226), - ('binary_expression -> binary_expression TIMES binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1227), - ('binary_expression -> binary_expression DIVIDE binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1228), - ('binary_expression -> binary_expression MOD binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1229), - ('binary_expression -> binary_expression PLUS binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1230), - ('binary_expression -> binary_expression MINUS binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1231), - ('binary_expression -> binary_expression RSHIFT binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1232), - ('binary_expression -> binary_expression LSHIFT binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1233), - ('binary_expression -> binary_expression LT binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1234), - ('binary_expression -> binary_expression LE binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1235), - ('binary_expression -> binary_expression GE binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1236), - ('binary_expression -> binary_expression GT binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1237), - ('binary_expression -> binary_expression EQ binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1238), - ('binary_expression -> binary_expression NE binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1239), - ('binary_expression -> binary_expression AND binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1240), - ('binary_expression -> binary_expression OR binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1241), - ('binary_expression -> binary_expression XOR binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1242), - ('binary_expression -> binary_expression LAND binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1243), - ('binary_expression -> binary_expression LOR binary_expression','binary_expression',3,'p_binary_expression','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1244), - ('cast_expression -> unary_expression','cast_expression',1,'p_cast_expression_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1252), - ('cast_expression -> LPAREN type_name RPAREN cast_expression','cast_expression',4,'p_cast_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1256), - ('unary_expression -> postfix_expression','unary_expression',1,'p_unary_expression_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1260), - ('unary_expression -> PLUSPLUS unary_expression','unary_expression',2,'p_unary_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1264), - ('unary_expression -> MINUSMINUS unary_expression','unary_expression',2,'p_unary_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1265), - ('unary_expression -> unary_operator cast_expression','unary_expression',2,'p_unary_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1266), - ('unary_expression -> SIZEOF unary_expression','unary_expression',2,'p_unary_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1271), - ('unary_expression -> SIZEOF LPAREN type_name RPAREN','unary_expression',4,'p_unary_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1272), - ('unary_operator -> AND','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1280), - ('unary_operator -> TIMES','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1281), - ('unary_operator -> PLUS','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1282), - ('unary_operator -> MINUS','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1283), - ('unary_operator -> NOT','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1284), - ('unary_operator -> LNOT','unary_operator',1,'p_unary_operator','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1285), - ('postfix_expression -> primary_expression','postfix_expression',1,'p_postfix_expression_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1290), - ('postfix_expression -> postfix_expression LBRACKET expression RBRACKET','postfix_expression',4,'p_postfix_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1294), - ('postfix_expression -> postfix_expression LPAREN argument_expression_list RPAREN','postfix_expression',4,'p_postfix_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1298), - ('postfix_expression -> postfix_expression LPAREN RPAREN','postfix_expression',3,'p_postfix_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1299), - ('postfix_expression -> postfix_expression PERIOD identifier','postfix_expression',3,'p_postfix_expression_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1304), - ('postfix_expression -> postfix_expression ARROW identifier','postfix_expression',3,'p_postfix_expression_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1305), - ('postfix_expression -> postfix_expression PLUSPLUS','postfix_expression',2,'p_postfix_expression_5','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1310), - ('postfix_expression -> postfix_expression MINUSMINUS','postfix_expression',2,'p_postfix_expression_5','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1311), - ('postfix_expression -> LPAREN type_name RPAREN brace_open initializer_list brace_close','postfix_expression',6,'p_postfix_expression_6','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1316), - ('postfix_expression -> LPAREN type_name RPAREN brace_open initializer_list COMMA brace_close','postfix_expression',7,'p_postfix_expression_6','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1317), - ('primary_expression -> identifier','primary_expression',1,'p_primary_expression_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1322), - ('primary_expression -> constant','primary_expression',1,'p_primary_expression_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1326), - ('primary_expression -> unified_string_literal','primary_expression',1,'p_primary_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1330), - ('primary_expression -> unified_wstring_literal','primary_expression',1,'p_primary_expression_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1331), - ('primary_expression -> LPAREN expression RPAREN','primary_expression',3,'p_primary_expression_4','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1336), - ('argument_expression_list -> assignment_expression','argument_expression_list',1,'p_argument_expression_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1340), - ('argument_expression_list -> argument_expression_list COMMA assignment_expression','argument_expression_list',3,'p_argument_expression_list','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1341), - ('identifier -> ID','identifier',1,'p_identifier','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1350), - ('constant -> INT_CONST_DEC','constant',1,'p_constant_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1354), - ('constant -> INT_CONST_OCT','constant',1,'p_constant_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1355), - ('constant -> INT_CONST_HEX','constant',1,'p_constant_1','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1356), - ('constant -> FLOAT_CONST','constant',1,'p_constant_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1362), - ('constant -> HEX_FLOAT_CONST','constant',1,'p_constant_2','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1363), - ('constant -> CHAR_CONST','constant',1,'p_constant_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1369), - ('constant -> WCHAR_CONST','constant',1,'p_constant_3','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1370), - ('unified_string_literal -> STRING_LITERAL','unified_string_literal',1,'p_unified_string_literal','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1381), - ('unified_string_literal -> unified_string_literal STRING_LITERAL','unified_string_literal',2,'p_unified_string_literal','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1382), - ('unified_wstring_literal -> WSTRING_LITERAL','unified_wstring_literal',1,'p_unified_wstring_literal','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1392), - ('unified_wstring_literal -> unified_wstring_literal WSTRING_LITERAL','unified_wstring_literal',2,'p_unified_wstring_literal','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1393), - ('brace_open -> LBRACE','brace_open',1,'p_brace_open','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1403), - ('brace_close -> RBRACE','brace_close',1,'p_brace_close','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1409), - ('empty -> ','empty',0,'p_empty','/home/fijal/src/pypy/lib_pypy/cffi/_pycparser/c_parser.py',1415), -] diff --git a/pypy/tool/release/package.py b/pypy/tool/release/package.py --- a/pypy/tool/release/package.py +++ b/pypy/tool/release/package.py @@ -17,6 +17,7 @@ import py import fnmatch from rpython.tool.udir import udir +import subprocess if sys.version_info < (2,6): py.test.skip("requires 2.6 so far") @@ -64,6 +65,8 @@ raise PyPyCNotFound( 'Bogus path: %r does not exist (see docstring for more info)' % (os.path.dirname(str(pypy_c)),)) + subprocess.check_call([str(pypy_c), '-c', 'import _sqlite3']) + subprocess.check_call([str(pypy_c), '-c', 'import _curses']) if sys.platform == 'win32' and not rename_pypy_c.lower().endswith('.exe'): rename_pypy_c += '.exe' binaries = [(pypy_c, rename_pypy_c)] @@ -73,9 +76,9 @@ #Instructions are provided on the website. # Can't rename a DLL: it is always called 'libpypy-c.dll' - + for extra in ['libpypy-c.dll', - 'libexpat.dll', 'sqlite3.dll', + 'libexpat.dll', 'sqlite3.dll', 'libeay32.dll', 'ssleay32.dll']: p = pypy_c.dirpath().join(extra) if not p.check(): @@ -93,7 +96,8 @@ ignore=ignore_patterns('.svn', 'py', '*.pyc', '*~')) shutil.copytree(str(basedir.join('lib_pypy')), str(pypydir.join('lib_pypy')), - ignore=ignore_patterns('.svn', 'py', '*.pyc', '*~')) + ignore=ignore_patterns('.svn', 'py', '*.pyc', '*~', + '*.c', '*.o')) for file in ['LICENSE', 'README.rst']: shutil.copy(str(basedir.join(file)), str(pypydir)) pypydir.ensure('include', dir=True) diff --git a/rpython/jit/backend/x86/test/test_zrpy_releasegil.py b/rpython/jit/backend/x86/test/test_zrpy_releasegil.py --- a/rpython/jit/backend/x86/test/test_zrpy_releasegil.py +++ b/rpython/jit/backend/x86/test/test_zrpy_releasegil.py @@ -68,10 +68,12 @@ c_qsort = rffi.llexternal('qsort', [rffi.VOIDP, rffi.SIZE_T, rffi.SIZE_T, CALLBACK], lltype.Void) # - def f42(): + def f42(n): length = len(glob.lst) raw = alloc1() fn = llhelper(CALLBACK, rffi._make_wrapper_for(CALLBACK, callback)) + if n & 1: # to create a loop and a bridge, and also + pass # to run the qsort() call in the blackhole interp c_qsort(rffi.cast(rffi.VOIDP, raw), rffi.cast(rffi.SIZE_T, 2), rffi.cast(rffi.SIZE_T, 8), fn) free1(raw) @@ -85,7 +87,7 @@ None, None, None, None, None, None) # def f(n, x, *args): - f42() + f42(n) n -= 1 return (n, x) + args return before, f, None diff --git a/rpython/memory/gctransform/asmgcroot.py b/rpython/memory/gctransform/asmgcroot.py --- a/rpython/memory/gctransform/asmgcroot.py +++ b/rpython/memory/gctransform/asmgcroot.py @@ -1,13 +1,15 @@ from rpython.flowspace.model import (Constant, Variable, Block, Link, - copygraph, SpaceOperation) + copygraph, SpaceOperation, checkgraph) from rpython.rlib.debug import ll_assert +from rpython.rlib.nonconst import NonConstant from rpython.rtyper.annlowlevel import llhelper from rpython.rtyper.lltypesystem import lltype, llmemory, rffi from rpython.rtyper.lltypesystem.lloperation import llop from rpython.memory.gctransform.framework import ( BaseFrameworkGCTransformer, BaseRootWalker) from rpython.rtyper.rbuiltin import gen_cast -from rpython.translator.unsimplify import copyvar +from rpython.translator.unsimplify import copyvar, varoftype +from rpython.translator.tool.cbuild import ExternalCompilationInfo import sys @@ -22,6 +24,7 @@ class AsmGcRootFrameworkGCTransformer(BaseFrameworkGCTransformer): _asmgcc_save_restore_arguments = None + _seen_gctransformer_hint_close_stack = None def push_roots(self, hop, keep_current_args=False): livevars = self.get_livevars_for_roots(hop, keep_current_args) @@ -57,10 +60,22 @@ def handle_call_with_close_stack(self, hop): fnptr = hop.spaceop.args[0].value + if self._seen_gctransformer_hint_close_stack is None: + self._seen_gctransformer_hint_close_stack = {} + if fnptr._obj.graph not in self._seen_gctransformer_hint_close_stack: + self._transform_hint_close_stack(fnptr) + self._seen_gctransformer_hint_close_stack[fnptr._obj.graph] = True + # + livevars = self.push_roots(hop) + self.default(hop) + self.pop_roots(hop, livevars) + + def _transform_hint_close_stack(self, fnptr): # We cannot easily pass variable amount of arguments of the call # across the call to the pypy_asm_stackwalk helper. So we store - # them away and restore them. We need to make a new graph - # that starts with restoring the arguments. + # them away and restore them. More precisely, we need to + # replace 'graph' with code that saves the arguments, and make + # a new graph that starts with restoring the arguments. if self._asmgcc_save_restore_arguments is None: self._asmgcc_save_restore_arguments = {} sradict = self._asmgcc_save_restore_arguments @@ -80,25 +95,52 @@ sradict[key] = Constant(p, lltype.Ptr(CONTAINER)) sra.append(sradict[key]) # - # store the value of the arguments - livevars = self.push_roots(hop) + # make a copy of the graph that will reload the values + graph = fnptr._obj.graph + graph2 = copygraph(graph) + # + # edit the original graph to only store the value of the arguments + block = Block(graph.startblock.inputargs) c_item0 = Constant('item0', lltype.Void) - for v_arg, c_p in zip(hop.spaceop.args[1:], sra): + assert len(block.inputargs) == len(sra) + for v_arg, c_p in zip(block.inputargs, sra): if isinstance(v_arg.concretetype, lltype.Ptr): - v_arg = hop.genop("cast_ptr_to_adr", [v_arg], - resulttype=llmemory.Address) - hop.genop("bare_setfield", [c_p, c_item0, v_arg]) + v_adr = varoftype(llmemory.Address) + block.operations.append( + SpaceOperation("cast_ptr_to_adr", [v_arg], v_adr)) + v_arg = v_adr + v_void = varoftype(lltype.Void) + block.operations.append( + SpaceOperation("bare_setfield", [c_p, c_item0, v_arg], v_void)) # - # make a copy of the graph that will reload the values - graph2 = copygraph(fnptr._obj.graph) + # call asm_stackwalk(graph2) + FUNC2 = lltype.FuncType([], FUNC1.RESULT) + fnptr2 = lltype.functionptr(FUNC2, + fnptr._obj._name + '_reload', + graph=graph2) + c_fnptr2 = Constant(fnptr2, lltype.Ptr(FUNC2)) + HELPERFUNC = lltype.FuncType([lltype.Ptr(FUNC2), + ASM_FRAMEDATA_HEAD_PTR], FUNC1.RESULT) + v_asm_stackwalk = varoftype(lltype.Ptr(HELPERFUNC), "asm_stackwalk") + block.operations.append( + SpaceOperation("cast_pointer", [c_asm_stackwalk], v_asm_stackwalk)) + v_result = varoftype(FUNC1.RESULT) + block.operations.append( + SpaceOperation("indirect_call", [v_asm_stackwalk, c_fnptr2, + c_gcrootanchor, + Constant(None, lltype.Void)], + v_result)) + block.closeblock(Link([v_result], graph.returnblock)) + graph.startblock = block + # + # edit the copy of the graph to reload the values block2 = graph2.startblock block1 = Block([]) reloadedvars = [] for v, c_p in zip(block2.inputargs, sra): v = copyvar(None, v) if isinstance(v.concretetype, lltype.Ptr): - w = Variable('tmp') - w.concretetype = llmemory.Address + w = varoftype(llmemory.Address) else: w = v block1.operations.append(SpaceOperation('getfield', @@ -109,21 +151,9 @@ reloadedvars.append(v) block1.closeblock(Link(reloadedvars, block2)) graph2.startblock = block1 - FUNC2 = lltype.FuncType([], FUNC1.RESULT) - fnptr2 = lltype.functionptr(FUNC2, - fnptr._obj._name + '_reload', - graph=graph2) - c_fnptr2 = Constant(fnptr2, lltype.Ptr(FUNC2)) - HELPERFUNC = lltype.FuncType([lltype.Ptr(FUNC2), - ASM_FRAMEDATA_HEAD_PTR], FUNC1.RESULT) # - v_asm_stackwalk = hop.genop("cast_pointer", [c_asm_stackwalk], - resulttype=lltype.Ptr(HELPERFUNC)) - hop.genop("indirect_call", - [v_asm_stackwalk, c_fnptr2, c_gcrootanchor, - Constant(None, lltype.Void)], - resultvar=hop.spaceop.result) - self.pop_roots(hop, livevars) + checkgraph(graph) + checkgraph(graph2) class AsmStackRootWalker(BaseRootWalker): @@ -284,6 +314,8 @@ stackscount += 1 # expected = rffi.stackcounter.stacks_counter + if NonConstant(0): + rffi.stackcounter.stacks_counter += 42 # hack to force it ll_assert(not (stackscount < expected), "non-closed stacks around") ll_assert(not (stackscount > expected), "stacks counter corruption?") lltype.free(otherframe, flavor='raw') @@ -681,13 +713,16 @@ gcrootanchor.next = gcrootanchor c_gcrootanchor = Constant(gcrootanchor, ASM_FRAMEDATA_HEAD_PTR) +eci = ExternalCompilationInfo(pre_include_bits=['#define PYPY_USE_ASMGCC']) + pypy_asm_stackwalk = rffi.llexternal('pypy_asm_stackwalk', [ASM_CALLBACK_PTR, ASM_FRAMEDATA_HEAD_PTR], lltype.Signed, sandboxsafe=True, _nowrapper=True, - random_effects_on_gcobjs=True) + random_effects_on_gcobjs=True, + compilation_info=eci) c_asm_stackwalk = Constant(pypy_asm_stackwalk, lltype.typeOf(pypy_asm_stackwalk)) diff --git a/rpython/rtyper/lltypesystem/rffi.py b/rpython/rtyper/lltypesystem/rffi.py --- a/rpython/rtyper/lltypesystem/rffi.py +++ b/rpython/rtyper/lltypesystem/rffi.py @@ -282,13 +282,13 @@ args = ', '.join(['a%d' % i for i in range(len(TP.TO.ARGS))]) source = py.code.Source(r""" def wrapper(%(args)s): # no *args - no GIL for mallocing the tuple - llop.gc_stack_bottom(lltype.Void) # marker for trackgcroot.py if aroundstate is not None: after = aroundstate.after if after: after() # from now on we hold the GIL stackcounter.stacks_counter += 1 + llop.gc_stack_bottom(lltype.Void) # marker for trackgcroot.py try: result = callable(%(args)s) except Exception, e: diff --git a/rpython/translator/c/gcc/test/test_asmgcroot.py b/rpython/translator/c/gcc/test/test_asmgcroot.py --- a/rpython/translator/c/gcc/test/test_asmgcroot.py +++ b/rpython/translator/c/gcc/test/test_asmgcroot.py @@ -195,8 +195,8 @@ @entrypoint("x42", [lltype.Signed, lltype.Signed], c_name='callback') def mycallback(a, b): + rffi.stackcounter.stacks_counter += 1 llop.gc_stack_bottom(lltype.Void) - rffi.stackcounter.stacks_counter += 1 gc.collect() rffi.stackcounter.stacks_counter -= 1 return a + b diff --git a/rpython/translator/c/src/mem.c b/rpython/translator/c/src/mem.c --- a/rpython/translator/c/src/mem.c +++ b/rpython/translator/c/src/mem.c @@ -96,3 +96,27 @@ GC_set_warn_proc(mem_boehm_ignore); } #endif /* BOEHM GC */ + + +#ifdef RPY_ASSERT +# ifdef PYPY_USE_ASMGCC +# include "structdef.h" +# include "forwarddecl.h" +# endif +void pypy_check_stack_count(void) +{ +# ifdef PYPY_USE_ASMGCC + void *anchor = (void*)&pypy_g_ASM_FRAMEDATA_HEAD; + void *fd = ((void* *) (((char *)anchor) + sizeof(void*)))[0]; + long got = 0; + long stacks_counter = + pypy_g_rpython_rtyper_lltypesystem_rffi_StackCounter.sc_inst_stacks_counter; + while (fd != anchor) { + got += 1; + fd = ((void* *) (((char *)fd) + sizeof(void*)))[0]; + } + RPyAssert(got == stacks_counter - 1, + "bad stacks_counter or non-closed stacks around"); +# endif +} +#endif diff --git a/rpython/translator/c/src/mem.h b/rpython/translator/c/src/mem.h --- a/rpython/translator/c/src/mem.h +++ b/rpython/translator/c/src/mem.h @@ -195,8 +195,14 @@ "g" (v)) /* marker for trackgcroot.py, and inhibits tail calls */ -#define pypy_asm_stack_bottom() asm volatile ("/* GC_STACK_BOTTOM */" : : : \ - "memory") +#define pypy_asm_stack_bottom() { asm volatile ("/* GC_STACK_BOTTOM */" : : : \ + "memory"); pypy_check_stack_count(); } +#ifdef RPY_ASSERT +void pypy_check_stack_count(void); +#else +static void pypy_check_stack_count(void) { } +#endif + #define OP_GC_ASMGCROOT_STATIC(i, r) r = \ i == 0 ? (void*)&__gcmapstart : \ From noreply at buildbot.pypy.org Thu Apr 4 23:50:09 2013 From: noreply at buildbot.pypy.org (arigo) Date: Thu, 4 Apr 2013 23:50:09 +0200 (CEST) Subject: [pypy-commit] cffi default: Fix the docstring. Message-ID: <20130404215009.3FE991C305F@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r1232:95cea550141d Date: 2013-04-04 23:49 +0200 http://bitbucket.org/cffi/cffi/changeset/95cea550141d/ Log: Fix the docstring. diff --git a/cffi/api.py b/cffi/api.py --- a/cffi/api.py +++ b/cffi/api.py @@ -221,7 +221,7 @@ it as a string or unicode string. If 'cdata' is an enum, returns the value of the enumerator as a - string, or '#NUMBER' if the value is out of range. + string, or 'NUMBER' if the value is out of range. """ return self._backend.string(cdata, maxlen) From noreply at buildbot.pypy.org Fri Apr 5 00:35:22 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Fri, 5 Apr 2013 00:35:22 +0200 (CEST) Subject: [pypy-commit] pypy default: test sqlite3 using cffi.backend_ctypes on cpython Message-ID: <20130404223522.967E31C06BD@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63030:f081ae9b7d19 Date: 2013-04-04 18:34 -0400 http://bitbucket.org/pypy/pypy/changeset/f081ae9b7d19/ Log: test sqlite3 using cffi.backend_ctypes on cpython diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -48,7 +48,13 @@ from cffi import FFI as _FFI -_ffi = _FFI() +if '__pypy__' not in sys.builtin_module_names: + from cffi.backend_ctypes import CTypesBackend + backend = CTypesBackend() +else: + backend = None + +_ffi = _FFI(backend=backend) _ffi.cdef(""" #define SQLITE_OK ... @@ -251,7 +257,7 @@ def _has_load_extension(): """Only available since 3.3.6""" - unverified_ffi = _FFI() + unverified_ffi = _FFI(backend=backend) unverified_ffi.cdef(""" typedef ... sqlite3; int sqlite3_enable_load_extension(sqlite3 *db, int onoff); diff --git a/lib_pypy/cffi/cparser.py b/lib_pypy/cffi/cparser.py --- a/lib_pypy/cffi/cparser.py +++ b/lib_pypy/cffi/cparser.py @@ -2,7 +2,7 @@ from . import api, model from .commontypes import COMMON_TYPES, resolve_common_type try: - from cffi import _pycparser as pycparser + from . import _pycparser as pycparser except ImportError: import pycparser import weakref, re, sys From noreply at buildbot.pypy.org Fri Apr 5 00:58:57 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 5 Apr 2013 00:58:57 +0200 (CEST) Subject: [pypy-commit] cffi default: Use a relative import. Message-ID: <20130404225857.1A65D1C305F@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r1233:f154db447b34 Date: 2013-04-05 00:57 +0200 http://bitbucket.org/cffi/cffi/changeset/f154db447b34/ Log: Use a relative import. diff --git a/cffi/cparser.py b/cffi/cparser.py --- a/cffi/cparser.py +++ b/cffi/cparser.py @@ -2,7 +2,7 @@ from . import api, model from .commontypes import COMMON_TYPES, resolve_common_type try: - from cffi import _pycparser as pycparser + from . import _pycparser as pycparser except ImportError: import pycparser import weakref, re, sys From noreply at buildbot.pypy.org Fri Apr 5 01:10:34 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 5 Apr 2013 01:10:34 +0200 (CEST) Subject: [pypy-commit] pypy default: Run import_cffi.py. Message-ID: <20130404231034.A776E1C301F@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63031:a69998ec15d5 Date: 2013-04-05 01:02 +0200 http://bitbucket.org/pypy/pypy/changeset/a69998ec15d5/ Log: Run import_cffi.py. diff --git a/lib_pypy/cffi/api.py b/lib_pypy/cffi/api.py --- a/lib_pypy/cffi/api.py +++ b/lib_pypy/cffi/api.py @@ -25,6 +25,7 @@ line = '' return '%s%s' % (line, self.args[0]) + class FFI(object): r''' The main top-level class that you instantiate once, or once per module. @@ -220,7 +221,7 @@ it as a string or unicode string. If 'cdata' is an enum, returns the value of the enumerator as a - string, or '#NUMBER' if the value is out of range. + string, or 'NUMBER' if the value is out of range. """ return self._backend.string(cdata, maxlen) diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/setup.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/setup.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/setup.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py from distutils.core import setup import snip_basic_verify diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/snip_basic_verify.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/snip_basic_verify.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/snip_basic_verify.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/snip_basic_verify.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py from cffi import FFI import sys diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/setup.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/setup.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/setup.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py from distutils.core import setup import snip_basic_verify1 diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/snip_basic_verify1/__init__.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/snip_basic_verify1/__init__.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/snip_basic_verify1/__init__.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/snip_basic_verify1/__init__.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py from cffi import FFI import sys diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/setup.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/setup.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/setup.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py from distutils.core import setup import snip_basic_verify2 diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/snip_basic_verify2/__init__.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/snip_basic_verify2/__init__.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/snip_basic_verify2/__init__.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/snip_basic_verify2/__init__.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py from cffi import FFI import sys diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/setup.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/setup.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/setup.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py from distutils.core import setup diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/snip_infrastructure/__init__.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/snip_infrastructure/__init__.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/snip_infrastructure/__init__.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/snip_infrastructure/__init__.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py def func(): return 42 diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/setup.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/setup.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/setup.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py from setuptools import setup import snip_setuptools_verify diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/snip_setuptools_verify.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/snip_setuptools_verify.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/snip_setuptools_verify.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/snip_setuptools_verify.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py from cffi import FFI import sys diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/setup.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/setup.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/setup.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py from setuptools import setup import snip_setuptools_verify1 diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/snip_setuptools_verify1/__init__.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/snip_setuptools_verify1/__init__.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/snip_setuptools_verify1/__init__.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/snip_setuptools_verify1/__init__.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py from cffi import FFI import sys diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/setup.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/setup.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/setup.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py from setuptools import setup import snip_setuptools_verify2 diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/snip_setuptools_verify2/__init__.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/snip_setuptools_verify2/__init__.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/snip_setuptools_verify2/__init__.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/snip_setuptools_verify2/__init__.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py from cffi import FFI import sys From noreply at buildbot.pypy.org Fri Apr 5 01:18:46 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Fri, 5 Apr 2013 01:18:46 +0200 (CEST) Subject: [pypy-commit] pypy py3k: cleanup long's class hierarchy: stop using W_AbstractIntObject. fixes Message-ID: <20130404231846.A02641C06BD@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63032:edd8750a09ee Date: 2013-04-04 16:13 -0700 http://bitbucket.org/pypy/pypy/changeset/edd8750a09ee/ Log: cleanup long's class hierarchy: stop using W_AbstractIntObject. fixes unwrapping of smalllongs diff --git a/pypy/objspace/std/intobject.py b/pypy/objspace/std/intobject.py --- a/pypy/objspace/std/intobject.py +++ b/pypy/objspace/std/intobject.py @@ -20,7 +20,7 @@ __slots__ = 'intval' _immutable_fields_ = ['intval'] - from pypy.objspace.std.longtype import long_typedef as typedef +# from pypy.objspace.std.inttype import int_typedef as typedef def __init__(w_self, intval): assert is_valid_int(intval) @@ -57,7 +57,7 @@ a = self.intval return wrapint(space, a) -registerimplementation(W_IntObject) +#registerimplementation(W_IntObject) # NB: This code is shared by smallintobject.py, and thus no other Int # multimethods should be invoked from these implementations. Instead, add an diff --git a/pypy/objspace/std/longobject.py b/pypy/objspace/std/longobject.py --- a/pypy/objspace/std/longobject.py +++ b/pypy/objspace/std/longobject.py @@ -4,13 +4,13 @@ from pypy.objspace.std.model import registerimplementation, W_Object from pypy.objspace.std.register_all import register_all from pypy.objspace.std.multimethod import FailedToImplementArgs -from pypy.objspace.std.intobject import W_IntObject, W_AbstractIntObject +from pypy.objspace.std.intobject import W_IntObject from pypy.objspace.std.noneobject import W_NoneObject from rpython.rlib.rbigint import rbigint -from pypy.objspace.std.longtype import long_typedef +from pypy.objspace.std.longtype import long_typedef, W_AbstractLongObject -class W_LongObject(W_AbstractIntObject): +class W_LongObject(W_AbstractLongObject): """This is a wrapper of rbigint.""" _immutable_fields_ = ['num'] diff --git a/pypy/objspace/std/longtype.py b/pypy/objspace/std/longtype.py --- a/pypy/objspace/std/longtype.py +++ b/pypy/objspace/std/longtype.py @@ -182,8 +182,8 @@ m - divmod_near(m, 10**n)[1] """ - from pypy.objspace.std.longobject import W_AbstractIntObject, newlong - assert isinstance(w_long, W_AbstractIntObject) + from pypy.objspace.std.longobject import newlong + assert isinstance(w_long, W_AbstractLongObject) if w_ndigits is None: return space.int(w_long) diff --git a/pypy/objspace/std/model.py b/pypy/objspace/std/model.py --- a/pypy/objspace/std/model.py +++ b/pypy/objspace/std/model.py @@ -86,7 +86,7 @@ self.typeorder = { objectobject.W_ObjectObject: [], boolobject.W_BoolObject: [], - intobject.W_IntObject: [], + #intobject.W_IntObject: [], floatobject.W_FloatObject: [], tupleobject.W_TupleObject: [], listobject.W_ListObject: [], @@ -161,24 +161,24 @@ register_delegates(self.typeorder) self.typeorder[boolobject.W_BoolObject] += [ - (intobject.W_IntObject, boolobject.delegate_Bool2IntObject), + #(intobject.W_IntObject, boolobject.delegate_Bool2IntObject), (floatobject.W_FloatObject, floatobject.delegate_Bool2Float), (longobject.W_LongObject, longobject.delegate_Bool2Long), (complexobject.W_ComplexObject, complexobject.delegate_Bool2Complex), ] - self.typeorder[intobject.W_IntObject] += [ - (longobject.W_LongObject, longobject.delegate_Int2Long), - (floatobject.W_FloatObject, floatobject.delegate_Int2Float), - (complexobject.W_ComplexObject, complexobject.delegate_Int2Complex), - ] + #self.typeorder[intobject.W_IntObject] += [ + # (longobject.W_LongObject, longobject.delegate_Int2Long), + # (floatobject.W_FloatObject, floatobject.delegate_Int2Float), + # (complexobject.W_ComplexObject, complexobject.delegate_Int2Complex), + # ] if config.objspace.std.withsmalllong: from pypy.objspace.std import smalllongobject self.typeorder[boolobject.W_BoolObject] += [ (smalllongobject.W_SmallLongObject, smalllongobject.delegate_Bool2SmallLong), ] - self.typeorder[intobject.W_IntObject] += [ - (smalllongobject.W_SmallLongObject, smalllongobject.delegate_Int2SmallLong), - ] + #self.typeorder[intobject.W_IntObject] += [ + # (smalllongobject.W_SmallLongObject, smalllongobject.delegate_Int2SmallLong), + # ] self.typeorder[smalllongobject.W_SmallLongObject] += [ (longobject.W_LongObject, smalllongobject.delegate_SmallLong2Long), (floatobject.W_FloatObject, smalllongobject.delegate_SmallLong2Float), @@ -229,6 +229,7 @@ # Prebuilt common integer values if config.objspace.std.withprebuiltint: + # XXX: currently broken on py3k intobject.W_IntObject.PREBUILT = [] for i in range(config.objspace.std.prebuiltintfrom, config.objspace.std.prebuiltintto): diff --git a/pypy/objspace/std/smalllongobject.py b/pypy/objspace/std/smalllongobject.py --- a/pypy/objspace/std/smalllongobject.py +++ b/pypy/objspace/std/smalllongobject.py @@ -9,7 +9,7 @@ from rpython.rlib.rarithmetic import r_longlong, r_int, r_uint from rpython.rlib.rarithmetic import intmask, LONGLONG_BIT from rpython.rlib.rbigint import rbigint -from pypy.objspace.std.longobject import W_AbstractIntObject, W_LongObject +from pypy.objspace.std.longobject import W_AbstractLongObject, W_LongObject from pypy.objspace.std.intobject import W_IntObject from pypy.objspace.std.noneobject import W_NoneObject from pypy.interpreter.error import OperationError @@ -17,7 +17,7 @@ LONGLONG_MIN = r_longlong((-1) << (LONGLONG_BIT-1)) -class W_SmallLongObject(W_AbstractIntObject): +class W_SmallLongObject(W_AbstractLongObject): from pypy.objspace.std.longtype import long_typedef as typedef _immutable_fields_ = ['longlong'] From noreply at buildbot.pypy.org Fri Apr 5 01:18:47 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Fri, 5 Apr 2013 01:18:47 +0200 (CEST) Subject: [pypy-commit] pypy py3k: apply a workaround for test_13_genexp from default Message-ID: <20130404231847.CE24F1C06BD@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63033:0b705246a80a Date: 2013-04-04 16:14 -0700 http://bitbucket.org/pypy/pypy/changeset/0b705246a80a/ Log: apply a workaround for test_13_genexp from default diff --git a/lib-python/3/test/test_sys_settrace.py b/lib-python/3/test/test_sys_settrace.py --- a/lib-python/3/test/test_sys_settrace.py +++ b/lib-python/3/test/test_sys_settrace.py @@ -213,12 +213,17 @@ "finally" def generator_example(): # any() will leave the generator before its end - x = any(generator_function()) + x = any(generator_function()); gc.collect() # the following lines were not traced for x in range(10): y = x +# On CPython, when the generator is decref'ed to zero, we see the trace +# for the "finally:" portion. On PyPy, we don't see it before the next +# garbage collection. That's why we put gc.collect() on the same line +# above. + generator_example.events = ([(0, 'call'), (2, 'line'), (-6, 'call'), @@ -323,17 +328,24 @@ self.run_test(tighterloop_example) def test_13_genexp(self): - self.run_test(generator_example) - # issue1265: if the trace function contains a generator, - # and if the traced function contains another generator - # that is not completely exhausted, the trace stopped. - # Worse: the 'finally' clause was not invoked. - tracer = Tracer() - sys.settrace(tracer.traceWithGenexp) - generator_example() - sys.settrace(None) - self.compare_events(generator_example.__code__.co_firstlineno, - tracer.events, generator_example.events) + if self.using_gc: + support.gc_collect() + gc.enable() + try: + self.run_test(generator_example) + # issue1265: if the trace function contains a generator, + # and if the traced function contains another generator + # that is not completely exhausted, the trace stopped. + # Worse: the 'finally' clause was not invoked. + tracer = Tracer() + sys.settrace(tracer.traceWithGenexp) + generator_example() + sys.settrace(None) + self.compare_events(generator_example.__code__.co_firstlineno, + tracer.events, generator_example.events) + finally: + if self.using_gc: + gc.disable() def test_14_onliner_if(self): def onliners(): From noreply at buildbot.pypy.org Fri Apr 5 01:18:49 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Fri, 5 Apr 2013 01:18:49 +0200 (CEST) Subject: [pypy-commit] pypy py3k: loosen codegen's constant expression optimization, cpython's test_sys_settrace Message-ID: <20130404231849.11C531C06BD@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63034:ff08b8863a84 Date: 2013-04-04 16:17 -0700 http://bitbucket.org/pypy/pypy/changeset/ff08b8863a84/ Log: loosen codegen's constant expression optimization, cpython's test_sys_settrace expects a constant bool to be emitted, e.g. diff --git a/pypy/interpreter/astcompiler/codegen.py b/pypy/interpreter/astcompiler/codegen.py --- a/pypy/interpreter/astcompiler/codegen.py +++ b/pypy/interpreter/astcompiler/codegen.py @@ -844,8 +844,8 @@ if self.interactive: expr.value.walkabout(self) self.emit_op(ops.PRINT_EXPR) - # Only compile if the expression isn't constant. - elif not expr.value.constant: + elif not (isinstance(expr.value, ast.Num) or + isinstance(expr.value, ast.Str)): expr.value.walkabout(self) self.emit_op(ops.POP_TOP) diff --git a/pypy/interpreter/test/test_pyframe.py b/pypy/interpreter/test/test_pyframe.py --- a/pypy/interpreter/test/test_pyframe.py +++ b/pypy/interpreter/test/test_pyframe.py @@ -436,6 +436,25 @@ sys.settrace(None) assert res == 42 + def test_trace_onliner_if(self): + import sys + l = [] + def trace(frame, event, arg): + l.append((frame.f_lineno, event)) + return trace + def onliners(): + if True: False + else: True + return 0 + sys.settrace(trace) + onliners() + sys.settrace(None) + firstlineno = onliners.__code__.co_firstlineno + assert l == [(firstlineno + 0, 'call'), + (firstlineno + 1, 'line'), + (firstlineno + 3, 'line'), + (firstlineno + 3, 'return')] + def test_set_unset_f_trace(self): import sys seen = [] From noreply at buildbot.pypy.org Fri Apr 5 01:32:21 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Fri, 5 Apr 2013 01:32:21 +0200 (CEST) Subject: [pypy-commit] pypy default: don't use CTypesBackend to test on cpython Message-ID: <20130404233221.BD0001C305F@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63035:bf6aa926c0d9 Date: 2013-04-04 19:31 -0400 http://bitbucket.org/pypy/pypy/changeset/bf6aa926c0d9/ Log: don't use CTypesBackend to test on cpython diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -48,13 +48,7 @@ from cffi import FFI as _FFI -if '__pypy__' not in sys.builtin_module_names: - from cffi.backend_ctypes import CTypesBackend - backend = CTypesBackend() -else: - backend = None - -_ffi = _FFI(backend=backend) +_ffi = _FFI() _ffi.cdef(""" #define SQLITE_OK ... @@ -257,7 +251,7 @@ def _has_load_extension(): """Only available since 3.3.6""" - unverified_ffi = _FFI(backend=backend) + unverified_ffi = _FFI() unverified_ffi.cdef(""" typedef ... sqlite3; int sqlite3_enable_load_extension(sqlite3 *db, int onoff); From noreply at buildbot.pypy.org Fri Apr 5 02:58:32 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Fri, 5 Apr 2013 02:58:32 +0200 (CEST) Subject: [pypy-commit] pypy py3k: disable cpyext's int APIs, removes more W_IntObject references Message-ID: <20130405005832.64CF01C305F@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63036:d7a0fdc9bc85 Date: 2013-04-04 17:57 -0700 http://bitbucket.org/pypy/pypy/changeset/d7a0fdc9bc85/ Log: disable cpyext's int APIs, removes more W_IntObject references diff --git a/pypy/module/cpyext/__init__.py b/pypy/module/cpyext/__init__.py --- a/pypy/module/cpyext/__init__.py +++ b/pypy/module/cpyext/__init__.py @@ -38,7 +38,6 @@ import pypy.module.cpyext.tupleobject import pypy.module.cpyext.setobject import pypy.module.cpyext.dictobject -import pypy.module.cpyext.intobject import pypy.module.cpyext.longobject import pypy.module.cpyext.listobject import pypy.module.cpyext.sequence diff --git a/pypy/module/cpyext/longobject.py b/pypy/module/cpyext/longobject.py --- a/pypy/module/cpyext/longobject.py +++ b/pypy/module/cpyext/longobject.py @@ -4,7 +4,6 @@ CONST_STRING, ADDR, CANNOT_FAIL) from pypy.objspace.std.longobject import W_LongObject from pypy.interpreter.error import OperationError -from pypy.module.cpyext.intobject import PyInt_AsUnsignedLongMask from rpython.rlib.rbigint import rbigint from rpython.rlib.rarithmetic import intmask @@ -66,7 +65,8 @@ """Return a C unsigned long from a Python long integer, without checking for overflow. """ - return PyInt_AsUnsignedLongMask(space, w_long) + num = space.bigint_w(w_long) + return num.ulonglongmask() @cpython_api([PyObject], lltype.Signed, error=-1) def PyLong_AsLong(space, w_long): diff --git a/pypy/module/cpyext/structmember.py b/pypy/module/cpyext/structmember.py --- a/pypy/module/cpyext/structmember.py +++ b/pypy/module/cpyext/structmember.py @@ -3,7 +3,7 @@ from rpython.rtyper.lltypesystem import rffi, lltype from pypy.module.cpyext.structmemberdefs import * from pypy.module.cpyext.api import ADDR, PyObjectP, cpython_api -from pypy.module.cpyext.intobject import PyInt_AsLong, PyInt_AsUnsignedLong +from pypy.module.cpyext.longobject import PyLong_AsLong, PyLong_AsUnsignedLong from pypy.module.cpyext.pyerrors import PyErr_Occurred from pypy.module.cpyext.pyobject import PyObject, Py_DecRef, from_ref, make_ref from pypy.module.cpyext.unicodeobject import PyUnicode_FromString @@ -14,15 +14,15 @@ from rpython.rlib.unroll import unrolling_iterable integer_converters = unrolling_iterable([ - (T_SHORT, rffi.SHORT, PyInt_AsLong), - (T_INT, rffi.INT, PyInt_AsLong), - (T_LONG, rffi.LONG, PyInt_AsLong), - (T_USHORT, rffi.USHORT, PyInt_AsUnsignedLong), - (T_UINT, rffi.UINT, PyInt_AsUnsignedLong), - (T_ULONG, rffi.ULONG, PyInt_AsUnsignedLong), - (T_BYTE, rffi.SIGNEDCHAR, PyInt_AsLong), - (T_UBYTE, rffi.UCHAR, PyInt_AsUnsignedLong), - (T_BOOL, rffi.UCHAR, PyInt_AsLong), + (T_SHORT, rffi.SHORT, PyLong_AsLong), + (T_INT, rffi.INT, PyLong_AsLong), + (T_LONG, rffi.LONG, PyLong_AsLong), + (T_USHORT, rffi.USHORT, PyLong_AsUnsignedLong), + (T_UINT, rffi.UINT, PyLong_AsUnsignedLong), + (T_ULONG, rffi.ULONG, PyLong_AsUnsignedLong), + (T_BYTE, rffi.SIGNEDCHAR, PyLong_AsLong), + (T_UBYTE, rffi.UCHAR, PyLong_AsUnsignedLong), + (T_BOOL, rffi.UCHAR, PyLong_AsLong), (T_FLOAT, rffi.FLOAT, PyFloat_AsDouble), (T_DOUBLE, rffi.DOUBLE, PyFloat_AsDouble), (T_LONGLONG, rffi.LONGLONG, PyLong_AsLongLong), diff --git a/pypy/module/cpyext/test/test_longobject.py b/pypy/module/cpyext/test/test_longobject.py --- a/pypy/module/cpyext/test/test_longobject.py +++ b/pypy/module/cpyext/test/test_longobject.py @@ -123,6 +123,12 @@ assert api._PyLong_NumBits(space.wrap(3)) == 2 assert api._PyLong_NumBits(space.wrap(-3)) == 2 + def test_as_ulongmask(self, space, api): + assert api.PyLong_AsUnsignedLongMask( + space.wrap(sys.maxsize * 2 + 1)) == 18446744073709551615 + assert api.PyLong_AsUnsignedLongMask( + space.wrap(sys.maxsize * 2 + 2)) == 0 + class AppTestLongObject(AppTestCpythonExtensionBase): def test_fromunsignedlong(self): module = self.import_extension('foo', [ @@ -153,7 +159,7 @@ return PyLong_FromSize_t((size_t)-1); """)]) import sys - assert module.from_unsignedlong() == 2 * sys.maxint + 1 + assert module.from_unsignedlong() == 2 * sys.maxsize + 1 def test_fromstring(self): module = self.import_extension('foo', [ From noreply at buildbot.pypy.org Fri Apr 5 03:10:19 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Fri, 5 Apr 2013 03:10:19 +0200 (CEST) Subject: [pypy-commit] pypy py3k: switch back to int's id tag Message-ID: <20130405011019.7DB2E1C06BD@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63037:5110f1625ef0 Date: 2013-04-04 18:05 -0700 http://bitbucket.org/pypy/pypy/changeset/5110f1625ef0/ Log: switch back to int's id tag diff --git a/pypy/objspace/std/longtype.py b/pypy/objspace/std/longtype.py --- a/pypy/objspace/std/longtype.py +++ b/pypy/objspace/std/longtype.py @@ -214,7 +214,7 @@ def immutable_unique_id(self, space): if self.user_overridden_class: return None - from pypy.objspace.std.model import IDTAG_LONG as tag + from pypy.objspace.std.model import IDTAG_INT as tag b = space.bigint_w(self) b = b.lshift(3).or_(rbigint.fromint(tag)) return space.newlong_from_rbigint(b) diff --git a/pypy/objspace/std/model.py b/pypy/objspace/std/model.py --- a/pypy/objspace/std/model.py +++ b/pypy/objspace/std/model.py @@ -22,7 +22,7 @@ } IDTAG_INT = 1 -IDTAG_LONG = 3 +#IDTAG_LONG = 3 IDTAG_FLOAT = 5 IDTAG_COMPLEX = 7 From noreply at buildbot.pypy.org Fri Apr 5 03:10:20 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Fri, 5 Apr 2013 03:10:20 +0200 (CEST) Subject: [pypy-commit] pypy py3k: disable interp level W_IntObject tests Message-ID: <20130405011020.C00091C06BD@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63038:b0b275ecce2a Date: 2013-04-04 18:08 -0700 http://bitbucket.org/pypy/pypy/changeset/b0b275ecce2a/ Log: disable interp level W_IntObject tests diff --git a/pypy/objspace/std/test/test_intobject.py b/pypy/objspace/std/test/test_intobject.py --- a/pypy/objspace/std/test/test_intobject.py +++ b/pypy/objspace/std/test/test_intobject.py @@ -5,8 +5,10 @@ from rpython.rlib.rarithmetic import r_uint, is_valid_int from rpython.rlib.rbigint import rbigint +class TestW_IntObject: -class TestW_IntObject: + def setup_class(cls): + py.test.skip("W_IntObject was replaced w/ W_LongObject in py3k") def _longshiftresult(self, x): """ calculate an overflowing shift """ From noreply at buildbot.pypy.org Fri Apr 5 03:10:22 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Fri, 5 Apr 2013 03:10:22 +0200 (CEST) Subject: [pypy-commit] pypy py3k: disable PyInt_ API tests Message-ID: <20130405011022.0A0B71C06BD@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63039:6cb7774fb7c5 Date: 2013-04-04 18:08 -0700 http://bitbucket.org/pypy/pypy/changeset/6cb7774fb7c5/ Log: disable PyInt_ API tests diff --git a/pypy/module/cpyext/test/test_intobject.py b/pypy/module/cpyext/test/test_intobject.py --- a/pypy/module/cpyext/test/test_intobject.py +++ b/pypy/module/cpyext/test/test_intobject.py @@ -1,7 +1,10 @@ +import py.test from pypy.module.cpyext.test.test_api import BaseApiTest from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase import sys +py.test.skip("PyInt_ APIs were removed from py3k") + class TestIntObject(BaseApiTest): def test_intobject(self, space, api): assert api.PyInt_Check(space.wrap(3)) From noreply at buildbot.pypy.org Fri Apr 5 03:11:13 2013 From: noreply at buildbot.pypy.org (wlav) Date: Fri, 5 Apr 2013 03:11:13 +0200 (CEST) Subject: [pypy-commit] pypy reflex-support: merge default into branch Message-ID: <20130405011113.55D0E1C06BD@cobra.cs.uni-duesseldorf.de> Author: Wim Lavrijsen Branch: reflex-support Changeset: r63040:300a0b23172a Date: 2013-04-01 19:23 -0700 http://bitbucket.org/pypy/pypy/changeset/300a0b23172a/ Log: merge default into branch diff too long, truncating to 2000 out of 4659 lines diff --git a/.tddium.requirements.txt b/.tddium.requirements.txt new file mode 100644 --- /dev/null +++ b/.tddium.requirements.txt @@ -0,0 +1,1 @@ +pytest diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py --- a/pypy/config/pypyoption.py +++ b/pypy/config/pypyoption.py @@ -33,7 +33,7 @@ "crypt", "signal", "_rawffi", "termios", "zlib", "bz2", "struct", "_hashlib", "_md5", "_sha", "_minimal_curses", "cStringIO", "thread", "itertools", "pyexpat", "_ssl", "cpyext", "array", - "_bisect", "binascii", "_multiprocessing", '_warnings', + "binascii", "_multiprocessing", '_warnings', "_collections", "_multibytecodec", "micronumpy", "_ffi", "_continuation", "_cffi_backend", "_csv"] )) diff --git a/pypy/config/test/test_pypyoption.py b/pypy/config/test/test_pypyoption.py --- a/pypy/config/test/test_pypyoption.py +++ b/pypy/config/test/test_pypyoption.py @@ -11,11 +11,11 @@ assert conf.objspace.usemodules.gc - conf.objspace.std.withsmallint = True - assert not conf.objspace.std.withprebuiltint + conf.objspace.std.withmapdict = True + assert conf.objspace.std.withmethodcache conf = get_pypy_config() - conf.objspace.std.withprebuiltint = True - py.test.raises(ConfigError, "conf.objspace.std.withsmallint = True") + conf.objspace.std.withmethodcache = False + py.test.raises(ConfigError, "conf.objspace.std.withmapdict = True") def test_conflicting_gcrootfinder(): conf = get_pypy_config() diff --git a/pypy/doc/arm.rst b/pypy/doc/arm.rst --- a/pypy/doc/arm.rst +++ b/pypy/doc/arm.rst @@ -145,7 +145,7 @@ :: - pypy ~/path_to_pypy_checkout/rpython/translator/goal/translate.py -O1 --platform=arm target.py + pypy ~/path_to_pypy_checkout/rpython/bin/rpython -O1 --platform=arm target.py If everything worked correctly this should yield an ARM binary. Running this binary in the ARM chroot or on an ARM device should produce the output ``"Hello World"``. @@ -153,7 +153,7 @@ :: - pypy /rpython/translator/goal/translate.py -Ojit --platform=arm --gcrootfinder=shadowstack --jit-backend=arm targetpypystandalone.py + pypy /rpython/bin/rpython -Ojit --platform=arm --gcrootfinder=shadowstack --jit-backend=armv7 targetpypystandalone.py The gcrootfinder option is needed to work around `issue 1377`_ and the jit-backend works around `issue 1376`_ diff --git a/pypy/doc/config/objspace.std.withsmallint.txt b/pypy/doc/config/objspace.std.withsmallint.txt deleted file mode 100644 --- a/pypy/doc/config/objspace.std.withsmallint.txt +++ /dev/null @@ -1,6 +0,0 @@ -Use "tagged pointers" to represent small enough integer values: Integers that -fit into 31 bits (respective 63 bits on 64 bit machines) are not represented by -boxing them in an instance of ``W_IntObject``. Instead they are represented as a -pointer having the lowest bit set and the rest of the bits used to store the -value of the integer. This gives a small speedup for integer operations as well -as better memory behaviour. diff --git a/pypy/doc/config/objspace.usemodules._bisect.txt b/pypy/doc/config/objspace.usemodules._bisect.txt deleted file mode 100644 --- a/pypy/doc/config/objspace.usemodules._bisect.txt +++ /dev/null @@ -1,4 +0,0 @@ -Use the '_bisect' module. -Used, optionally, by the 'bisect' standard lib module. This module is expected to be working and is included by default. - - diff --git a/pypy/doc/config/translation.taggedpointers.txt b/pypy/doc/config/translation.taggedpointers.txt --- a/pypy/doc/config/translation.taggedpointers.txt +++ b/pypy/doc/config/translation.taggedpointers.txt @@ -1,3 +1,3 @@ Enable tagged pointers. This option is mostly useful for the Smalltalk and Prolog interpreters. For the Python interpreter the option -:config:`objspace.std.withsmallint` should be used. +:config:`objspace.std.withsmalllong` should be used. diff --git a/pypy/doc/cpython_differences.rst b/pypy/doc/cpython_differences.rst --- a/pypy/doc/cpython_differences.rst +++ b/pypy/doc/cpython_differences.rst @@ -21,7 +21,6 @@ __builtin__ `__pypy__`_ _ast - _bisect _codecs _collections `_continuation`_ diff --git a/pypy/doc/interpreter-optimizations.rst b/pypy/doc/interpreter-optimizations.rst --- a/pypy/doc/interpreter-optimizations.rst +++ b/pypy/doc/interpreter-optimizations.rst @@ -55,7 +55,7 @@ them from normal pointers. This completely avoids the boxing step, saving time and memory. -You can enable this feature with the :config:`objspace.std.withsmallint` option. +You can enable this feature with the :config:`objspace.std.withsmalllong` option. Dictionary Optimizations ------------------------ diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -42,6 +42,10 @@ .. branch: rpython-bytearray Rudimentary support for bytearray in RPython +.. branch: refactor-call_release_gil +Fix a bug which casused cffi to return the wrong result when calling a C +function which calls a Python callback which forces the frames + .. branches we don't care about .. branch: autoreds .. branch: reflex-support diff --git a/pypy/interpreter/function.py b/pypy/interpreter/function.py --- a/pypy/interpreter/function.py +++ b/pypy/interpreter/function.py @@ -22,7 +22,6 @@ assert not func.can_change_code return func.code - class Function(W_Root): """A function is a code object captured with some environment: an object space, a dictionary of globals, default arguments, diff --git a/pypy/interpreter/gateway.py b/pypy/interpreter/gateway.py --- a/pypy/interpreter/gateway.py +++ b/pypy/interpreter/gateway.py @@ -812,6 +812,8 @@ d = {} exec func_code.compile() in d f = d['f'] + f.__module__ = func.__module__ + # necessary for unique identifiers for pickling f.func_name = func.func_name if unwrap_spec is None: unwrap_spec = {} @@ -877,9 +879,9 @@ for name, defaultval in self._staticdefs: if name.startswith('w_'): assert defaultval is None, ( - "%s: default value for '%s' can only be None; " + "%s: default value for '%s' can only be None, got %r; " "use unwrap_spec(...=WrappedDefault(default))" % ( - self._code.identifier, name)) + self._code.identifier, name, defaultval)) defs_w.append(None) else: defs_w.append(space.wrap(defaultval)) diff --git a/pypy/module/__builtin__/functional.py b/pypy/module/__builtin__/functional.py --- a/pypy/module/__builtin__/functional.py +++ b/pypy/module/__builtin__/functional.py @@ -330,6 +330,7 @@ next = interp2app(W_ReversedIterator.descr_next), __reduce__ = interp2app(W_ReversedIterator.descr___reduce__), ) +W_ReversedIterator.typedef.acceptable_as_base_class = False # exported through _pickle_support def _make_reversed(space, w_seq, w_remaining): @@ -428,7 +429,7 @@ __reversed__ = interp2app(W_XRange.descr_reversed), __reduce__ = interp2app(W_XRange.descr_reduce), ) - +W_XRange.typedef.acceptable_as_base_class = False class W_XRangeIterator(W_Root): def __init__(self, space, current, remaining, step): @@ -475,6 +476,7 @@ next = interp2app(W_XRangeIterator.descr_next), __reduce__ = interp2app(W_XRangeIterator.descr_reduce), ) +W_XRangeIterator.typedef.acceptable_as_base_class = False class W_XRangeStepOneIterator(W_XRangeIterator): def __init__(self, space, start, stop): diff --git a/pypy/module/_bisect/__init__.py b/pypy/module/_bisect/__init__.py deleted file mode 100644 --- a/pypy/module/_bisect/__init__.py +++ /dev/null @@ -1,27 +0,0 @@ -""" -Mixed-module definition for the _bisect module. -This is an optional module; if not present, bisect.py uses the -pure Python version of these functions. -""" - -from pypy.interpreter.mixedmodule import MixedModule - - -class Module(MixedModule): - """\ -This module provides support for maintaining a list in sorted order without -having to sort the list after each insertion. For long lists of items with -expensive comparison operations, this can be an improvement over the more -common approach.""" - - appleveldefs = { - 'insort': 'app_bisect.insort_right', - 'insort_left': 'app_bisect.insort_left', - 'insort_right': 'app_bisect.insort_right', - } - - interpleveldefs = { - 'bisect': 'interp_bisect.bisect_right', - 'bisect_left': 'interp_bisect.bisect_left', - 'bisect_right': 'interp_bisect.bisect_right', - } diff --git a/pypy/module/_bisect/app_bisect.py b/pypy/module/_bisect/app_bisect.py deleted file mode 100644 --- a/pypy/module/_bisect/app_bisect.py +++ /dev/null @@ -1,23 +0,0 @@ -from _bisect import bisect_left, bisect_right - - -def insort_left(a, x, lo=0, hi=-1): - """Insert item x in list a, and keep it sorted assuming a is sorted. - -If x is already in a, insert it to the left of the leftmost x. - -Optional args lo (default 0) and hi (default len(a)) bound the -slice of a to be searched.""" - n = bisect_left(a, x, lo, hi) - a.insert(n, x) - - -def insort_right(a, x, lo=0, hi=-1): - """Insert item x in list a, and keep it sorted assuming a is sorted. - -If x is already in a, insert it to the right of the rightmost x. - -Optional args lo (default 0) and hi (default len(a)) bound the -slice of a to be searched.""" - n = bisect_right(a, x, lo, hi) - a.insert(n, x) diff --git a/pypy/module/_bisect/interp_bisect.py b/pypy/module/_bisect/interp_bisect.py deleted file mode 100644 --- a/pypy/module/_bisect/interp_bisect.py +++ /dev/null @@ -1,53 +0,0 @@ -from pypy.interpreter.error import OperationError -from pypy.interpreter.gateway import unwrap_spec -from rpython.rlib.rarithmetic import intmask, r_uint - - - at unwrap_spec(lo=int, hi=int) -def bisect_left(space, w_a, w_x, lo=0, hi=-1): - """Return the index where to insert item x in list a, assuming a is sorted. - -The return value i is such that all e in a[:i] have e < x, and all e in -a[i:] have e >= x. So if x already appears in the list, i points just -before the leftmost x already there. - -Optional args lo (default 0) and hi (default len(a)) bound the -slice of a to be searched.""" - if lo < 0: - raise OperationError(space.w_ValueError, - space.wrap("lo must be non-negative")) - if hi == -1: - hi = space.len_w(w_a) - while lo < hi: - mid = intmask((r_uint(lo) + r_uint(hi)) >> 1) - w_litem = space.getitem(w_a, space.wrap(mid)) - if space.is_true(space.lt(w_litem, w_x)): - lo = mid + 1 - else: - hi = mid - return space.wrap(lo) - - - at unwrap_spec(lo=int, hi=int) -def bisect_right(space, w_a, w_x, lo=0, hi=-1): - """Return the index where to insert item x in list a, assuming a is sorted. - -The return value i is such that all e in a[:i] have e <= x, and all e in -a[i:] have e > x. So if x already appears in the list, i points just -beyond the rightmost x already there - -Optional args lo (default 0) and hi (default len(a)) bound the -slice of a to be searched.""" - if lo < 0: - raise OperationError(space.w_ValueError, - space.wrap("lo must be non-negative")) - if hi == -1: - hi = space.len_w(w_a) - while lo < hi: - mid = intmask((r_uint(lo) + r_uint(hi)) >> 1) - w_litem = space.getitem(w_a, space.wrap(mid)) - if space.is_true(space.lt(w_x, w_litem)): - hi = mid - else: - lo = mid + 1 - return space.wrap(lo) diff --git a/pypy/module/_bisect/test/__init__.py b/pypy/module/_bisect/test/__init__.py deleted file mode 100644 diff --git a/pypy/module/_bisect/test/test_bisect.py b/pypy/module/_bisect/test/test_bisect.py deleted file mode 100644 --- a/pypy/module/_bisect/test/test_bisect.py +++ /dev/null @@ -1,100 +0,0 @@ - -class AppTestBisect: - spaceconfig = dict(usemodules=['_bisect']) - - def test_bisect_left(self): - from _bisect import bisect_left - a = [0, 5, 6, 6, 6, 7] - assert bisect_left(a, None) == 0 - assert bisect_left(a, -3) == 0 - assert bisect_left(a, 0) == 0 - assert bisect_left(a, 3) == 1 - assert bisect_left(a, 5) == 1 - assert bisect_left(a, 5.5) == 2 - assert bisect_left(a, 6) == 2 - assert bisect_left(a, 6.0) == 2 - assert bisect_left(a, 6.1) == 5 - assert bisect_left(a, 7) == 5 - assert bisect_left(a, 8) == 6 - a = [] - assert bisect_left(a, 123) == 0 - a = [9] - assert bisect_left(a, -123) == 0 - assert bisect_left(a, 9) == 0 - assert bisect_left(a, 123) == 1 - a = [9, 9] - assert bisect_left(a, -123) == 0 - assert bisect_left(a, 9) == 0 - assert bisect_left(a, 123) == 2 - a = [4, 6, 6, 9] - assert bisect_left(a, 6, 0) == 1 - assert bisect_left(a, 6, 1) == 1 - assert bisect_left(a, 6, 2) == 2 - assert bisect_left(a, 6, 3) == 3 - assert bisect_left(a, 6, 4) == 4 - assert bisect_left(a, 6, 0, 0) == 0 - assert bisect_left(a, 6, 0, 1) == 1 - assert bisect_left(a, 6, 0, 2) == 1 - assert bisect_left(a, 6, 0, 3) == 1 - assert bisect_left(a, 6, 0, 4) == 1 - - raises(ValueError, bisect_left, [1, 2, 3], 5, -1, 3) - - def test_bisect_right(self): - from _bisect import bisect_right - a = [0, 5, 6, 6, 6, 7] - assert bisect_right(a, None) == 0 - assert bisect_right(a, -3) == 0 - assert bisect_right(a, 0) == 1 - assert bisect_right(a, 3) == 1 - assert bisect_right(a, 5) == 2 - assert bisect_right(a, 5.5) == 2 - assert bisect_right(a, 6) == 5 - assert bisect_right(a, 6.0) == 5 - assert bisect_right(a, 6.1) == 5 - assert bisect_right(a, 7) == 6 - assert bisect_right(a, 8) == 6 - a = [] - assert bisect_right(a, 123) == 0 - a = [9] - assert bisect_right(a, -123) == 0 - assert bisect_right(a, 9) == 1 - assert bisect_right(a, 123) == 1 - a = [9, 9] - assert bisect_right(a, -123) == 0 - assert bisect_right(a, 9) == 2 - assert bisect_right(a, 123) == 2 - a = [4, 6, 6, 9] - assert bisect_right(a, 6, 0) == 3 - assert bisect_right(a, 6, 1) == 3 - assert bisect_right(a, 6, 2) == 3 - assert bisect_right(a, 6, 3) == 3 - assert bisect_right(a, 6, 4) == 4 - assert bisect_right(a, 6, 0, 0) == 0 - assert bisect_right(a, 6, 0, 1) == 1 - assert bisect_right(a, 6, 0, 2) == 2 - assert bisect_right(a, 6, 0, 3) == 3 - assert bisect_right(a, 6, 0, 4) == 3 - - def test_insort_left(self): - from _bisect import insort_left - a = [0, 5, 6, 6, 6, 7] - insort_left(a, 6.0) - assert a == [0, 5, 6.0, 6, 6, 6, 7] - assert map(type, a) == [int, int, float, int, int, int, int] - - def test_insort_right(self): - from _bisect import insort_right - a = [0, 5, 6, 6, 6, 7] - insort_right(a, 6.0) - assert a == [0, 5, 6, 6, 6, 6.0, 7] - assert map(type, a) == [int, int, int, int, int, float, int] - - def test_bisect_overflow(self): - from _bisect import bisect_left, bisect_right - import sys - - size = sys.maxsize - data = xrange(size - 1) - assert bisect_left(data, size - 3) == size - 3 - assert bisect_right(data, size - 3) == size - 2 diff --git a/pypy/module/_bisect/test/test_ztranslation.py b/pypy/module/_bisect/test/test_ztranslation.py deleted file mode 100644 --- a/pypy/module/_bisect/test/test_ztranslation.py +++ /dev/null @@ -1,4 +0,0 @@ -from pypy.objspace.fake.checkmodule import checkmodule - -def test_checkmodule(): - checkmodule('_bisect') diff --git a/pypy/module/_cffi_backend/cdataobj.py b/pypy/module/_cffi_backend/cdataobj.py --- a/pypy/module/_cffi_backend/cdataobj.py +++ b/pypy/module/_cffi_backend/cdataobj.py @@ -91,20 +91,15 @@ space = self.space cdata1 = self._cdata if isinstance(w_other, W_CData): - if requires_ordering: - if (isinstance(self.ctype, W_CTypePrimitive) or - isinstance(w_other.ctype, W_CTypePrimitive)): - raise OperationError(space.w_TypeError, - space.wrap("cannot do comparison on a " - "primitive cdata")) cdata2 = w_other._cdata - elif (misc.is_zero(space, w_other) and - not isinstance(self.ctype, W_CTypePrimitive)): - cdata2 = lltype.nullptr(rffi.CCHARP.TO) else: return space.w_NotImplemented if requires_ordering: + if (isinstance(self.ctype, W_CTypePrimitive) or + isinstance(w_other.ctype, W_CTypePrimitive)): + raise OperationError(space.w_TypeError, + space.wrap("cannot do comparison on a primitive cdata")) cdata1 = rffi.cast(lltype.Unsigned, cdata1) cdata2 = rffi.cast(lltype.Unsigned, cdata2) return space.newbool(op(cdata1, cdata2)) diff --git a/pypy/module/_cffi_backend/ctypeptr.py b/pypy/module/_cffi_backend/ctypeptr.py --- a/pypy/module/_cffi_backend/ctypeptr.py +++ b/pypy/module/_cffi_backend/ctypeptr.py @@ -152,10 +152,6 @@ def convert_from_object(self, cdata, w_ob): space = self.space if not isinstance(w_ob, cdataobj.W_CData): - if misc.is_zero(space, w_ob): - NULL = lltype.nullptr(rffi.CCHARP.TO) - rffi.cast(rffi.CCHARPP, cdata)[0] = NULL - return raise self._convert_error("cdata pointer", w_ob) other = w_ob.ctype if not isinstance(other, W_CTypePtrBase): @@ -257,15 +253,7 @@ def _prepare_pointer_call_argument(self, w_init, cdata): space = self.space - if misc.is_zero(space, w_init): - # Convert 0 to NULL. Note that passing 0 is not ambigous, - # despite the potential confusion: as a 'T*' argument, 0 means - # NULL, but as a 'T[]' argument it would mean "array of size 0" - # --- except that we specifically refuse to interpret numbers - # as the array size when passing arguments. - rffi.cast(rffi.CCHARPP, cdata)[0] = lltype.nullptr(rffi.CCHARP.TO) - return 3 - elif (space.isinstance_w(w_init, space.w_list) or + if (space.isinstance_w(w_init, space.w_list) or space.isinstance_w(w_init, space.w_tuple)): length = space.int_w(space.len(w_init)) elif space.isinstance_w(w_init, space.w_basestring): diff --git a/pypy/module/_cffi_backend/misc.py b/pypy/module/_cffi_backend/misc.py --- a/pypy/module/_cffi_backend/misc.py +++ b/pypy/module/_cffi_backend/misc.py @@ -202,11 +202,6 @@ neg_msg = "can't convert negative number to unsigned" ovf_msg = "long too big to convert" -def is_zero(space, w_ob): - return ((space.isinstance_w(w_ob, space.w_int) or - space.isinstance_w(w_ob, space.w_long)) - and not space.is_true(w_ob)) - # ____________________________________________________________ class _NotStandardObject(Exception): diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py --- a/pypy/module/_cffi_backend/test/_backend_test_c.py +++ b/pypy/module/_cffi_backend/test/_backend_test_c.py @@ -387,19 +387,8 @@ assert (x != None) is True assert (x == ["hello"]) is False assert (x != ["hello"]) is True - -def test_cmp_pointer_with_0(): - p = new_pointer_type(new_primitive_type("int")) - x = cast(p, 0) - assert (x == 0) is True - assert (x != 0) is False - assert (0 == x) is True - assert (0 != x) is False - y = cast(p, 42) - assert (y == 0) is False - assert (y != 0) is True - assert (0 == y) is False - assert (0 != y) is True + y = cast(p, 0) + assert (y == None) is False def test_invalid_indexing(): p = new_primitive_type("int") @@ -779,7 +768,7 @@ assert s.a2 == 456 assert s.a3 == 0 assert s.p4 == cast(BVoidP, 0) - assert s.p4 == 0 + assert s.p4 != 0 # s = newp(BStructPtr, {'a2': 41122, 'a3': -123}) assert s.a1 == 0 @@ -792,14 +781,11 @@ p = newp(BIntPtr, 14141) s = newp(BStructPtr, [12, 34, 56, p]) assert s.p4 == p - s.p4 = 0 - assert s.p4 == 0 + assert s.p4 # s = newp(BStructPtr, [12, 34, 56, cast(BVoidP, 0)]) - assert s.p4 == 0 - # - s = newp(BStructPtr, [12, 34, 56, 0]) assert s.p4 == cast(BVoidP, 0) + assert not s.p4 # py.test.raises(TypeError, newp, BStructPtr, [12, 34, 56, None]) @@ -1017,11 +1003,10 @@ f = cast(BFunc23, _testfunc(23)) res = f(b"foo") assert res == 1000 * ord(b'f') - res = f(0) # NULL - assert res == -42 - res = f(long(0)) # NULL + res = f(cast(BVoidP, 0)) # NULL assert res == -42 py.test.raises(TypeError, f, None) + py.test.raises(TypeError, f, 0) py.test.raises(TypeError, f, 0.0) def test_call_function_23_bis(): @@ -2277,6 +2262,7 @@ def test_longdouble(): py_py = 'PY_DOT_PY' in globals() + BInt = new_primitive_type("int") BLongDouble = new_primitive_type("long double") BLongDoublePtr = new_pointer_type(BLongDouble) BLongDoubleArray = new_array_type(BLongDoublePtr, None) @@ -2294,21 +2280,23 @@ assert float(x) == 1.23 assert int(x) == 1 # - BFunc19 = new_function_type((BLongDouble,), BLongDouble) + BFunc19 = new_function_type((BLongDouble, BInt), BLongDouble) f = cast(BFunc19, _testfunc(19)) - start = 8 + start = lstart = 1.5 for i in range(107): - start = f(start) - if sizeof(BLongDouble) > sizeof(new_primitive_type("double")): - if not py_py: - assert repr(start).startswith("") - # - c = newp(BLongDoubleArray, [start]) - x = c[0] - if not py_py: - assert repr(x).endswith("E+902>") - assert float(x) == float("inf") + start = 4 * start - start * start + lstart = f(lstart, 1) + lother = f(1.5, 107) + if not py_py: + assert float(lstart) == float(lother) + assert repr(lstart) == repr(lother) + if sizeof(BLongDouble) > sizeof(new_primitive_type("double")): + assert float(lstart) != start + assert repr(lstart).startswith("a1 + (int)ptr->a2; } -static long double _testfunc19(long double x) +static long double _testfunc19(long double x, int count) { int i; - for (i=0; i<28; i++) - x += x; + for (i=0; i>' % code_repr + expected = ('>' % repr(self.f.func_code)) + assert repr(all[0]) == expected assert len(all) == 2 pypyjit.set_compile_hook(None) self.on_compile() diff --git a/pypy/module/pypyjit/test_pypy_c/test_00_model.py b/pypy/module/pypyjit/test_pypy_c/test_00_model.py --- a/pypy/module/pypyjit/test_pypy_c/test_00_model.py +++ b/pypy/module/pypyjit/test_pypy_c/test_00_model.py @@ -75,6 +75,7 @@ rawtraces = logparser.extract_category(rawlog, 'jit-log-opt-') log = Log(rawtraces) log.result = eval(stdout) + log.logfile = str(logfile) # summaries = logparser.extract_category(rawlog, 'jit-summary') if len(summaries) > 0: diff --git a/pypy/module/pypyjit/test_pypy_c/test_call.py b/pypy/module/pypyjit/test_pypy_c/test_call.py --- a/pypy/module/pypyjit/test_pypy_c/test_call.py +++ b/pypy/module/pypyjit/test_pypy_c/test_call.py @@ -339,6 +339,7 @@ loop, = log.loops_by_filename(self.filepath) # the int strategy is used here assert loop.match_by_id('append', """ + guard_not_invalidated(descr=...) i13 = getfield_gc(p8, descr=) i15 = int_add(i13, 1) # Will be killed by the backend @@ -581,7 +582,7 @@ d = {'a': 2, 'b': 3, 'd':4} f(*a, **d) # ID: call i += 1 - return 13 + return 13 """, [1000]) loop, = log.loops_by_id('call') assert loop.match_by_id('call', ''' @@ -602,7 +603,7 @@ while i < stop: f(*a, **d) # ID: call i += 1 - return 13 + return 13 """, [1000]) def test_complex_case_loopconst(self): @@ -617,5 +618,5 @@ while i < stop: f(*a, **d) # ID: call i += 1 - return 13 + return 13 """, [1000]) diff --git a/pypy/module/pypyjit/test_pypy_c/test_jitlogparser.py b/pypy/module/pypyjit/test_pypy_c/test_jitlogparser.py new file mode 100644 --- /dev/null +++ b/pypy/module/pypyjit/test_pypy_c/test_jitlogparser.py @@ -0,0 +1,76 @@ +import re + +from rpython.tool.logparser import extract_category + +from pypy.tool.jitlogparser.parser import (import_log, parse_log_counts, + mangle_descr) +from pypy.module.pypyjit.test_pypy_c.test_00_model import BaseTestPyPyC + + +class TestLogParser(BaseTestPyPyC): + log_string = 'jit-log-opt,jit-backend' + + def test(self): + def fn_with_bridges(N): + def is_prime(x): + for y in xrange(2, x): + if x % y == 0: + return False + return True + result = 0 + for x in xrange(N): + if x % 3 == 0: + result += 5 + elif x % 5 == 0: + result += 3 + elif is_prime(x): + result += x + elif x == 99: + result *= 2 + return result + # + N = 10000 + _log = self.run(fn_with_bridges, [N]) + log, loops = import_log(_log.logfile) + parse_log_counts(extract_category(log, 'jit-backend-count'), loops) + + is_prime_loops = [] + fn_with_bridges_loops = [] + bridges = {} + + lib_re = re.compile("file '.*lib-python.*'") + for loop in loops: + if hasattr(loop, 'force_asm'): + loop.force_asm() + if lib_re.search(loop.comment) or \ + lib_re.search(loop.operations[0].repr()): + # do not care for _optimize_charset or _mk_bitmap + continue + assert loop.count > 0 + if ' is_prime, ' in loop.comment: + is_prime_loops.append(loop) + elif ' fn_with_bridges, ' in loop.comment: + fn_with_bridges_loops.append(loop) + else: + assert ' bridge ' in loop.comment + key = mangle_descr(loop.descr) + assert key not in bridges + bridges[key] = loop + + by_count = lambda l: -l.count + is_prime_loops.sort(key=by_count) + fn_with_bridges_loops.sort(key=by_count) + + # check that we can find bridges corresponding to " % 3" and " % 5" + mod_bridges = [] + for op in fn_with_bridges_loops[0].operations: + if op.descr is not None: + bridge = bridges.get(mangle_descr(op.descr)) + if bridge is not None: + mod_bridges.append(bridge) + assert len(mod_bridges) == 2 + + # check that counts are reasonable (precise # may change in the future) + assert N - 2000 < sum(l.count for l in fn_with_bridges_loops) < N + + diff --git a/pypy/module/zipimport/test/test_zipimport.py b/pypy/module/zipimport/test/test_zipimport.py --- a/pypy/module/zipimport/test/test_zipimport.py +++ b/pypy/module/zipimport/test/test_zipimport.py @@ -7,7 +7,7 @@ from StringIO import StringIO from rpython.tool.udir import udir -from zipfile import ZIP_STORED, ZIP_DEFLATED +from zipfile import ZIP_STORED class AppTestZipimport: @@ -53,7 +53,7 @@ space = cls.space - tmpdir = udir.ensure('zipimport_%s' % cls.__name__, dir=1) + tmpdir = udir.ensure('zipimport_%s_%s' % (__name__, cls.__name__), dir=1) now = time.time() cls.w_now = space.wrap(now) test_pyc = cls.make_pyc(space, co, now) @@ -360,20 +360,6 @@ assert co_filename == expected -class AppTestZipimportDeflated(AppTestZipimport): - compression = ZIP_DEFLATED - spaceconfig = { - "usemodules": ['zipimport', 'zlib', 'rctime', 'struct', 'itertools', 'binascii'], - } - - def setup_class(cls): - try: - import rpython.rlib.rzlib - except ImportError: - py.test.skip("zlib not available, cannot test compressed zipfiles") - cls.make_class() - - if os.sep != '/': class AppTestNativePathSep(AppTestZipimport): pathsep = os.sep diff --git a/pypy/module/zipimport/test/test_zipimport_deflated.py b/pypy/module/zipimport/test/test_zipimport_deflated.py new file mode 100644 --- /dev/null +++ b/pypy/module/zipimport/test/test_zipimport_deflated.py @@ -0,0 +1,18 @@ +import py + +from zipfile import ZIP_DEFLATED + +from pypy.module.zipimport.test.test_zipimport import AppTestZipimport as Base + +class AppTestZipimportDeflated(Base): + compression = ZIP_DEFLATED + spaceconfig = { + "usemodules": ['zipimport', 'zlib', 'rctime', 'struct', 'itertools', 'binascii'], + } + + def setup_class(cls): + try: + import rpython.rlib.rzlib + except ImportError: + py.test.skip("zlib not available, cannot test compressed zipfiles") + cls.make_class() diff --git a/pypy/objspace/std/dictmultiobject.py b/pypy/objspace/std/dictmultiobject.py --- a/pypy/objspace/std/dictmultiobject.py +++ b/pypy/objspace/std/dictmultiobject.py @@ -12,6 +12,8 @@ from rpython.rlib import rerased, jit +UNROLL_CUTOFF = 5 + def _is_str(space, w_key): return space.is_w(space.type(w_key), space.w_str) @@ -35,7 +37,7 @@ an actual dict """ return jit.isvirtual(w_dct) or (jit.isconstant(w_dct) and - w_dct.length() <= jit.UNROLL_CUTOFF) + w_dct.length() <= UNROLL_CUTOFF) class W_DictMultiObject(W_Object): diff --git a/pypy/objspace/std/floatobject.py b/pypy/objspace/std/floatobject.py --- a/pypy/objspace/std/floatobject.py +++ b/pypy/objspace/std/floatobject.py @@ -1,7 +1,7 @@ import operator -from pypy.interpreter import gateway from pypy.interpreter.error import OperationError from pypy.objspace.std import model, newformat +from pypy.objspace.std.floattype import float_typedef, W_AbstractFloatObject from pypy.objspace.std.multimethod import FailedToImplementArgs from pypy.objspace.std.model import registerimplementation, W_Object from pypy.objspace.std.register_all import register_all @@ -19,36 +19,14 @@ import math from pypy.objspace.std.intobject import W_IntObject -class W_AbstractFloatObject(W_Object): - __slots__ = () - - def is_w(self, space, w_other): - from rpython.rlib.longlong2float import float2longlong - if not isinstance(w_other, W_AbstractFloatObject): - return False - if self.user_overridden_class or w_other.user_overridden_class: - return self is w_other - one = float2longlong(space.float_w(self)) - two = float2longlong(space.float_w(w_other)) - return one == two - - def immutable_unique_id(self, space): - if self.user_overridden_class: - return None - from rpython.rlib.longlong2float import float2longlong - from pypy.objspace.std.model import IDTAG_FLOAT as tag - val = float2longlong(space.float_w(self)) - b = rbigint.fromrarith_int(val) - b = b.lshift(3).or_(rbigint.fromint(tag)) - return space.newlong_from_rbigint(b) - class W_FloatObject(W_AbstractFloatObject): """This is a implementation of the app-level 'float' type. The constructor takes an RPython float as an argument.""" - from pypy.objspace.std.floattype import float_typedef as typedef _immutable_fields_ = ['floatval'] + typedef = float_typedef + def __init__(w_self, floatval): w_self.floatval = floatval @@ -59,6 +37,9 @@ return self.floatval def int(self, space): + if (type(self) is not W_FloatObject and + space.is_overloaded(self, space.w_float, '__int__')): + return W_Object.int(self, space) try: value = ovfcheck_float_to_int(self.floatval) except OverflowError: diff --git a/pypy/objspace/std/floattype.py b/pypy/objspace/std/floattype.py --- a/pypy/objspace/std/floattype.py +++ b/pypy/objspace/std/floattype.py @@ -3,13 +3,15 @@ from rpython.rlib.unroll import unrolling_iterable from rpython.rlib import rfloat, rarithmetic from pypy.interpreter import typedef -from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault -from pypy.interpreter.baseobjspace import ObjSpace, W_Root +from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault,\ + interpindirect2app from pypy.interpreter.error import OperationError from pypy.objspace.std.register_all import register_all from pypy.objspace.std.stdtypedef import StdTypeDef, SMM from pypy.objspace.std.strutil import ParseStringError from pypy.objspace.std.strutil import string_to_float +from pypy.objspace.std.model import W_Object +from rpython.rlib.rbigint import rbigint float_as_integer_ratio = SMM("as_integer_ratio", 1) @@ -270,6 +272,32 @@ # ____________________________________________________________ +class W_AbstractFloatObject(W_Object): + __slots__ = () + + def is_w(self, space, w_other): + from rpython.rlib.longlong2float import float2longlong + if not isinstance(w_other, W_AbstractFloatObject): + return False + if self.user_overridden_class or w_other.user_overridden_class: + return self is w_other + one = float2longlong(space.float_w(self)) + two = float2longlong(space.float_w(w_other)) + return one == two + + def immutable_unique_id(self, space): + if self.user_overridden_class: + return None + from rpython.rlib.longlong2float import float2longlong + from pypy.objspace.std.model import IDTAG_FLOAT as tag + val = float2longlong(space.float_w(self)) + b = rbigint.fromrarith_int(val) + b = b.lshift(3).or_(rbigint.fromint(tag)) + return space.newlong_from_rbigint(b) + + def int(self, space): + raise NotImplementedError + float_typedef = StdTypeDef("float", __doc__ = '''float(x) -> floating point number @@ -280,5 +308,6 @@ conjugate = interp2app(descr_conjugate), real = typedef.GetSetProperty(descr_get_real), imag = typedef.GetSetProperty(descr_get_imag), + __int__ = interpindirect2app(W_AbstractFloatObject.int), ) float_typedef.registermethods(globals()) diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py --- a/pypy/objspace/std/listobject.py +++ b/pypy/objspace/std/listobject.py @@ -18,6 +18,7 @@ from pypy.objspace.std.stdtypedef import StdTypeDef, SMM from sys import maxint +UNROLL_CUTOFF = 5 class W_AbstractListObject(W_Object): __slots__ = () @@ -42,7 +43,7 @@ return W_ListObject.from_storage_and_strategy(space, storage, strategy) @jit.look_inside_iff(lambda space, list_w, sizehint: - jit.loop_unrolling_heuristic(list_w, len(list_w))) + jit.loop_unrolling_heuristic(list_w, len(list_w), UNROLL_CUTOFF)) def get_strategy_from_list_objects(space, list_w, sizehint): if not list_w: if sizehint != -1: @@ -956,7 +957,7 @@ raise NotImplementedError("abstract base class") @jit.look_inside_iff(lambda space, w_list, list_w: - jit.loop_unrolling_heuristic(list_w, len(list_w))) + jit.loop_unrolling_heuristic(list_w, len(list_w), UNROLL_CUTOFF)) def init_from_list_w(self, w_list, list_w): l = [self.unwrap(w_item) for w_item in list_w] w_list.lstorage = self.erase(l) @@ -1005,7 +1006,7 @@ return self.wrap(r) @jit.look_inside_iff(lambda self, w_list: - jit.loop_unrolling_heuristic(w_list, w_list.length())) + jit.loop_unrolling_heuristic(w_list, w_list.length(), UNROLL_CUTOFF)) def getitems_copy(self, w_list): return [self.wrap(item) for item in self.unerase(w_list.lstorage)] @@ -1014,7 +1015,7 @@ return [self.wrap(item) for item in self.unerase(w_list.lstorage)] @jit.look_inside_iff(lambda self, w_list: - jit.loop_unrolling_heuristic(w_list, w_list.length())) + jit.loop_unrolling_heuristic(w_list, w_list.length(), UNROLL_CUTOFF)) def getitems_fixedsize(self, w_list): return self.getitems_unroll(w_list) @@ -1476,8 +1477,8 @@ return w_list def list_unroll_condition(space, w_list1, w_list2): - return jit.loop_unrolling_heuristic(w_list1, w_list1.length()) or \ - jit.loop_unrolling_heuristic(w_list2, w_list2.length()) + return jit.loop_unrolling_heuristic(w_list1, w_list1.length(), UNROLL_CUTOFF) or \ + jit.loop_unrolling_heuristic(w_list2, w_list2.length(), UNROLL_CUTOFF) @jit.look_inside_iff(list_unroll_condition) def eq__List_List(space, w_list1, w_list2): diff --git a/pypy/objspace/std/longobject.py b/pypy/objspace/std/longobject.py --- a/pypy/objspace/std/longobject.py +++ b/pypy/objspace/std/longobject.py @@ -6,35 +6,16 @@ from pypy.objspace.std.multimethod import FailedToImplementArgs from pypy.objspace.std.intobject import W_IntObject from pypy.objspace.std.noneobject import W_NoneObject -from rpython.rlib.rbigint import rbigint, SHIFT - -class W_AbstractLongObject(W_Object): - __slots__ = () - - def is_w(self, space, w_other): - if not isinstance(w_other, W_AbstractLongObject): - return False - if self.user_overridden_class or w_other.user_overridden_class: - return self is w_other - return space.bigint_w(self).eq(space.bigint_w(w_other)) - - def immutable_unique_id(self, space): - if self.user_overridden_class: - return None - from pypy.objspace.std.model import IDTAG_LONG as tag - b = space.bigint_w(self) - b = b.lshift(3).or_(rbigint.fromint(tag)) - return space.newlong_from_rbigint(b) - - def unwrap(w_self, space): #YYYYYY - return w_self.longval() +from rpython.rlib.rbigint import rbigint +from pypy.objspace.std.longtype import long_typedef, W_AbstractLongObject class W_LongObject(W_AbstractLongObject): """This is a wrapper of rbigint.""" - from pypy.objspace.std.longtype import long_typedef as typedef _immutable_fields_ = ['num'] + typedef = long_typedef + def __init__(w_self, l): w_self.num = l # instance of rbigint @@ -88,6 +69,9 @@ return self.num.tofloat() def int(self, space): + if (type(self) is not W_LongObject and + space.is_overloaded(self, space.w_long, '__int__')): + return W_Object.int(self, space) try: return space.newint(self.num.toint()) except OverflowError: diff --git a/pypy/objspace/std/longtype.py b/pypy/objspace/std/longtype.py --- a/pypy/objspace/std/longtype.py +++ b/pypy/objspace/std/longtype.py @@ -1,9 +1,11 @@ from pypy.interpreter.error import OperationError from pypy.interpreter import typedef -from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault -from pypy.objspace.std.register_all import register_all -from pypy.objspace.std.stdtypedef import StdTypeDef, SMM +from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault,\ + interpindirect2app +from pypy.objspace.std.model import W_Object +from pypy.objspace.std.stdtypedef import StdTypeDef from pypy.objspace.std.strutil import string_to_bigint, ParseStringError +from rpython.rlib.rbigint import rbigint def descr_conjugate(space, w_int): return space.long(w_int) @@ -12,7 +14,6 @@ @unwrap_spec(w_x = WrappedDefault(0)) def descr__new__(space, w_longtype, w_x, w_base=None): from pypy.objspace.std.longobject import W_LongObject - from rpython.rlib.rbigint import rbigint if space.config.objspace.std.withsmalllong: from pypy.objspace.std.smalllongobject import W_SmallLongObject else: @@ -56,7 +57,7 @@ else: try: s = space.str_w(w_value) - except OperationError, e: + except OperationError: raise OperationError(space.w_TypeError, space.wrap("long() can't convert non-string " "with explicit base")) @@ -114,6 +115,30 @@ # ____________________________________________________________ +class W_AbstractLongObject(W_Object): + __slots__ = () + + def is_w(self, space, w_other): + if not isinstance(w_other, W_AbstractLongObject): + return False + if self.user_overridden_class or w_other.user_overridden_class: + return self is w_other + return space.bigint_w(self).eq(space.bigint_w(w_other)) + + def immutable_unique_id(self, space): + if self.user_overridden_class: + return None + from pypy.objspace.std.model import IDTAG_LONG as tag + b = space.bigint_w(self) + b = b.lshift(3).or_(rbigint.fromint(tag)) + return space.newlong_from_rbigint(b) + + def unwrap(w_self, space): #YYYYYY + return w_self.longval() + + def int(self, space): + raise NotImplementedError + long_typedef = StdTypeDef("long", __doc__ = '''long(x[, base]) -> integer @@ -129,5 +154,6 @@ real = typedef.GetSetProperty(descr_get_real), imag = typedef.GetSetProperty(descr_get_imag), bit_length = interp2app(bit_length), + __int__ = interpindirect2app(W_AbstractLongObject.int), ) long_typedef.registermethods(globals()) diff --git a/pypy/objspace/std/setobject.py b/pypy/objspace/std/setobject.py --- a/pypy/objspace/std/setobject.py +++ b/pypy/objspace/std/setobject.py @@ -15,6 +15,8 @@ from rpython.rlib.rarithmetic import intmask, r_uint from rpython.rlib import rerased, jit +UNROLL_CUTOFF = 5 + class W_BaseSetObject(W_Object): typedef = None @@ -391,7 +393,7 @@ raise NotImplementedError @jit.look_inside_iff(lambda self, list_w: - jit.loop_unrolling_heuristic(list_w, len(list_w))) + jit.loop_unrolling_heuristic(list_w, len(list_w), UNROLL_CUTOFF)) def get_storage_from_list(self, list_w): setdata = self.get_empty_dict() for w_item in list_w: @@ -399,7 +401,7 @@ return self.erase(setdata) @jit.look_inside_iff(lambda self, items: - jit.loop_unrolling_heuristic(items, len(items))) + jit.loop_unrolling_heuristic(items, len(items), UNROLL_CUTOFF)) def get_storage_from_unwrapped_list(self, items): setdata = self.get_empty_dict() for item in items: @@ -1033,7 +1035,7 @@ _pick_correct_strategy(space, w_set, iterable_w) @jit.look_inside_iff(lambda space, w_set, iterable_w: - jit.loop_unrolling_heuristic(iterable_w, len(iterable_w))) + jit.loop_unrolling_heuristic(iterable_w, len(iterable_w), UNROLL_CUTOFF)) def _pick_correct_strategy(space, w_set, iterable_w): # check for integers for w_item in iterable_w: diff --git a/pypy/objspace/std/test/test_longobject.py b/pypy/objspace/std/test/test_longobject.py --- a/pypy/objspace/std/test/test_longobject.py +++ b/pypy/objspace/std/test/test_longobject.py @@ -231,13 +231,13 @@ def test_math_log(self): import math - raises(ValueError, math.log, 0L) - raises(ValueError, math.log, -1L) - raises(ValueError, math.log, -2L) + raises(ValueError, math.log, 0L) + raises(ValueError, math.log, -1L) + raises(ValueError, math.log, -2L) raises(ValueError, math.log, -(1L << 10000)) - #raises(ValueError, math.log, 0) - raises(ValueError, math.log, -1) - raises(ValueError, math.log, -2) + #raises(ValueError, math.log, 0) + raises(ValueError, math.log, -1) + raises(ValueError, math.log, -2) def test_long(self): import sys @@ -327,3 +327,11 @@ class A(long): pass b = A(5).real assert type(b) is long + + def test__int__(self): + class A(long): + def __int__(self): + return 42 + + assert int(long(3)) == long(3) + assert int(A(13)) == 42 diff --git a/pypy/objspace/std/tupleobject.py b/pypy/objspace/std/tupleobject.py --- a/pypy/objspace/std/tupleobject.py +++ b/pypy/objspace/std/tupleobject.py @@ -10,6 +10,7 @@ from rpython.rlib import jit from rpython.tool.sourcetools import func_with_new_name +UNROLL_CUTOFF = 10 class W_AbstractTupleObject(W_Object): __slots__ = () @@ -84,7 +85,7 @@ return space.newtuple(w_tuple.wrappeditems[start:stop]) @jit.look_inside_iff(lambda space, w_tuple, w_obj: - jit.loop_unrolling_heuristic(w_tuple, len(w_tuple.wrappeditems))) + jit.loop_unrolling_heuristic(w_tuple, len(w_tuple.wrappeditems), UNROLL_CUTOFF)) def contains__Tuple_ANY(space, w_tuple, w_obj): for w_item in w_tuple.wrappeditems: if space.eq_w(w_item, w_obj): @@ -119,8 +120,8 @@ return mul_tuple_times(space, w_tuple, w_times) def tuple_unroll_condition(space, w_tuple1, w_tuple2): - return jit.loop_unrolling_heuristic(w_tuple1, len(w_tuple1.wrappeditems)) or \ - jit.loop_unrolling_heuristic(w_tuple2, len(w_tuple2.wrappeditems)) + return jit.loop_unrolling_heuristic(w_tuple1, len(w_tuple1.wrappeditems), UNROLL_CUTOFF) or \ + jit.loop_unrolling_heuristic(w_tuple2, len(w_tuple2.wrappeditems), UNROLL_CUTOFF) @jit.look_inside_iff(tuple_unroll_condition) def eq__Tuple_Tuple(space, w_tuple1, w_tuple2): @@ -173,7 +174,7 @@ return space.wrap(hash_tuple(space, w_tuple.wrappeditems)) @jit.look_inside_iff(lambda space, wrappeditems: - jit.loop_unrolling_heuristic(wrappeditems, len(wrappeditems))) + jit.loop_unrolling_heuristic(wrappeditems, len(wrappeditems), UNROLL_CUTOFF)) def hash_tuple(space, wrappeditems): # this is the CPython 2.4 algorithm (changed from 2.3) mult = 1000003 diff --git a/pypy/tool/jitlogparser/parser.py b/pypy/tool/jitlogparser/parser.py --- a/pypy/tool/jitlogparser/parser.py +++ b/pypy/tool/jitlogparser/parser.py @@ -447,6 +447,17 @@ num, count = line.split(':', 2) mapping[num].count = int(count) + +def mangle_descr(descr): + if descr.startswith('TargetToken('): + return descr[len('TargetToken('):-1] + if descr.startswith('> 16 - self.MOVW_ri(r, bottom, cond) - if top: - self.MOVT_ri(r, top, cond) + bottom = value & 0xFFFF + top = value >> 16 + self.MOVW_ri(r, bottom, cond) + if top: + self.MOVT_ri(r, top, cond) - max_size_of_gen_load_int = 2 * WORD + +class AbstractARMv6Builder(AbstractARMv7Builder): + + def __init__(self): + AbstractARMv7Builder.__init__(self) + + def gen_load_int(self, r, value, cond=cond.AL): + from rpython.jit.backend.arm.conditions import AL + if cond != AL or 0 <= value <= 0xFFFF: + self._load_by_shifting(r, value, cond) + else: + self.LDR_ri(r, reg.pc.value) + self.MOV_rr(reg.pc.value, reg.pc.value) + self.write32(value) + + max_size_of_gen_load_int = 4 ofs_shift = zip(range(8, 25, 8), range(12, 0, -4)) def _load_by_shifting(self, r, value, c=cond.AL): # to be sure it is only called for the correct cases @@ -276,10 +288,15 @@ t = b | (shift << 8) self.ORR_ri(r, r, imm=t, cond=c) +if autodetect().startswith('armv7'): + AbstractBuilder = AbstractARMv7Builder +else: + AbstractBuilder = AbstractARMv6Builder -class OverwritingBuilder(AbstractARMv7Builder): + +class OverwritingBuilder(AbstractBuilder): def __init__(self, cb, start, size): - AbstractARMv7Builder.__init__(self) + AbstractBuilder.__init__(self) self.cb = cb self.index = start self.end = start + size @@ -293,9 +310,9 @@ self.index += 1 -class ARMv7Builder(BlockBuilderMixin, AbstractARMv7Builder): +class InstrBuilder(BlockBuilderMixin, AbstractBuilder): def __init__(self): - AbstractARMv7Builder.__init__(self) + AbstractBuilder.__init__(self) self.init_block_builder() # # ResOperation --> offset in the assembly. @@ -349,4 +366,4 @@ return self.get_relative_pos() -define_instructions(AbstractARMv7Builder) +define_instructions(AbstractBuilder) diff --git a/rpython/jit/backend/arm/helper/assembler.py b/rpython/jit/backend/arm/helper/assembler.py --- a/rpython/jit/backend/arm/helper/assembler.py +++ b/rpython/jit/backend/arm/helper/assembler.py @@ -1,7 +1,7 @@ from __future__ import with_statement from rpython.jit.backend.arm import conditions as c from rpython.jit.backend.arm import registers as r -from rpython.jit.backend.arm.codebuilder import AbstractARMv7Builder +from rpython.jit.backend.arm.codebuilder import InstrBuilder from rpython.jit.metainterp.history import ConstInt, BoxInt, FLOAT from rpython.rlib.rarithmetic import r_uint, r_longlong, intmask from rpython.jit.metainterp.resoperation import rop @@ -34,8 +34,8 @@ return f def gen_emit_op_ri(name, opname): - ri_op = getattr(AbstractARMv7Builder, '%s_ri' % opname) - rr_op = getattr(AbstractARMv7Builder, '%s_rr' % opname) + ri_op = getattr(InstrBuilder, '%s_ri' % opname) + rr_op = getattr(InstrBuilder, '%s_rr' % opname) def f(self, op, arglocs, regalloc, fcond): assert fcond is not None l0, l1, res = arglocs @@ -48,7 +48,7 @@ return f def gen_emit_op_by_helper_call(name, opname): - helper = getattr(AbstractARMv7Builder, opname) + helper = getattr(InstrBuilder, opname) def f(self, op, arglocs, regalloc, fcond): assert fcond is not None if op.result: @@ -97,7 +97,7 @@ return f def gen_emit_float_op(name, opname): - op_rr = getattr(AbstractARMv7Builder, opname) + op_rr = getattr(InstrBuilder, opname) def f(self, op, arglocs, regalloc, fcond): arg1, arg2, result = arglocs op_rr(self.mc, result.value, arg1.value, arg2.value) @@ -105,7 +105,7 @@ f.__name__ = 'emit_op_%s' % name return f def gen_emit_unary_float_op(name, opname): - op_rr = getattr(AbstractARMv7Builder, opname) + op_rr = getattr(InstrBuilder, opname) def f(self, op, arglocs, regalloc, fcond): arg1, result = arglocs op_rr(self.mc, result.value, arg1.value) diff --git a/rpython/jit/backend/arm/helper/regalloc.py b/rpython/jit/backend/arm/helper/regalloc.py --- a/rpython/jit/backend/arm/helper/regalloc.py +++ b/rpython/jit/backend/arm/helper/regalloc.py @@ -1,6 +1,5 @@ from rpython.jit.backend.arm import conditions as c from rpython.jit.backend.arm import registers as r -from rpython.jit.backend.arm.codebuilder import AbstractARMv7Builder from rpython.jit.metainterp.history import ConstInt, BoxInt, Box, FLOAT from rpython.jit.metainterp.history import ConstInt from rpython.rlib.objectmodel import we_are_translated diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -17,7 +17,7 @@ saved_registers, count_reg_args) from rpython.jit.backend.arm.helper.regalloc import check_imm_arg -from rpython.jit.backend.arm.codebuilder import ARMv7Builder, OverwritingBuilder +from rpython.jit.backend.arm.codebuilder import InstrBuilder, OverwritingBuilder from rpython.jit.backend.arm.jump import remap_frame_layout from rpython.jit.backend.arm.regalloc import TempInt, TempPtr from rpython.jit.backend.arm.locations import imm @@ -299,19 +299,10 @@ is_guard_not_invalidated=True) def emit_op_jump(self, op, arglocs, regalloc, fcond): - # The backend's logic assumes that the target code is in a piece of - # assembler that was also called with the same number of arguments, - # so that the locations [ebp+8..] of the input arguments are valid - # stack locations both before and after the jump. - # target_token = op.getdescr() + assert isinstance(target_token, TargetToken) target = target_token._ll_loop_code - assert isinstance(target_token, TargetToken) assert fcond == c.AL - my_nbargs = self.current_clt._debug_nbargs - target_nbargs = target_token._arm_clt._debug_nbargs - assert my_nbargs == target_nbargs - if target_token in self.target_tokens_currently_compiling: self.mc.B_offs(target, fcond) else: @@ -576,10 +567,12 @@ def emit_op_cond_call_gc_wb(self, op, arglocs, regalloc, fcond): self._write_barrier_fastpath(self.mc, op.getdescr(), arglocs, fcond) + return fcond def emit_op_cond_call_gc_wb_array(self, op, arglocs, regalloc, fcond): self._write_barrier_fastpath(self.mc, op.getdescr(), arglocs, fcond, array=True) + return fcond def _write_barrier_fastpath(self, mc, descr, arglocs, fcond=c.AL, array=False, is_frame=False): @@ -1219,7 +1212,7 @@ baseofs = self.cpu.get_baseofs_of_frame_field() newlooptoken.compiled_loop_token.update_frame_info( oldlooptoken.compiled_loop_token, baseofs) - mc = ARMv7Builder() + mc = InstrBuilder() mc.B(target) mc.copy_to_raw_memory(oldadr) diff --git a/rpython/jit/backend/arm/regalloc.py b/rpython/jit/backend/arm/regalloc.py --- a/rpython/jit/backend/arm/regalloc.py +++ b/rpython/jit/backend/arm/regalloc.py @@ -752,6 +752,7 @@ # self.frame_manager.hint_frame_locations[box] = loc def prepare_op_jump(self, op, fcond): + assert self.jump_target_descr is None descr = op.getdescr() assert isinstance(descr, TargetToken) self.jump_target_descr = descr diff --git a/rpython/jit/backend/arm/runner.py b/rpython/jit/backend/arm/runner.py --- a/rpython/jit/backend/arm/runner.py +++ b/rpython/jit/backend/arm/runner.py @@ -86,10 +86,10 @@ possible then to re-call invalidate_loop() on the same looptoken, which must invalidate all newer GUARD_NOT_INVALIDATED, but not the old one that already has a bridge attached to it.""" - from rpython.jit.backend.arm.codebuilder import ARMv7Builder + from rpython.jit.backend.arm.codebuilder import InstrBuilder for jmp, tgt in looptoken.compiled_loop_token.invalidate_positions: - mc = ARMv7Builder() + mc = InstrBuilder() mc.B_offs(tgt) mc.copy_to_raw_memory(jmp) # positions invalidated @@ -106,27 +106,26 @@ return l def build_regalloc(self): - ''' for tests''' - from rpython.jit.backend.arm.regalloc import Regalloc - assert self.assembler is not None - return Regalloc(self.assembler) + ''' for tests''' + from rpython.jit.backend.arm.regalloc import Regalloc + assert self.assembler is not None + return Regalloc(self.assembler) class CPU_ARM(AbstractARMCPU): """ARM v7 uses softfp ABI, requires vfp""" - backend_name = "arm" + backend_name = "armv7" ArmCPU = CPU_ARM class CPU_ARMHF(AbstractARMCPU): """ARM v7 uses hardfp ABI, requires vfp""" use_hf_abi = True - backend_name = "armhf" + backend_name = "armv7hf" supports_floats = False supports_singlefloats = False class CPU_ARMv6(AbstractARMCPU): """ ARM v6, uses hardfp ABI, requires vfp""" use_hf_abi = True - backend_name = "armv6" + backend_name = "armv6hf" supports_floats = False supports_singlefloats = False - diff --git a/rpython/jit/backend/arm/test/conftest.py b/rpython/jit/backend/arm/test/conftest.py --- a/rpython/jit/backend/arm/test/conftest.py +++ b/rpython/jit/backend/arm/test/conftest.py @@ -17,5 +17,5 @@ help="run tests that translate code") def pytest_runtest_setup(item): - if cpu not in ('arm', 'armhf'): + if not cpu.startswith('arm'): py.test.skip("ARM(v7) tests skipped: cpu is %r" % (cpu,)) diff --git a/rpython/jit/backend/arm/test/support.py b/rpython/jit/backend/arm/test/support.py --- a/rpython/jit/backend/arm/test/support.py +++ b/rpython/jit/backend/arm/test/support.py @@ -39,6 +39,11 @@ i = commands.getoutput("%s -version &1" % AS) check_skip(i) +def get_as_version(): + import commands + i = commands.getoutput("%s -v &1" % AS) + return tuple([int(j) for j in i.split()[-1].split('.')]) + def check_skip(inp, search='arm', msg='only for arm'): skip = True try: diff --git a/rpython/jit/backend/arm/test/test_assembler.py b/rpython/jit/backend/arm/test/test_assembler.py --- a/rpython/jit/backend/arm/test/test_assembler.py +++ b/rpython/jit/backend/arm/test/test_assembler.py @@ -240,9 +240,11 @@ x = 0x60002224 self.a.gen_func_prolog() self.a.mc.gen_load_int(r.r1.value, x) + self.a.mc.SUB_ri(r.sp.value, r.sp.value, 8) self.a.mc.MOV_ri(r.r3.value, 8) - self.a.mc.STR_rr(r.r1.value, r.fp.value, r.r3.value) - self.a.mc.LDR_ri(r.r0.value, r.fp.value, 8) + self.a.mc.STR_rr(r.r1.value, r.sp.value, r.r3.value) + self.a.mc.LDR_ri(r.r0.value, r.sp.value, 8) + self.a.mc.ADD_ri(r.sp.value, r.sp.value, 8) self.a.gen_func_epilog() assert run_asm(self.a) == x diff --git a/rpython/jit/backend/arm/test/test_calling_convention.py b/rpython/jit/backend/arm/test/test_calling_convention.py --- a/rpython/jit/backend/arm/test/test_calling_convention.py +++ b/rpython/jit/backend/arm/test/test_calling_convention.py @@ -1,10 +1,12 @@ +import py + from rpython.rtyper.annlowlevel import llhelper from rpython.jit.metainterp.history import JitCellToken from rpython.jit.backend.test.calling_convention_test import CallingConvTests, parse from rpython.rtyper.lltypesystem import lltype from rpython.jit.codewriter.effectinfo import EffectInfo -from rpython.jit.backend.arm.codebuilder import ARMv7Builder +from rpython.jit.backend.arm.codebuilder import InstrBuilder from rpython.jit.backend.arm import registers as r from rpython.jit.backend.arm.test.support import skip_unless_run_slow_tests from rpython.jit.backend.arm.test.test_runner import boxfloat, constfloat @@ -25,9 +27,9 @@ # ../../test/calling_convention_test.py def make_function_returning_stack_pointer(self): - mc = ARMv7Builder() - mc.MOV_rr(r.r0.value, r.sp.value) - mc.MOV_rr(r.pc.value, r.lr.value) + mc = InstrBuilder() + mc.MOV_rr(r.r0.value, r.sp.value) + mc.MOV_rr(r.pc.value, r.lr.value) return mc.materialize(self.cpu.asmmemmgr, []) def get_alignment_requirements(self): diff --git a/rpython/jit/backend/arm/test/test_instr_codebuilder.py b/rpython/jit/backend/arm/test/test_instr_codebuilder.py --- a/rpython/jit/backend/arm/test/test_instr_codebuilder.py +++ b/rpython/jit/backend/arm/test/test_instr_codebuilder.py @@ -2,13 +2,16 @@ from rpython.jit.backend.arm import codebuilder from rpython.jit.backend.arm import conditions from rpython.jit.backend.arm import instructions -from rpython.jit.backend.arm.test.support import (requires_arm_as, define_test, gen_test_function) +from rpython.jit.backend.arm.test.support import requires_arm_as +from rpython.jit.backend.arm.test.support import get_as_version +from rpython.jit.backend.arm.test.support import define_test +from rpython.jit.backend.arm.test.support import gen_test_function from gen import assemble import py requires_arm_as() -class CodeBuilder(codebuilder.ARMv7Builder): +class CodeBuilder(codebuilder.InstrBuilder): def __init__(self): self.buffer = [] @@ -80,6 +83,9 @@ self.assert_equal('ORR r0, r7, r12, lsl #8') def test_push_one_reg(self): + if get_as_version() < (2, 23): + py.test.xfail("GNU as before version 2.23 generates encoding A1 for " + "pushing only one register") self.cb.PUSH([r.r1.value]) self.assert_equal('PUSH {r1}') diff --git a/rpython/jit/backend/arm/test/test_runner.py b/rpython/jit/backend/arm/test/test_runner.py --- a/rpython/jit/backend/arm/test/test_runner.py +++ b/rpython/jit/backend/arm/test/test_runner.py @@ -27,6 +27,19 @@ bridge_loop_instructions = ['ldr', 'mov', 'nop', 'cmp', 'bge', 'push', 'mov', 'mov', 'push', 'mov', 'mov', 'blx', 'mov', 'mov', 'bx'] + if CPU.backend_name.startswith('armv7'): + bridge_loop_instructions = ['ldr', 'mov', 'nop', 'cmp', 'bge', + 'push', 'mov', 'mov', 'push', 'mov', 'mov', + 'blx', 'mov', 'mov', 'bx'] + else: + bridge_loop_instructions = ['ldr', 'mov', 'nop', 'nop', 'nop', 'cmp', 'bge', + 'push', 'ldr', 'mov', + '', # inline constant + 'push', 'ldr', 'mov', + 'ldrsblt', #inline constant (decodes as instruction) + 'blx', 'ldr', 'mov', + '', # inline constant + 'bx'] def get_cpu(self): cpu = CPU(rtyper=None, stats=FakeStats()) diff --git a/rpython/jit/backend/llsupport/regalloc.py b/rpython/jit/backend/llsupport/regalloc.py --- a/rpython/jit/backend/llsupport/regalloc.py +++ b/rpython/jit/backend/llsupport/regalloc.py @@ -278,11 +278,11 @@ no_lower_byte_regs = [] save_around_call_regs = [] frame_reg = None - temp_boxes = [] def __init__(self, longevity, frame_manager=None, assembler=None): self.free_regs = self.all_regs[:] self.longevity = longevity + self.temp_boxes = [] if not we_are_translated(): self.reg_bindings = OrderedDict() else: diff --git a/rpython/jit/backend/llsupport/test/test_regalloc_integration.py b/rpython/jit/backend/llsupport/test/test_regalloc_integration.py --- a/rpython/jit/backend/llsupport/test/test_regalloc_integration.py +++ b/rpython/jit/backend/llsupport/test/test_regalloc_integration.py @@ -515,6 +515,10 @@ # FIXME: Verify that i19 - i23 are removed class TestRegallocFloats(BaseTestRegalloc): + def setup_class(cls): + if not cls.cpu.supports_floats: + py.test.skip("needs float support") + def test_float_add(self): ops = ''' [f0, f1] diff --git a/rpython/jit/backend/test/test_zll_stress_0.py b/rpython/jit/backend/test/test_zll_stress_0.py new file mode 100644 --- /dev/null +++ b/rpython/jit/backend/test/test_zll_stress_0.py @@ -0,0 +1,4 @@ +from rpython.jit.backend.test import zll_stress + +def test_stress_0(): + zll_stress.do_test_stress(0) diff --git a/rpython/jit/backend/test/test_zll_stress_1.py b/rpython/jit/backend/test/test_zll_stress_1.py new file mode 100644 --- /dev/null +++ b/rpython/jit/backend/test/test_zll_stress_1.py @@ -0,0 +1,4 @@ +from rpython.jit.backend.test import zll_stress + +def test_stress_1(): + zll_stress.do_test_stress(1) diff --git a/rpython/jit/backend/test/test_zll_stress_2.py b/rpython/jit/backend/test/test_zll_stress_2.py new file mode 100644 --- /dev/null +++ b/rpython/jit/backend/test/test_zll_stress_2.py @@ -0,0 +1,4 @@ +from rpython.jit.backend.test import zll_stress + +def test_stress_2(): + zll_stress.do_test_stress(2) diff --git a/rpython/jit/backend/test/test_zll_stress_3.py b/rpython/jit/backend/test/test_zll_stress_3.py new file mode 100644 --- /dev/null +++ b/rpython/jit/backend/test/test_zll_stress_3.py @@ -0,0 +1,4 @@ +from rpython.jit.backend.test import zll_stress + +def test_stress_3(): + zll_stress.do_test_stress(3) diff --git a/rpython/jit/backend/test/test_zll_stress.py b/rpython/jit/backend/test/zll_stress.py rename from rpython/jit/backend/test/test_zll_stress.py rename to rpython/jit/backend/test/zll_stress.py --- a/rpython/jit/backend/test/test_zll_stress.py +++ b/rpython/jit/backend/test/zll_stress.py @@ -5,14 +5,18 @@ CPU = getcpuclass() -iterations = 1000 +total_iterations = 1000 if platform.machine().startswith('arm'): - iterations = 100 + total_iterations = 100 +pieces = 4 +per_piece = total_iterations / pieces -def test_stress(): + +def do_test_stress(piece): cpu = CPU(None, None) cpu.setup_once() r = Random() - for i in range(iterations): - check_random_function(cpu, LLtypeOperationBuilder, r, i, iterations) + r.jumpahead(piece*per_piece) + for i in range(piece*per_piece, (piece+1)*per_piece): + check_random_function(cpu, LLtypeOperationBuilder, r, i, total_iterations) diff --git a/rpython/jit/backend/tool/viewcode.py b/rpython/jit/backend/tool/viewcode.py --- a/rpython/jit/backend/tool/viewcode.py +++ b/rpython/jit/backend/tool/viewcode.py @@ -53,8 +53,8 @@ 'x86_32': 'i386', 'x86_64': 'x86-64', 'i386': 'i386', - 'arm': 'arm', - 'arm_32': 'arm', + 'armv6_32': 'arm', + 'armv7_32': 'arm', } cmd = find_objdump() objdump = ('%(command)s -M %(backend)s -b binary -m %(machine)s ' diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py --- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py @@ -7,7 +7,7 @@ from rpython.jit.metainterp.history import AbstractDescr, ConstInt, BoxInt from rpython.jit.metainterp.history import TreeLoop from rpython.jit.metainterp import compile, resume -from rpython.jit.metainterp.resoperation import rop, opname, opargnum +from rpython.jit.metainterp.resoperation import rop, opname, oparity from rpython.jit.metainterp.optimizeopt.test.test_optimizebasic import FakeMetaInterpStaticData def test_build_opt_chain(): @@ -188,7 +188,7 @@ if 'FLOAT' in op: continue args = [] From noreply at buildbot.pypy.org Fri Apr 5 03:11:14 2013 From: noreply at buildbot.pypy.org (wlav) Date: Fri, 5 Apr 2013 03:11:14 +0200 (CEST) Subject: [pypy-commit] pypy reflex-support: setting a way-point towards a loadable capi Message-ID: <20130405011114.99AD71C06BD@cobra.cs.uni-duesseldorf.de> Author: Wim Lavrijsen Branch: reflex-support Changeset: r63041:bd29d442538f Date: 2013-04-02 14:51 -0700 http://bitbucket.org/pypy/pypy/changeset/bd29d442538f/ Log: setting a way-point towards a loadable capi diff --git a/pypy/module/cppyy/capi/__init__.py b/pypy/module/cppyy/capi/__init__.py --- a/pypy/module/cppyy/capi/__init__.py +++ b/pypy/module/cppyy/capi/__init__.py @@ -9,29 +9,11 @@ # the selection of the desired backend (default is Reflex). # choose C-API access method: -from loadable_capi import * -#from builtin_capi import * +#from pypy.module.cppyy.capi.loadable_capi import * +from pypy.module.cppyy.capi.builtin_capi import * -# shared definitions -_C_OPAQUE_PTR = rffi.LONG -_C_OPAQUE_NULL = lltype.nullptr(rffi.LONGP.TO)# ALT: _C_OPAQUE_PTR.TO - -C_SCOPE = _C_OPAQUE_PTR -C_NULL_SCOPE = rffi.cast(C_SCOPE, _C_OPAQUE_NULL) - -C_TYPE = C_SCOPE -C_NULL_TYPE = C_NULL_SCOPE - -C_OBJECT = _C_OPAQUE_PTR -C_NULL_OBJECT = rffi.cast(C_OBJECT, _C_OPAQUE_NULL) - -C_METHOD = _C_OPAQUE_PTR -C_INDEX = rffi.LONG -C_INDEX_ARRAY = rffi.LONGP -WLAVC_INDEX = rffi.LONG - -C_METHPTRGETTER = lltype.FuncType([C_OBJECT], rffi.VOIDP) -C_METHPTRGETTER_PTR = lltype.Ptr(C_METHPTRGETTER) +from pypy.module.cppyy.capi.capi_types import C_OBJECT,\ + C_NULL_TYPE, C_NULL_OBJECT def direct_ptradd(ptr, offset): offset = rffi.cast(rffi.SIZE_T, offset) diff --git a/pypy/module/cppyy/capi/builtin_capi.py b/pypy/module/cppyy/capi/builtin_capi.py --- a/pypy/module/cppyy/capi/builtin_capi.py +++ b/pypy/module/cppyy/capi/builtin_capi.py @@ -4,6 +4,10 @@ import reflex_capi as backend #import cint_capi as backend +from pypy.module.cppyy.capi.capi_types import C_SCOPE, C_TYPE, C_OBJECT,\ + C_METHOD, C_INDEX, C_INDEX_ARRAY, WLAVC_INDEX,\ + C_METHPTRGETTER, C_METHPTRGETTER_PTR + identify = backend.identify pythonize = backend.pythonize register_pythonizations = backend.register_pythonizations @@ -14,39 +18,9 @@ ts_memory = backend.ts_memory ts_helper = backend.ts_helper -_C_OPAQUE_PTR = rffi.LONG -_C_OPAQUE_NULL = lltype.nullptr(rffi.LONGP.TO)# ALT: _C_OPAQUE_PTR.TO - -C_SCOPE = _C_OPAQUE_PTR -C_NULL_SCOPE = rffi.cast(C_SCOPE, _C_OPAQUE_NULL) - -C_TYPE = C_SCOPE -C_NULL_TYPE = C_NULL_SCOPE - -C_OBJECT = _C_OPAQUE_PTR -C_NULL_OBJECT = rffi.cast(C_OBJECT, _C_OPAQUE_NULL) - -C_METHOD = _C_OPAQUE_PTR -C_INDEX = rffi.LONG -C_INDEX_ARRAY = rffi.LONGP -WLAVC_INDEX = rffi.LONG - -C_METHPTRGETTER = lltype.FuncType([C_OBJECT], rffi.VOIDP) -C_METHPTRGETTER_PTR = lltype.Ptr(C_METHPTRGETTER) - def verify_backend(space): return True # by definition -def direct_ptradd(ptr, offset): - offset = rffi.cast(rffi.SIZE_T, offset) - jit.promote(offset) - assert lltype.typeOf(ptr) == C_OBJECT - address = rffi.cast(rffi.CCHARP, ptr) - return rffi.cast(C_OBJECT, lltype.direct_ptradd(address, offset)) - -def exchange_address(ptr, cif_descr, index): - return rffi.ptradd(ptr, cif_descr.exchange_args[index]) - c_load_dictionary = backend.c_load_dictionary # name to opaque C++ scope representation ------------------------------------ @@ -61,16 +35,16 @@ "cppyy_scope_name", [C_SCOPE, rffi.INT], rffi.CCHARP, compilation_info = backend.eci) -def c_scope_name(cppscope, iscope): - return charp2str_free(_c_scope_name(cppscope.handle, iscope)) +def c_scope_name(space, cppscope, iscope): + return charp2str_free(space, _c_scope_name(cppscope.handle, iscope)) _c_resolve_name = rffi.llexternal( "cppyy_resolve_name", [rffi.CCHARP], rffi.CCHARP, threadsafe=ts_reflect, compilation_info=backend.eci) -def c_resolve_name(name): - return charp2str_free(_c_resolve_name(name)) +def c_resolve_name(space, name): + return charp2str_free(space, _c_resolve_name(name)) _c_get_scope_opaque = rffi.llexternal( "cppyy_get_scope", [rffi.CCHARP], C_SCOPE, @@ -78,11 +52,13 @@ compilation_info=backend.eci) def c_get_scope_opaque(space, name): return _c_get_scope_opaque(name) -c_get_template = rffi.llexternal( +_c_get_template = rffi.llexternal( "cppyy_get_template", [rffi.CCHARP], C_TYPE, threadsafe=ts_reflect, compilation_info=backend.eci) +def c_get_template(space, name): + return _c_get_template(name) _c_actual_class = rffi.llexternal( "cppyy_actual_class", [C_TYPE, C_OBJECT], C_TYPE, @@ -97,92 +73,116 @@ [C_TYPE], C_OBJECT, threadsafe=ts_memory, compilation_info=backend.eci) -def c_allocate(cppclass): +def c_allocate(space, cppclass): return _c_allocate(cppclass.handle) _c_deallocate = rffi.llexternal( "cppyy_deallocate", [C_TYPE, C_OBJECT], lltype.Void, threadsafe=ts_memory, compilation_info=backend.eci) -def c_deallocate(cppclass, cppobject): +def c_deallocate(space, cppclass, cppobject): _c_deallocate(cppclass.handle, cppobject) _c_destruct = rffi.llexternal( "cppyy_destruct", [C_TYPE, C_OBJECT], lltype.Void, threadsafe=ts_call, compilation_info=backend.eci) -def c_destruct(cppclass, cppobject): +def c_destruct(space, cppclass, cppobject): _c_destruct(cppclass.handle, cppobject) # method/function dispatching ------------------------------------------------ -c_call_v = rffi.llexternal( +_c_call_v = rffi.llexternal( "cppyy_call_v", [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], lltype.Void, threadsafe=ts_call, compilation_info=backend.eci) -c_call_b = rffi.llexternal( +def c_call_v(space, cppmethod, cppobject, nargs, args): + _c_call_v(cppmethod, cppobject, nargs, args) +_c_call_b = rffi.llexternal( "cppyy_call_b", [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.UCHAR, threadsafe=ts_call, compilation_info=backend.eci) -c_call_c = rffi.llexternal( +def c_call_b(space, cppmethod, cppobject, nargs, args): + return _c_call_b(cppmethod, cppobject, nargs, args) +_c_call_c = rffi.llexternal( "cppyy_call_c", [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.CHAR, threadsafe=ts_call, compilation_info=backend.eci) -c_call_h = rffi.llexternal( +def c_call_c(space, cppmethod, cppobject, nargs, args): + return _c_call_c(cppmethod, cppobject, nargs, args) +_c_call_h = rffi.llexternal( "cppyy_call_h", [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.SHORT, threadsafe=ts_call, compilation_info=backend.eci) -c_call_i = rffi.llexternal( +def c_call_h(space, cppmethod, cppobject, nargs, args): + return _c_call_h(cppmethod, cppobject, nargs, args) +_c_call_i = rffi.llexternal( "cppyy_call_i", [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.INT, threadsafe=ts_call, compilation_info=backend.eci) -c_call_l = rffi.llexternal( +def c_call_i(space, cppmethod, cppobject, nargs, args): + return _c_call_i(cppmethod, cppobject, nargs, args) +_c_call_l = rffi.llexternal( "cppyy_call_l", [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.LONG, threadsafe=ts_call, compilation_info=backend.eci) -c_call_ll = rffi.llexternal( +def c_call_l(space, cppmethod, cppobject, nargs, args): + return _c_call_l(cppmethod, cppobject, nargs, args) +_c_call_ll = rffi.llexternal( "cppyy_call_ll", [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.LONGLONG, threadsafe=ts_call, compilation_info=backend.eci) -c_call_f = rffi.llexternal( +def c_call_ll(space, cppmethod, cppobject, nargs, args): + return _c_call_ll(cppmethod, cppobject, nargs, args) +_c_call_f = rffi.llexternal( "cppyy_call_f", [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.FLOAT, threadsafe=ts_call, compilation_info=backend.eci) -c_call_d = rffi.llexternal( +def c_call_f(space, cppmethod, cppobject, nargs, args): + return _c_call_f(cppmethod, cppobject, nargs, args) +_c_call_d = rffi.llexternal( "cppyy_call_d", [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.DOUBLE, threadsafe=ts_call, compilation_info=backend.eci) +def c_call_d(space, cppmethod, cppobject, nargs, args): + return _c_call_d(cppmethod, cppobject, nargs, args) -c_call_r = rffi.llexternal( +_c_call_r = rffi.llexternal( "cppyy_call_r", [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.VOIDP, threadsafe=ts_call, compilation_info=backend.eci) -c_call_s = rffi.llexternal( +def c_call_r(space, cppmethod, cppobject, nargs, args): + return _c_call_r(cppmethod, cppobject, nargs, args) +_c_call_s = rffi.llexternal( "cppyy_call_s", [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.CCHARP, threadsafe=ts_call, compilation_info=backend.eci) +def c_call_s(space, cppmethod, cppobject, nargs, args): + return _c_call_s(cppmethod, cppobject, nargs, args) -c_constructor = rffi.llexternal( +_c_constructor = rffi.llexternal( "cppyy_constructor", [C_METHOD, C_TYPE, rffi.INT, rffi.VOIDP], C_OBJECT, threadsafe=ts_call, compilation_info=backend.eci) +def c_constructor(space, cppmethod, cppobject, nargs, args): + return _c_constructor(cppmethod, cppobject, nargs, args) _c_call_o = rffi.llexternal( "cppyy_call_o", [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP, C_TYPE], rffi.LONG, threadsafe=ts_call, compilation_info=backend.eci) -def c_call_o(method, cppobj, nargs, args, cppclass): +def c_call_o(space, method, cppobj, nargs, args, cppclass): return _c_call_o(method, cppobj, nargs, args, cppclass.handle) _c_get_methptr_getter = rffi.llexternal( @@ -236,34 +236,36 @@ [C_TYPE], rffi.CCHARP, threadsafe=ts_reflect, compilation_info=backend.eci) -def c_final_name(cpptype): - return charp2str_free(_c_final_name(cpptype)) +def c_final_name(space, cpptype): + return charp2str_free(space, _c_final_name(cpptype)) _c_scoped_final_name = rffi.llexternal( "cppyy_scoped_final_name", [C_TYPE], rffi.CCHARP, threadsafe=ts_reflect, compilation_info=backend.eci) -def c_scoped_final_name(cpptype): - return charp2str_free(_c_scoped_final_name(cpptype)) -c_has_complex_hierarchy = rffi.llexternal( +def c_scoped_final_name(space, cpptype): + return charp2str_free(space, _c_scoped_final_name(cpptype)) +_c_has_complex_hierarchy = rffi.llexternal( "cppyy_has_complex_hierarchy", [C_TYPE], rffi.INT, threadsafe=ts_reflect, compilation_info=backend.eci) +def c_has_complex_hierarchy(space, cpptype): + return _c_has_complex_hierarchy(cpptype) _c_num_bases = rffi.llexternal( "cppyy_num_bases", [C_TYPE], rffi.INT, threadsafe=ts_reflect, compilation_info=backend.eci) -def c_num_bases(cppclass): +def c_num_bases(space, cppclass): return _c_num_bases(cppclass.handle) _c_base_name = rffi.llexternal( "cppyy_base_name", [C_TYPE, rffi.INT], rffi.CCHARP, threadsafe=ts_reflect, compilation_info=backend.eci) -def c_base_name(cppclass, base_index): - return charp2str_free(_c_base_name(cppclass.handle, base_index)) +def c_base_name(space, cppclass, base_index): + return charp2str_free(space, _c_base_name(cppclass.handle, base_index)) _c_is_subtype = rffi.llexternal( "cppyy_is_subtype", [C_TYPE, C_TYPE], rffi.INT, @@ -310,7 +312,7 @@ [C_SCOPE, rffi.CCHARP], C_INDEX_ARRAY, threadsafe=ts_reflect, compilation_info=backend.eci) -def c_method_indices_from_name(cppscope, name): +def c_method_indices_from_name(space, cppscope, name): indices = _c_method_indices_from_name(cppscope.handle, name) if not indices: return [] @@ -329,15 +331,15 @@ [C_SCOPE, C_INDEX], rffi.CCHARP, threadsafe=ts_reflect, compilation_info=backend.eci) -def c_method_name(cppscope, index): - return charp2str_free(_c_method_name(cppscope.handle, index)) +def c_method_name(space, cppscope, index): + return charp2str_free(space, _c_method_name(cppscope.handle, index)) _c_method_result_type = rffi.llexternal( "cppyy_method_result_type", [C_SCOPE, C_INDEX], rffi.CCHARP, threadsafe=ts_reflect, compilation_info=backend.eci) -def c_method_result_type(cppscope, index): - return charp2str_free(_c_method_result_type(cppscope.handle, index)) +def c_method_result_type(space, cppscope, index): + return charp2str_free(space, _c_method_result_type(cppscope.handle, index)) _c_method_num_args = rffi.llexternal( "cppyy_method_num_args", [C_SCOPE, C_INDEX], rffi.INT, @@ -357,22 +359,22 @@ [C_SCOPE, C_INDEX, rffi.INT], rffi.CCHARP, threadsafe=ts_reflect, compilation_info=backend.eci) -def c_method_arg_type(cppscope, index, arg_index): - return charp2str_free(_c_method_arg_type(cppscope.handle, index, arg_index)) +def c_method_arg_type(space, cppscope, index, arg_index): + return charp2str_free(space, _c_method_arg_type(cppscope.handle, index, arg_index)) _c_method_arg_default = rffi.llexternal( "cppyy_method_arg_default", [C_SCOPE, C_INDEX, rffi.INT], rffi.CCHARP, threadsafe=ts_reflect, compilation_info=backend.eci) -def c_method_arg_default(cppscope, index, arg_index): - return charp2str_free(_c_method_arg_default(cppscope.handle, index, arg_index)) +def c_method_arg_default(space, cppscope, index, arg_index): + return charp2str_free(space, _c_method_arg_default(cppscope.handle, index, arg_index)) _c_method_signature = rffi.llexternal( "cppyy_method_signature", [C_SCOPE, C_INDEX], rffi.CCHARP, threadsafe=ts_reflect, compilation_info=backend.eci) -def c_method_signature(cppscope, index): - return charp2str_free(_c_method_signature(cppscope.handle, index)) +def c_method_signature(space, cppscope, index): + return charp2str_free(space, _c_method_signature(cppscope.handle, index)) _c_method_is_template = rffi.llexternal( "cppyy_method_is_template", @@ -391,10 +393,10 @@ [C_SCOPE, C_INDEX, C_INDEX], rffi.CCHARP, threadsafe=ts_reflect, compilation_info=backend.eci) -def c_template_args(cppscope, index): +def c_template_args(space, cppscope, index): nargs = _c_method_num_template_args(cppscope.handle, index) - args = [c_resolve_name( - charp2str_free(_c_method_template_arg_name(cppscope.handle, index, iarg))) + args = [c_resolve_name(space, + charp2str_free(space, _c_method_template_arg_name(cppscope.handle, index, iarg))) for iarg in range(nargs)] return args @@ -444,15 +446,15 @@ [C_SCOPE, rffi.INT], rffi.CCHARP, threadsafe=ts_reflect, compilation_info=backend.eci) -def c_datamember_name(cppscope, datamember_index): - return charp2str_free(_c_datamember_name(cppscope.handle, datamember_index)) +def c_datamember_name(space, cppscope, datamember_index): + return charp2str_free(space, _c_datamember_name(cppscope.handle, datamember_index)) _c_datamember_type = rffi.llexternal( "cppyy_datamember_type", [C_SCOPE, rffi.INT], rffi.CCHARP, threadsafe=ts_reflect, compilation_info=backend.eci) -def c_datamember_type(cppscope, datamember_index): - return charp2str_free(_c_datamember_type(cppscope.handle, datamember_index)) +def c_datamember_type(space, cppscope, datamember_index): + return charp2str_free(space, _c_datamember_type(cppscope.handle, datamember_index)) _c_datamember_offset = rffi.llexternal( "cppyy_datamember_offset", [C_SCOPE, rffi.INT], rffi.SIZE_T, @@ -502,7 +504,7 @@ threadsafe=ts_memory, compilation_info=backend.eci) -def charp2str_free(charp): +def charp2str_free(space, charp): string = rffi.charp2str(charp) voidp = rffi.cast(rffi.VOIDP, charp) c_free(voidp) diff --git a/pypy/module/cppyy/capi/capi_types.py b/pypy/module/cppyy/capi/capi_types.py new file mode 100644 --- /dev/null +++ b/pypy/module/cppyy/capi/capi_types.py @@ -0,0 +1,22 @@ +from rpython.rtyper.lltypesystem import rffi, lltype + +# shared ll definitions +_C_OPAQUE_PTR = rffi.LONG +_C_OPAQUE_NULL = lltype.nullptr(rffi.LONGP.TO)# ALT: _C_OPAQUE_PTR.TO + +C_SCOPE = _C_OPAQUE_PTR +C_NULL_SCOPE = rffi.cast(C_SCOPE, _C_OPAQUE_NULL) + +C_TYPE = C_SCOPE +C_NULL_TYPE = C_NULL_SCOPE + +C_OBJECT = _C_OPAQUE_PTR +C_NULL_OBJECT = rffi.cast(C_OBJECT, _C_OPAQUE_NULL) + +C_METHOD = _C_OPAQUE_PTR +C_INDEX = rffi.LONG +C_INDEX_ARRAY = rffi.LONGP +WLAVC_INDEX = rffi.LONG + +C_METHPTRGETTER = lltype.FuncType([C_OBJECT], rffi.VOIDP) +C_METHPTRGETTER_PTR = lltype.Ptr(C_METHPTRGETTER) diff --git a/pypy/module/cppyy/capi/cint_capi.py b/pypy/module/cppyy/capi/cint_capi.py --- a/pypy/module/cppyy/capi/cint_capi.py +++ b/pypy/module/cppyy/capi/cint_capi.py @@ -221,7 +221,7 @@ # placeholder w_typename = space.call_method(w_leaf, "GetTypeName" ) from pypy.module.cppyy import capi - typename = capi.c_resolve_name(space.str_w(w_typename)) + typename = capi.c_resolve_name(space, space.str_w(w_typename)) if typename == 'bool': typename = '_Bool' w_address = space.call_method(w_leaf, "GetValuePointer") from pypy.module._cffi_backend import cdataobj, newtype diff --git a/pypy/module/cppyy/capi/loadable_capi.py b/pypy/module/cppyy/capi/loadable_capi.py --- a/pypy/module/cppyy/capi/loadable_capi.py +++ b/pypy/module/cppyy/capi/loadable_capi.py @@ -6,19 +6,17 @@ from pypy.interpreter.error import OperationError -from pypy.module._cffi_backend.libraryobj import W_Library -from pypy.module._cffi_backend.ctypefunc import W_CTypeFunc -from pypy.module._cffi_backend.newtype import new_primitive_type, new_pointer_type -from pypy.module._cffi_backend.cdataobj import W_CData - +from pypy.module.cppyy.capi.capi_types import C_SCOPE, C_TYPE, C_OBJECT,\ + C_METHOD, C_INDEX, C_INDEX_ARRAY, WLAVC_INDEX,\ + C_METHPTRGETTER, C_METHPTRGETTER_PTR import reflex_capi as backend -#import cint_capi as backend + +reflection_library = 'rflxlib.so' def identify(): return 'loadable_capi' -pythonize = backend.pythonize -register_pythonizations = backend.register_pythonizations + std_string_name = backend.std_string_name ts_reflect = backend.ts_reflect @@ -26,36 +24,6 @@ ts_memory = backend.ts_memory ts_helper = backend.ts_helper -_C_OPAQUE_PTR = rffi.LONG -_C_OPAQUE_NULL = lltype.nullptr(rffi.LONGP.TO)# ALT: _C_OPAQUE_PTR.TO - -C_SCOPE = _C_OPAQUE_PTR -C_NULL_SCOPE = rffi.cast(C_SCOPE, _C_OPAQUE_NULL) - -C_TYPE = C_SCOPE -C_NULL_TYPE = C_NULL_SCOPE - -C_OBJECT = _C_OPAQUE_PTR -C_NULL_OBJECT = rffi.cast(C_OBJECT, _C_OPAQUE_NULL) - -C_METHOD = _C_OPAQUE_PTR -C_INDEX = rffi.LONG -C_INDEX_ARRAY = rffi.LONGP -WLAVC_INDEX = rffi.LONG - -C_METHPTRGETTER = lltype.FuncType([C_OBJECT], rffi.VOIDP) -C_METHPTRGETTER_PTR = lltype.Ptr(C_METHPTRGETTER) - -def direct_ptradd(ptr, offset): - offset = rffi.cast(rffi.SIZE_T, offset) - jit.promote(offset) - assert lltype.typeOf(ptr) == C_OBJECT - address = rffi.cast(rffi.CCHARP, ptr) - return rffi.cast(C_OBJECT, lltype.direct_ptradd(address, offset)) - -def exchange_address(ptr, cif_descr, index): - return rffi.ptradd(ptr, cif_descr.exchange_args[index]) - c_load_dictionary = backend.c_load_dictionary class State(object): @@ -63,187 +31,214 @@ self.library = None self.capi_calls = {} - c_scope_s = 'long' - c_type_s = 'long' + import pypy.module._cffi_backend.newtype as nt + + # TODO: the following need to match up with the globally defined C_XYZ low-level + # types (see capi/__init__.py), but by using strings here, that isn't guaranteed + c_opaque_ptr = nt.new_primitive_type(space, 'long') + + c_scope = c_opaque_ptr + c_type = c_scope + c_object = c_opaque_ptr + c_method = c_opaque_ptr + c_index = nt.new_primitive_type(space, 'long') + + c_void = nt.new_void_type(space) + c_char = nt.new_primitive_type(space, 'char') + c_uchar = nt.new_primitive_type(space, 'unsigned char') + c_short = nt.new_primitive_type(space, 'short') + c_int = nt.new_primitive_type(space, 'int') + c_long = nt.new_primitive_type(space, 'long') + c_llong = nt.new_primitive_type(space, 'long long') + c_float = nt.new_primitive_type(space, 'float') + c_double = nt.new_primitive_type(space, 'double') + + c_ccharp = nt.new_pointer_type(space, c_char) + c_voidp = nt.new_primitive_type(space, 'unsigned long') # b/c voidp can not be wrapped self.capi_call_ifaces = { - 'num_scopes' : ([new_primitive_type(space, c_scope_s)], - new_primitive_type(space, 'int')), - 'scope_name' : ([new_primitive_type(space, c_scope_s), new_primitive_type(space, 'int')], - new_pointer_type(space, new_primitive_type(space, 'char'))), + # name to opaque C++ scope representation + 'num_scopes' : ([c_scope], c_int), + 'scope_name' : ([c_scope, c_int], c_ccharp), - 'get_scope' : ([new_pointer_type(space, new_primitive_type(space, 'char'))], - new_primitive_type(space, c_scope_s)), + 'resolve_name' : ([c_ccharp], c_ccharp), + 'get_scope' : ([c_ccharp], c_scope), + 'get_template' : ([c_ccharp], c_type), + 'actual_class' : ([c_type, c_object], c_type), - 'actual_class' : ([new_primitive_type(space, c_type_s), new_primitive_type(space, c_scope_s)], - new_primitive_type(space, c_type_s)), + # memory management + 'allocate' : ([c_type], c_object), + 'deallocate' : ([c_type, c_object], c_void), + 'destruct' : ([c_type, c_object], c_void), + + # method/function dispatching + 'call_v' : ([c_method, c_object, c_int, c_voidp], c_void), + 'call_b' : ([c_method, c_object, c_int, c_voidp], c_uchar), + 'call_c' : ([c_method, c_object, c_int, c_voidp], c_char), + 'call_h' : ([c_method, c_object, c_int, c_voidp], c_short), + 'call_i' : ([c_method, c_object, c_int, c_voidp], c_int), + 'call_l' : ([c_method, c_object, c_int, c_voidp], c_long), + 'call_ll' : ([c_method, c_object, c_int, c_voidp], c_llong), + 'call_f' : ([c_method, c_object, c_int, c_voidp], c_float), + 'call_d' : ([c_method, c_object, c_int, c_voidp], c_double), + + 'call_r' : ([c_method, c_object, c_int, c_voidp], c_voidp), + 'call_s' : ([c_method, c_object, c_int, c_voidp], c_ccharp), + + 'constructor' : ([c_method, c_object, c_int, c_voidp], c_object), + 'call_o' : ([c_method, c_object, c_int, c_voidp, c_type], c_object), + + # type/class reflection information + 'final_name' : ([c_type], c_ccharp), + 'scoped_final_name' : ([c_type], c_ccharp), + 'has_complex_hierarchy' : ([c_type], c_int), + 'num_bases' : ([c_type], c_int), + 'base_name' : ([c_type, c_int], c_ccharp), + + # method/function reflection information + + 'method_name' : ([c_scope, c_index], c_ccharp), + 'method_result_type' : ([c_scope, c_index], c_ccharp), + + 'method_arg_type' : ([c_scope, c_index, c_int], c_ccharp), + 'method_arg_default' : ([c_scope, c_index, c_int], c_ccharp), + 'method_signature' : ([c_scope, c_index], c_ccharp), + + 'method_template_arg_name' : ([c_scope, c_index, c_index], c_ccharp), + + # data member reflection information + 'datamember_name' : ([c_scope, c_int], c_ccharp), + 'datamember_type' : ([c_scope, c_int], c_ccharp), + + # misc helpers + 'free' : ([c_voidp], c_void), } +def load_reflection_library(space): + state = space.fromcache(State) + if state.library is None: + from pypy.module._cffi_backend.libraryobj import W_Library + state.library = W_Library(space, reflection_library, rdynload.RTLD_LOCAL | rdynload.RTLD_LAZY) + return state.library + def verify_backend(space): - state = space.fromcache(State) try: - if state.library is None: - state.library = W_Library(space, 'rflxlib.so', rdynload.RTLD_LOCAL | rdynload.RTLD_LAZY) + load_reflection_library(space) except Exception: if objectmodel.we_are_translated(): raise OperationError(space.w_ImportError, - space.wrap("missing reflection module rflxlib.so!")) + space.wrap("missing reflection library rflxlib.so")) return False return True -def get_capi_call(space, name): +def call_capi(space, name, args_w): state = space.fromcache(State) try: - return state.capi_calls[name] + c_call = state.capi_calls[name] except KeyError: - pass - try: if state.library is None: - state.library = W_Library(space, 'rflxlib.so', rdynload.RTLD_LOCAL | rdynload.RTLD_LAZY) + load_reflection_library(space) iface = state.capi_call_ifaces[name] + from pypy.module._cffi_backend.ctypefunc import W_CTypeFunc cfunc = W_CTypeFunc(space, iface[0], iface[1], False) - capi_call = state.library.load_function(cfunc, 'cppyy_'+name) + c_call = state.library.load_function(cfunc, 'cppyy_'+name) # TODO: there must be a better way to trick the leakfinder ... if not objectmodel.we_are_translated(): - leakfinder.remember_free(capi_call.ctype.cif_descr._obj0) - state.capi_calls[name] = capi_call - return capi_call - except Exception: - pass - return None + leakfinder.remember_free(c_call.ctype.cif_descr._obj0) + state.capi_calls[name] = c_call + return c_call.call(args_w) # name to opaque C++ scope representation ------------------------------------ def c_num_scopes(space, cppscope): - num_scopes = get_capi_call(space, 'num_scopes') - if num_scopes: - return space.int_w(num_scopes.call([space.wrap(cppscope.handle)])) - return 0 -_c_scope_name = rffi.llexternal( - "cppyy_scope_name", - [C_SCOPE, rffi.INT], rffi.CCHARP, - compilation_info = backend.eci) -def c_scope_name(cppscope, iscope): - return charp2str_free(_c_scope_name(cppscope.handle, iscope)) + args_w = [space.wrap(cppscope.handle)] + return space.int_w(call_capi(space, 'num_scopes', args_w)) +def c_scope_name(space, cppscope, iscope): + args_w = [space.wrap(cppscope.handle), space.wrap(iscope)] + return charp2str_free(space, call_capi(space, 'scope_name', args_w)) -_c_resolve_name = rffi.llexternal( - "cppyy_resolve_name", - [rffi.CCHARP], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_resolve_name(name): - return charp2str_free(_c_resolve_name(name)) +def c_resolve_name(space, name): + args_w = [space.wrap(name)] + return charp2str_free(space, call_capi(space, 'resolve_name', args_w)) def c_get_scope_opaque(space, name): - get_scope = get_capi_call(space, 'get_scope') - if get_scope: - return rffi.cast(C_SCOPE, space.int_w(get_scope.call([space.wrap(name)]))) - return rffi.cast(C_SCOPE, 0) - -c_get_template = rffi.llexternal( - "cppyy_get_template", - [rffi.CCHARP], C_TYPE, - threadsafe=ts_reflect, - compilation_info=backend.eci) + args_w = [space.wrap(name)] + return rffi.cast(C_SCOPE, space.int_w(call_capi(space, 'get_scope', args_w))) +def c_get_template(space, name): + args_w = [space.wrap(name)] + return rffi.cast(C_TYPE, space.int_w(call_capi(space, 'get_template', args_w))) def c_actual_class(space, cppclass, cppobj): - actual_class = get_capi_call(space, 'actual_class') - if actual_class: - return rffi.cast(C_TYPE, space.int_w( - actual_class.call([space.wrap(cppclass.handle), space.wrap(cppobj)]))) - return rffi.cast(C_TYPE, 0) + args_w = [space.wrap(cppclass.handle), space.wrap(cppobj)] + return rffi.cast(C_TYPE, space.int_w(call_capi(space, 'actual_class', args_w))) # memory management ---------------------------------------------------------- -_c_allocate = rffi.llexternal( - "cppyy_allocate", - [C_TYPE], C_OBJECT, - threadsafe=ts_memory, - compilation_info=backend.eci) -def c_allocate(cppclass): - return _c_allocate(cppclass.handle) -_c_deallocate = rffi.llexternal( - "cppyy_deallocate", - [C_TYPE, C_OBJECT], lltype.Void, - threadsafe=ts_memory, - compilation_info=backend.eci) -def c_deallocate(cppclass, cppobject): - _c_deallocate(cppclass.handle, cppobject) -_c_destruct = rffi.llexternal( - "cppyy_destruct", - [C_TYPE, C_OBJECT], lltype.Void, - threadsafe=ts_call, - compilation_info=backend.eci) -def c_destruct(cppclass, cppobject): - _c_destruct(cppclass.handle, cppobject) +def c_allocate(space, cppclass): + args_w = [space.wrap(cppclass.handle)] + return rffi.cast(C_OBJECT, space.int_w(call_capi(space, 'allocate', args_w))) +def c_deallocate(space, cppclass, cppobject): + args_w = [space.wrap(cppclass.handle), space.wrap(cppobject)] + call_capi(space, 'deallocate', args_w) +def c_destruct(space, cppclass, cppobject): + args_w = [space.wrap(cppclass.handle), space.wrap(cppobject)] + call_capi(space, 'destruct', args_w) # method/function dispatching ------------------------------------------------ -c_call_v = rffi.llexternal( - "cppyy_call_v", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], lltype.Void, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_b = rffi.llexternal( - "cppyy_call_b", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.UCHAR, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_c = rffi.llexternal( - "cppyy_call_c", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.CHAR, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_h = rffi.llexternal( - "cppyy_call_h", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.SHORT, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_i = rffi.llexternal( - "cppyy_call_i", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.INT, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_l = rffi.llexternal( - "cppyy_call_l", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.LONG, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_ll = rffi.llexternal( - "cppyy_call_ll", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.LONGLONG, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_f = rffi.llexternal( - "cppyy_call_f", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.FLOAT, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_d = rffi.llexternal( - "cppyy_call_d", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.DOUBLE, - threadsafe=ts_call, - compilation_info=backend.eci) +def c_call_v(space, cppmethod, cppobject, nargs, args): + args_w = [space.wrap(cppmethod), space.wrap(cppobject), + space.wrap(nargs), space.wrap(rffi.cast(rffi.ULONG, args))] + call_capi(space, 'call_v', args_w) +# TODO: these method do not actually need unwrapping, as the excutors simply +# wrap the values again, but the other backends expect that ... +def c_call_b(space, cppmethod, cppobject, nargs, args): + args_w = [space.wrap(cppmethod), space.wrap(cppobject), + space.wrap(nargs), space.wrap(rffi.cast(rffi.ULONG, args))] + return rffi.cast(rffi.UCHAR, space.int_w(call_capi(space, 'call_b', args_w))) +def c_call_c(space, cppmethod, cppobject, nargs, args): + args_w = [space.wrap(cppmethod), space.wrap(cppobject), + space.wrap(nargs), space.wrap(rffi.cast(rffi.ULONG, args))] + return rffi.cast(rffi.CHAR, space.str_w(call_capi(space, 'call_c', args_w))) +def c_call_h(space, cppmethod, cppobject, nargs, args): + args_w = [space.wrap(cppmethod), space.wrap(cppobject), + space.wrap(nargs), space.wrap(rffi.cast(rffi.ULONG, args))] + return rffi.cast(rffi.SHORT, space.int_w(call_capi(space, 'call_h', args_w))) +def c_call_i(space, cppmethod, cppobject, nargs, args): + args_w = [space.wrap(cppmethod), space.wrap(cppobject), + space.wrap(nargs), space.wrap(rffi.cast(rffi.ULONG, args))] + return rffi.cast(rffi.INT, space.int_w(call_capi(space, 'call_i', args_w))) +def c_call_l(space, cppmethod, cppobject, nargs, args): + args_w = [space.wrap(cppmethod), space.wrap(cppobject), + space.wrap(nargs), space.wrap(rffi.cast(rffi.ULONG, args))] + return rffi.cast(rffi.LONG, space.int_w(call_capi(space, 'call_l', args_w))) +def c_call_ll(space, cppmethod, cppobject, nargs, args): + args_w = [space.wrap(cppmethod), space.wrap(cppobject), + space.wrap(nargs), space.wrap(rffi.cast(rffi.ULONG, args))] + return rffi.cast(rffi.LONGLONG, space.int_w(call_capi(space, 'call_ll', args_w))) +def c_call_f(space, cppmethod, cppobject, nargs, args): + args_w = [space.wrap(cppmethod), space.wrap(cppobject), + space.wrap(nargs), space.wrap(rffi.cast(rffi.ULONG, args))] + return rffi.cast(rffi.FLOAT, space.float_w(call_capi(space, 'call_f', args_w))) +def c_call_d(space, cppmethod, cppobject, nargs, args): + args_w = [space.wrap(cppmethod), space.wrap(cppobject), + space.wrap(nargs), space.wrap(rffi.cast(rffi.ULONG, args))] + return rffi.cast(rffi.DOUBLE, space.float_w(call_capi(space, 'call_d', args_w))) -c_call_r = rffi.llexternal( - "cppyy_call_r", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.VOIDP, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_s = rffi.llexternal( - "cppyy_call_s", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.CCHARP, - threadsafe=ts_call, - compilation_info=backend.eci) +def c_call_r(space, cppmethod, cppobject, nargs, args): + args_w = [space.wrap(cppmethod), space.wrap(cppobject), + space.wrap(nargs), space.wrap(rffi.cast(rffi.ULONG, args))] + return rffi.cast(rffi.VOIDP, space.int_w(call_capi(space, 'call_r', args_w))) +def c_call_s(space, cppmethod, cppobject, nargs, args): + args_w = [space.wrap(cppmethod), space.wrap(cppobject), + space.wrap(nargs), space.wrap(rffi.cast(rffi.ULONG, args))] + return call_capi(space, 'call_s', args_w) -c_constructor = rffi.llexternal( - "cppyy_constructor", - [C_METHOD, C_TYPE, rffi.INT, rffi.VOIDP], C_OBJECT, - threadsafe=ts_call, - compilation_info=backend.eci) -_c_call_o = rffi.llexternal( - "cppyy_call_o", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP, C_TYPE], rffi.LONG, - threadsafe=ts_call, - compilation_info=backend.eci) -def c_call_o(method, cppobj, nargs, args, cppclass): - return _c_call_o(method, cppobj, nargs, args, cppclass.handle) +def c_constructor(space, cppmethod, cppobject, nargs, args): + args_w = [space.wrap(cppmethod), space.wrap(cppobject), + space.wrap(nargs), space.wrap(rffi.cast(rffi.ULONG, args))] + return rffi.cast(C_OBJECT, space.int_w(call_capi(space, 'constructor', args_w))) +def c_call_o(space, cppmethod, cppobject, nargs, args, cppclass): + args_w = [space.wrap(cppmethod), space.wrap(cppobject), + space.wrap(nargs), space.wrap(rffi.cast(rffi.ULONG, args)), + space.wrap(cppclass.handle)] + return rffi.cast(C_OBJECT, space.int_w(call_capi(space, 'call_o', args_w))) _c_get_methptr_getter = rffi.llexternal( "cppyy_get_methptr_getter", @@ -291,39 +286,21 @@ compilation_info=backend.eci) # type/class reflection information ------------------------------------------ -_c_final_name = rffi.llexternal( - "cppyy_final_name", - [C_TYPE], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_final_name(cpptype): - return charp2str_free(_c_final_name(cpptype)) -_c_scoped_final_name = rffi.llexternal( - "cppyy_scoped_final_name", - [C_TYPE], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_scoped_final_name(cpptype): - return charp2str_free(_c_scoped_final_name(cpptype)) -c_has_complex_hierarchy = rffi.llexternal( - "cppyy_has_complex_hierarchy", - [C_TYPE], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -_c_num_bases = rffi.llexternal( - "cppyy_num_bases", - [C_TYPE], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_num_bases(cppclass): - return _c_num_bases(cppclass.handle) -_c_base_name = rffi.llexternal( - "cppyy_base_name", - [C_TYPE, rffi.INT], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_base_name(cppclass, base_index): - return charp2str_free(_c_base_name(cppclass.handle, base_index)) +def c_final_name(space, cpptype): + args_w = [space.wrap(cpptype)] + return charp2str_free(space, call_capi(space, 'final_name', args_w)) +def c_scoped_final_name(space, cpptype): + args_w = [space.wrap(cpptype)] + return charp2str_free(space, call_capi(space, 'scoped_final_name', args_w)) +def c_has_complex_hierarchy(space, handle): + args_w = [space.wrap(handle)] + return space.int_w(call_capi(space, 'has_complex_hierarchy', args_w)) +def c_num_bases(space, cppclass): + args_w = [space.wrap(cppclass.handle)] + return space.int_w(call_capi(space, 'num_bases', args_w)) +def c_base_name(space, cppclass, base_index): + args_w = [space.wrap(cppclass.handle), space.wrap(base_index)] + return charp2str_free(space, call_capi(space, 'base_name', args_w)) _c_is_subtype = rffi.llexternal( "cppyy_is_subtype", [C_TYPE, C_TYPE], rffi.INT, @@ -370,7 +347,7 @@ [C_SCOPE, rffi.CCHARP], C_INDEX_ARRAY, threadsafe=ts_reflect, compilation_info=backend.eci) -def c_method_indices_from_name(cppscope, name): +def c_method_indices_from_name(space, cppscope, name): indices = _c_method_indices_from_name(cppscope.handle, name) if not indices: return [] @@ -381,23 +358,15 @@ i += 1 py_indices.append(index) index = indices[i] - c_free(rffi.cast(rffi.VOIDP, indices)) # c_free defined below + c_free(space, rffi.cast(rffi.VOIDP, indices)) # c_free defined below return py_indices -_c_method_name = rffi.llexternal( - "cppyy_method_name", - [C_SCOPE, C_INDEX], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_name(cppscope, index): - return charp2str_free(_c_method_name(cppscope.handle, index)) -_c_method_result_type = rffi.llexternal( - "cppyy_method_result_type", - [C_SCOPE, C_INDEX], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_result_type(cppscope, index): - return charp2str_free(_c_method_result_type(cppscope.handle, index)) +def c_method_name(space, cppscope, index): + args_w = [space.wrap(cppscope.handle), space.wrap(index)] + return charp2str_free(space, call_capi(space, 'method_name', args_w)) +def c_method_result_type(space, cppscope, index): + args_w = [space.wrap(cppscope.handle), space.wrap(index)] + return charp2str_free(space, call_capi(space, 'method_result_type', args_w)) _c_method_num_args = rffi.llexternal( "cppyy_method_num_args", [C_SCOPE, C_INDEX], rffi.INT, @@ -412,27 +381,15 @@ compilation_info=backend.eci) def c_method_req_args(cppscope, index): return _c_method_req_args(cppscope.handle, index) -_c_method_arg_type = rffi.llexternal( - "cppyy_method_arg_type", - [C_SCOPE, C_INDEX, rffi.INT], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_arg_type(cppscope, index, arg_index): - return charp2str_free(_c_method_arg_type(cppscope.handle, index, arg_index)) -_c_method_arg_default = rffi.llexternal( - "cppyy_method_arg_default", - [C_SCOPE, C_INDEX, rffi.INT], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_arg_default(cppscope, index, arg_index): - return charp2str_free(_c_method_arg_default(cppscope.handle, index, arg_index)) -_c_method_signature = rffi.llexternal( - "cppyy_method_signature", - [C_SCOPE, C_INDEX], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_signature(cppscope, index): - return charp2str_free(_c_method_signature(cppscope.handle, index)) +def c_method_arg_type(space, cppscope, index, arg_index): + args_w = [space.wrap(cppscope.handle), space.wrap(index), space.wrap(arg_index)] + return charp2str_free(space, call_capi(space, 'method_arg_type', args_w)) +def c_method_arg_default(space, cppscope, index, arg_index): + args_w = [space.wrap(cppscope.handle), space.wrap(index), space.wrap(arg_index)] + return charp2str_free(space, call_capi(space, 'method_arg_default', args_w)) +def c_method_signature(space, cppscope, index): + args_w = [space.wrap(cppscope.handle), space.wrap(index)] + return charp2str_free(space, call_capi(space, 'method_signature', args_w)) _c_method_is_template = rffi.llexternal( "cppyy_method_is_template", @@ -451,11 +408,13 @@ [C_SCOPE, C_INDEX, C_INDEX], rffi.CCHARP, threadsafe=ts_reflect, compilation_info=backend.eci) -def c_template_args(cppscope, index): +def c_template_args(space, cppscope, index): nargs = _c_method_num_template_args(cppscope.handle, index) - args = [c_resolve_name( - charp2str_free(_c_method_template_arg_name(cppscope.handle, index, iarg))) - for iarg in range(nargs)] + args = [c_resolve_name(space, charp2str_free(space, + call_capi(space, 'method_template_arg_name', + [space.wrap(cppscope.handle), space.wrap(index), space.wrap(iarg)]) + ) + ) for iarg in range(nargs)] return args _c_get_method = rffi.llexternal( @@ -504,15 +463,17 @@ [C_SCOPE, rffi.INT], rffi.CCHARP, threadsafe=ts_reflect, compilation_info=backend.eci) -def c_datamember_name(cppscope, datamember_index): - return charp2str_free(_c_datamember_name(cppscope.handle, datamember_index)) +def c_datamember_name(space, cppscope, datamember_index): + args_w = [space.wrap(cppscope.handle), space.wrap(datamember_index)] + return charp2str_free(space, call_capi(space, 'datamember_name', args_w)) _c_datamember_type = rffi.llexternal( "cppyy_datamember_type", [C_SCOPE, rffi.INT], rffi.CCHARP, threadsafe=ts_reflect, compilation_info=backend.eci) -def c_datamember_type(cppscope, datamember_index): - return charp2str_free(_c_datamember_type(cppscope.handle, datamember_index)) +def c_datamember_type(space, cppscope, datamember_index): + args_w = [space.wrap(cppscope.handle), space.wrap(datamember_index)] + return charp2str_free(space, call_capi(space, 'datamember_type', args_w)) _c_datamember_offset = rffi.llexternal( "cppyy_datamember_offset", [C_SCOPE, rffi.INT], rffi.SIZE_T, @@ -556,17 +517,16 @@ [rffi.CCHARP], rffi.ULONGLONG, threadsafe=ts_helper, compilation_info=backend.eci) -c_free = rffi.llexternal( - "cppyy_free", - [rffi.VOIDP], lltype.Void, - threadsafe=ts_memory, - compilation_info=backend.eci) +def c_free(space, voidp): + args_w = [space.wrap(rffi.cast(rffi.ULONG, voidp))] + call_capi(space, 'free', args_w) -def charp2str_free(charp): - string = rffi.charp2str(charp) +def charp2str_free(space, cdata): + charp = rffi.cast(rffi.CCHARP, cdata._cdata) + pystr = rffi.charp2str(charp) voidp = rffi.cast(rffi.VOIDP, charp) - c_free(voidp) - return string + c_free(space, voidp) + return pystr c_charp2stdstring = rffi.llexternal( "cppyy_charp2stdstring", @@ -588,3 +548,12 @@ [C_OBJECT], lltype.Void, threadsafe=ts_helper, compilation_info=backend.eci) + + +# loadable-capi-specific pythonizations (none, as the capi isn't known until runtime) +def register_pythonizations(space): + "NOT_RPYTHON" + pass + +def pythonize(space, name, w_pycppclass): + pass diff --git a/pypy/module/cppyy/converter.py b/pypy/module/cppyy/converter.py --- a/pypy/module/cppyy/converter.py +++ b/pypy/module/cppyy/converter.py @@ -599,7 +599,7 @@ # 4) generalized cases (covers basically all user classes) # 5) void converter, which fails on use - name = capi.c_resolve_name(name) + name = capi.c_resolve_name(space, name) # 1) full, exact match try: @@ -615,7 +615,7 @@ # 2) match of decorated, unqualified type compound = helper.compound(name) - clean_name = capi.c_resolve_name(helper.clean_type(name)) + clean_name = capi.c_resolve_name(space, helper.clean_type(name)) try: # array_index may be negative to indicate no size or no size found array_size = helper.array_size(name) diff --git a/pypy/module/cppyy/executor.py b/pypy/module/cppyy/executor.py --- a/pypy/module/cppyy/executor.py +++ b/pypy/module/cppyy/executor.py @@ -52,7 +52,7 @@ def execute(self, space, cppmethod, cppthis, num_args, args): if hasattr(space, "fake"): raise NotImplementedError - lresult = capi.c_call_l(cppmethod, cppthis, num_args, args) + lresult = capi.c_call_l(space, cppmethod, cppthis, num_args, args) address = rffi.cast(rffi.ULONG, lresult) arr = space.interp_w(W_Array, unpack_simple_shape(space, space.wrap(self.typecode))) if address == 0: @@ -72,7 +72,7 @@ libffitype = jit_libffi.types.void def execute(self, space, cppmethod, cppthis, num_args, args): - capi.c_call_v(cppmethod, cppthis, num_args, args) + capi.c_call_v(space, cppmethod, cppthis, num_args, args) return space.w_None def execute_libffi(self, space, cif_descr, funcaddr, buffer): @@ -87,7 +87,7 @@ return space.wrap(obj) def execute(self, space, cppmethod, cppthis, num_args, args): - result = self.c_stubcall(cppmethod, cppthis, num_args, args) + result = self.c_stubcall(space, cppmethod, cppthis, num_args, args) return self._wrap_object(space, rffi.cast(self.c_type, result)) def execute_libffi(self, space, cif_descr, funcaddr, buffer): @@ -118,7 +118,7 @@ return self._wrap_object(space, rffiptr[0]) # all paths, for rtyper def execute(self, space, cppmethod, cppthis, num_args, args): - result = capi.c_call_r(cppmethod, cppthis, num_args, args) + result = capi.c_call_r(space, cppmethod, cppthis, num_args, args) return self._wrap_reference(space, rffi.cast(self.c_ptrtype, result)) def execute_libffi(self, space, cif_descr, funcaddr, buffer): @@ -131,7 +131,7 @@ class CStringExecutor(FunctionExecutor): def execute(self, space, cppmethod, cppthis, num_args, args): - lresult = capi.c_call_l(cppmethod, cppthis, num_args, args) + lresult = capi.c_call_l(space, cppmethod, cppthis, num_args, args) ccpresult = rffi.cast(rffi.CCHARP, lresult) if ccpresult: result = rffi.charp2str(ccpresult) # TODO: make it a choice to free @@ -143,7 +143,7 @@ def execute(self, space, cppmethod, cpptype, num_args, args): from pypy.module.cppyy import interp_cppyy - newthis = capi.c_constructor(cppmethod, cpptype, num_args, args) + newthis = capi.c_constructor(space, cppmethod, cpptype, num_args, args) assert lltype.typeOf(newthis) == capi.C_OBJECT return space.wrap(newthis) @@ -159,7 +159,7 @@ def execute(self, space, cppmethod, cppthis, num_args, args): from pypy.module.cppyy import interp_cppyy - long_result = capi.c_call_l(cppmethod, cppthis, num_args, args) + long_result = capi.c_call_l(space, cppmethod, cppthis, num_args, args) ptr_result = rffi.cast(capi.C_OBJECT, long_result) return interp_cppyy.wrap_cppobject(space, ptr_result, self.cppclass) @@ -174,7 +174,7 @@ def execute(self, space, cppmethod, cppthis, num_args, args): from pypy.module.cppyy import interp_cppyy - voidp_result = capi.c_call_r(cppmethod, cppthis, num_args, args) + voidp_result = capi.c_call_r(space, cppmethod, cppthis, num_args, args) ref_address = rffi.cast(rffi.VOIDPP, voidp_result) ptr_result = rffi.cast(capi.C_OBJECT, ref_address[0]) return interp_cppyy.wrap_cppobject(space, ptr_result, self.cppclass) @@ -187,7 +187,7 @@ def execute(self, space, cppmethod, cppthis, num_args, args): from pypy.module.cppyy import interp_cppyy - long_result = capi.c_call_o(cppmethod, cppthis, num_args, args, self.cppclass) + long_result = capi.c_call_o(space, cppmethod, cppthis, num_args, args, self.cppclass) ptr_result = rffi.cast(capi.C_OBJECT, long_result) return interp_cppyy.wrap_cppobject(space, ptr_result, self.cppclass, do_cast=False, python_owns=True) @@ -200,8 +200,8 @@ class StdStringExecutor(InstancePtrExecutor): def execute(self, space, cppmethod, cppthis, num_args, args): - charp_result = capi.c_call_s(cppmethod, cppthis, num_args, args) - return space.wrap(capi.charp2str_free(charp_result)) + charp_result = capi.c_call_s(space, cppmethod, cppthis, num_args, args) + return space.wrap(capi.charp2str_free(space, charp_result)) def execute_libffi(self, space, cif_descr, funcaddr, buffer): from pypy.module.cppyy.interp_cppyy import FastCallNotPossible @@ -222,7 +222,7 @@ def execute(self, space, cppmethod, cppthis, num_args, args): if hasattr(space, "fake"): raise NotImplementedError - lresult = capi.c_call_l(cppmethod, cppthis, num_args, args) + lresult = capi.c_call_l(space, cppmethod, cppthis, num_args, args) return self.wrap_result(space, lresult) def execute_libffi(self, space, cif_descr, funcaddr, buffer): @@ -243,7 +243,7 @@ # # If all fails, a default is used, which can be ignored at least until use. - name = capi.c_resolve_name(name) + name = capi.c_resolve_name(space, name) # 1) full, qualified match try: @@ -252,7 +252,7 @@ pass compound = helper.compound(name) - clean_name = capi.c_resolve_name(helper.clean_type(name)) + clean_name = capi.c_resolve_name(space, helper.clean_type(name)) # 1a) clean lookup try: diff --git a/pypy/module/cppyy/helper.py b/pypy/module/cppyy/helper.py --- a/pypy/module/cppyy/helper.py +++ b/pypy/module/cppyy/helper.py @@ -63,7 +63,7 @@ #- operator mappings -------------------------------------------------------- _operator_mappings = {} -def map_operator_name(cppname, nargs, result_type): +def map_operator_name(space, cppname, nargs, result_type): from pypy.module.cppyy import capi if cppname[0:8] == "operator": @@ -104,7 +104,7 @@ # is put at the end only as it is unlikely and may trigger unwanted # errors in class loaders in the backend, because a typical operator # name is illegal as a class name) - true_op = capi.c_resolve_name(op) + true_op = capi.c_resolve_name(space, op) try: return _operator_mappings[true_op] diff --git a/pypy/module/cppyy/interp_cppyy.py b/pypy/module/cppyy/interp_cppyy.py --- a/pypy/module/cppyy/interp_cppyy.py +++ b/pypy/module/cppyy/interp_cppyy.py @@ -46,11 +46,11 @@ @unwrap_spec(name=str) def resolve_name(space, name): - return space.wrap(capi.c_resolve_name(name)) + return space.wrap(capi.c_resolve_name(space, name)) @unwrap_spec(name=str) def scope_byname(space, name): - true_name = capi.c_resolve_name(name) + true_name = capi.c_resolve_name(space, name) state = space.fromcache(State) try: @@ -61,10 +61,10 @@ opaque_handle = capi.c_get_scope_opaque(space, true_name) assert lltype.typeOf(opaque_handle) == capi.C_SCOPE if opaque_handle: - final_name = capi.c_final_name(opaque_handle) + final_name = capi.c_final_name(space, opaque_handle) if capi.c_is_namespace(opaque_handle): cppscope = W_CPPNamespace(space, final_name, opaque_handle) - elif capi.c_has_complex_hierarchy(opaque_handle): + elif capi.c_has_complex_hierarchy(space, opaque_handle): cppscope = W_ComplexCPPClass(space, final_name, opaque_handle) else: cppscope = W_CPPClass(space, final_name, opaque_handle) @@ -84,7 +84,7 @@ except KeyError: pass - opaque_handle = capi.c_get_template(name) + opaque_handle = capi.c_get_template(space, name) assert lltype.typeOf(opaque_handle) == capi.C_TYPE if opaque_handle: cpptemplate = W_CPPTemplateType(space, name, opaque_handle) @@ -236,7 +236,7 @@ self.converters = [converter.get_converter(self.space, arg_type, arg_dflt) for arg_type, arg_dflt in self.arg_defs] self.executor = executor.get_executor( - self.space, capi.c_method_result_type(self.scope, self.index)) + self.space, capi.c_method_result_type(self.space, self.scope, self.index)) for conv in self.converters: if conv.uses_local: @@ -360,7 +360,7 @@ capi.c_deallocate_function_args(args) def signature(self): - return capi.c_method_signature(self.scope, self.index) + return capi.c_method_signature(self.space, self.scope, self.index) def priority(self): total_arg_priority = 0 @@ -411,7 +411,7 @@ s = self.space.str_w(args_w[i]) except OperationError: s = self.space.str_w(self.space.getattr(args_w[i], self.space.wrap('__name__'))) - s = capi.c_resolve_name(s) + s = capi.c_resolve_name(self.space, s) if s != self.templ_args[i]: raise OperationError(self.space.w_TypeError, self.space.wrap( "non-matching template (got %s where %s expected" % (s, self.templ_args[i]))) @@ -661,10 +661,10 @@ methods_temp = {} for i in range(capi.c_num_methods(self)): idx = capi.c_method_index_at(self, i) - pyname = helper.map_operator_name( - capi.c_method_name(self, idx), + pyname = helper.map_operator_name(self.space, + capi.c_method_name(self.space, self, idx), capi.c_method_num_args(self, idx), - capi.c_method_result_type(self, idx)) + capi.c_method_result_type(self.space, self, idx)) cppmethod = self._make_cppfunction(pyname, idx) methods_temp.setdefault(pyname, []).append(cppmethod) # the following covers the case where the only kind of operator[](idx) @@ -685,7 +685,7 @@ self.methods[pyname] = overload def full_name(self): - return capi.c_scoped_final_name(self.handle) + return capi.c_scoped_final_name(self.space, self.handle) def get_method_names(self): return self.space.newlist([self.space.wrap(name) for name in self.methods]) @@ -748,13 +748,13 @@ args_required = capi.c_method_req_args(self, index) arg_defs = [] for i in range(num_args): - arg_type = capi.c_method_arg_type(self, index, i) - arg_dflt = capi.c_method_arg_default(self, index, i) + arg_type = capi.c_method_arg_type(self.space, self, index, i) + arg_dflt = capi.c_method_arg_default(self.space, self, index, i) arg_defs.append((arg_type, arg_dflt)) return CPPFunction(self.space, self, index, arg_defs, args_required) def _make_datamember(self, dm_name, dm_idx): - type_name = capi.c_datamember_type(self, dm_idx) + type_name = capi.c_datamember_type(self.space, self, dm_idx) offset = capi.c_datamember_offset(self, dm_idx) datamember = W_CPPStaticData(self.space, self, type_name, offset) self.datamembers[dm_name] = datamember @@ -765,12 +765,12 @@ for i in range(num_datamembers): if not capi.c_is_publicdata(self, i): continue - datamember_name = capi.c_datamember_name(self, i) + datamember_name = capi.c_datamember_name(self.space, self, i) if not datamember_name in self.datamembers: self._make_datamember(datamember_name, i) def find_overload(self, meth_name): - indices = capi.c_method_indices_from_name(self, meth_name) + indices = capi.c_method_indices_from_name(self.space, self, meth_name) if not indices: raise self.missing_attribute_error(meth_name) cppfunctions = [] @@ -796,17 +796,17 @@ # taken for functions, which need not be unique (overloading). alldir = [] for i in range(capi.c_num_scopes(self.space, self)): - sname = capi.c_scope_name(self, i) + sname = capi.c_scope_name(self.space, self, i) if sname: alldir.append(self.space.wrap(sname)) allmeth = {} for i in range(capi.c_num_methods(self)): idx = capi.c_method_index_at(self, i) - mname = capi.c_method_name(self, idx) + mname = capi.c_method_name(self.space, self, idx) if mname: allmeth.setdefault(mname, 0) for m in allmeth.keys(): alldir.append(self.space.wrap(m)) for i in range(capi.c_num_datamembers(self)): - dname = capi.c_datamember_name(self, i) + dname = capi.c_datamember_name(self.space, self, i) if dname: alldir.append(self.space.wrap(dname)) return self.space.newlist(alldir) @@ -838,15 +838,15 @@ args_required = capi.c_method_req_args(self, index) arg_defs = [] for i in range(num_args): - arg_type = capi.c_method_arg_type(self, index, i) - arg_dflt = capi.c_method_arg_default(self, index, i) + arg_type = capi.c_method_arg_type(self.space, self, index, i) + arg_dflt = capi.c_method_arg_default(self.space, self, index, i) arg_defs.append((arg_type, arg_dflt)) if capi.c_is_constructor(self, index): cppfunction = CPPConstructor(self.space, self, index, arg_defs, args_required) if args_required == 0: self.default_constructor = cppfunction elif capi.c_method_is_template(self, index): - templ_args = capi.c_template_args(self, index) + templ_args = capi.c_template_args(self.space, self, index) cppfunction = CPPTemplatedCall(self.space, templ_args, self, index, arg_defs, args_required) elif capi.c_is_staticmethod(self, index): cppfunction = CPPFunction(self.space, self, index, arg_defs, args_required) @@ -861,8 +861,8 @@ for i in range(num_datamembers): if not capi.c_is_publicdata(self, i): continue - datamember_name = capi.c_datamember_name(self, i) - type_name = capi.c_datamember_type(self, i) + datamember_name = capi.c_datamember_name(self.space, self, i) + type_name = capi.c_datamember_type(self.space, self, i) offset = capi.c_datamember_offset(self, i) is_static = bool(capi.c_is_staticdata(self, i)) if is_static: @@ -891,9 +891,9 @@ def get_base_names(self): bases = [] - num_bases = capi.c_num_bases(self) + num_bases = capi.c_num_bases(self.space, self) for i in range(num_bases): - base_name = capi.c_base_name(self, i) + base_name = capi.c_base_name(self.space, self, i) bases.append(self.space.wrap(base_name)) return self.space.newlist(bases) @@ -1073,7 +1073,7 @@ assert isinstance(self, W_CPPInstance) if self._rawobject and not self.isref: memory_regulator.unregister(self) - capi.c_destruct(self.cppclass, self._rawobject) + capi.c_destruct(self.space, self.cppclass, self._rawobject) self._rawobject = capi.C_NULL_OBJECT def __del__(self): @@ -1127,7 +1127,7 @@ try: w_pycppclass = state.cppclass_registry[handle] except KeyError: - final_name = capi.c_scoped_final_name(handle) + final_name = capi.c_scoped_final_name(space, handle) # the callback will cache the class by calling register_class w_pycppclass = space.call_function(state.w_clgen_callback, space.wrap(final_name)) return w_pycppclass diff --git a/pypy/module/cppyy/test/test_aclassloader.py b/pypy/module/cppyy/test/test_aclassloader.py --- a/pypy/module/cppyy/test/test_aclassloader.py +++ b/pypy/module/cppyy/test/test_aclassloader.py @@ -14,6 +14,10 @@ class AppTestACLASSLOADER: spaceconfig = dict(usemodules=['cppyy']) + def setup_class(cls): + cls.space.appexec([], """(): + import cppyy""") + def test01_class_autoloading(self): """Test whether a class can be found through .rootmap.""" import cppyy diff --git a/pypy/module/cppyy/test/test_helper.py b/pypy/module/cppyy/test/test_helper.py --- a/pypy/module/cppyy/test/test_helper.py +++ b/pypy/module/cppyy/test/test_helper.py @@ -33,20 +33,20 @@ def test_operator_mapping(): - assert helper.map_operator_name("operator[]", 1, "const int&") == "__getitem__" - assert helper.map_operator_name("operator[]", 1, "int&") == "__setitem__" + assert helper.map_operator_name(None, "operator[]", 1, "const int&") == "__getitem__" + assert helper.map_operator_name(None, "operator[]", 1, "int&") == "__setitem__" - assert helper.map_operator_name("operator()", 1, "") == "__call__" - assert helper.map_operator_name("operator%", 1, "") == "__mod__" - assert helper.map_operator_name("operator**", 1, "") == "__pow__" - assert helper.map_operator_name("operator<<", 1, "") == "__lshift__" - assert helper.map_operator_name("operator|", 1, "") == "__or__" + assert helper.map_operator_name(None, "operator()", 1, "") == "__call__" + assert helper.map_operator_name(None, "operator%", 1, "") == "__mod__" + assert helper.map_operator_name(None, "operator**", 1, "") == "__pow__" + assert helper.map_operator_name(None, "operator<<", 1, "") == "__lshift__" + assert helper.map_operator_name(None, "operator|", 1, "") == "__or__" - assert helper.map_operator_name("operator*", 1, "") == "__mul__" - assert helper.map_operator_name("operator*", 0, "") == "__deref__" + assert helper.map_operator_name(None, "operator*", 1, "") == "__mul__" + assert helper.map_operator_name(None, "operator*", 0, "") == "__deref__" - assert helper.map_operator_name("operator+", 1, "") == "__add__" - assert helper.map_operator_name("operator+", 0, "") == "__pos__" + assert helper.map_operator_name(None, "operator+", 1, "") == "__add__" + assert helper.map_operator_name(None, "operator+", 0, "") == "__pos__" - assert helper.map_operator_name("func", 0, "") == "func" - assert helper.map_operator_name("some_method", 0, "") == "some_method" + assert helper.map_operator_name(None, "func", 0, "") == "func" + assert helper.map_operator_name(None, "some_method", 0, "") == "some_method" From noreply at buildbot.pypy.org Fri Apr 5 03:11:15 2013 From: noreply at buildbot.pypy.org (wlav) Date: Fri, 5 Apr 2013 03:11:15 +0200 (CEST) Subject: [pypy-commit] pypy reflex-support: second waypoint towards a loadable capi Message-ID: <20130405011115.C17E51C06BD@cobra.cs.uni-duesseldorf.de> Author: Wim Lavrijsen Branch: reflex-support Changeset: r63042:4fd9f26c848e Date: 2013-04-03 20:57 -0700 http://bitbucket.org/pypy/pypy/changeset/4fd9f26c848e/ Log: second waypoint towards a loadable capi diff --git a/pypy/module/cppyy/capi/__init__.py b/pypy/module/cppyy/capi/__init__.py --- a/pypy/module/cppyy/capi/__init__.py +++ b/pypy/module/cppyy/capi/__init__.py @@ -9,8 +9,8 @@ # the selection of the desired backend (default is Reflex). # choose C-API access method: -#from pypy.module.cppyy.capi.loadable_capi import * -from pypy.module.cppyy.capi.builtin_capi import * +from pypy.module.cppyy.capi.loadable_capi import * +#from pypy.module.cppyy.capi.builtin_capi import * from pypy.module.cppyy.capi.capi_types import C_OBJECT,\ C_NULL_TYPE, C_NULL_OBJECT diff --git a/pypy/module/cppyy/capi/builtin_capi.py b/pypy/module/cppyy/capi/builtin_capi.py --- a/pypy/module/cppyy/capi/builtin_capi.py +++ b/pypy/module/cppyy/capi/builtin_capi.py @@ -191,44 +191,56 @@ threadsafe=ts_reflect, compilation_info=backend.eci, elidable_function=True) -def c_get_methptr_getter(cppscope, index): +def c_get_methptr_getter(space, cppscope, index): return _c_get_methptr_getter(cppscope.handle, index) # handling of function argument buffer --------------------------------------- -c_allocate_function_args = rffi.llexternal( +_c_allocate_function_args = rffi.llexternal( "cppyy_allocate_function_args", [rffi.SIZE_T], rffi.VOIDP, threadsafe=ts_memory, compilation_info=backend.eci) -c_deallocate_function_args = rffi.llexternal( +def c_allocate_function_args(space, size): + return _c_allocate_function_args(size) +_c_deallocate_function_args = rffi.llexternal( "cppyy_deallocate_function_args", [rffi.VOIDP], lltype.Void, threadsafe=ts_memory, compilation_info=backend.eci) -c_function_arg_sizeof = rffi.llexternal( +def c_deallocate_function_args(space, args): + _c_deallocate_function_args(args) +_c_function_arg_sizeof = rffi.llexternal( "cppyy_function_arg_sizeof", [], rffi.SIZE_T, threadsafe=ts_memory, compilation_info=backend.eci, elidable_function=True) -c_function_arg_typeoffset = rffi.llexternal( +def c_function_arg_sizeof(space): + return _c_function_arg_sizeof() +_c_function_arg_typeoffset = rffi.llexternal( "cppyy_function_arg_typeoffset", [], rffi.SIZE_T, threadsafe=ts_memory, compilation_info=backend.eci, elidable_function=True) +def c_function_arg_typeoffset(space): + return _c_function_arg_typeoffset() # scope reflection information ----------------------------------------------- -c_is_namespace = rffi.llexternal( +_c_is_namespace = rffi.llexternal( "cppyy_is_namespace", [C_SCOPE], rffi.INT, threadsafe=ts_reflect, compilation_info=backend.eci) -c_is_enum = rffi.llexternal( +def c_is_namespace(space, scope): + return _c_is_namespace(scope) +_c_is_enum = rffi.llexternal( "cppyy_is_enum", [rffi.CCHARP], rffi.INT, threadsafe=ts_reflect, compilation_info=backend.eci) +def c_is_enum(space, name): + return _c_is_enum(name) # type/class reflection information ------------------------------------------ _c_final_name = rffi.llexternal( @@ -273,7 +285,7 @@ compilation_info=backend.eci, elidable_function=True) @jit.elidable_promote() -def c_is_subtype(derived, base): +def c_is_subtype(space, derived, base): if derived == base: return 1 return _c_is_subtype(derived.handle, base.handle) @@ -285,11 +297,12 @@ compilation_info=backend.eci, elidable_function=True) @jit.elidable_promote() -def c_base_offset(derived, base, address, direction): +def c_base_offset(space, derived, base, address, direction): if derived == base: return 0 return _c_base_offset(derived.handle, base.handle, address, direction) -def c_base_offset1(derived_h, base, address, direction): + at jit.elidable_promote() +def c_base_offset1(space, derived_h, base, address, direction): return _c_base_offset(derived_h, base.handle, address, direction) # method/function reflection information ------------------------------------- @@ -298,14 +311,14 @@ [C_SCOPE], rffi.INT, threadsafe=ts_reflect, compilation_info=backend.eci) -def c_num_methods(cppscope): +def c_num_methods(space, cppscope): return _c_num_methods(cppscope.handle) _c_method_index_at = rffi.llexternal( "cppyy_method_index_at", [C_SCOPE, rffi.INT], C_INDEX, threadsafe=ts_reflect, compilation_info=backend.eci) -def c_method_index_at(cppscope, imethod): +def c_method_index_at(space, cppscope, imethod): return _c_method_index_at(cppscope.handle, imethod) _c_method_indices_from_name = rffi.llexternal( "cppyy_method_indices_from_name", diff --git a/pypy/module/cppyy/capi/loadable_capi.py b/pypy/module/cppyy/capi/loadable_capi.py --- a/pypy/module/cppyy/capi/loadable_capi.py +++ b/pypy/module/cppyy/capi/loadable_capi.py @@ -1,14 +1,13 @@ -import atexit - from rpython.rtyper.lltypesystem import rffi, lltype -from rpython.rlib import jit, rdynload, objectmodel +from rpython.rlib import jit, jit_libffi, rdynload, objectmodel from rpython.tool import leakfinder from pypy.interpreter.error import OperationError +from pypy.module._cffi_backend import ctypefunc, ctypeprim, ctypeptr, misc + from pypy.module.cppyy.capi.capi_types import C_SCOPE, C_TYPE, C_OBJECT,\ - C_METHOD, C_INDEX, C_INDEX_ARRAY, WLAVC_INDEX,\ - C_METHPTRGETTER, C_METHPTRGETTER_PTR + C_METHOD, C_INDEX, C_INDEX_ARRAY, WLAVC_INDEX, C_METHPTRGETTER_PTR import reflex_capi as backend @@ -17,6 +16,69 @@ def identify(): return 'loadable_capi' +class _Arg: # poor man's union + _immutable_ = True + def __init__(self, l = 0, s = '', vp = rffi.cast(rffi.VOIDP, 0) ): + self._long = l + self._string = s + self._voidp = vp + +# For the loadable CAPI, the calls start and end in RPython. Therefore, the standard +# _call of W_CTypeFunc, which expects wrapped objects, does not quite work: some +# vars (e.g. void* equivalent) can not be wrapped, and others (such as rfloat) risk +# rounding problems. This W_RCTypeFun then, takes args, instead of args_w. Note that +# rcall() is a new method, so as to not interfere with the base class call and _call +# when rtyping. It is also called directly (see call_capi below). +class W_RCTypeFunc(ctypefunc.W_CTypeFunc): + @jit.unroll_safe + def rcall(self, funcaddr, args): + assert self.cif_descr + self = jit.promote(self) + # no checking of len(args) needed, as calls in this context are not dynamic + + # The following code is functionally similar to W_CTypeFunc._call, but its + # implementation is tailored to the restricted use (include memory handling) + # of the CAPI calls. + space = self.space + cif_descr = self.cif_descr + size = cif_descr.exchange_size + raw_string = rffi.cast(rffi.CCHARP, 0) # only ever have one in the CAPI + buffer = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') + try: + for i in range(len(args)): + data = rffi.ptradd(buffer, cif_descr.exchange_args[i]) + obj = args[i] + argtype = self.fargs[i] + # the following is clumsy, but the data types used as arguments are + # very limited, so it'll do for now + if isinstance(argtype, ctypeprim.W_CTypePrimitiveSigned): + misc.write_raw_integer_data(data, rffi.cast(rffi.LONG, obj._long), argtype.size) + elif isinstance(argtype, ctypeprim.W_CTypePrimitiveUnsigned): + misc.write_raw_integer_data(data, rffi.cast(rffi.ULONG, obj._long), argtype.size) + elif obj._voidp != rffi.cast(rffi.VOIDP, 0): + data = rffi.cast(rffi.VOIDPP, data) + data[0] = obj._voidp + else: # only other use is sring + n = len(obj._string) + assert raw_string == rffi.cast(rffi.CCHARP, 0) + raw_string = lltype.malloc(rffi.CCHARP.TO, n+1, flavor='raw') + for j in range(n): + raw_string[j] = obj._string[j] + raw_string[n] = '\x00' + data = rffi.cast(rffi.CCHARPP, data) + data[0] = raw_string + + jit_libffi.jit_ffi_call(cif_descr, + rffi.cast(rffi.VOIDP, funcaddr), + buffer) + + resultdata = rffi.ptradd(buffer, cif_descr.exchange_result) + finally: + if raw_string != rffi.cast(rffi.CCHARP, 0): + lltype.free(raw_string, flavor='raw') + lltype.free(buffer, flavor='raw') + return rffi.cast(rffi.LONGP, resultdata) + std_string_name = backend.std_string_name ts_reflect = backend.ts_reflect @@ -54,7 +116,10 @@ c_double = nt.new_primitive_type(space, 'double') c_ccharp = nt.new_pointer_type(space, c_char) - c_voidp = nt.new_primitive_type(space, 'unsigned long') # b/c voidp can not be wrapped + c_index_array = nt.new_primitive_type(space, 'unsigned long') # likewise ... + + c_voidp = nt.new_pointer_type(space, c_void) + c_size_t = nt.new_primitive_type(space, 'size_t') self.capi_call_ifaces = { # name to opaque C++ scope representation @@ -88,23 +153,42 @@ 'constructor' : ([c_method, c_object, c_int, c_voidp], c_object), 'call_o' : ([c_method, c_object, c_int, c_voidp, c_type], c_object), + 'get_methptr_getter' : ([c_scope, c_index], c_voidp), # TODO: verify + + # handling of function argument buffer + 'allocate_function_args' : ([c_size_t], c_voidp), + 'deallocate_function_args' : ([c_voidp], c_void), + 'function_arg_sizeof' : ([], c_size_t), + 'function_arg_typeoffset' : ([], c_size_t), + + # scope reflection information + 'is_namespace' : ([c_scope], c_int), + 'is_enum' : ([c_ccharp], c_int), + # type/class reflection information 'final_name' : ([c_type], c_ccharp), 'scoped_final_name' : ([c_type], c_ccharp), 'has_complex_hierarchy' : ([c_type], c_int), 'num_bases' : ([c_type], c_int), 'base_name' : ([c_type, c_int], c_ccharp), + 'is_subtype' : ([c_type, c_type], c_int), + + 'base_offset' : ([c_type, c_type, c_object, c_int], c_long), # method/function reflection information + 'num_methods' : ([c_scope], c_int), + 'method_index_at' : ([c_scope, c_int], c_index), + 'method_indices_from_name' : ([c_scope, c_ccharp], c_index_array), 'method_name' : ([c_scope, c_index], c_ccharp), 'method_result_type' : ([c_scope, c_index], c_ccharp), + 'method_num_args' : ([c_scope, c_index], c_int), 'method_arg_type' : ([c_scope, c_index, c_int], c_ccharp), 'method_arg_default' : ([c_scope, c_index, c_int], c_ccharp), 'method_signature' : ([c_scope, c_index], c_ccharp), - 'method_template_arg_name' : ([c_scope, c_index, c_index], c_ccharp), + 'method_template_arg_name' : ([c_scope, c_index, c_index], c_ccharp), # data member reflection information 'datamember_name' : ([c_scope, c_int], c_ccharp), @@ -131,7 +215,7 @@ return False return True -def call_capi(space, name, args_w): +def call_capi(space, name, args): state = space.fromcache(State) try: c_call = state.capi_calls[name] @@ -139,216 +223,149 @@ if state.library is None: load_reflection_library(space) iface = state.capi_call_ifaces[name] - from pypy.module._cffi_backend.ctypefunc import W_CTypeFunc - cfunc = W_CTypeFunc(space, iface[0], iface[1], False) + cfunc = W_RCTypeFunc(space, iface[0], iface[1], False) c_call = state.library.load_function(cfunc, 'cppyy_'+name) # TODO: there must be a better way to trick the leakfinder ... if not objectmodel.we_are_translated(): leakfinder.remember_free(c_call.ctype.cif_descr._obj0) state.capi_calls[name] = c_call - return c_call.call(args_w) + return c_call.ctype.rcall(c_call._cdata, args) +def _longptr_to_int(longptr): + return int(rffi.cast(rffi.INTP, longptr)[0]) # name to opaque C++ scope representation ------------------------------------ def c_num_scopes(space, cppscope): - args_w = [space.wrap(cppscope.handle)] - return space.int_w(call_capi(space, 'num_scopes', args_w)) + return call_capi(space, 'num_scopes', [_Arg(l=cppscope.handle)])[0] def c_scope_name(space, cppscope, iscope): - args_w = [space.wrap(cppscope.handle), space.wrap(iscope)] - return charp2str_free(space, call_capi(space, 'scope_name', args_w)) + args = [_Arg(l=cppscope.handle), _Arg(l=iscope)] + return charp2str_free(space, call_capi(space, 'scope_name', args)) def c_resolve_name(space, name): - args_w = [space.wrap(name)] - return charp2str_free(space, call_capi(space, 'resolve_name', args_w)) + return charp2str_free(space, call_capi(space, 'resolve_name', [_Arg(s=name)])) def c_get_scope_opaque(space, name): - args_w = [space.wrap(name)] - return rffi.cast(C_SCOPE, space.int_w(call_capi(space, 'get_scope', args_w))) + return rffi.cast(C_SCOPE, call_capi(space, 'get_scope', [_Arg(s=name)])[0]) def c_get_template(space, name): - args_w = [space.wrap(name)] - return rffi.cast(C_TYPE, space.int_w(call_capi(space, 'get_template', args_w))) + return rffi.cast(C_TYPE, call_capi(space, 'get_template', [_Arg(s=name)])[0]) def c_actual_class(space, cppclass, cppobj): - args_w = [space.wrap(cppclass.handle), space.wrap(cppobj)] - return rffi.cast(C_TYPE, space.int_w(call_capi(space, 'actual_class', args_w))) + args = [_Arg(l=cppclass.handle), _Arg(l=cppobj)] + return rffi.cast(C_TYPE, call_capi(space, 'actual_class', args)[0]) # memory management ---------------------------------------------------------- def c_allocate(space, cppclass): - args_w = [space.wrap(cppclass.handle)] - return rffi.cast(C_OBJECT, space.int_w(call_capi(space, 'allocate', args_w))) + return rffi.cast(C_OBJECT, call_capi(space, 'allocate', [_Arg(l=cppclass.handle)])[0]) def c_deallocate(space, cppclass, cppobject): - args_w = [space.wrap(cppclass.handle), space.wrap(cppobject)] - call_capi(space, 'deallocate', args_w) + call_capi(space, 'deallocate', [_Arg(l=cppclass.handle), _Arg(l=cppobject)]) def c_destruct(space, cppclass, cppobject): - args_w = [space.wrap(cppclass.handle), space.wrap(cppobject)] - call_capi(space, 'destruct', args_w) + call_capi(space, 'destruct', [_Arg(l=cppclass.handle), _Arg(l=cppobject)]) # method/function dispatching ------------------------------------------------ -def c_call_v(space, cppmethod, cppobject, nargs, args): - args_w = [space.wrap(cppmethod), space.wrap(cppobject), - space.wrap(nargs), space.wrap(rffi.cast(rffi.ULONG, args))] - call_capi(space, 'call_v', args_w) -# TODO: these method do not actually need unwrapping, as the excutors simply -# wrap the values again, but the other backends expect that ... -def c_call_b(space, cppmethod, cppobject, nargs, args): - args_w = [space.wrap(cppmethod), space.wrap(cppobject), - space.wrap(nargs), space.wrap(rffi.cast(rffi.ULONG, args))] - return rffi.cast(rffi.UCHAR, space.int_w(call_capi(space, 'call_b', args_w))) -def c_call_c(space, cppmethod, cppobject, nargs, args): - args_w = [space.wrap(cppmethod), space.wrap(cppobject), - space.wrap(nargs), space.wrap(rffi.cast(rffi.ULONG, args))] - return rffi.cast(rffi.CHAR, space.str_w(call_capi(space, 'call_c', args_w))) -def c_call_h(space, cppmethod, cppobject, nargs, args): - args_w = [space.wrap(cppmethod), space.wrap(cppobject), - space.wrap(nargs), space.wrap(rffi.cast(rffi.ULONG, args))] - return rffi.cast(rffi.SHORT, space.int_w(call_capi(space, 'call_h', args_w))) -def c_call_i(space, cppmethod, cppobject, nargs, args): - args_w = [space.wrap(cppmethod), space.wrap(cppobject), - space.wrap(nargs), space.wrap(rffi.cast(rffi.ULONG, args))] - return rffi.cast(rffi.INT, space.int_w(call_capi(space, 'call_i', args_w))) -def c_call_l(space, cppmethod, cppobject, nargs, args): - args_w = [space.wrap(cppmethod), space.wrap(cppobject), - space.wrap(nargs), space.wrap(rffi.cast(rffi.ULONG, args))] - return rffi.cast(rffi.LONG, space.int_w(call_capi(space, 'call_l', args_w))) -def c_call_ll(space, cppmethod, cppobject, nargs, args): - args_w = [space.wrap(cppmethod), space.wrap(cppobject), - space.wrap(nargs), space.wrap(rffi.cast(rffi.ULONG, args))] - return rffi.cast(rffi.LONGLONG, space.int_w(call_capi(space, 'call_ll', args_w))) -def c_call_f(space, cppmethod, cppobject, nargs, args): - args_w = [space.wrap(cppmethod), space.wrap(cppobject), - space.wrap(nargs), space.wrap(rffi.cast(rffi.ULONG, args))] - return rffi.cast(rffi.FLOAT, space.float_w(call_capi(space, 'call_f', args_w))) -def c_call_d(space, cppmethod, cppobject, nargs, args): - args_w = [space.wrap(cppmethod), space.wrap(cppobject), - space.wrap(nargs), space.wrap(rffi.cast(rffi.ULONG, args))] - return rffi.cast(rffi.DOUBLE, space.float_w(call_capi(space, 'call_d', args_w))) +def c_call_v(space, cppmethod, cppobject, nargs, cargs): + args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)] + call_capi(space, 'call_v', args) +def c_call_b(space, cppmethod, cppobject, nargs, cargs): + args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)] + return rffi.cast(rffi.UCHARP, call_capi(space, 'call_b', args))[0] +def c_call_c(space, cppmethod, cppobject, nargs, cargs): + args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)] + return rffi.cast(rffi.CCHARP, call_capi(space, 'call_c', args))[0] +def c_call_h(space, cppmethod, cppobject, nargs, cargs): + args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)] + return rffi.cast(rffi.SHORTP, call_capi(space, 'call_h', args))[0] +def c_call_i(space, cppmethod, cppobject, nargs, cargs): + args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)] + return rffi.cast(rffi.INTP, call_capi(space, 'call_i', args))[0] +def c_call_l(space, cppmethod, cppobject, nargs, cargs): + args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)] + return rffi.cast(rffi.LONGP, call_capi(space, 'call_l', args))[0] +def c_call_ll(space, cppmethod, cppobject, nargs, cargs): + args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)] + return rffi.cast(rffi.LONGLONGP, call_capi(space, 'call_ll', args))[0] +def c_call_f(space, cppmethod, cppobject, nargs, cargs): + args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)] + return rffi.cast(rffi.FLOATP, call_capi(space, 'call_f', args))[0] +def c_call_d(space, cppmethod, cppobject, nargs, cargs): + args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)] + return rffi.cast(rffi.DOUBLEP, call_capi(space, 'call_d', args))[0] -def c_call_r(space, cppmethod, cppobject, nargs, args): - args_w = [space.wrap(cppmethod), space.wrap(cppobject), - space.wrap(nargs), space.wrap(rffi.cast(rffi.ULONG, args))] - return rffi.cast(rffi.VOIDP, space.int_w(call_capi(space, 'call_r', args_w))) -def c_call_s(space, cppmethod, cppobject, nargs, args): - args_w = [space.wrap(cppmethod), space.wrap(cppobject), - space.wrap(nargs), space.wrap(rffi.cast(rffi.ULONG, args))] - return call_capi(space, 'call_s', args_w) +def c_call_r(space, cppmethod, cppobject, nargs, cargs): + args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)] + return rffi.cast(rffi.VOIDPP, call_capi(space, 'call_r', args))[0] +def c_call_s(space, cppmethod, cppobject, nargs, cargs): + args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)] + return call_capi(space, 'call_s', args) -def c_constructor(space, cppmethod, cppobject, nargs, args): - args_w = [space.wrap(cppmethod), space.wrap(cppobject), - space.wrap(nargs), space.wrap(rffi.cast(rffi.ULONG, args))] - return rffi.cast(C_OBJECT, space.int_w(call_capi(space, 'constructor', args_w))) -def c_call_o(space, cppmethod, cppobject, nargs, args, cppclass): - args_w = [space.wrap(cppmethod), space.wrap(cppobject), - space.wrap(nargs), space.wrap(rffi.cast(rffi.ULONG, args)), - space.wrap(cppclass.handle)] - return rffi.cast(C_OBJECT, space.int_w(call_capi(space, 'call_o', args_w))) +def c_constructor(space, cppmethod, cppobject, nargs, cargs): + args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)] + return rffi.cast(C_OBJECT, call_capi(space, 'constructor', args)[0]) +def c_call_o(space, cppmethod, cppobject, nargs, cargs, cppclass): + args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs), _Arg(l=cppclass.handle)] + return rffi.cast(C_OBJECT, call_capi(space, 'call_o', args)[0]) -_c_get_methptr_getter = rffi.llexternal( - "cppyy_get_methptr_getter", - [C_SCOPE, C_INDEX], C_METHPTRGETTER_PTR, - threadsafe=ts_reflect, - compilation_info=backend.eci, - elidable_function=True) -def c_get_methptr_getter(cppscope, index): - return _c_get_methptr_getter(cppscope.handle, index) + at jit.elidable_promote() +def c_get_methptr_getter(space, cppscope, index): + args = [_Arg(l=cppscope.handle), _Arg(l=index)] + return rffi.cast(C_METHPTRGETTER_PTR, call_capi(space, 'get_methptr_getter', args)[0]) # handling of function argument buffer --------------------------------------- -c_allocate_function_args = rffi.llexternal( - "cppyy_allocate_function_args", - [rffi.SIZE_T], rffi.VOIDP, - threadsafe=ts_memory, - compilation_info=backend.eci) -c_deallocate_function_args = rffi.llexternal( - "cppyy_deallocate_function_args", - [rffi.VOIDP], lltype.Void, - threadsafe=ts_memory, - compilation_info=backend.eci) -c_function_arg_sizeof = rffi.llexternal( - "cppyy_function_arg_sizeof", - [], rffi.SIZE_T, - threadsafe=ts_memory, - compilation_info=backend.eci, - elidable_function=True) -c_function_arg_typeoffset = rffi.llexternal( - "cppyy_function_arg_typeoffset", - [], rffi.SIZE_T, - threadsafe=ts_memory, - compilation_info=backend.eci, - elidable_function=True) +def c_allocate_function_args(space, size): + return rffi.cast(rffi.VOIDP, call_capi(space, 'allocate_function_args', [_Arg(l=size)])[0]) +def c_deallocate_function_args(space, cargs): + call_capi(space, 'deallocate_function_args', [_Arg(vp=cargs)]) + at jit.elidable_promote() +def c_function_arg_sizeof(space): + return rffi.cast(rffi.SIZE_T, call_capi(space, 'function_arg_sizeof', [])[0]) + at jit.elidable_promote() +def c_function_arg_typeoffset(space): + return rffi.cast(rffi.SIZE_T, call_capi(space, 'function_arg_typeoffset', [])[0]) # scope reflection information ----------------------------------------------- -c_is_namespace = rffi.llexternal( - "cppyy_is_namespace", - [C_SCOPE], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -c_is_enum = rffi.llexternal( - "cppyy_is_enum", - [rffi.CCHARP], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) +def c_is_namespace(space, scope): + return _longptr_to_int(call_capi(space, 'is_namespace', [_Arg(l=scope)])) +def c_is_enum(space, name): + return _longptr_to_int(call_capi(space, 'is_enum', [_Arg(s=name)])) # type/class reflection information ------------------------------------------ def c_final_name(space, cpptype): - args_w = [space.wrap(cpptype)] - return charp2str_free(space, call_capi(space, 'final_name', args_w)) + return charp2str_free(space, call_capi(space, 'final_name', [_Arg(l=cpptype)])) def c_scoped_final_name(space, cpptype): - args_w = [space.wrap(cpptype)] - return charp2str_free(space, call_capi(space, 'scoped_final_name', args_w)) + return charp2str_free(space, call_capi(space, 'scoped_final_name', [_Arg(l=cpptype)])) def c_has_complex_hierarchy(space, handle): - args_w = [space.wrap(handle)] - return space.int_w(call_capi(space, 'has_complex_hierarchy', args_w)) + return _longptr_to_int(call_capi(space, 'has_complex_hierarchy', [_Arg(l=handle)])) def c_num_bases(space, cppclass): - args_w = [space.wrap(cppclass.handle)] - return space.int_w(call_capi(space, 'num_bases', args_w)) + return _longptr_to_int(call_capi(space, 'num_bases', [_Arg(l=cppclass.handle)])) def c_base_name(space, cppclass, base_index): - args_w = [space.wrap(cppclass.handle), space.wrap(base_index)] - return charp2str_free(space, call_capi(space, 'base_name', args_w)) -_c_is_subtype = rffi.llexternal( - "cppyy_is_subtype", - [C_TYPE, C_TYPE], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci, - elidable_function=True) + args = [_Arg(l=cppclass.handle), _Arg(l=base_index)] + return charp2str_free(space, call_capi(space, 'base_name', args)) @jit.elidable_promote() -def c_is_subtype(derived, base): +def c_is_subtype(space, derived, base): if derived == base: return 1 - return _c_is_subtype(derived.handle, base.handle) + return _longptr_to_int(call_capi(space, 'is_subtype', [_Arg(l=derived.handle), _Arg(l=base.handle)])) -_c_base_offset = rffi.llexternal( - "cppyy_base_offset", - [C_TYPE, C_TYPE, C_OBJECT, rffi.INT], rffi.SIZE_T, - threadsafe=ts_reflect, - compilation_info=backend.eci, - elidable_function=True) @jit.elidable_promote() -def c_base_offset(derived, base, address, direction): +def _c_base_offset(space, derived_h, base_h, address, direction): + args = [_Arg(l=derived_h), _Arg(l=base_h), _Arg(l=address), _Arg(l=direction)] + return rffi.cast(rffi.SIZE_T, rffi.cast(rffi.ULONGP, call_capi(space, 'base_offset', args))[0]) + at jit.elidable_promote() +def c_base_offset(space, derived, base, address, direction): if derived == base: return 0 - return _c_base_offset(derived.handle, base.handle, address, direction) -def c_base_offset1(derived_h, base, address, direction): - return _c_base_offset(derived_h, base.handle, address, direction) + return _c_base_offset(space, derived.handle, base.handle, address, direction) + at jit.elidable_promote() +def c_base_offset1(space, derived_h, base, address, direction): + return _c_base_offset(space, derived_h, base.handle, address, direction) # method/function reflection information ------------------------------------- -_c_num_methods = rffi.llexternal( - "cppyy_num_methods", - [C_SCOPE], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_num_methods(cppscope): - return _c_num_methods(cppscope.handle) -_c_method_index_at = rffi.llexternal( - "cppyy_method_index_at", - [C_SCOPE, rffi.INT], C_INDEX, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_index_at(cppscope, imethod): - return _c_method_index_at(cppscope.handle, imethod) -_c_method_indices_from_name = rffi.llexternal( - "cppyy_method_indices_from_name", - [C_SCOPE, rffi.CCHARP], C_INDEX_ARRAY, - threadsafe=ts_reflect, - compilation_info=backend.eci) +def c_num_methods(space, cppscope): + args = [_Arg(l=cppscope.handle)] + return _longptr_to_int(call_capi(space, 'num_methods', args)) +def c_method_index_at(space, cppscope, imethod): + args = [_Arg(l=cppscope.handle), _Arg(l=imethod)] + return call_capi(space, 'method_index_at', args)[0] def c_method_indices_from_name(space, cppscope, name): - indices = _c_method_indices_from_name(cppscope.handle, name) + args = [_Arg(l=cppscope.handle), _Arg(s=name)] + indices = rffi.cast(C_INDEX_ARRAY, call_capi(space, 'method_indices_from_name', args)[0]) if not indices: return [] py_indices = [] @@ -362,17 +379,18 @@ return py_indices def c_method_name(space, cppscope, index): - args_w = [space.wrap(cppscope.handle), space.wrap(index)] - return charp2str_free(space, call_capi(space, 'method_name', args_w)) + args = [_Arg(l=cppscope.handle), _Arg(l=index)] + return charp2str_free(space, call_capi(space, 'method_name', args)) def c_method_result_type(space, cppscope, index): - args_w = [space.wrap(cppscope.handle), space.wrap(index)] - return charp2str_free(space, call_capi(space, 'method_result_type', args_w)) + args = [_Arg(l=cppscope.handle), _Arg(l=index)] + return charp2str_free(space, call_capi(space, 'method_result_type', args)) _c_method_num_args = rffi.llexternal( "cppyy_method_num_args", [C_SCOPE, C_INDEX], rffi.INT, threadsafe=ts_reflect, compilation_info=backend.eci) def c_method_num_args(cppscope, index): + args = [_Arg(l=cppscope.handle), _Arg(l=index)] return _c_method_num_args(cppscope.handle, index) _c_method_req_args = rffi.llexternal( "cppyy_method_req_args", @@ -382,14 +400,14 @@ def c_method_req_args(cppscope, index): return _c_method_req_args(cppscope.handle, index) def c_method_arg_type(space, cppscope, index, arg_index): - args_w = [space.wrap(cppscope.handle), space.wrap(index), space.wrap(arg_index)] - return charp2str_free(space, call_capi(space, 'method_arg_type', args_w)) + args = [_Arg(l=cppscope.handle), _Arg(l=index), _Arg(l=arg_index)] + return charp2str_free(space, call_capi(space, 'method_arg_type', args)) def c_method_arg_default(space, cppscope, index, arg_index): - args_w = [space.wrap(cppscope.handle), space.wrap(index), space.wrap(arg_index)] - return charp2str_free(space, call_capi(space, 'method_arg_default', args_w)) + args = [_Arg(l=cppscope.handle), _Arg(l=index), _Arg(l=arg_index)] + return charp2str_free(space, call_capi(space, 'method_arg_default', args)) def c_method_signature(space, cppscope, index): - args_w = [space.wrap(cppscope.handle), space.wrap(index)] - return charp2str_free(space, call_capi(space, 'method_signature', args_w)) + args = [_Arg(l=cppscope.handle), _Arg(l=index)] + return charp2str_free(space, call_capi(space, 'method_signature', args)) _c_method_is_template = rffi.llexternal( "cppyy_method_is_template", @@ -403,17 +421,12 @@ [C_SCOPE, C_INDEX], rffi.INT, threadsafe=ts_reflect, compilation_info=backend.eci) -_c_method_template_arg_name = rffi.llexternal( - "cppyy_method_template_arg_name", - [C_SCOPE, C_INDEX, C_INDEX], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) def c_template_args(space, cppscope, index): nargs = _c_method_num_template_args(cppscope.handle, index) + arg1 = _Arg(l=cppscope.handle) + arg2 = _Arg(l=index) args = [c_resolve_name(space, charp2str_free(space, - call_capi(space, 'method_template_arg_name', - [space.wrap(cppscope.handle), space.wrap(index), space.wrap(iarg)]) - ) + call_capi(space, 'method_template_arg_name', [arg1, arg2, _Arg(l=iarg)])) ) for iarg in range(nargs)] return args @@ -464,16 +477,16 @@ threadsafe=ts_reflect, compilation_info=backend.eci) def c_datamember_name(space, cppscope, datamember_index): - args_w = [space.wrap(cppscope.handle), space.wrap(datamember_index)] - return charp2str_free(space, call_capi(space, 'datamember_name', args_w)) + args = [_Arg(l=cppscope.handle), _Arg(l=datamember_index)] + return charp2str_free(space, call_capi(space, 'datamember_name', args)) _c_datamember_type = rffi.llexternal( "cppyy_datamember_type", [C_SCOPE, rffi.INT], rffi.CCHARP, threadsafe=ts_reflect, compilation_info=backend.eci) def c_datamember_type(space, cppscope, datamember_index): - args_w = [space.wrap(cppscope.handle), space.wrap(datamember_index)] - return charp2str_free(space, call_capi(space, 'datamember_type', args_w)) + args = [_Arg(l=cppscope.handle), _Arg(l=datamember_index)] + return charp2str_free(space, call_capi(space, 'datamember_type', args)) _c_datamember_offset = rffi.llexternal( "cppyy_datamember_offset", [C_SCOPE, rffi.INT], rffi.SIZE_T, @@ -518,14 +531,12 @@ threadsafe=ts_helper, compilation_info=backend.eci) def c_free(space, voidp): - args_w = [space.wrap(rffi.cast(rffi.ULONG, voidp))] - call_capi(space, 'free', args_w) + call_capi(space, 'free', [_Arg(vp=voidp)]) def charp2str_free(space, cdata): - charp = rffi.cast(rffi.CCHARP, cdata._cdata) + charp = rffi.cast(rffi.CCHARPP, cdata)[0] pystr = rffi.charp2str(charp) - voidp = rffi.cast(rffi.VOIDP, charp) - c_free(space, voidp) + c_free(space, rffi.cast(rffi.VOIDP, charp)) return pystr c_charp2stdstring = rffi.llexternal( diff --git a/pypy/module/cppyy/converter.py b/pypy/module/cppyy/converter.py --- a/pypy/module/cppyy/converter.py +++ b/pypy/module/cppyy/converter.py @@ -178,7 +178,7 @@ raise OperationError(space.w_TypeError, space.wrap("raw buffer interface not supported")) ba = rffi.cast(rffi.CCHARP, address) - ba[capi.c_function_arg_typeoffset()] = 'o' + ba[capi.c_function_arg_typeoffset(space)] = 'o' def from_memory(self, space, w_obj, w_pycppclass, offset): # read access, so no copy needed @@ -249,7 +249,7 @@ x = rffi.cast(self.c_ptrtype, address) x[0] = self._unwrap_object(space, w_obj) ba = rffi.cast(rffi.CCHARP, address) - ba[capi.c_function_arg_typeoffset()] = self.typecode + ba[capi.c_function_arg_typeoffset(space)] = self.typecode class VoidConverter(TypeConverter): @@ -352,7 +352,7 @@ arg = space.str_w(w_obj) x[0] = rffi.cast(rffi.LONG, rffi.str2charp(arg)) ba = rffi.cast(rffi.CCHARP, address) - ba[capi.c_function_arg_typeoffset()] = 'o' + ba[capi.c_function_arg_typeoffset(space)] = 'o' def from_memory(self, space, w_obj, w_pycppclass, offset): address = self._get_raw_address(space, w_obj, offset) @@ -379,7 +379,7 @@ x = rffi.cast(rffi.VOIDPP, address) x[0] = self._unwrap_object(space, w_obj) ba = rffi.cast(rffi.CCHARP, address) - ba[capi.c_function_arg_typeoffset()] = 'o' + ba[capi.c_function_arg_typeoffset(space)] = 'o' def convert_argument_libffi(self, space, w_obj, address, call_local): x = rffi.cast(rffi.VOIDPP, address) @@ -399,7 +399,7 @@ except TypeError: r[0] = rffi.cast(rffi.VOIDP, get_rawobject(space, w_obj)) x[0] = rffi.cast(rffi.VOIDP, call_local) - ba[capi.c_function_arg_typeoffset()] = 'a' + ba[capi.c_function_arg_typeoffset(space)] = 'a' def finalize_call(self, space, w_obj, call_local): r = rffi.cast(rffi.VOIDPP, call_local) @@ -425,9 +425,9 @@ def _unwrap_object(self, space, w_obj): from pypy.module.cppyy.interp_cppyy import W_CPPInstance if isinstance(w_obj, W_CPPInstance): - if capi.c_is_subtype(w_obj.cppclass, self.cppclass): + if capi.c_is_subtype(space, w_obj.cppclass, self.cppclass): rawobject = w_obj.get_rawobject() - offset = capi.c_base_offset(w_obj.cppclass, self.cppclass, rawobject, 1) + offset = capi.c_base_offset(space, w_obj.cppclass, self.cppclass, rawobject, 1) obj_address = capi.direct_ptradd(rawobject, offset) return rffi.cast(capi.C_OBJECT, obj_address) raise OperationError(space.w_TypeError, @@ -439,7 +439,7 @@ x[0] = rffi.cast(rffi.VOIDP, self._unwrap_object(space, w_obj)) address = rffi.cast(capi.C_OBJECT, address) ba = rffi.cast(rffi.CCHARP, address) - ba[capi.c_function_arg_typeoffset()] = 'o' + ba[capi.c_function_arg_typeoffset(space)] = 'o' def convert_argument_libffi(self, space, w_obj, address, call_local): x = rffi.cast(rffi.VOIDPP, address) @@ -481,7 +481,7 @@ x[0] = rffi.cast(rffi.VOIDP, call_local) address = rffi.cast(capi.C_OBJECT, address) ba = rffi.cast(rffi.CCHARP, address) - ba[capi.c_function_arg_typeoffset()] = 'o' + ba[capi.c_function_arg_typeoffset(space)] = 'o' def convert_argument_libffi(self, space, w_obj, address, call_local): # TODO: finalize_call not yet called for fast call (see interp_cppyy.py) @@ -556,7 +556,7 @@ x = rffi.cast(rffi.VOIDPP, address) x[0] = rffi.cast(rffi.VOIDP, ref) ba = rffi.cast(rffi.CCHARP, address) - ba[capi.c_function_arg_typeoffset()] = 'a' + ba[capi.c_function_arg_typeoffset(space)] = 'a' def convert_argument_libffi(self, space, w_obj, address, call_local): # TODO: free_argument not yet called for fast call (see interp_cppyy.py) @@ -638,7 +638,7 @@ return InstancePtrPtrConverter(space, cppclass) elif compound == "": return InstanceConverter(space, cppclass) - elif capi.c_is_enum(clean_name): + elif capi.c_is_enum(space, clean_name): return _converters['unsigned'](space, default) # 5) void converter, which fails on use @@ -711,7 +711,7 @@ x = rffi.cast(self.c_ptrtype, address) x[0] = self._unwrap_object(space, w_obj) ba = rffi.cast(rffi.CCHARP, address) - ba[capi.c_function_arg_typeoffset()] = self.typecode + ba[capi.c_function_arg_typeoffset(space)] = self.typecode for name in names: _converters[name] = BasicConverter _converters["const "+name+"&"] = ConstRefConverter diff --git a/pypy/module/cppyy/executor.py b/pypy/module/cppyy/executor.py --- a/pypy/module/cppyy/executor.py +++ b/pypy/module/cppyy/executor.py @@ -200,8 +200,8 @@ class StdStringExecutor(InstancePtrExecutor): def execute(self, space, cppmethod, cppthis, num_args, args): - charp_result = capi.c_call_s(space, cppmethod, cppthis, num_args, args) - return space.wrap(capi.charp2str_free(space, charp_result)) + cstr_result = capi.c_call_s(space, cppmethod, cppthis, num_args, args) + return space.wrap(capi.charp2str_free(space, cstr_result)) def execute_libffi(self, space, cif_descr, funcaddr, buffer): from pypy.module.cppyy.interp_cppyy import FastCallNotPossible @@ -281,7 +281,7 @@ return InstancePtrExecutor(space, cppclass) elif compound == '**' or compound == '*&': return InstancePtrPtrExecutor(space, cppclass) - elif capi.c_is_enum(clean_name): + elif capi.c_is_enum(space, clean_name): return _executors['unsigned int'](space, None) # 4) additional special cases diff --git a/pypy/module/cppyy/interp_cppyy.py b/pypy/module/cppyy/interp_cppyy.py --- a/pypy/module/cppyy/interp_cppyy.py +++ b/pypy/module/cppyy/interp_cppyy.py @@ -62,7 +62,7 @@ assert lltype.typeOf(opaque_handle) == capi.C_SCOPE if opaque_handle: final_name = capi.c_final_name(space, opaque_handle) - if capi.c_is_namespace(opaque_handle): + if capi.c_is_namespace(space, opaque_handle): cppscope = W_CPPNamespace(space, final_name, opaque_handle) elif capi.c_has_complex_hierarchy(space, opaque_handle): cppscope = W_ComplexCPPClass(space, final_name, opaque_handle) @@ -246,7 +246,7 @@ # Each CPPMethod corresponds one-to-one to a C++ equivalent and cppthis # has been offset to the matching class. Hence, the libffi pointer is # uniquely defined and needs to be setup only once. - methgetter = capi.c_get_methptr_getter(self.scope, self.index) + methgetter = capi.c_get_methptr_getter(self.space, self.scope, self.index) if methgetter and cppthis: # methods only for now cif_descr = lltype.nullptr(jit_libffi.CIF_DESCRIPTION) try: @@ -328,8 +328,8 @@ @jit.unroll_safe def prepare_arguments(self, args_w, call_local): - args = capi.c_allocate_function_args(len(args_w)) - stride = capi.c_function_arg_sizeof() + args = capi.c_allocate_function_args(self.space, len(args_w)) + stride = capi.c_function_arg_sizeof(self.space) for i in range(len(args_w)): conv = self.converters[i] w_arg = args_w[i] @@ -344,20 +344,20 @@ arg_j = lltype.direct_ptradd(rffi.cast(rffi.CCHARP, args), j*stride) loc_j = self._address_from_local_buffer(call_local, j) conv.free_argument(self.space, rffi.cast(capi.C_OBJECT, arg_j), loc_j) - capi.c_deallocate_function_args(args) + capi.c_deallocate_function_args(self.space, args) raise return args @jit.unroll_safe def finalize_call(self, args, args_w, call_local): - stride = capi.c_function_arg_sizeof() + stride = capi.c_function_arg_sizeof(self.space) for i in range(len(args_w)): conv = self.converters[i] arg_i = lltype.direct_ptradd(rffi.cast(rffi.CCHARP, args), i*stride) loc_i = self._address_from_local_buffer(call_local, i) conv.finalize_call(self.space, args_w[i], loc_i) conv.free_argument(self.space, rffi.cast(capi.C_OBJECT, arg_i), loc_i) - capi.c_deallocate_function_args(args) + capi.c_deallocate_function_args(self.space, args) def signature(self): return capi.c_method_signature(self.space, self.scope, self.index) @@ -584,7 +584,7 @@ def _get_offset(self, cppinstance): if cppinstance: assert lltype.typeOf(cppinstance.cppclass.handle) == lltype.typeOf(self.scope.handle) - offset = self.offset + capi.c_base_offset( + offset = self.offset + capi.c_base_offset(self.space, cppinstance.cppclass, self.scope, cppinstance.get_rawobject(), 1) else: offset = self.offset @@ -659,8 +659,8 @@ def _build_methods(self): assert len(self.methods) == 0 methods_temp = {} - for i in range(capi.c_num_methods(self)): - idx = capi.c_method_index_at(self, i) + for i in range(capi.c_num_methods(self.space, self)): + idx = capi.c_method_index_at(self.space, self, i) pyname = helper.map_operator_name(self.space, capi.c_method_name(self.space, self, idx), capi.c_method_num_args(self, idx), @@ -799,8 +799,8 @@ sname = capi.c_scope_name(self.space, self, i) if sname: alldir.append(self.space.wrap(sname)) allmeth = {} - for i in range(capi.c_num_methods(self)): - idx = capi.c_method_index_at(self, i) + for i in range(capi.c_num_methods(self.space, self)): + idx = capi.c_method_index_at(self.space, self, i) mname = capi.c_method_name(self.space, self, idx) if mname: allmeth.setdefault(mname, 0) for m in allmeth.keys(): @@ -915,7 +915,8 @@ def get_cppthis(self, cppinstance, calling_scope): assert self == cppinstance.cppclass - offset = capi.c_base_offset(self, calling_scope, cppinstance.get_rawobject(), 1) + offset = capi.c_base_offset(self.space, + self, calling_scope, cppinstance.get_rawobject(), 1) return capi.direct_ptradd(cppinstance.get_rawobject(), offset) W_ComplexCPPClass.typedef = TypeDef( @@ -1143,7 +1144,7 @@ if actual != cppclass.handle: try: w_pycppclass = get_pythonized_cppclass(space, actual) - offset = capi.c_base_offset1(actual, cppclass, rawobject, -1) + offset = capi.c_base_offset1(space, actual, cppclass, rawobject, -1) rawobject = capi.direct_ptradd(rawobject, offset) w_cppclass = space.findattr(w_pycppclass, space.wrap("_cpp_proxy")) cppclass = space.interp_w(W_CPPClass, w_cppclass, can_be_None=False) @@ -1164,7 +1165,7 @@ # fresh creation w_cppinstance = space.allocate_instance(W_CPPInstance, w_pycppclass) - cppinstance = space.interp_w(W_CPPInstance, w_cppinstance) + cppinstance = space.interp_w(W_CPPInstance, w_cppinstance, can_be_None=False) cppinstance.__init__(space, cppclass, rawobject, is_ref, python_owns) memory_regulator.register(cppinstance) return w_cppinstance From noreply at buildbot.pypy.org Fri Apr 5 03:11:16 2013 From: noreply at buildbot.pypy.org (wlav) Date: Fri, 5 Apr 2013 03:11:16 +0200 (CEST) Subject: [pypy-commit] pypy reflex-support: third waypoint; loadable capi now works, but not yet set as default Message-ID: <20130405011116.E38FB1C06BD@cobra.cs.uni-duesseldorf.de> Author: Wim Lavrijsen Branch: reflex-support Changeset: r63043:2694840763c7 Date: 2013-04-04 14:37 -0700 http://bitbucket.org/pypy/pypy/changeset/2694840763c7/ Log: third waypoint; loadable capi now works, but not yet set as default diff --git a/pypy/module/cppyy/capi/__init__.py b/pypy/module/cppyy/capi/__init__.py --- a/pypy/module/cppyy/capi/__init__.py +++ b/pypy/module/cppyy/capi/__init__.py @@ -9,8 +9,8 @@ # the selection of the desired backend (default is Reflex). # choose C-API access method: -from pypy.module.cppyy.capi.loadable_capi import * -#from pypy.module.cppyy.capi.builtin_capi import * +#from pypy.module.cppyy.capi.loadable_capi import * +from pypy.module.cppyy.capi.builtin_capi import * from pypy.module.cppyy.capi.capi_types import C_OBJECT,\ C_NULL_TYPE, C_NULL_OBJECT diff --git a/pypy/module/cppyy/capi/builtin_capi.py b/pypy/module/cppyy/capi/builtin_capi.py --- a/pypy/module/cppyy/capi/builtin_capi.py +++ b/pypy/module/cppyy/capi/builtin_capi.py @@ -358,14 +358,14 @@ [C_SCOPE, C_INDEX], rffi.INT, threadsafe=ts_reflect, compilation_info=backend.eci) -def c_method_num_args(cppscope, index): +def c_method_num_args(space, cppscope, index): return _c_method_num_args(cppscope.handle, index) _c_method_req_args = rffi.llexternal( "cppyy_method_req_args", [C_SCOPE, C_INDEX], rffi.INT, threadsafe=ts_reflect, compilation_info=backend.eci) -def c_method_req_args(cppscope, index): +def c_method_req_args(space, cppscope, index): return _c_method_req_args(cppscope.handle, index) _c_method_arg_type = rffi.llexternal( "cppyy_method_arg_type", @@ -394,7 +394,7 @@ [C_SCOPE, C_INDEX], rffi.INT, threadsafe=ts_reflect, compilation_info=backend.eci) -def c_method_is_template(cppscope, index): +def c_method_is_template(space, cppscope, index): return _c_method_is_template(cppscope.handle, index) _c_method_num_template_args = rffi.llexternal( "cppyy_method_num_template_args", @@ -418,14 +418,14 @@ [C_SCOPE, C_INDEX], C_METHOD, threadsafe=ts_reflect, compilation_info=backend.eci) -def c_get_method(cppscope, index): +def c_get_method(space, cppscope, index): return _c_get_method(cppscope.handle, index) _c_get_global_operator = rffi.llexternal( "cppyy_get_global_operator", [C_SCOPE, C_SCOPE, C_SCOPE, rffi.CCHARP], WLAVC_INDEX, threadsafe=ts_reflect, compilation_info=backend.eci) -def c_get_global_operator(nss, lc, rc, op): +def c_get_global_operator(space, nss, lc, rc, op): if nss is not None: return _c_get_global_operator(nss.handle, lc.handle, rc.handle, op) return rffi.cast(WLAVC_INDEX, -1) @@ -436,14 +436,14 @@ [C_TYPE, C_INDEX], rffi.INT, threadsafe=ts_reflect, compilation_info=backend.eci) -def c_is_constructor(cppclass, index): +def c_is_constructor(space, cppclass, index): return _c_is_constructor(cppclass.handle, index) _c_is_staticmethod = rffi.llexternal( "cppyy_is_staticmethod", [C_TYPE, C_INDEX], rffi.INT, threadsafe=ts_reflect, compilation_info=backend.eci) -def c_is_staticmethod(cppclass, index): +def c_is_staticmethod(space, cppclass, index): return _c_is_staticmethod(cppclass.handle, index) # data member reflection information ----------------------------------------- @@ -452,7 +452,7 @@ [C_SCOPE], rffi.INT, threadsafe=ts_reflect, compilation_info=backend.eci) -def c_num_datamembers(cppscope): +def c_num_datamembers(space, cppscope): return _c_num_datamembers(cppscope.handle) _c_datamember_name = rffi.llexternal( "cppyy_datamember_name", @@ -473,7 +473,7 @@ [C_SCOPE, rffi.INT], rffi.SIZE_T, threadsafe=ts_reflect, compilation_info=backend.eci) -def c_datamember_offset(cppscope, datamember_index): +def c_datamember_offset(space, cppscope, datamember_index): return _c_datamember_offset(cppscope.handle, datamember_index) _c_datamember_index = rffi.llexternal( @@ -481,7 +481,7 @@ [C_SCOPE, rffi.CCHARP], rffi.INT, threadsafe=ts_reflect, compilation_info=backend.eci) -def c_datamember_index(cppscope, name): +def c_datamember_index(space, cppscope, name): return _c_datamember_index(cppscope.handle, name) # data member properties ----------------------------------------------------- @@ -490,27 +490,31 @@ [C_SCOPE, rffi.INT], rffi.INT, threadsafe=ts_reflect, compilation_info=backend.eci) -def c_is_publicdata(cppscope, datamember_index): +def c_is_publicdata(space, cppscope, datamember_index): return _c_is_publicdata(cppscope.handle, datamember_index) _c_is_staticdata = rffi.llexternal( "cppyy_is_staticdata", [C_SCOPE, rffi.INT], rffi.INT, threadsafe=ts_reflect, compilation_info=backend.eci) -def c_is_staticdata(cppscope, datamember_index): +def c_is_staticdata(space, cppscope, datamember_index): return _c_is_staticdata(cppscope.handle, datamember_index) # misc helpers --------------------------------------------------------------- -c_strtoll = rffi.llexternal( +_c_strtoll = rffi.llexternal( "cppyy_strtoll", [rffi.CCHARP], rffi.LONGLONG, threadsafe=ts_helper, compilation_info=backend.eci) -c_strtoull = rffi.llexternal( +def c_strtoll(space, svalue): + return _c_strtoll(svalue) +_c_strtoull = rffi.llexternal( "cppyy_strtoull", [rffi.CCHARP], rffi.ULONGLONG, threadsafe=ts_helper, compilation_info=backend.eci) +def c_strtoull(space, svalue): + return _c_strtoull(svalue) c_free = rffi.llexternal( "cppyy_free", [rffi.VOIDP], lltype.Void, @@ -523,23 +527,36 @@ c_free(voidp) return string -c_charp2stdstring = rffi.llexternal( +_c_charp2stdstring = rffi.llexternal( "cppyy_charp2stdstring", [rffi.CCHARP], C_OBJECT, threadsafe=ts_helper, compilation_info=backend.eci) -c_stdstring2stdstring = rffi.llexternal( +def c_charp2stdstring(space, svalue): + charp = rffi.str2charp(svalue) + result = _c_charp2stdstring(charp) + rffi.free_charp(charp) + return result +_c_stdstring2stdstring = rffi.llexternal( "cppyy_stdstring2stdstring", [C_OBJECT], C_OBJECT, threadsafe=ts_helper, compilation_info=backend.eci) -c_assign2stdstring = rffi.llexternal( +def c_stdstring2stdstring(space, cppobject): + return _c_stdstring2stdstring(cppobject) +_c_assign2stdstring = rffi.llexternal( "cppyy_assign2stdstring", [C_OBJECT, rffi.CCHARP], lltype.Void, threadsafe=ts_helper, compilation_info=backend.eci) -c_free_stdstring = rffi.llexternal( +def c_assign2stdstring(space, cppobject, svalue): + charp = rffi.str2charp(svalue) + _c_assign2stdstring(cppobject, charp) + rffi.free_charp(charp) +_c_free_stdstring = rffi.llexternal( "cppyy_free_stdstring", [C_OBJECT], lltype.Void, threadsafe=ts_helper, compilation_info=backend.eci) +def c_free_stdstring(space, cppobject): + _c_free_stdstring(cppobject) diff --git a/pypy/module/cppyy/capi/loadable_capi.py b/pypy/module/cppyy/capi/loadable_capi.py --- a/pypy/module/cppyy/capi/loadable_capi.py +++ b/pypy/module/cppyy/capi/loadable_capi.py @@ -1,5 +1,5 @@ from rpython.rtyper.lltypesystem import rffi, lltype -from rpython.rlib import jit, jit_libffi, rdynload, objectmodel +from rpython.rlib import jit, jit_libffi, libffi, rdynload, objectmodel from rpython.tool import leakfinder from pypy.interpreter.error import OperationError @@ -9,13 +9,15 @@ from pypy.module.cppyy.capi.capi_types import C_SCOPE, C_TYPE, C_OBJECT,\ C_METHOD, C_INDEX, C_INDEX_ARRAY, WLAVC_INDEX, C_METHPTRGETTER_PTR -import reflex_capi as backend reflection_library = 'rflxlib.so' def identify(): return 'loadable_capi' +# this is not technically correct, but will do for now +std_string_name = 'std::basic_string' + class _Arg: # poor man's union _immutable_ = True def __init__(self, l = 0, s = '', vp = rffi.cast(rffi.VOIDP, 0) ): @@ -61,10 +63,7 @@ else: # only other use is sring n = len(obj._string) assert raw_string == rffi.cast(rffi.CCHARP, 0) - raw_string = lltype.malloc(rffi.CCHARP.TO, n+1, flavor='raw') - for j in range(n): - raw_string[j] = obj._string[j] - raw_string[n] = '\x00' + raw_string = rffi.str2charp(obj._string) data = rffi.cast(rffi.CCHARPP, data) data[0] = raw_string @@ -75,19 +74,10 @@ resultdata = rffi.ptradd(buffer, cif_descr.exchange_result) finally: if raw_string != rffi.cast(rffi.CCHARP, 0): - lltype.free(raw_string, flavor='raw') + rffi.free_charp(raw_string) lltype.free(buffer, flavor='raw') return rffi.cast(rffi.LONGP, resultdata) -std_string_name = backend.std_string_name - -ts_reflect = backend.ts_reflect -ts_call = backend.ts_call -ts_memory = backend.ts_memory -ts_helper = backend.ts_helper - -c_load_dictionary = backend.c_load_dictionary - class State(object): def __init__(self, space): self.library = None @@ -112,6 +102,7 @@ c_int = nt.new_primitive_type(space, 'int') c_long = nt.new_primitive_type(space, 'long') c_llong = nt.new_primitive_type(space, 'long long') + c_ullong = nt.new_primitive_type(space, 'unsigned long long') c_float = nt.new_primitive_type(space, 'float') c_double = nt.new_primitive_type(space, 'double') @@ -123,23 +114,24 @@ self.capi_call_ifaces = { # name to opaque C++ scope representation - 'num_scopes' : ([c_scope], c_int), - 'scope_name' : ([c_scope, c_int], c_ccharp), + 'num_scopes' : ([c_scope], c_int), + 'scope_name' : ([c_scope, c_int], c_ccharp), - 'resolve_name' : ([c_ccharp], c_ccharp), - 'get_scope' : ([c_ccharp], c_scope), - 'get_template' : ([c_ccharp], c_type), - 'actual_class' : ([c_type, c_object], c_type), + 'resolve_name' : ([c_ccharp], c_ccharp), + 'get_scope' : ([c_ccharp], c_scope), + 'get_template' : ([c_ccharp], c_type), + 'actual_class' : ([c_type, c_object], c_type), # memory management - 'allocate' : ([c_type], c_object), - 'deallocate' : ([c_type, c_object], c_void), - 'destruct' : ([c_type, c_object], c_void), + 'allocate' : ([c_type], c_object), + 'deallocate' : ([c_type, c_object], c_void), + 'destruct' : ([c_type, c_object], c_void), # method/function dispatching 'call_v' : ([c_method, c_object, c_int, c_voidp], c_void), 'call_b' : ([c_method, c_object, c_int, c_voidp], c_uchar), 'call_c' : ([c_method, c_object, c_int, c_voidp], c_char), + 'call_h' : ([c_method, c_object, c_int, c_voidp], c_short), 'call_i' : ([c_method, c_object, c_int, c_voidp], c_int), 'call_l' : ([c_method, c_object, c_int, c_voidp], c_long), @@ -153,7 +145,7 @@ 'constructor' : ([c_method, c_object, c_int, c_voidp], c_object), 'call_o' : ([c_method, c_object, c_int, c_voidp, c_type], c_object), - 'get_methptr_getter' : ([c_scope, c_index], c_voidp), # TODO: verify + 'get_methptr_getter' : ([c_scope, c_index], c_voidp), # TODO: verify # handling of function argument buffer 'allocate_function_args' : ([c_size_t], c_voidp), @@ -162,40 +154,64 @@ 'function_arg_typeoffset' : ([], c_size_t), # scope reflection information - 'is_namespace' : ([c_scope], c_int), - 'is_enum' : ([c_ccharp], c_int), + 'is_namespace' : ([c_scope], c_int), + 'is_enum' : ([c_ccharp], c_int), # type/class reflection information - 'final_name' : ([c_type], c_ccharp), - 'scoped_final_name' : ([c_type], c_ccharp), - 'has_complex_hierarchy' : ([c_type], c_int), - 'num_bases' : ([c_type], c_int), - 'base_name' : ([c_type, c_int], c_ccharp), - 'is_subtype' : ([c_type, c_type], c_int), + 'final_name' : ([c_type], c_ccharp), + 'scoped_final_name' : ([c_type], c_ccharp), + 'has_complex_hierarchy' : ([c_type], c_int), + 'num_bases' : ([c_type], c_int), + 'base_name' : ([c_type, c_int], c_ccharp), + 'is_subtype' : ([c_type, c_type], c_int), - 'base_offset' : ([c_type, c_type, c_object, c_int], c_long), + 'base_offset' : ([c_type, c_type, c_object, c_int], c_long), # method/function reflection information - 'num_methods' : ([c_scope], c_int), - 'method_index_at' : ([c_scope, c_int], c_index), + 'num_methods' : ([c_scope], c_int), + 'method_index_at' : ([c_scope, c_int], c_index), 'method_indices_from_name' : ([c_scope, c_ccharp], c_index_array), - 'method_name' : ([c_scope, c_index], c_ccharp), - 'method_result_type' : ([c_scope, c_index], c_ccharp), - 'method_num_args' : ([c_scope, c_index], c_int), + 'method_name' : ([c_scope, c_index], c_ccharp), + 'method_result_type' : ([c_scope, c_index], c_ccharp), + 'method_num_args' : ([c_scope, c_index], c_int), + 'method_req_args' : ([c_scope, c_index], c_int), + 'method_arg_type' : ([c_scope, c_index, c_int], c_ccharp), + 'method_arg_default' : ([c_scope, c_index, c_int], c_ccharp), + 'method_signature' : ([c_scope, c_index], c_ccharp), - 'method_arg_type' : ([c_scope, c_index, c_int], c_ccharp), - 'method_arg_default' : ([c_scope, c_index, c_int], c_ccharp), - 'method_signature' : ([c_scope, c_index], c_ccharp), - + 'method_is_template' : ([c_scope, c_index], c_int), + 'method_num_template_args' : ([c_scope, c_index], c_int), 'method_template_arg_name' : ([c_scope, c_index, c_index], c_ccharp), + 'get_method' : ([c_scope, c_index], c_method), + 'get_global_operator' : ([c_scope, c_scope, c_scope, c_ccharp], c_index), + + # method properties + 'is_constructor' : ([c_type, c_index], c_int), + 'is_staticmethod' : ([c_type, c_index], c_int), + # data member reflection information - 'datamember_name' : ([c_scope, c_int], c_ccharp), - 'datamember_type' : ([c_scope, c_int], c_ccharp), + 'num_datamembers' : ([c_scope], c_int), + 'datamember_name' : ([c_scope, c_int], c_ccharp), + 'datamember_type' : ([c_scope, c_int], c_ccharp), + 'datamember_offset' : ([c_scope, c_int], c_size_t), + + 'datamember_index' : ([c_scope, c_ccharp], c_int), + + # data member properties + 'is_publicdata' : ([c_scope, c_int], c_int), + 'is_staticdata' : ([c_scope, c_int], c_int), # misc helpers - 'free' : ([c_voidp], c_void), + 'strtoll' : ([c_ccharp], c_llong), + 'strtoull' : ([c_ccharp], c_ullong), + 'free' : ([c_voidp], c_void), + + 'charp2stdstring' : ([c_ccharp], c_object), + 'stdstring2stdstring' : ([c_object], c_object), + 'assign2stdstring' : ([c_object, c_ccharp], c_void), + 'free_stdstring' : ([c_object], c_void), } def load_reflection_library(space): @@ -232,7 +248,11 @@ return c_call.ctype.rcall(c_call._cdata, args) def _longptr_to_int(longptr): - return int(rffi.cast(rffi.INTP, longptr)[0]) + # TODO: not understanding why this should be rffi.LONGP instead of rffi.INTP ?? + return int(rffi.cast(rffi.LONGP, longptr)[0]) + +def c_load_dictionary(name): + return libffi.CDLL(name) # name to opaque C++ scope representation ------------------------------------ def c_num_scopes(space, cppscope): @@ -274,7 +294,7 @@ return rffi.cast(rffi.SHORTP, call_capi(space, 'call_h', args))[0] def c_call_i(space, cppmethod, cppobject, nargs, cargs): args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)] - return rffi.cast(rffi.INTP, call_capi(space, 'call_i', args))[0] + return rffi.cast(rffi.INTP, call_capi(space, 'call_i', args))[0] # TODO: should this be LONGP, too? def c_call_l(space, cppmethod, cppobject, nargs, cargs): args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)] return rffi.cast(rffi.LONGP, call_capi(space, 'call_l', args))[0] @@ -384,21 +404,12 @@ def c_method_result_type(space, cppscope, index): args = [_Arg(l=cppscope.handle), _Arg(l=index)] return charp2str_free(space, call_capi(space, 'method_result_type', args)) -_c_method_num_args = rffi.llexternal( - "cppyy_method_num_args", - [C_SCOPE, C_INDEX], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_num_args(cppscope, index): +def c_method_num_args(space, cppscope, index): args = [_Arg(l=cppscope.handle), _Arg(l=index)] - return _c_method_num_args(cppscope.handle, index) -_c_method_req_args = rffi.llexternal( - "cppyy_method_req_args", - [C_SCOPE, C_INDEX], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_req_args(cppscope, index): - return _c_method_req_args(cppscope.handle, index) + return _longptr_to_int(call_capi(space, 'method_num_args', args)) +def c_method_req_args(space, cppscope, index): + args = [_Arg(l=cppscope.handle), _Arg(l=index)] + return _longptr_to_int(call_capi(space, 'method_req_args', args)) def c_method_arg_type(space, cppscope, index, arg_index): args = [_Arg(l=cppscope.handle), _Arg(l=index), _Arg(l=arg_index)] return charp2str_free(space, call_capi(space, 'method_arg_type', args)) @@ -409,20 +420,14 @@ args = [_Arg(l=cppscope.handle), _Arg(l=index)] return charp2str_free(space, call_capi(space, 'method_signature', args)) -_c_method_is_template = rffi.llexternal( - "cppyy_method_is_template", - [C_SCOPE, C_INDEX], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_is_template(cppscope, index): - return _c_method_is_template(cppscope.handle, index) -_c_method_num_template_args = rffi.llexternal( - "cppyy_method_num_template_args", - [C_SCOPE, C_INDEX], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) +def c_method_is_template(space, cppscope, index): + args = [_Arg(l=cppscope.handle), _Arg(l=index)] + return _longptr_to_int(call_capi(space, 'method_is_template', args)) +def _c_method_num_template_args(space, cppscope, index): + args = [_Arg(l=cppscope.handle), _Arg(l=index)] + return _longptr_to_int(call_capi(space, 'method_num_template_args', args)) def c_template_args(space, cppscope, index): - nargs = _c_method_num_template_args(cppscope.handle, index) + nargs = _c_method_num_template_args(space, cppscope, index) arg1 = _Arg(l=cppscope.handle) arg2 = _Arg(l=index) args = [c_resolve_name(space, charp2str_free(space, @@ -430,106 +435,53 @@ ) for iarg in range(nargs)] return args -_c_get_method = rffi.llexternal( - "cppyy_get_method", - [C_SCOPE, C_INDEX], C_METHOD, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_get_method(cppscope, index): - return _c_get_method(cppscope.handle, index) -_c_get_global_operator = rffi.llexternal( - "cppyy_get_global_operator", - [C_SCOPE, C_SCOPE, C_SCOPE, rffi.CCHARP], WLAVC_INDEX, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_get_global_operator(nss, lc, rc, op): +def c_get_method(space, cppscope, index): + args = [_Arg(l=cppscope.handle), _Arg(l=index)] + return rffi.cast(C_METHOD, call_capi(space, 'get_method', args)[0]) +def c_get_global_operator(space, nss, lc, rc, op): if nss is not None: - return _c_get_global_operator(nss.handle, lc.handle, rc.handle, op) + args = [_Arg(l=nss.handle), _Arg(l=lc.handle), _Arg(l=rc.handle), _Arg(s=op)] + return rffi.cast(WLAVC_INDEX, call_capi(space, 'get_global_operator', args)[0]) return rffi.cast(WLAVC_INDEX, -1) # method properties ---------------------------------------------------------- -_c_is_constructor = rffi.llexternal( - "cppyy_is_constructor", - [C_TYPE, C_INDEX], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_is_constructor(cppclass, index): - return _c_is_constructor(cppclass.handle, index) -_c_is_staticmethod = rffi.llexternal( - "cppyy_is_staticmethod", - [C_TYPE, C_INDEX], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_is_staticmethod(cppclass, index): - return _c_is_staticmethod(cppclass.handle, index) +def c_is_constructor(space, cppclass, index): + args = [_Arg(l=cppclass.handle), _Arg(l=index)] + return _longptr_to_int(call_capi(space, 'is_constructor', args)) +def c_is_staticmethod(space, cppclass, index): + args = [_Arg(l=cppclass.handle), _Arg(l=index)] + return _longptr_to_int(call_capi(space, 'is_staticmethod', args)) # data member reflection information ----------------------------------------- -_c_num_datamembers = rffi.llexternal( - "cppyy_num_datamembers", - [C_SCOPE], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_num_datamembers(cppscope): - return _c_num_datamembers(cppscope.handle) -_c_datamember_name = rffi.llexternal( - "cppyy_datamember_name", - [C_SCOPE, rffi.INT], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) +def c_num_datamembers(space, cppscope): + return _longptr_to_int(call_capi(space, 'num_datamembers', [_Arg(l=cppscope.handle)])) def c_datamember_name(space, cppscope, datamember_index): args = [_Arg(l=cppscope.handle), _Arg(l=datamember_index)] return charp2str_free(space, call_capi(space, 'datamember_name', args)) -_c_datamember_type = rffi.llexternal( - "cppyy_datamember_type", - [C_SCOPE, rffi.INT], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) def c_datamember_type(space, cppscope, datamember_index): args = [_Arg(l=cppscope.handle), _Arg(l=datamember_index)] return charp2str_free(space, call_capi(space, 'datamember_type', args)) -_c_datamember_offset = rffi.llexternal( - "cppyy_datamember_offset", - [C_SCOPE, rffi.INT], rffi.SIZE_T, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_datamember_offset(cppscope, datamember_index): - return _c_datamember_offset(cppscope.handle, datamember_index) +def c_datamember_offset(space, cppscope, datamember_index): + args = [_Arg(l=cppscope.handle), _Arg(l=datamember_index)] + return rffi.cast(rffi.SIZE_T, rffi.cast(rffi.ULONGP, call_capi(space, 'datamember_offset', args))[0]) -_c_datamember_index = rffi.llexternal( - "cppyy_datamember_index", - [C_SCOPE, rffi.CCHARP], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_datamember_index(cppscope, name): - return _c_datamember_index(cppscope.handle, name) +def c_datamember_index(space, cppscope, name): + args = [_Arg(l=cppscope.handle), _Arg(s=name)] + return _longptr_to_int(call_capi(space, 'datamember_index', args)) # data member properties ----------------------------------------------------- -_c_is_publicdata = rffi.llexternal( - "cppyy_is_publicdata", - [C_SCOPE, rffi.INT], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_is_publicdata(cppscope, datamember_index): - return _c_is_publicdata(cppscope.handle, datamember_index) -_c_is_staticdata = rffi.llexternal( - "cppyy_is_staticdata", - [C_SCOPE, rffi.INT], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_is_staticdata(cppscope, datamember_index): - return _c_is_staticdata(cppscope.handle, datamember_index) +def c_is_publicdata(space, cppscope, datamember_index): + args = [_Arg(l=cppscope.handle), _Arg(l=datamember_index)] + return _longptr_to_int(call_capi(space, 'is_publicdata', args)) +def c_is_staticdata(space, cppscope, datamember_index): + args = [_Arg(l=cppscope.handle), _Arg(l=datamember_index)] + return _longptr_to_int(call_capi(space, 'is_staticdata', args)) # misc helpers --------------------------------------------------------------- -c_strtoll = rffi.llexternal( - "cppyy_strtoll", - [rffi.CCHARP], rffi.LONGLONG, - threadsafe=ts_helper, - compilation_info=backend.eci) -c_strtoull = rffi.llexternal( - "cppyy_strtoull", - [rffi.CCHARP], rffi.ULONGLONG, - threadsafe=ts_helper, - compilation_info=backend.eci) +def c_strtoll(space, svalue): + return rffi.cast(rffi.LONGLONGP, call_capi(space, 'strtoll', [_Arg(s=svalue)]))[0] +def c_strtoull(space, svalue): + return rffi.cast(rffi.ULONGLONGP, call_capi(space, 'strtoull', [_Arg(s=svalue)]))[0] def c_free(space, voidp): call_capi(space, 'free', [_Arg(vp=voidp)]) @@ -539,27 +491,15 @@ c_free(space, rffi.cast(rffi.VOIDP, charp)) return pystr -c_charp2stdstring = rffi.llexternal( - "cppyy_charp2stdstring", - [rffi.CCHARP], C_OBJECT, - threadsafe=ts_helper, - compilation_info=backend.eci) -c_stdstring2stdstring = rffi.llexternal( - "cppyy_stdstring2stdstring", - [C_OBJECT], C_OBJECT, - threadsafe=ts_helper, - compilation_info=backend.eci) -c_assign2stdstring = rffi.llexternal( - "cppyy_assign2stdstring", - [C_OBJECT, rffi.CCHARP], lltype.Void, - threadsafe=ts_helper, - compilation_info=backend.eci) -c_free_stdstring = rffi.llexternal( - "cppyy_free_stdstring", - [C_OBJECT], lltype.Void, - threadsafe=ts_helper, - compilation_info=backend.eci) - +def c_charp2stdstring(space, svalue): + return rffi.cast(C_OBJECT, call_capi(space, 'charp2stdstring', [_Arg(s=svalue)])[0]) +def c_stdstring2stdstring(space, cppobject): + return rffi.cast(C_OBJECT, call_capi(space, 'stdstring2stdstring', [_Arg(l=cppobject)])[0]) +def c_assign2stdstring(space, cppobject, svalue): + args = [_Arg(l=cppobject), _Arg(s=svalue)] + return rffi.cast(C_OBJECT, call_capi(space, 'assign2stdstring', args)[0]) +def c_free_stdstring(space, cppobject): + call_capi(space, 'free_stdstring', [_Arg(l=cppobject)])[0] # loadable-capi-specific pythonizations (none, as the capi isn't known until runtime) def register_pythonizations(space): diff --git a/pypy/module/cppyy/converter.py b/pypy/module/cppyy/converter.py --- a/pypy/module/cppyy/converter.py +++ b/pypy/module/cppyy/converter.py @@ -511,27 +511,23 @@ def _unwrap_object(self, space, w_obj): try: - charp = rffi.str2charp(space.str_w(w_obj)) - arg = capi.c_charp2stdstring(charp) - rffi.free_charp(charp) - return arg - except OperationError: + return capi.c_charp2stdstring(space, space.str_w(w_obj)) + except Exception, e: arg = InstanceConverter._unwrap_object(self, space, w_obj) - return capi.c_stdstring2stdstring(arg) + result = capi.c_stdstring2stdstring(space, arg) + return result def to_memory(self, space, w_obj, w_value, offset): try: address = rffi.cast(capi.C_OBJECT, self._get_raw_address(space, w_obj, offset)) - charp = rffi.str2charp(space.str_w(w_value)) - capi.c_assign2stdstring(address, charp) - rffi.free_charp(charp) + capi.c_assign2stdstring(space, address, space.str_w(w_value)) return except Exception: pass return InstanceConverter.to_memory(self, space, w_obj, w_value, offset) def free_argument(self, space, arg, call_local): - capi.c_free_stdstring(rffi.cast(capi.C_OBJECT, rffi.cast(rffi.VOIDPP, arg)[0])) + capi.c_free_stdstring(space, rffi.cast(capi.C_OBJECT, rffi.cast(rffi.VOIDPP, arg)[0])) class StdStringRefConverter(InstancePtrConverter): _immutable_fields_ = ['cppclass'] @@ -685,7 +681,7 @@ class BasicConverter(ffitypes.typeid(c_type), IntTypeConverterMixin, TypeConverter): _immutable_ = True def __init__(self, space, default): - self.default = rffi.cast(self.c_type, capi.c_strtoll(default)) + self.default = rffi.cast(self.c_type, capi.c_strtoll(space, default)) class ConstRefConverter(ConstRefNumericTypeConverterMixin, BasicConverter): _immutable_ = True libffitype = jit_libffi.types.pointer @@ -702,7 +698,7 @@ class BasicConverter(ffitypes.typeid(c_type), IntTypeConverterMixin, TypeConverter): _immutable_ = True def __init__(self, space, default): - self.default = rffi.cast(self.c_type, capi.c_strtoll(default)) + self.default = rffi.cast(self.c_type, capi.c_strtoll(space, default)) class ConstRefConverter(ConstRefNumericTypeConverterMixin, BasicConverter): _immutable_ = True libffitype = jit_libffi.types.pointer @@ -728,7 +724,7 @@ class BasicConverter(ffitypes.typeid(c_type), IntTypeConverterMixin, TypeConverter): _immutable_ = True def __init__(self, space, default): - self.default = rffi.cast(self.c_type, capi.c_strtoull(default)) + self.default = rffi.cast(self.c_type, capi.c_strtoull(space, default)) class ConstRefConverter(ConstRefNumericTypeConverterMixin, BasicConverter): _immutable_ = True libffitype = jit_libffi.types.pointer diff --git a/pypy/module/cppyy/interp_cppyy.py b/pypy/module/cppyy/interp_cppyy.py --- a/pypy/module/cppyy/interp_cppyy.py +++ b/pypy/module/cppyy/interp_cppyy.py @@ -139,7 +139,7 @@ self.space = space self.scope = containing_scope self.index = method_index - self.cppmethod = capi.c_get_method(self.scope, method_index) + self.cppmethod = capi.c_get_method(self.space, self.scope, method_index) self.arg_defs = arg_defs self.args_required = args_required self.args_expected = len(arg_defs) @@ -663,7 +663,7 @@ idx = capi.c_method_index_at(self.space, self, i) pyname = helper.map_operator_name(self.space, capi.c_method_name(self.space, self, idx), - capi.c_method_num_args(self, idx), + capi.c_method_num_args(self.space, self, idx), capi.c_method_result_type(self.space, self, idx)) cppmethod = self._make_cppfunction(pyname, idx) methods_temp.setdefault(pyname, []).append(cppmethod) @@ -744,8 +744,8 @@ kind = "namespace" def _make_cppfunction(self, pyname, index): - num_args = capi.c_method_num_args(self, index) - args_required = capi.c_method_req_args(self, index) + num_args = capi.c_method_num_args(self.space, self, index) + args_required = capi.c_method_req_args(self.space, self, index) arg_defs = [] for i in range(num_args): arg_type = capi.c_method_arg_type(self.space, self, index, i) @@ -755,15 +755,15 @@ def _make_datamember(self, dm_name, dm_idx): type_name = capi.c_datamember_type(self.space, self, dm_idx) - offset = capi.c_datamember_offset(self, dm_idx) + offset = capi.c_datamember_offset(self.space, self, dm_idx) datamember = W_CPPStaticData(self.space, self, type_name, offset) self.datamembers[dm_name] = datamember return datamember def _find_datamembers(self): - num_datamembers = capi.c_num_datamembers(self) + num_datamembers = capi.c_num_datamembers(self.space, self) for i in range(num_datamembers): - if not capi.c_is_publicdata(self, i): + if not capi.c_is_publicdata(self.space, self, i): continue datamember_name = capi.c_datamember_name(self.space, self, i) if not datamember_name in self.datamembers: @@ -781,7 +781,7 @@ return overload def find_datamember(self, dm_name): - dm_idx = capi.c_datamember_index(self, dm_name) + dm_idx = capi.c_datamember_index(self.space, self, dm_name) if dm_idx < 0: raise self.missing_attribute_error(dm_name) datamember = self._make_datamember(dm_name, dm_idx) @@ -805,7 +805,7 @@ if mname: allmeth.setdefault(mname, 0) for m in allmeth.keys(): alldir.append(self.space.wrap(m)) - for i in range(capi.c_num_datamembers(self)): + for i in range(capi.c_num_datamembers(self.space, self)): dname = capi.c_datamember_name(self.space, self, i) if dname: alldir.append(self.space.wrap(dname)) return self.space.newlist(alldir) @@ -834,21 +834,21 @@ self.default_constructor = None def _make_cppfunction(self, pyname, index): - num_args = capi.c_method_num_args(self, index) - args_required = capi.c_method_req_args(self, index) + num_args = capi.c_method_num_args(self.space, self, index) + args_required = capi.c_method_req_args(self.space, self, index) arg_defs = [] for i in range(num_args): arg_type = capi.c_method_arg_type(self.space, self, index, i) arg_dflt = capi.c_method_arg_default(self.space, self, index, i) arg_defs.append((arg_type, arg_dflt)) - if capi.c_is_constructor(self, index): + if capi.c_is_constructor(self.space, self, index): cppfunction = CPPConstructor(self.space, self, index, arg_defs, args_required) if args_required == 0: self.default_constructor = cppfunction - elif capi.c_method_is_template(self, index): + elif capi.c_method_is_template(self.space, self, index): templ_args = capi.c_template_args(self.space, self, index) cppfunction = CPPTemplatedCall(self.space, templ_args, self, index, arg_defs, args_required) - elif capi.c_is_staticmethod(self, index): + elif capi.c_is_staticmethod(self.space, self, index): cppfunction = CPPFunction(self.space, self, index, arg_defs, args_required) elif pyname == "__setitem__": cppfunction = CPPSetItem(self.space, self, index, arg_defs, args_required) @@ -857,14 +857,14 @@ return cppfunction def _find_datamembers(self): - num_datamembers = capi.c_num_datamembers(self) + num_datamembers = capi.c_num_datamembers(self.space, self) for i in range(num_datamembers): - if not capi.c_is_publicdata(self, i): + if not capi.c_is_publicdata(self.space, self, i): continue datamember_name = capi.c_datamember_name(self.space, self, i) type_name = capi.c_datamember_type(self.space, self, i) - offset = capi.c_datamember_offset(self, i) - is_static = bool(capi.c_is_staticdata(self, i)) + offset = capi.c_datamember_offset(self.space, self, i) + is_static = bool(capi.c_is_staticdata(self.space, self, i)) if is_static: datamember = W_CPPStaticData(self.space, self, type_name, offset) else: @@ -1017,7 +1017,7 @@ other = self.space.interp_w(W_CPPInstance, w_other, can_be_None=False) for name in ["", "__gnu_cxx"]: nss = scope_byname(self.space, name) - meth_idx = capi.c_get_global_operator(nss, self.cppclass, other.cppclass, "==") + meth_idx = capi.c_get_global_operator(self.space, nss, self.cppclass, other.cppclass, "==") if meth_idx != -1: f = nss._make_cppfunction("operator==", meth_idx) ol = W_CPPOverload(self.space, nss, [f]) From noreply at buildbot.pypy.org Fri Apr 5 11:23:41 2013 From: noreply at buildbot.pypy.org (fijal) Date: Fri, 5 Apr 2013 11:23:41 +0200 (CEST) Subject: [pypy-commit] pypy release-2.0-beta2: fix those tests (how it have ever worked?) Message-ID: <20130405092341.0B9C51C0F0F@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: release-2.0-beta2 Changeset: r63045:fa07639d3d4e Date: 2013-04-05 11:23 +0200 http://bitbucket.org/pypy/pypy/changeset/fa07639d3d4e/ Log: fix those tests (how it have ever worked?) diff --git a/pypy/tool/release/package.py b/pypy/tool/release/package.py --- a/pypy/tool/release/package.py +++ b/pypy/tool/release/package.py @@ -43,6 +43,7 @@ def fix_permissions(basedir): if sys.platform != 'win32': os.system("chmod -R a+rX %s" % basedir) + os.system("chmod -R g-w %s" % basedir) def package(basedir, name='pypy-nightly', rename_pypy_c='pypy', copy_to_dir = None, override_pypy_c = None, nostrip=False): From noreply at buildbot.pypy.org Fri Apr 5 11:24:22 2013 From: noreply at buildbot.pypy.org (fijal) Date: Fri, 5 Apr 2013 11:24:22 +0200 (CEST) Subject: [pypy-commit] pypy default: fix those tests (how it have ever worked?) Message-ID: <20130405092422.802BD1C0F0F@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r63046:44a0540290bc Date: 2013-04-05 11:23 +0200 http://bitbucket.org/pypy/pypy/changeset/44a0540290bc/ Log: fix those tests (how it have ever worked?) diff --git a/pypy/tool/release/package.py b/pypy/tool/release/package.py --- a/pypy/tool/release/package.py +++ b/pypy/tool/release/package.py @@ -43,6 +43,7 @@ def fix_permissions(basedir): if sys.platform != 'win32': os.system("chmod -R a+rX %s" % basedir) + os.system("chmod -R g-w %s" % basedir) def package(basedir, name='pypy-nightly', rename_pypy_c='pypy', copy_to_dir = None, override_pypy_c = None, nostrip=False): From noreply at buildbot.pypy.org Fri Apr 5 11:58:43 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 5 Apr 2013 11:58:43 +0200 (CEST) Subject: [pypy-commit] pypy default: Add a failing test Message-ID: <20130405095843.056E01C11CF@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63047:a163d0d435d5 Date: 2013-04-05 11:57 +0200 http://bitbucket.org/pypy/pypy/changeset/a163d0d435d5/ Log: Add a failing test diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -218,7 +218,7 @@ const char **pzTail /* OUT: Pointer to unused portion of zSql */ ); -void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); +void sqlite3_result_blob(sqlite3_context*, const char*, int, void(*)(void*)); void sqlite3_result_double(sqlite3_context*, double); void sqlite3_result_error(sqlite3_context*, const char*, int); void sqlite3_result_error16(sqlite3_context*, const void*, int); diff --git a/pypy/module/test_lib_pypy/test_sqlite3.py b/pypy/module/test_lib_pypy/test_sqlite3.py --- a/pypy/module/test_lib_pypy/test_sqlite3.py +++ b/pypy/module/test_lib_pypy/test_sqlite3.py @@ -198,3 +198,15 @@ con = _sqlite3.connect(':memory:') con.row_factory = 42 con.execute('select 1') + +def test_returning_blob_must_own_memory(): + import gc + con = _sqlite3.connect(":memory:") + con.create_function("returnblob", 0, lambda: buffer("blob")) + cur = con.cursor() + cur.execute("select returnblob()") + val = cur.fetchone()[0] + for i in range(5): + gc.collect() + got = (val[0], val[1], val[2], val[3]) + assert got == ('b', 'l', 'o', 'b') From noreply at buildbot.pypy.org Fri Apr 5 11:58:44 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 5 Apr 2013 11:58:44 +0200 (CEST) Subject: [pypy-commit] pypy default: Fix the failing test (blob returned by sqlite3 need to be kept alive, Message-ID: <20130405095844.23A671C11CF@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63048:961fb066e7b7 Date: 2013-04-05 12:00 +0200 http://bitbucket.org/pypy/pypy/changeset/961fb066e7b7/ Log: Fix the failing test (blob returned by sqlite3 need to be kept alive, which require making a copy; CPython does a copy too.) diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -29,6 +29,7 @@ import string import sys import weakref +import array from threading import _get_ident as _thread_get_ident try: from __pypy__ import newlist_hint @@ -958,7 +959,11 @@ elif typ == _lib.SQLITE_BLOB: blob = _lib.sqlite3_column_blob(self.__statement._statement, i) blob_len = _lib.sqlite3_column_bytes(self.__statement._statement, i) - val = _BLOB_TYPE(_ffi.buffer(blob, blob_len)) + # make a copy of the data into an array, in order to get + # a read-write buffer in the end, and one that own the + # memory for a more predictable length of time than 'blob' + copy = array.array("c", _ffi.buffer(blob, blob_len)) + val = _BLOB_TYPE(copy) row.append(val) return tuple(row) From noreply at buildbot.pypy.org Fri Apr 5 12:13:55 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 5 Apr 2013 12:13:55 +0200 (CEST) Subject: [pypy-commit] pypy default: Don't track allocations that go straight into "setdata()", where they Message-ID: <20130405101355.EA48A1C0F0F@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63049:c2e8c09de077 Date: 2013-04-05 12:13 +0200 http://bitbucket.org/pypy/pypy/changeset/c2e8c09de077/ Log: Don't track allocations that go straight into "setdata()", where they will be handled by the __del__(). diff --git a/rpython/rlib/rsocket.py b/rpython/rlib/rsocket.py --- a/rpython/rlib/rsocket.py +++ b/rpython/rlib/rsocket.py @@ -80,7 +80,7 @@ def __del__(self): if self.addr_p: - lltype.free(self.addr_p, flavor='raw') + lltype.free(self.addr_p, flavor='raw', track_allocation=False) def setdata(self, addr, addrlen): # initialize self.addr and self.addrlen. 'addr' can be a different @@ -271,7 +271,8 @@ result = instantiate(INETAddress) # store the malloc'ed data into 'result' as soon as possible # to avoid leaks if an exception occurs inbetween - sin = lltype.malloc(_c.sockaddr_in, flavor='raw', zero=True) + sin = lltype.malloc(_c.sockaddr_in, flavor='raw', zero=True, + track_allocation=False) result.setdata(sin, sizeof(_c.sockaddr_in)) # PLAT sin_len rffi.setintfield(sin, 'c_sin_family', AF_INET) @@ -337,7 +338,8 @@ result = instantiate(INET6Address) # store the malloc'ed data into 'result' as soon as possible # to avoid leaks if an exception occurs inbetween - sin = lltype.malloc(_c.sockaddr_in6, flavor='raw', zero=True) + sin = lltype.malloc(_c.sockaddr_in6, flavor='raw', zero=True, + track_allocation=False) result.setdata(sin, sizeof(_c.sockaddr_in6)) rffi.setintfield(sin, 'c_sin6_family', AF_INET6) rffi.structcopy(sin.c_sin6_addr, in6_addr) @@ -360,7 +362,8 @@ maxlen = sizeof(struct) def __init__(self, path): - sun = lltype.malloc(_c.sockaddr_un, flavor='raw', zero=True) + sun = lltype.malloc(_c.sockaddr_un, flavor='raw', zero=True, + track_allocation=False) baseofs = offsetof(_c.sockaddr_un, 'c_sun_path') self.setdata(sun, baseofs + len(path)) rffi.setintfield(sun, 'c_sun_family', AF_UNIX) @@ -409,7 +412,8 @@ maxlen = minlen = sizeof(struct) def __init__(self, pid, groups): - addr = lltype.malloc(_c.sockaddr_nl, flavor='raw', zero=True) + addr = lltype.malloc(_c.sockaddr_nl, flavor='raw', zero=True, + track_allocation=False) self.setdata(addr, NETLINKAddress.maxlen) rffi.setintfield(addr, 'c_nl_family', AF_NETLINK) rffi.setintfield(addr, 'c_nl_pid', pid) @@ -444,7 +448,8 @@ raise RSocketError("address family mismatched") # copy into a new buffer the address that 'addrptr' points to addrlen = rffi.cast(lltype.Signed, addrlen) - buf = lltype.malloc(rffi.CCHARP.TO, addrlen, flavor='raw') + buf = lltype.malloc(rffi.CCHARP.TO, addrlen, flavor='raw', + track_allocation=False) src = rffi.cast(rffi.CCHARP, addrptr) for i in range(addrlen): buf[i] = src[i] @@ -456,7 +461,8 @@ result = instantiate(INETAddress) elif result.family != AF_INET: raise RSocketError("address family mismatched") - sin = lltype.malloc(_c.sockaddr_in, flavor='raw', zero=True) + sin = lltype.malloc(_c.sockaddr_in, flavor='raw', zero=True, + track_allocation=False) result.setdata(sin, sizeof(_c.sockaddr_in)) rffi.setintfield(sin, 'c_sin_family', AF_INET) # PLAT sin_len rffi.setintfield(sin.c_sin_addr, 'c_s_addr', s_addr) @@ -465,7 +471,8 @@ def make_null_address(family): klass = familyclass(family) result = instantiate(klass) - buf = lltype.malloc(rffi.CCHARP.TO, klass.maxlen, flavor='raw', zero=True) + buf = lltype.malloc(rffi.CCHARP.TO, klass.maxlen, flavor='raw', zero=True, + track_allocation=False) # Initialize the family to the correct value. Avoids surprizes on # Windows when calling a function that unexpectedly does not set # the output address (e.g. recvfrom() on a connected IPv4 socket). From noreply at buildbot.pypy.org Fri Apr 5 12:21:17 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 5 Apr 2013 12:21:17 +0200 (CEST) Subject: [pypy-commit] pypy default: Use ctypes to get the size of "long double" reasonably. The issue is Message-ID: <20130405102117.5E5C21C039A@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63050:20bd465b4b06 Date: 2013-04-05 12:20 +0200 http://bitbucket.org/pypy/pypy/changeset/20bd465b4b06/ Log: Use ctypes to get the size of "long double" reasonably. The issue is that it's not always 12/16 on all platforms; e.g. on Windows it is 8. diff --git a/rpython/rtyper/lltypesystem/rffi.py b/rpython/rtyper/lltypesystem/rffi.py --- a/rpython/rtyper/lltypesystem/rffi.py +++ b/rpython/rtyper/lltypesystem/rffi.py @@ -934,10 +934,8 @@ if tp is lltype.SingleFloat: return 4 if tp is lltype.LongFloat: - if globals()['r_void*'].BITS == 32: - return 12 - else: - return 16 + import ctypes # :-/ + return ctypes.sizeof(ctypes.c_longdouble) assert isinstance(tp, lltype.Number) if tp is lltype.Signed: return LONG_BIT/8 From noreply at buildbot.pypy.org Fri Apr 5 13:00:25 2013 From: noreply at buildbot.pypy.org (mattip) Date: Fri, 5 Apr 2013 13:00:25 +0200 (CEST) Subject: [pypy-commit] pypy default: add libsqlite3 to build instructions Message-ID: <20130405110025.342911C0337@cobra.cs.uni-duesseldorf.de> Author: Matti Picus Branch: Changeset: r63051:0bd57f2b6c51 Date: 2013-04-05 14:00 +0300 http://bitbucket.org/pypy/pypy/changeset/0bd57f2b6c51/ Log: add libsqlite3 to build instructions diff --git a/pypy/doc/getting-started-python.rst b/pypy/doc/getting-started-python.rst --- a/pypy/doc/getting-started-python.rst +++ b/pypy/doc/getting-started-python.rst @@ -46,14 +46,14 @@ 2. Install build-time dependencies. On a Debian box these are:: [user at debian-box ~]$ sudo apt-get install \ - gcc make python-dev libffi-dev pkg-config \ + gcc make python-dev libffi-dev lib-sqlite3-dev pkg-config \ libz-dev libbz2-dev libncurses-dev libexpat1-dev \ libssl-dev libgc-dev python-sphinx python-greenlet On a Fedora-16 box these are:: [user at fedora-or-rh-box ~]$ sudo yum install \ - gcc make python-devel libffi-devel pkgconfig \ + gcc make python-devel libffi-devel lib-sqlite3-devel pkgconfig \ zlib-devel bzip2-devel ncurses-devel expat-devel \ openssl-devel gc-devel python-sphinx python-greenlet @@ -62,6 +62,7 @@ * ``pkg-config`` (to help us locate libffi files) * ``libz-dev`` (for the optional ``zlib`` module) * ``libbz2-dev`` (for the optional ``bz2`` module) + * ``libsqlite3-dev`` (for the optional ``sqlite3`` modulei via cffi) * ``libncurses-dev`` (for the optional ``_minimal_curses`` module) * ``libexpat1-dev`` (for the optional ``pyexpat`` module) * ``libssl-dev`` (for the optional ``_ssl`` module) diff --git a/pypy/doc/windows.rst b/pypy/doc/windows.rst --- a/pypy/doc/windows.rst +++ b/pypy/doc/windows.rst @@ -111,6 +111,18 @@ cd bzip2-1.0.5 nmake -f makefile.msc +The sqlite3 database library +~~~~~~~~~~~~~~~~~~~~ + +Download http://www.sqlite.org/2013/sqlite-amalgamation-3071601.zip and extract +it into a directory under the base directory. Also get +http://www.sqlite.org/2013/sqlite-dll-win32-x86-3071601.zip and extract the dll +into the bin directory, and the sqlite3.def into the sources directory. +Now build the import library so cffi can use the header and dll:: + lib /DEF:sqlite3.def" /OUT:sqlite3.lib" + copy sqlite3.lib path\to\libs + + The expat XML parser ~~~~~~~~~~~~~~~~~~~~ From noreply at buildbot.pypy.org Fri Apr 5 13:04:53 2013 From: noreply at buildbot.pypy.org (mattip) Date: Fri, 5 Apr 2013 13:04:53 +0200 (CEST) Subject: [pypy-commit] pypy default: typo Message-ID: <20130405110453.705E81C06BD@cobra.cs.uni-duesseldorf.de> Author: Matti Picus Branch: Changeset: r63052:13d908d37509 Date: 2013-04-05 14:04 +0300 http://bitbucket.org/pypy/pypy/changeset/13d908d37509/ Log: typo diff --git a/pypy/doc/getting-started-python.rst b/pypy/doc/getting-started-python.rst --- a/pypy/doc/getting-started-python.rst +++ b/pypy/doc/getting-started-python.rst @@ -62,7 +62,7 @@ * ``pkg-config`` (to help us locate libffi files) * ``libz-dev`` (for the optional ``zlib`` module) * ``libbz2-dev`` (for the optional ``bz2`` module) - * ``libsqlite3-dev`` (for the optional ``sqlite3`` modulei via cffi) + * ``libsqlite3-dev`` (for the optional ``sqlite3`` module via cffi) * ``libncurses-dev`` (for the optional ``_minimal_curses`` module) * ``libexpat1-dev`` (for the optional ``pyexpat`` module) * ``libssl-dev`` (for the optional ``_ssl`` module) From noreply at buildbot.pypy.org Fri Apr 5 13:31:36 2013 From: noreply at buildbot.pypy.org (fijal) Date: Fri, 5 Apr 2013 13:31:36 +0200 (CEST) Subject: [pypy-commit] pypy release-2.0-beta2: merge default Message-ID: <20130405113136.DEAA21C0A11@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: release-2.0-beta2 Changeset: r63053:da4d2a8bc441 Date: 2013-04-05 13:31 +0200 http://bitbucket.org/pypy/pypy/changeset/da4d2a8bc441/ Log: merge default diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -1167,7 +1167,7 @@ if ret == _lib.SQLITE_OK and not self._statement: # an empty statement, work around that, as it's the least trouble - c_sql = _ffi.new("char[]", "select 42") + c_sql = _ffi.new("char[]", b"select 42") ret = _lib.sqlite3_prepare_v2(self.__con._db, c_sql, -1, statement_star, next_char) self._statement = statement_star[0] diff --git a/lib_pypy/cffi/api.py b/lib_pypy/cffi/api.py --- a/lib_pypy/cffi/api.py +++ b/lib_pypy/cffi/api.py @@ -25,6 +25,7 @@ line = '' return '%s%s' % (line, self.args[0]) + class FFI(object): r''' The main top-level class that you instantiate once, or once per module. @@ -220,7 +221,7 @@ it as a string or unicode string. If 'cdata' is an enum, returns the value of the enumerator as a - string, or '#NUMBER' if the value is out of range. + string, or 'NUMBER' if the value is out of range. """ return self._backend.string(cdata, maxlen) diff --git a/lib_pypy/cffi/cparser.py b/lib_pypy/cffi/cparser.py --- a/lib_pypy/cffi/cparser.py +++ b/lib_pypy/cffi/cparser.py @@ -2,7 +2,7 @@ from . import api, model from .commontypes import COMMON_TYPES, resolve_common_type try: - from cffi import _pycparser as pycparser + from . import _pycparser as pycparser except ImportError: import pycparser import weakref, re, sys diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/setup.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/setup.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/setup.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py from distutils.core import setup import snip_basic_verify diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/snip_basic_verify.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/snip_basic_verify.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/snip_basic_verify.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/snip_basic_verify.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py from cffi import FFI import sys diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/setup.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/setup.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/setup.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py from distutils.core import setup import snip_basic_verify1 diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/snip_basic_verify1/__init__.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/snip_basic_verify1/__init__.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/snip_basic_verify1/__init__.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/snip_basic_verify1/__init__.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py from cffi import FFI import sys diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/setup.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/setup.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/setup.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py from distutils.core import setup import snip_basic_verify2 diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/snip_basic_verify2/__init__.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/snip_basic_verify2/__init__.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/snip_basic_verify2/__init__.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/snip_basic_verify2/__init__.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py from cffi import FFI import sys diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/setup.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/setup.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/setup.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py from distutils.core import setup diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/snip_infrastructure/__init__.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/snip_infrastructure/__init__.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/snip_infrastructure/__init__.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/snip_infrastructure/__init__.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py def func(): return 42 diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/setup.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/setup.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/setup.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py from setuptools import setup import snip_setuptools_verify diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/snip_setuptools_verify.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/snip_setuptools_verify.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/snip_setuptools_verify.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/snip_setuptools_verify.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py from cffi import FFI import sys diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/setup.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/setup.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/setup.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py from setuptools import setup import snip_setuptools_verify1 diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/snip_setuptools_verify1/__init__.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/snip_setuptools_verify1/__init__.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/snip_setuptools_verify1/__init__.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/snip_setuptools_verify1/__init__.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py from cffi import FFI import sys diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/setup.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/setup.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/setup.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py from setuptools import setup import snip_setuptools_verify2 diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/snip_setuptools_verify2/__init__.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/snip_setuptools_verify2/__init__.py --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/snip_setuptools_verify2/__init__.py +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/snip_setuptools_verify2/__init__.py @@ -1,3 +1,4 @@ +# Generated by pypy/tool/import_cffi.py from cffi import FFI import sys From noreply at buildbot.pypy.org Fri Apr 5 14:01:36 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 5 Apr 2013 14:01:36 +0200 (CEST) Subject: [pypy-commit] pypy.org extradoc: Add the text from esr as the first part of "performance.html". Message-ID: <20130405120136.928DC1C039A@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: extradoc Changeset: r385:a1796ffb4d27 Date: 2013-04-05 14:01 +0200 http://bitbucket.org/pypy/pypy.org/changeset/a1796ffb4d27/ Log: Add the text from esr as the first part of "performance.html". diff --git a/performance.html b/performance.html --- a/performance.html +++ b/performance.html @@ -46,6 +46,214 @@

Performance

+ +

This document collects strategies, tactics and tricks for making your +code run faster under PyPy. Many of these are also useful hints for +stock Python and other languages. For contrast, we also describe some +CPython (stock Python) optimizations that are not needed in PyPy.

+
+

Optimization strategy

+

These suggestions apply to all computer languages. They're here as +reminders of things to try before any Python or PyPy-specific tweaking.

+
+

Build a regression-test suite

+

Before you start tuning, build a regression-test suite for your code. +This front-loads a significant amount of work, but it means you can +try lots of optimizations without worrying so much about introducing +functional bugs.

+
+
+

Measure, don't guess

+

Human beings are bad at guessing or intuiting where the hotspots in code are. +Measure, don't guess; use a profiler to pin down the 20% of the +code where the code is spending 80% of its time, then speed-tune that.

+

Measuring will save you a lot of effort wasted on tuning parts of the code +that aren't actually bottlenecks.

+

As you tune, re-profile frequently so you can see how the hottest spots +are shifting around.

+
+
+

I/O-bound is different from compute-bound

+

Be aware of the difference between code that is compute-bound (slow +because it's doing a huge number of instructions) and code that is I/O +bound (slow because of disk or network delays).

+

Expect to get most of your gains from optimizing compute-bound code. +It's usually (though not always) a sign that you're near the end of +worthwhile tuning when profiling shows that the bulk of the +application's time is spent on network and disk I/O.

+
+
+

Tune your algorithms first

+

Generally, when your code is doing things that are O(n**2) or larger +in the size of your data set, the cost of those operations is going +to swamp any small gains you can pick up with the tricks we describe +here.

+

Tune your algorithms first. It's time to think about applying our +list of micro-tuning tips after you think you've optimized out +intrinsically expensive operations.

+

That said, be prepared for the possibility that you will discover +better-hidden algorithmic problems as you micro-tune. Likely +you will go through this cycle more than once.

+
+
+

Focus on tight loops

+

It's extremely common for high time costs to lurk within some +innocuous-looking code inside a tight loop - especially in code +that does something like a searching/matching/lookup operation +or any kind of graph traversal.

+

Probably the most common kind of performance-killer in compute-bound +code is an O(n**2) operation that is disguised by being some sort of +O(n) lookup or match inside an O(n) loop.

+

Another common time-sink is relatively expensive common-setup +operations that are performed inside tight loops but could be moved +to before they start. (For a representative case of this, see the +micro-tuning tip on regexp compilation.)

+
+
+

Smaller is faster

+

Modern computers have multiple levels of memory caching, some directly +on the processor chip. Causing a cache miss at any level incurs a +performance penalty proportional to random-access time for the next +outward (and much slower) layer of cache.

+

Accordingly, smaller is faster. Programs or routines with a small +enough working set to fit inside a fast cache will be as fast as +that cache is. To make your code fast, reduce the length of the +series of Python or JIT-compiler opcodes it generates by making +it simpler.

+

The tradeoff here is that algorithmic tuning often trades time for +space - that is, it increases the size of an algorithm's working set +by including pre-computations or tables or reverse maps in order to +avoid O(n**2) operations.

+

It's impossible to predict in advance where the sweet spot in that +tradeoff will be. You have to try different things and measure - +which takes us right back to “Measure, don't guess”. And another +function of your regression test suite can be as a speed benchmark.

+
+
+
+

Micro-tuning tips

+

These are in no particular order.

+
+

Keep it simple

+

Simple is better than complex. The PyPy JIT is not very smart; the +simpler your code is the better it will run. Here again, though, you face +a tradeoff: you may need to pay with more algorithmic complexity in order +to avoid brute-force operations that are O(n**2) or worse.

+

Write plain-vanilla code in plain-vanilla ways. The PyPy JIT has many +productions that optimize a common usage pattern against an uncommon +usage pattern.

+
+
+

Global variables

+

In CPython, global variables and functions (including package imports) +are much more expensive to reference than locals; avoid them. (This +is also good modularity practice).

+

The cost of CPython global references is high enough that, for example, if you +have code in a frequently-visited inner loop that uses int() a lot, it +may be worthwhile to create a local copy of the reference with “int = +int” in an enclosing block.

+

However, this in not true in JITted PyPy code. The “int = int” hack +won't buy you performance, it's just an extra copy. The modularity +reason for avoiding globals are still valid.

+
+
+

Regular expressions

+

Regular-expression compilation is expensive. If the regexp pattern in +a search, match, or replace operation is static (doesn't mutate at +runtime) refactor so it's only done once.

+

If the regexp compilation is in a class method, consider doing it as +the initializer of a regexp-valued static (shared) class member and +using that class member in your operation.

+

If the regexp compilation is in a free function, consider moving it +to module level and referencing the resulting regexp object +(but see the warning above about global variables).

+
+
+

Old- vs. new-style classes

+

New-style classes allow faster attribute access and take up less core +per instance than old-style classes. Much of this advantage may be +lostm, however, if attribute names are not constant. For example: x.a += y or even setattr(x, ‘a’, y) will be much faster than a dynamic +version: setattr(x, ‘a’ + some_variable, y).

+

Classes that inherit from both new- and old-style classes are +extremely slow; avoid at all costs.

+

In PyPy, isinstance() called against an old-style class was very slow +until 2.0.

+
+
+

String concatenation is expensive

+

In CPython, you may want to replace:

+
+s = head + body + maybe + tail
+
+

with the admittedly less readable:

+
+s = "%(head)%(body)%(maybe)%(tail)" % locals()
+
+

or even:

+
+s = "{head}{body}{maybe}{tail}".format(locals())
+
+

Both of the latter forms avoid multiple-allocation overhead. +But PyPy's JIT makes the overhead of intermediate concatenations +go away in linear code that keeps the number of concatenations +small, bound and constant. (And locals() is rather slow +with PyPy's JIT.)

+

On the other hand, in code like this with a string-valued foo() function:

+
+for x in mylist:
+    s += foo(x)
+
+

the JIT cannot optimize out intermediate copies. This code is +actually quadratic in the total size of the mylist strings due to +repeated string copies of ever-larger prefix segments.

+

This:

+
+parts = []
+for x in mylist:
+    parts.append(foo(x))
+s = "".join(parts)
+
+

can be much faster because all the string concatenation in the last +line creates exactly one new string object with one C-level copy +sequence (and list operations are relatively cheap).

+
+
+

Frame introspection and tracing are slow

+

Certain function calls can disable PyPy's speed options over +stretches of surrounding code called “JIT scopes”.

+

A JIT like PyPy's works based on the assumption that the only thing +worth optimizing are loops that are executed often. Whenever the +interpreter enters a loop in the interpreted program, the JIT records +what the interpreter does, creating a trace. This trace is optimized, +compiled to machine code and executed when the loop is hit with the +conditions observed during tracing. This trace is one kind of JIT scope.

+

Another kind of JIT scope that matters is a function, considered as +a unit for inlining.

+

Note that a JIT scope is a run-time phenomenon, not a compile-time +one. It's not confined by source-code module boundaries. A library- +or foreign-module call in a frequently-called loop or inlined function +will be part of its JIT scope.

+

locals(), globals(), sys._getframe(), sys.exc_info(), and sys.settrace +work in PyPy, but they incur a performance penalty that can be huge by +disabling the JIT over the enclosing JIT scope.

+

One unobvious case where frame introspection is used is the logging +module. Don't use the logging module if you need to run fast.

+

(Thanks Eric S. Raymond for the text above)

+
+
+
+

Insider's point of view

+

This section describes performance issues from the point of view of +insiders of the project; it should be particularly interesting if you +plan to contribute in that area.

One of the goals of the PyPy project is to provide a fast and compliant python interpreter. Some of the ways we achieve this are by providing a high-performance garbage collector (GC) and a high-performance @@ -116,15 +324,14 @@ reduce(), and to some extend map() (although the simple case is JITted), and to all usages of the operator module we can think of. -

  • Ctypes: Ctypes is a mixed bunch. If you're lucky you'll hit the -sweetspot and be really fast. If you're unlucky, you'll miss the -sweetspot and hit the slowpath which is much slower than CPython (2-10x -has been reported).
  • +
  • Ctypes: Ctypes is slower than on CPython. Consider CFFI instead, +which has special paths inside the JIT.
  • We generally consider things that are slower on PyPy than CPython to be bugs of PyPy. If you find some issue that is not documented here, please report it to our bug tracker for investigation.

    +
    diff --git a/source/performance.txt b/source/performance.txt --- a/source/performance.txt +++ b/source/performance.txt @@ -3,6 +3,252 @@ title: Performance --- +.. contents:: + :depth: 1 + +This document collects strategies, tactics and tricks for making your +code run faster under PyPy. Many of these are also useful hints for +stock Python and other languages. For contrast, we also describe some +CPython (stock Python) optimizations that are not needed in PyPy. + +Optimization strategy +===================== + +These suggestions apply to all computer languages. They're here as +reminders of things to try before any Python or PyPy-specific tweaking. + +Build a regression-test suite +----------------------------- + +Before you start tuning, build a regression-test suite for your code. +This front-loads a significant amount of work, but it means you can +try lots of optimizations without worrying so much about introducing +functional bugs. + +Measure, don't guess +-------------------- + +Human beings are bad at guessing or intuiting where the hotspots in code are. +Measure, don't guess; use a profiler to pin down the 20% of the +code where the code is spending 80% of its time, then speed-tune that. + +Measuring will save you a lot of effort wasted on tuning parts of the code +that aren't actually bottlenecks. + +As you tune, re-profile frequently so you can see how the hottest spots +are shifting around. + +I/O-bound is different from compute-bound +----------------------------------------- + +Be aware of the difference between code that is compute-bound (slow +because it's doing a huge number of instructions) and code that is I/O +bound (slow because of disk or network delays). + +Expect to get most of your gains from optimizing compute-bound code. +It's usually (though not always) a sign that you're near the end of +worthwhile tuning when profiling shows that the bulk of the +application's time is spent on network and disk I/O. + +Tune your algorithms first +-------------------------- + +Generally, when your code is doing things that are O(n**2) or larger +in the size of your data set, the cost of those operations is going +to swamp any small gains you can pick up with the tricks we describe +here. + +Tune your algorithms first. It's time to think about applying our +list of micro-tuning tips *after* you think you've optimized out +intrinsically expensive operations. + +That said, be prepared for the possibility that you will discover +better-hidden algorithmic problems as you micro-tune. Likely +you will go through this cycle more than once. + +Focus on tight loops +-------------------- + +It's extremely common for high time costs to lurk within some +innocuous-looking code inside a tight loop - especially in code +that does something like a searching/matching/lookup operation +or any kind of graph traversal. + +Probably the most common kind of performance-killer in compute-bound +code is an O(n**2) operation that is disguised by being some sort of +O(n) lookup or match inside an O(n) loop. + +Another common time-sink is relatively expensive common-setup +operations that are performed inside tight loops but could be moved +to before they start. (For a representative case of this, see the +micro-tuning tip on regexp compilation.) + +Smaller is faster +----------------- + +Modern computers have multiple levels of memory caching, some directly +on the processor chip. Causing a cache miss at any level incurs a +performance penalty proportional to random-access time for the next +outward (and much slower) layer of cache. + +Accordingly, smaller is faster. Programs or routines with a small +enough working set to fit inside a fast cache will be as fast as +that cache is. To make your code fast, reduce the length of the +series of Python or JIT-compiler opcodes it generates by making +it simpler. + +The tradeoff here is that algorithmic tuning often trades time for +space - that is, it increases the size of an algorithm's working set +by including pre-computations or tables or reverse maps in order to +avoid O(n**2) operations. + +It's impossible to predict in advance where the sweet spot in that +tradeoff will be. You have to try different things and measure - +which takes us right back to "Measure, don't guess". And another +function of your regression test suite can be as a speed benchmark. + +Micro-tuning tips +================= + +These are in no particular order. + +Keep it simple +-------------- + +Simple is better than complex. The PyPy JIT is not very smart; the +simpler your code is the better it will run. Here again, though, you face +a tradeoff: you may need to pay with more algorithmic complexity in order +to avoid brute-force operations that are O(n**2) or worse. + +Write plain-vanilla code in plain-vanilla ways. The PyPy JIT has many +productions that optimize a common usage pattern against an uncommon +usage pattern. + +Global variables +---------------- + +In CPython, global variables and functions (including package imports) +are much more expensive to reference than locals; avoid them. (This +is also good modularity practice). + +The cost of CPython global references is high enough that, for example, if you +have code in a frequently-visited inner loop that uses int() a lot, it +may be worthwhile to create a local copy of the reference with "int = +int" in an enclosing block. + +However, this in *not* true in JITted PyPy code. The "int = int" hack +won't buy you performance, it's just an extra copy. The modularity +reason for avoiding globals are still valid. + +Regular expressions +------------------- + +Regular-expression compilation is expensive. If the regexp pattern in +a search, match, or replace operation is static (doesn't mutate at +runtime) refactor so it's only done once. + +If the regexp compilation is in a class method, consider doing it as +the initializer of a regexp-valued static (shared) class member and +using that class member in your operation. + +If the regexp compilation is in a free function, consider moving it +to module level and referencing the resulting regexp object +(but see the warning above about global variables). + +Old- vs. new-style classes +-------------------------- + +New-style classes allow faster attribute access and take up less core +per instance than old-style classes. Much of this advantage may be +lostm, however, if attribute names are not constant. For example: x.a += y or even setattr(x, 'a', y) will be much faster than a dynamic +version: setattr(x, 'a' + some_variable, y). + +Classes that inherit from both new- and old-style classes are +*extremely* slow; avoid at all costs. + +In PyPy, isinstance() called against an old-style class was very slow +until 2.0. + +String concatenation is expensive +---------------------------------- + +In CPython, you may want to replace:: + + s = head + body + maybe + tail + +with the admittedly less readable:: + + s = "%(head)%(body)%(maybe)%(tail)" % locals() + +or even:: + + s = "{head}{body}{maybe}{tail}".format(locals()) + +Both of the latter forms avoid multiple-allocation overhead. +But PyPy's JIT makes the overhead of intermediate concatenations +go away in linear code that keeps the number of concatenations +small, bound and constant. (And ``locals()`` is rather slow +with PyPy's JIT.) + +On the other hand, in code like this with a string-valued foo() function:: + + for x in mylist: + s += foo(x) + +the JIT cannot optimize out intermediate copies. This code is +actually quadratic in the total size of the mylist strings due to +repeated string copies of ever-larger prefix segments. + +This:: + + parts = [] + for x in mylist: + parts.append(foo(x)) + s = "".join(parts) + +can be much faster because all the string concatenation in the last +line creates exactly one new string object with one C-level copy +sequence (and list operations are relatively cheap). + +Frame introspection and tracing are slow +---------------------------------------- + +Certain function calls can disable PyPy's speed options over +stretches of surrounding code called "JIT scopes". + +A JIT like PyPy's works based on the assumption that the only thing +worth optimizing are loops that are executed often. Whenever the +interpreter enters a loop in the interpreted program, the JIT records +what the interpreter does, creating a trace. This trace is optimized, +compiled to machine code and executed when the loop is hit with the +conditions observed during tracing. This trace is one kind of JIT scope. + +Another kind of JIT scope that matters is a function, considered as +a unit for inlining. + +Note that a JIT scope is a run-time phenomenon, not a compile-time +one. It's not confined by source-code module boundaries. A library- +or foreign-module call in a frequently-called loop or inlined function +will be part of its JIT scope. + +locals(), globals(), sys._getframe(), sys.exc_info(), and sys.settrace +work in PyPy, but they incur a performance penalty that can be huge by +disabling the JIT over the enclosing JIT scope. + +One unobvious case where frame introspection is used is the logging +module. Don't use the logging module if you need to run fast. + +*(Thanks Eric S. Raymond for the text above)* + + +Insider's point of view +======================= + +This section describes performance issues from the point of view of +insiders of the project; it should be particularly interesting if you +plan to contribute in that area. + One of the goals of the PyPy project is to provide a fast and compliant python interpreter. Some of the ways we achieve this are by providing a high-performance garbage collector (GC) and a high-performance @@ -81,10 +327,8 @@ is JITted), and to all usages of the ``operator`` module we can think of. -* **Ctypes**: Ctypes is a mixed bunch. If you're lucky you'll hit the - sweetspot and be **really** fast. If you're unlucky, you'll miss the - sweetspot and hit the slowpath which is much slower than CPython (2-10x - has been reported). +* **Ctypes**: Ctypes is slower than on CPython. Consider CFFI_ instead, + which has special paths inside the JIT. We generally consider things that are slower on PyPy than CPython to be bugs of PyPy. If you find some issue that is not documented here, @@ -92,4 +336,4 @@ .. _`bug tracker`: http://bugs.pypy.org .. _`speed website`: http://speed.pypy.org - +.. _CFFI: http://cffi.readthedocs.org/ From noreply at buildbot.pypy.org Fri Apr 5 14:13:35 2013 From: noreply at buildbot.pypy.org (fijal) Date: Fri, 5 Apr 2013 14:13:35 +0200 (CEST) Subject: [pypy-commit] pypy default: write the release announcement Message-ID: <20130405121335.87B3E1C039A@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r63054:03d69244d043 Date: 2013-04-05 14:12 +0200 http://bitbucket.org/pypy/pypy/changeset/03d69244d043/ Log: write the release announcement diff --git a/pypy/doc/release-2.0.0-beta2.rst b/pypy/doc/release-2.0.0-beta2.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/release-2.0.0-beta2.rst @@ -0,0 +1,84 @@ +=============== +PyPy 2.0 beta 2 +=============== + +We're pleased to announce the 2.0 beta 2 release of PyPy. This is a major +release of PyPy and we're getting very close to 2.0 final, however it includes +quite a few new features that require further testing. Please test and report +issues, so we can have a rock-solid 2.0 final. It also includes a performance +regression of about 5% compared to 2.0 beta 1 that we hope to fix before +2.0 final. The ARM support is not working yet and we're working hard to +make it happen before the 2.0 final. The new major features are: + +* JIT now supports stackless features, that is greenlets and stacklets. This + means that JIT can now optimize the code that switches the context. It enables + running `eventlet`_ and `gevent`_ on PyPy (although gevent requires some + special support that's not quite finished, read below). + +* This is the first PyPy release that includes `cffi`_ as a core library. + Version 0.6 comes included in the PyPy library. cffi has seen a lot of + adoption among library authors and we believe it's the best way to wrap + C libaries. You can see examples of cffi usage in `_curses.py`_ and + `_sqlite3.py`_ in the PyPy source code. + +You can download the PyPy 2.0 beta 2 release here: + + http://pypy.org/download.html + +What is PyPy? +============= + +PyPy is a very compliant Python interpreter, almost a drop-in replacement for +CPython 2.7.3. It's fast (`pypy 2.0 beta 2 and cpython 2.7.3`_ +performance comparison) due to its integrated tracing JIT compiler. + +This release supports x86 machines running Linux 32/64, Mac OS X 64 or +Windows 32. It also supports ARM machines running Linux, however this is +disabled for the beta 2 release. +Windows 64 work is still stalling, we would welcome a volunteer +to handle that. + +.. _`pypy 2.0 beta 2 and cpython 2.7.3`: http://bit.ly/USXqpP + +How to use PyPy? +================ + +We suggest using PyPy from a `virtualenv`_. Once you have a virtualenv +installed, you can follow instructions from `pypy documentation`_ on how +to proceed. This document also covers other `installation schemes`_. + +.. _`pypy documentation`: http://doc.pypy.org/en/latest/getting-started.html#installing-using-virtualenv +.. _`virtualenv`: http://www.virtualenv.org/en/latest/ +.. _`installation schemes`: http://doc.pypy.org/en/latest/getting-started.html#installing-pypy + +Highlights +========== + +* ``cffi`` is officially supported by PyPy. It comes included in the standard + library, just use ``import cffi`` + +* stackless support - `eventlet`_ just works and `gevent`_ requires `pypycore`_ + and `pypy-hacks`_ branch of gevent (which mostly disables cython-based + modules) + +* callbacks from C are now much faster. pyexpat is about 3x faster, cffi + callbacks around the same + +* ``__length_hint__`` is implemented (PEP 424) + +* a lot of numpy improvements + +Improvements since 1.9 +====================== + +* `JIT hooks`_ are now a powerful tool to introspect the JITting process that + PyPy performs + +* various performance improvements compared to 1.9 and 2.0 beta 1 + +* operations on ``long`` objects are now as fast as in CPython (from + roughly 2x slower) + +* we now have special strategies for ``dict``/``set``/``list`` which contain + unicode strings, which means that now such collections will be both faster + and more compact. From noreply at buildbot.pypy.org Fri Apr 5 14:13:37 2013 From: noreply at buildbot.pypy.org (fijal) Date: Fri, 5 Apr 2013 14:13:37 +0200 (CEST) Subject: [pypy-commit] pypy default: merge Message-ID: <20130405121337.05CD01C039A@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r63055:1f9677f6bba1 Date: 2013-04-05 14:13 +0200 http://bitbucket.org/pypy/pypy/changeset/1f9677f6bba1/ Log: merge diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -29,6 +29,7 @@ import string import sys import weakref +import array from threading import _get_ident as _thread_get_ident try: from __pypy__ import newlist_hint @@ -218,7 +219,7 @@ const char **pzTail /* OUT: Pointer to unused portion of zSql */ ); -void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); +void sqlite3_result_blob(sqlite3_context*, const char*, int, void(*)(void*)); void sqlite3_result_double(sqlite3_context*, double); void sqlite3_result_error(sqlite3_context*, const char*, int); void sqlite3_result_error16(sqlite3_context*, const void*, int); @@ -958,7 +959,11 @@ elif typ == _lib.SQLITE_BLOB: blob = _lib.sqlite3_column_blob(self.__statement._statement, i) blob_len = _lib.sqlite3_column_bytes(self.__statement._statement, i) - val = _BLOB_TYPE(_ffi.buffer(blob, blob_len)) + # make a copy of the data into an array, in order to get + # a read-write buffer in the end, and one that own the + # memory for a more predictable length of time than 'blob' + copy = array.array("c", _ffi.buffer(blob, blob_len)) + val = _BLOB_TYPE(copy) row.append(val) return tuple(row) diff --git a/pypy/doc/getting-started-python.rst b/pypy/doc/getting-started-python.rst --- a/pypy/doc/getting-started-python.rst +++ b/pypy/doc/getting-started-python.rst @@ -46,14 +46,14 @@ 2. Install build-time dependencies. On a Debian box these are:: [user at debian-box ~]$ sudo apt-get install \ - gcc make python-dev libffi-dev pkg-config \ + gcc make python-dev libffi-dev lib-sqlite3-dev pkg-config \ libz-dev libbz2-dev libncurses-dev libexpat1-dev \ libssl-dev libgc-dev python-sphinx python-greenlet On a Fedora-16 box these are:: [user at fedora-or-rh-box ~]$ sudo yum install \ - gcc make python-devel libffi-devel pkgconfig \ + gcc make python-devel libffi-devel lib-sqlite3-devel pkgconfig \ zlib-devel bzip2-devel ncurses-devel expat-devel \ openssl-devel gc-devel python-sphinx python-greenlet @@ -62,6 +62,7 @@ * ``pkg-config`` (to help us locate libffi files) * ``libz-dev`` (for the optional ``zlib`` module) * ``libbz2-dev`` (for the optional ``bz2`` module) + * ``libsqlite3-dev`` (for the optional ``sqlite3`` module via cffi) * ``libncurses-dev`` (for the optional ``_minimal_curses`` module) * ``libexpat1-dev`` (for the optional ``pyexpat`` module) * ``libssl-dev`` (for the optional ``_ssl`` module) diff --git a/pypy/doc/windows.rst b/pypy/doc/windows.rst --- a/pypy/doc/windows.rst +++ b/pypy/doc/windows.rst @@ -111,6 +111,18 @@ cd bzip2-1.0.5 nmake -f makefile.msc +The sqlite3 database library +~~~~~~~~~~~~~~~~~~~~ + +Download http://www.sqlite.org/2013/sqlite-amalgamation-3071601.zip and extract +it into a directory under the base directory. Also get +http://www.sqlite.org/2013/sqlite-dll-win32-x86-3071601.zip and extract the dll +into the bin directory, and the sqlite3.def into the sources directory. +Now build the import library so cffi can use the header and dll:: + lib /DEF:sqlite3.def" /OUT:sqlite3.lib" + copy sqlite3.lib path\to\libs + + The expat XML parser ~~~~~~~~~~~~~~~~~~~~ diff --git a/pypy/module/test_lib_pypy/test_sqlite3.py b/pypy/module/test_lib_pypy/test_sqlite3.py --- a/pypy/module/test_lib_pypy/test_sqlite3.py +++ b/pypy/module/test_lib_pypy/test_sqlite3.py @@ -198,3 +198,15 @@ con = _sqlite3.connect(':memory:') con.row_factory = 42 con.execute('select 1') + +def test_returning_blob_must_own_memory(): + import gc + con = _sqlite3.connect(":memory:") + con.create_function("returnblob", 0, lambda: buffer("blob")) + cur = con.cursor() + cur.execute("select returnblob()") + val = cur.fetchone()[0] + for i in range(5): + gc.collect() + got = (val[0], val[1], val[2], val[3]) + assert got == ('b', 'l', 'o', 'b') diff --git a/rpython/rlib/rsocket.py b/rpython/rlib/rsocket.py --- a/rpython/rlib/rsocket.py +++ b/rpython/rlib/rsocket.py @@ -80,7 +80,7 @@ def __del__(self): if self.addr_p: - lltype.free(self.addr_p, flavor='raw') + lltype.free(self.addr_p, flavor='raw', track_allocation=False) def setdata(self, addr, addrlen): # initialize self.addr and self.addrlen. 'addr' can be a different @@ -271,7 +271,8 @@ result = instantiate(INETAddress) # store the malloc'ed data into 'result' as soon as possible # to avoid leaks if an exception occurs inbetween - sin = lltype.malloc(_c.sockaddr_in, flavor='raw', zero=True) + sin = lltype.malloc(_c.sockaddr_in, flavor='raw', zero=True, + track_allocation=False) result.setdata(sin, sizeof(_c.sockaddr_in)) # PLAT sin_len rffi.setintfield(sin, 'c_sin_family', AF_INET) @@ -337,7 +338,8 @@ result = instantiate(INET6Address) # store the malloc'ed data into 'result' as soon as possible # to avoid leaks if an exception occurs inbetween - sin = lltype.malloc(_c.sockaddr_in6, flavor='raw', zero=True) + sin = lltype.malloc(_c.sockaddr_in6, flavor='raw', zero=True, + track_allocation=False) result.setdata(sin, sizeof(_c.sockaddr_in6)) rffi.setintfield(sin, 'c_sin6_family', AF_INET6) rffi.structcopy(sin.c_sin6_addr, in6_addr) @@ -360,7 +362,8 @@ maxlen = sizeof(struct) def __init__(self, path): - sun = lltype.malloc(_c.sockaddr_un, flavor='raw', zero=True) + sun = lltype.malloc(_c.sockaddr_un, flavor='raw', zero=True, + track_allocation=False) baseofs = offsetof(_c.sockaddr_un, 'c_sun_path') self.setdata(sun, baseofs + len(path)) rffi.setintfield(sun, 'c_sun_family', AF_UNIX) @@ -409,7 +412,8 @@ maxlen = minlen = sizeof(struct) def __init__(self, pid, groups): - addr = lltype.malloc(_c.sockaddr_nl, flavor='raw', zero=True) + addr = lltype.malloc(_c.sockaddr_nl, flavor='raw', zero=True, + track_allocation=False) self.setdata(addr, NETLINKAddress.maxlen) rffi.setintfield(addr, 'c_nl_family', AF_NETLINK) rffi.setintfield(addr, 'c_nl_pid', pid) @@ -444,7 +448,8 @@ raise RSocketError("address family mismatched") # copy into a new buffer the address that 'addrptr' points to addrlen = rffi.cast(lltype.Signed, addrlen) - buf = lltype.malloc(rffi.CCHARP.TO, addrlen, flavor='raw') + buf = lltype.malloc(rffi.CCHARP.TO, addrlen, flavor='raw', + track_allocation=False) src = rffi.cast(rffi.CCHARP, addrptr) for i in range(addrlen): buf[i] = src[i] @@ -456,7 +461,8 @@ result = instantiate(INETAddress) elif result.family != AF_INET: raise RSocketError("address family mismatched") - sin = lltype.malloc(_c.sockaddr_in, flavor='raw', zero=True) + sin = lltype.malloc(_c.sockaddr_in, flavor='raw', zero=True, + track_allocation=False) result.setdata(sin, sizeof(_c.sockaddr_in)) rffi.setintfield(sin, 'c_sin_family', AF_INET) # PLAT sin_len rffi.setintfield(sin.c_sin_addr, 'c_s_addr', s_addr) @@ -465,7 +471,8 @@ def make_null_address(family): klass = familyclass(family) result = instantiate(klass) - buf = lltype.malloc(rffi.CCHARP.TO, klass.maxlen, flavor='raw', zero=True) + buf = lltype.malloc(rffi.CCHARP.TO, klass.maxlen, flavor='raw', zero=True, + track_allocation=False) # Initialize the family to the correct value. Avoids surprizes on # Windows when calling a function that unexpectedly does not set # the output address (e.g. recvfrom() on a connected IPv4 socket). diff --git a/rpython/rtyper/lltypesystem/rffi.py b/rpython/rtyper/lltypesystem/rffi.py --- a/rpython/rtyper/lltypesystem/rffi.py +++ b/rpython/rtyper/lltypesystem/rffi.py @@ -934,10 +934,8 @@ if tp is lltype.SingleFloat: return 4 if tp is lltype.LongFloat: - if globals()['r_void*'].BITS == 32: - return 12 - else: - return 16 + import ctypes # :-/ + return ctypes.sizeof(ctypes.c_longdouble) assert isinstance(tp, lltype.Number) if tp is lltype.Signed: return LONG_BIT/8 From noreply at buildbot.pypy.org Fri Apr 5 14:15:07 2013 From: noreply at buildbot.pypy.org (fijal) Date: Fri, 5 Apr 2013 14:15:07 +0200 (CEST) Subject: [pypy-commit] pypy default: update this Message-ID: <20130405121507.B789B1C039A@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r63056:09ca29d0ccba Date: 2013-04-05 14:14 +0200 http://bitbucket.org/pypy/pypy/changeset/09ca29d0ccba/ Log: update this diff --git a/pypy/doc/index.rst b/pypy/doc/index.rst --- a/pypy/doc/index.rst +++ b/pypy/doc/index.rst @@ -15,7 +15,7 @@ * `FAQ`_: some frequently asked questions. -* `Release 2.0 beta 1`_: the latest official release +* `Release 2.0 beta 2`_: the latest official release * `PyPy Blog`_: news and status info about PyPy @@ -75,7 +75,7 @@ .. _`Getting Started`: getting-started.html .. _`Papers`: extradoc.html .. _`Videos`: video-index.html -.. _`Release 2.0 beta 1`: http://pypy.org/download.html +.. _`Release 2.0 beta 2`: http://pypy.org/download.html .. _`speed.pypy.org`: http://speed.pypy.org .. _`RPython toolchain`: translation.html .. _`potential project ideas`: project-ideas.html From noreply at buildbot.pypy.org Fri Apr 5 14:21:18 2013 From: noreply at buildbot.pypy.org (fijal) Date: Fri, 5 Apr 2013 14:21:18 +0200 (CEST) Subject: [pypy-commit] pypy release-2.0-beta2: merge default Message-ID: <20130405122118.A38EA1C0337@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: release-2.0-beta2 Changeset: r63057:a7ee6d151d4e Date: 2013-04-05 14:21 +0200 http://bitbucket.org/pypy/pypy/changeset/a7ee6d151d4e/ Log: merge default diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -29,6 +29,7 @@ import string import sys import weakref +import array from threading import _get_ident as _thread_get_ident try: from __pypy__ import newlist_hint @@ -218,7 +219,7 @@ const char **pzTail /* OUT: Pointer to unused portion of zSql */ ); -void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); +void sqlite3_result_blob(sqlite3_context*, const char*, int, void(*)(void*)); void sqlite3_result_double(sqlite3_context*, double); void sqlite3_result_error(sqlite3_context*, const char*, int); void sqlite3_result_error16(sqlite3_context*, const void*, int); @@ -958,7 +959,11 @@ elif typ == _lib.SQLITE_BLOB: blob = _lib.sqlite3_column_blob(self.__statement._statement, i) blob_len = _lib.sqlite3_column_bytes(self.__statement._statement, i) - val = _BLOB_TYPE(_ffi.buffer(blob, blob_len)) + # make a copy of the data into an array, in order to get + # a read-write buffer in the end, and one that own the + # memory for a more predictable length of time than 'blob' + copy = array.array("c", _ffi.buffer(blob, blob_len)) + val = _BLOB_TYPE(copy) row.append(val) return tuple(row) diff --git a/pypy/doc/getting-started-python.rst b/pypy/doc/getting-started-python.rst --- a/pypy/doc/getting-started-python.rst +++ b/pypy/doc/getting-started-python.rst @@ -46,14 +46,14 @@ 2. Install build-time dependencies. On a Debian box these are:: [user at debian-box ~]$ sudo apt-get install \ - gcc make python-dev libffi-dev pkg-config \ + gcc make python-dev libffi-dev lib-sqlite3-dev pkg-config \ libz-dev libbz2-dev libncurses-dev libexpat1-dev \ libssl-dev libgc-dev python-sphinx python-greenlet On a Fedora-16 box these are:: [user at fedora-or-rh-box ~]$ sudo yum install \ - gcc make python-devel libffi-devel pkgconfig \ + gcc make python-devel libffi-devel lib-sqlite3-devel pkgconfig \ zlib-devel bzip2-devel ncurses-devel expat-devel \ openssl-devel gc-devel python-sphinx python-greenlet @@ -62,6 +62,7 @@ * ``pkg-config`` (to help us locate libffi files) * ``libz-dev`` (for the optional ``zlib`` module) * ``libbz2-dev`` (for the optional ``bz2`` module) + * ``libsqlite3-dev`` (for the optional ``sqlite3`` module via cffi) * ``libncurses-dev`` (for the optional ``_minimal_curses`` module) * ``libexpat1-dev`` (for the optional ``pyexpat`` module) * ``libssl-dev`` (for the optional ``_ssl`` module) diff --git a/pypy/doc/index.rst b/pypy/doc/index.rst --- a/pypy/doc/index.rst +++ b/pypy/doc/index.rst @@ -15,7 +15,7 @@ * `FAQ`_: some frequently asked questions. -* `Release 2.0 beta 1`_: the latest official release +* `Release 2.0 beta 2`_: the latest official release * `PyPy Blog`_: news and status info about PyPy @@ -75,7 +75,7 @@ .. _`Getting Started`: getting-started.html .. _`Papers`: extradoc.html .. _`Videos`: video-index.html -.. _`Release 2.0 beta 1`: http://pypy.org/download.html +.. _`Release 2.0 beta 2`: http://pypy.org/download.html .. _`speed.pypy.org`: http://speed.pypy.org .. _`RPython toolchain`: translation.html .. _`potential project ideas`: project-ideas.html diff --git a/pypy/doc/release-2.0.0-beta2.rst b/pypy/doc/release-2.0.0-beta2.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/release-2.0.0-beta2.rst @@ -0,0 +1,84 @@ +=============== +PyPy 2.0 beta 2 +=============== + +We're pleased to announce the 2.0 beta 2 release of PyPy. This is a major +release of PyPy and we're getting very close to 2.0 final, however it includes +quite a few new features that require further testing. Please test and report +issues, so we can have a rock-solid 2.0 final. It also includes a performance +regression of about 5% compared to 2.0 beta 1 that we hope to fix before +2.0 final. The ARM support is not working yet and we're working hard to +make it happen before the 2.0 final. The new major features are: + +* JIT now supports stackless features, that is greenlets and stacklets. This + means that JIT can now optimize the code that switches the context. It enables + running `eventlet`_ and `gevent`_ on PyPy (although gevent requires some + special support that's not quite finished, read below). + +* This is the first PyPy release that includes `cffi`_ as a core library. + Version 0.6 comes included in the PyPy library. cffi has seen a lot of + adoption among library authors and we believe it's the best way to wrap + C libaries. You can see examples of cffi usage in `_curses.py`_ and + `_sqlite3.py`_ in the PyPy source code. + +You can download the PyPy 2.0 beta 2 release here: + + http://pypy.org/download.html + +What is PyPy? +============= + +PyPy is a very compliant Python interpreter, almost a drop-in replacement for +CPython 2.7.3. It's fast (`pypy 2.0 beta 2 and cpython 2.7.3`_ +performance comparison) due to its integrated tracing JIT compiler. + +This release supports x86 machines running Linux 32/64, Mac OS X 64 or +Windows 32. It also supports ARM machines running Linux, however this is +disabled for the beta 2 release. +Windows 64 work is still stalling, we would welcome a volunteer +to handle that. + +.. _`pypy 2.0 beta 2 and cpython 2.7.3`: http://bit.ly/USXqpP + +How to use PyPy? +================ + +We suggest using PyPy from a `virtualenv`_. Once you have a virtualenv +installed, you can follow instructions from `pypy documentation`_ on how +to proceed. This document also covers other `installation schemes`_. + +.. _`pypy documentation`: http://doc.pypy.org/en/latest/getting-started.html#installing-using-virtualenv +.. _`virtualenv`: http://www.virtualenv.org/en/latest/ +.. _`installation schemes`: http://doc.pypy.org/en/latest/getting-started.html#installing-pypy + +Highlights +========== + +* ``cffi`` is officially supported by PyPy. It comes included in the standard + library, just use ``import cffi`` + +* stackless support - `eventlet`_ just works and `gevent`_ requires `pypycore`_ + and `pypy-hacks`_ branch of gevent (which mostly disables cython-based + modules) + +* callbacks from C are now much faster. pyexpat is about 3x faster, cffi + callbacks around the same + +* ``__length_hint__`` is implemented (PEP 424) + +* a lot of numpy improvements + +Improvements since 1.9 +====================== + +* `JIT hooks`_ are now a powerful tool to introspect the JITting process that + PyPy performs + +* various performance improvements compared to 1.9 and 2.0 beta 1 + +* operations on ``long`` objects are now as fast as in CPython (from + roughly 2x slower) + +* we now have special strategies for ``dict``/``set``/``list`` which contain + unicode strings, which means that now such collections will be both faster + and more compact. diff --git a/pypy/doc/windows.rst b/pypy/doc/windows.rst --- a/pypy/doc/windows.rst +++ b/pypy/doc/windows.rst @@ -111,6 +111,18 @@ cd bzip2-1.0.5 nmake -f makefile.msc +The sqlite3 database library +~~~~~~~~~~~~~~~~~~~~ + +Download http://www.sqlite.org/2013/sqlite-amalgamation-3071601.zip and extract +it into a directory under the base directory. Also get +http://www.sqlite.org/2013/sqlite-dll-win32-x86-3071601.zip and extract the dll +into the bin directory, and the sqlite3.def into the sources directory. +Now build the import library so cffi can use the header and dll:: + lib /DEF:sqlite3.def" /OUT:sqlite3.lib" + copy sqlite3.lib path\to\libs + + The expat XML parser ~~~~~~~~~~~~~~~~~~~~ diff --git a/pypy/module/test_lib_pypy/test_sqlite3.py b/pypy/module/test_lib_pypy/test_sqlite3.py --- a/pypy/module/test_lib_pypy/test_sqlite3.py +++ b/pypy/module/test_lib_pypy/test_sqlite3.py @@ -198,3 +198,15 @@ con = _sqlite3.connect(':memory:') con.row_factory = 42 con.execute('select 1') + +def test_returning_blob_must_own_memory(): + import gc + con = _sqlite3.connect(":memory:") + con.create_function("returnblob", 0, lambda: buffer("blob")) + cur = con.cursor() + cur.execute("select returnblob()") + val = cur.fetchone()[0] + for i in range(5): + gc.collect() + got = (val[0], val[1], val[2], val[3]) + assert got == ('b', 'l', 'o', 'b') diff --git a/rpython/rlib/rsocket.py b/rpython/rlib/rsocket.py --- a/rpython/rlib/rsocket.py +++ b/rpython/rlib/rsocket.py @@ -80,7 +80,7 @@ def __del__(self): if self.addr_p: - lltype.free(self.addr_p, flavor='raw') + lltype.free(self.addr_p, flavor='raw', track_allocation=False) def setdata(self, addr, addrlen): # initialize self.addr and self.addrlen. 'addr' can be a different @@ -271,7 +271,8 @@ result = instantiate(INETAddress) # store the malloc'ed data into 'result' as soon as possible # to avoid leaks if an exception occurs inbetween - sin = lltype.malloc(_c.sockaddr_in, flavor='raw', zero=True) + sin = lltype.malloc(_c.sockaddr_in, flavor='raw', zero=True, + track_allocation=False) result.setdata(sin, sizeof(_c.sockaddr_in)) # PLAT sin_len rffi.setintfield(sin, 'c_sin_family', AF_INET) @@ -337,7 +338,8 @@ result = instantiate(INET6Address) # store the malloc'ed data into 'result' as soon as possible # to avoid leaks if an exception occurs inbetween - sin = lltype.malloc(_c.sockaddr_in6, flavor='raw', zero=True) + sin = lltype.malloc(_c.sockaddr_in6, flavor='raw', zero=True, + track_allocation=False) result.setdata(sin, sizeof(_c.sockaddr_in6)) rffi.setintfield(sin, 'c_sin6_family', AF_INET6) rffi.structcopy(sin.c_sin6_addr, in6_addr) @@ -360,7 +362,8 @@ maxlen = sizeof(struct) def __init__(self, path): - sun = lltype.malloc(_c.sockaddr_un, flavor='raw', zero=True) + sun = lltype.malloc(_c.sockaddr_un, flavor='raw', zero=True, + track_allocation=False) baseofs = offsetof(_c.sockaddr_un, 'c_sun_path') self.setdata(sun, baseofs + len(path)) rffi.setintfield(sun, 'c_sun_family', AF_UNIX) @@ -409,7 +412,8 @@ maxlen = minlen = sizeof(struct) def __init__(self, pid, groups): - addr = lltype.malloc(_c.sockaddr_nl, flavor='raw', zero=True) + addr = lltype.malloc(_c.sockaddr_nl, flavor='raw', zero=True, + track_allocation=False) self.setdata(addr, NETLINKAddress.maxlen) rffi.setintfield(addr, 'c_nl_family', AF_NETLINK) rffi.setintfield(addr, 'c_nl_pid', pid) @@ -444,7 +448,8 @@ raise RSocketError("address family mismatched") # copy into a new buffer the address that 'addrptr' points to addrlen = rffi.cast(lltype.Signed, addrlen) - buf = lltype.malloc(rffi.CCHARP.TO, addrlen, flavor='raw') + buf = lltype.malloc(rffi.CCHARP.TO, addrlen, flavor='raw', + track_allocation=False) src = rffi.cast(rffi.CCHARP, addrptr) for i in range(addrlen): buf[i] = src[i] @@ -456,7 +461,8 @@ result = instantiate(INETAddress) elif result.family != AF_INET: raise RSocketError("address family mismatched") - sin = lltype.malloc(_c.sockaddr_in, flavor='raw', zero=True) + sin = lltype.malloc(_c.sockaddr_in, flavor='raw', zero=True, + track_allocation=False) result.setdata(sin, sizeof(_c.sockaddr_in)) rffi.setintfield(sin, 'c_sin_family', AF_INET) # PLAT sin_len rffi.setintfield(sin.c_sin_addr, 'c_s_addr', s_addr) @@ -465,7 +471,8 @@ def make_null_address(family): klass = familyclass(family) result = instantiate(klass) - buf = lltype.malloc(rffi.CCHARP.TO, klass.maxlen, flavor='raw', zero=True) + buf = lltype.malloc(rffi.CCHARP.TO, klass.maxlen, flavor='raw', zero=True, + track_allocation=False) # Initialize the family to the correct value. Avoids surprizes on # Windows when calling a function that unexpectedly does not set # the output address (e.g. recvfrom() on a connected IPv4 socket). diff --git a/rpython/rtyper/lltypesystem/rffi.py b/rpython/rtyper/lltypesystem/rffi.py --- a/rpython/rtyper/lltypesystem/rffi.py +++ b/rpython/rtyper/lltypesystem/rffi.py @@ -934,10 +934,8 @@ if tp is lltype.SingleFloat: return 4 if tp is lltype.LongFloat: - if globals()['r_void*'].BITS == 32: - return 12 - else: - return 16 + import ctypes # :-/ + return ctypes.sizeof(ctypes.c_longdouble) assert isinstance(tp, lltype.Number) if tp is lltype.Signed: return LONG_BIT/8 From noreply at buildbot.pypy.org Fri Apr 5 14:22:27 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 5 Apr 2013 14:22:27 +0200 (CEST) Subject: [pypy-commit] cffi default: Hack to support, on top of CPython, older versions of pycparser Message-ID: <20130405122227.042E51C039A@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r1234:c2539e8cdc21 Date: 2013-04-05 14:22 +0200 http://bitbucket.org/cffi/cffi/changeset/c2539e8cdc21/ Log: Hack to support, on top of CPython, older versions of pycparser diff --git a/testing/test_zintegration.py b/testing/test_zintegration.py --- a/testing/test_zintegration.py +++ b/testing/test_zintegration.py @@ -23,6 +23,12 @@ modules = ('cffi', '_cffi_backend') except ImportError: modules = ('cffi', '_cffi_backend', 'pycparser') + try: + import ply + except ImportError: + pass + else: + modules += ('ply',) # needed for older versions of pycparser for module in modules: target = imp.find_module(module)[1] os.symlink(target, os.path.join(site_packages, From noreply at buildbot.pypy.org Fri Apr 5 14:28:03 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 5 Apr 2013 14:28:03 +0200 (CEST) Subject: [pypy-commit] cffi release-0.6: Mark the release 0.6. Message-ID: <20130405122803.A85A81C0337@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: release-0.6 Changeset: r1235:22024b307b76 Date: 2013-04-05 14:27 +0200 http://bitbucket.org/cffi/cffi/changeset/22024b307b76/ Log: Mark the release 0.6. From noreply at buildbot.pypy.org Fri Apr 5 14:28:14 2013 From: noreply at buildbot.pypy.org (fijal) Date: Fri, 5 Apr 2013 14:28:14 +0200 (CEST) Subject: [pypy-commit] pypy default: we can't reset the statement to none here, fix it Message-ID: <20130405122814.118EC1C0337@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r63058:221d5aeae574 Date: 2013-04-05 14:27 +0200 http://bitbucket.org/pypy/pypy/changeset/221d5aeae574/ Log: we can't reset the statement to none here, fix it diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -1080,7 +1080,6 @@ next_row = self.__next_row except AttributeError: self.__statement._reset() - self.__statement = None raise StopIteration del self.__next_row diff --git a/pypy/module/test_lib_pypy/test_sqlite3.py b/pypy/module/test_lib_pypy/test_sqlite3.py --- a/pypy/module/test_lib_pypy/test_sqlite3.py +++ b/pypy/module/test_lib_pypy/test_sqlite3.py @@ -210,3 +210,9 @@ gc.collect() got = (val[0], val[1], val[2], val[3]) assert got == ('b', 'l', 'o', 'b') + +def test_description_after_fetchall(): + con = _sqlite3.connect(":memory:") + cur = con.cursor() + cur.execute("select 42").fetchall() + assert cur.description is not None From noreply at buildbot.pypy.org Fri Apr 5 14:29:11 2013 From: noreply at buildbot.pypy.org (fijal) Date: Fri, 5 Apr 2013 14:29:11 +0200 (CEST) Subject: [pypy-commit] pypy release-2.0-beta2: merge default Message-ID: <20130405122911.31EE21C0337@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: release-2.0-beta2 Changeset: r63059:61273f6466dc Date: 2013-04-05 14:28 +0200 http://bitbucket.org/pypy/pypy/changeset/61273f6466dc/ Log: merge default diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -1080,7 +1080,6 @@ next_row = self.__next_row except AttributeError: self.__statement._reset() - self.__statement = None raise StopIteration del self.__next_row diff --git a/pypy/module/test_lib_pypy/test_sqlite3.py b/pypy/module/test_lib_pypy/test_sqlite3.py --- a/pypy/module/test_lib_pypy/test_sqlite3.py +++ b/pypy/module/test_lib_pypy/test_sqlite3.py @@ -210,3 +210,9 @@ gc.collect() got = (val[0], val[1], val[2], val[3]) assert got == ('b', 'l', 'o', 'b') + +def test_description_after_fetchall(): + con = _sqlite3.connect(":memory:") + cur = con.cursor() + cur.execute("select 42").fetchall() + assert cur.description is not None From noreply at buildbot.pypy.org Fri Apr 5 14:35:08 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 5 Apr 2013 14:35:08 +0200 (CEST) Subject: [pypy-commit] cffi release-0.6: Add the checksums Message-ID: <20130405123508.9F1EA1C039A@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: release-0.6 Changeset: r1236:4cf03951bacb Date: 2013-04-05 14:31 +0200 http://bitbucket.org/cffi/cffi/changeset/4cf03951bacb/ Log: Add the checksums diff --git a/doc/source/index.rst b/doc/source/index.rst --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -94,9 +94,9 @@ - Or grab the most current version by following the instructions below. - - MD5: ... + - MD5: 5be33b1ab0247a984d42b27344519337 - - SHA: ... + - SHA: e104c0d385e46c008080a3c751fa40d3f07f88be * Or get it from the `Bitbucket page`_: ``hg clone https://bitbucket.org/cffi/cffi`` From noreply at buildbot.pypy.org Fri Apr 5 14:41:02 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 5 Apr 2013 14:41:02 +0200 (CEST) Subject: [pypy-commit] cffi default: Update the version of PyPy required Message-ID: <20130405124102.39CB81C0A11@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r1237:6ae25e98df41 Date: 2013-04-05 14:40 +0200 http://bitbucket.org/cffi/cffi/changeset/6ae25e98df41/ Log: Update the version of PyPy required diff --git a/doc/source/index.rst b/doc/source/index.rst --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -63,7 +63,7 @@ left. It supports CPython 2.6; 2.7; 3.x (tested with 3.2 and 3.3); -and PyPy 2.0 beta1 or later. +and PyPy 2.0 beta2 or later. Its speed is comparable to ctypes on CPython (a bit faster but a higher warm-up time). It is already faster on PyPy (1.5x-2x), but not yet @@ -71,7 +71,7 @@ Requirements: -* CPython 2.6 or 2.7 or 3.x, or PyPy trunk +* CPython 2.6 or 2.7 or 3.x, or PyPy 2.0 beta2 * on CPython you need to build the C extension module, so you need ``python-dev`` and ``libffi-dev`` (for Windows, libffi is included From noreply at buildbot.pypy.org Fri Apr 5 14:41:03 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 5 Apr 2013 14:41:03 +0200 (CEST) Subject: [pypy-commit] cffi release-0.6: hg merge default Message-ID: <20130405124103.5433D1C0A11@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: release-0.6 Changeset: r1238:598753c0dca2 Date: 2013-04-05 14:40 +0200 http://bitbucket.org/cffi/cffi/changeset/598753c0dca2/ Log: hg merge default diff --git a/doc/source/index.rst b/doc/source/index.rst --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -63,7 +63,7 @@ left. It supports CPython 2.6; 2.7; 3.x (tested with 3.2 and 3.3); -and PyPy 2.0 beta1 or later. +and PyPy 2.0 beta2 or later. Its speed is comparable to ctypes on CPython (a bit faster but a higher warm-up time). It is already faster on PyPy (1.5x-2x), but not yet @@ -71,7 +71,7 @@ Requirements: -* CPython 2.6 or 2.7 or 3.x, or PyPy trunk +* CPython 2.6 or 2.7 or 3.x, or PyPy 2.0 beta2 * on CPython you need to build the C extension module, so you need ``python-dev`` and ``libffi-dev`` (for Windows, libffi is included From noreply at buildbot.pypy.org Fri Apr 5 15:19:02 2013 From: noreply at buildbot.pypy.org (fijal) Date: Fri, 5 Apr 2013 15:19:02 +0200 (CEST) Subject: [pypy-commit] pypy.org extradoc: fix the typo Message-ID: <20130405131902.6F2FC1C0337@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: extradoc Changeset: r386:261b2d7db039 Date: 2013-04-05 15:18 +0200 http://bitbucket.org/pypy/pypy.org/changeset/261b2d7db039/ Log: fix the typo diff --git a/source/performance.txt b/source/performance.txt --- a/source/performance.txt +++ b/source/performance.txt @@ -179,7 +179,7 @@ with the admittedly less readable:: - s = "%(head)%(body)%(maybe)%(tail)" % locals() + s = "%(head)s%(body)s%(maybe)s%(tail)s" % locals() or even:: From noreply at buildbot.pypy.org Fri Apr 5 15:19:42 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 5 Apr 2013 15:19:42 +0200 (CEST) Subject: [pypy-commit] pypy.org extradoc: Regenerate Message-ID: <20130405131942.397DE1C0337@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: extradoc Changeset: r387:9fe79f577903 Date: 2013-04-05 15:19 +0200 http://bitbucket.org/pypy/pypy.org/changeset/9fe79f577903/ Log: Regenerate diff --git a/performance.html b/performance.html --- a/performance.html +++ b/performance.html @@ -195,7 +195,7 @@

    with the admittedly less readable:

    -s = "%(head)%(body)%(maybe)%(tail)" % locals()
    +s = "%(head)s%(body)s%(maybe)s%(tail)s" % locals()
     

    or even:

    
    From noreply at buildbot.pypy.org  Fri Apr  5 17:20:43 2013
    From: noreply at buildbot.pypy.org (bivab)
    Date: Fri,  5 Apr 2013 17:20:43 +0200 (CEST)
    Subject: [pypy-commit] pypy default: (fijal,
     bivab) fix test_gc_integration on ARM. When calling the
     writebarrier on
    Message-ID: <20130405152043.E86391C0337@cobra.cs.uni-duesseldorf.de>
    
    Author: David Schneider 
    Branch: 
    Changeset: r63062:55a59cc5a0b5
    Date: 2013-04-05 17:06 +0200
    http://bitbucket.org/pypy/pypy/changeset/55a59cc5a0b5/
    
    Log:	(fijal, bivab) fix test_gc_integration on ARM. When calling the
    	writebarrier on the jitframe the argument was not passed correctly
    
    diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py
    --- a/rpython/jit/backend/arm/assembler.py
    +++ b/rpython/jit/backend/arm/assembler.py
    @@ -526,9 +526,7 @@
                 self.gen_shadowstack_header(gcrootmap)
     
         def gen_shadowstack_header(self, gcrootmap):
    -        # we need to put two words into the shadowstack: the MARKER_FRAME
    -        # and the address of the frame (fp, actually)
    -        # lr = rst addr
    +        # lr = shadow stack top addr
             # ip = *lr
             rst = gcrootmap.get_root_stack_top_addr()
             self.mc.gen_load_int(r.lr.value, rst)
    diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py
    --- a/rpython/jit/backend/arm/opassembler.py
    +++ b/rpython/jit/backend/arm/opassembler.py
    @@ -628,12 +628,14 @@
                                         bool(self._regalloc.vfprm.reg_bindings))
                 assert self.wb_slowpath[helper_num] != 0
             #
    -        if not is_frame and loc_base is not r.r0:
    +        if loc_base is not r.r0:
                 # push two registers to keep stack aligned
                 mc.PUSH([r.r0.value, loc_base.value])
    -            remap_frame_layout(self, [loc_base], [r.r0], r.ip)
    +            mc.MOV_rr(r.r0.value, loc_base.value)
    +            if is_frame:
    +                assert loc_base is r.fp
             mc.BL(self.wb_slowpath[helper_num])
    -        if not is_frame and loc_base is not r.r0:
    +        if loc_base is not r.r0:
                 mc.POP([r.r0.value, loc_base.value])
     
             if card_marking:
    diff --git a/rpython/jit/backend/llsupport/test/test_gc_integration.py b/rpython/jit/backend/llsupport/test/test_gc_integration.py
    --- a/rpython/jit/backend/llsupport/test/test_gc_integration.py
    +++ b/rpython/jit/backend/llsupport/test/test_gc_integration.py
    @@ -256,7 +256,9 @@
                 if self.cpu.IS_64_BIT:
                     assert frame.jf_gcmap[idx] == (1<<29) | (1 << 30)
                 else:
    -                assert frame.jf_gcmap[idx] == (1<<24) | (1 << 23)
    +                assert frame.jf_gcmap[idx]
    +                exp_idx = self.cpu.JITFRAME_FIXED_SIZE - 32 * idx + 1 # +1 from i0
    +                assert frame.jf_gcmap[idx] == (1 << (exp_idx + 1)) | (1 << exp_idx)
     
             self.cpu = self.getcpu(check)
             ops = '''
    @@ -680,7 +682,7 @@
     
             def f(frame, x):
                 # all the gc pointers are alive p1 -> p7 (but not p0)
    -            assert bin(frame.jf_gcmap[0]).count('1') == 7
    +            assert getmap(frame).count('1') == 7 #
                 assert x == 1
                 return 2
             
    @@ -713,7 +715,7 @@
             def f(frame, arg, x):
                 assert not arg
                 assert frame.jf_gcmap[0] & 31 == 0
    -            assert bin(frame.jf_gcmap[0]).count('1') == 3 # p1, p2, p3, but
    +            assert getmap(frame).count('1') == 3 # p1, p2, p3, but
                 # not in registers
                 frame.jf_descr = frame.jf_force_descr # make guard_not_forced fail
                 assert x == 1
    @@ -749,7 +751,8 @@
             cpu.compile_loop(loop.inputargs, loop.operations, token)
             frame = lltype.cast_opaque_ptr(JITFRAMEPTR,
                                            cpu.execute_token(token, 1, a))
    -        assert bin(frame.jf_gcmap[0]).count('1') == 4
    +        
    +        assert getmap(frame).count('1') == 4
     
         def test_call_gcmap_no_guard(self):
             cpu = self.cpu
    @@ -757,7 +760,7 @@
             def f(frame, arg, x):
                 assert not arg
                 assert frame.jf_gcmap[0] & 31 == 0
    -            assert bin(frame.jf_gcmap[0]).count('1') == 3 # p1, p2, p3
    +            assert getmap(frame).count('1') == 3 # p1, p2, p3
                 frame.jf_descr = frame.jf_force_descr # make guard_not_forced fail
                 assert x == 1
                 return lltype.nullptr(llmemory.GCREF.TO)
    @@ -792,4 +795,5 @@
             cpu.compile_loop(loop.inputargs, loop.operations, token)
             frame = lltype.cast_opaque_ptr(JITFRAMEPTR,
                                            cpu.execute_token(token, 1, a))
    -        assert bin(frame.jf_gcmap[0]).count('1') == 4
    +        assert getmap(frame).count('1') == 4
    +
    
    From noreply at buildbot.pypy.org  Fri Apr  5 17:20:45 2013
    From: noreply at buildbot.pypy.org (bivab)
    Date: Fri,  5 Apr 2013 17:20:45 +0200 (CEST)
    Subject: [pypy-commit] pypy default: Enable float support on ARM hardfloat.
    Message-ID: <20130405152045.0A2A71C0337@cobra.cs.uni-duesseldorf.de>
    
    Author: David Schneider 
    Branch: 
    Changeset: r63063:473a75371871
    Date: 2013-04-05 17:17 +0200
    http://bitbucket.org/pypy/pypy/changeset/473a75371871/
    
    Log:	Enable float support on ARM hardfloat.
    
    	Currently requires a patched version of CPython with the latest
    	libffi from git to run all the tests successfully.
    
    diff --git a/rpython/jit/backend/arm/runner.py b/rpython/jit/backend/arm/runner.py
    --- a/rpython/jit/backend/arm/runner.py
    +++ b/rpython/jit/backend/arm/runner.py
    @@ -120,7 +120,7 @@
         """ARM v7 uses hardfp ABI, requires vfp"""
         hf_abi = True
         backend_name = "armv7hf"
    -    supports_floats = False
    +    supports_floats = True
         supports_singlefloats = False
     
     
    @@ -129,5 +129,5 @@
         hf_abi = True
         arch_version = 6
         backend_name = "armv6hf"
    -    supports_floats = False
    +    supports_floats = True
         supports_singlefloats = False
    
    From noreply at buildbot.pypy.org  Fri Apr  5 17:20:46 2013
    From: noreply at buildbot.pypy.org (bivab)
    Date: Fri,  5 Apr 2013 17:20:46 +0200 (CEST)
    Subject: [pypy-commit] pypy default: merge heads
    Message-ID: <20130405152046.2786A1C0337@cobra.cs.uni-duesseldorf.de>
    
    Author: David Schneider 
    Branch: 
    Changeset: r63064:7fdab13dc79c
    Date: 2013-04-05 17:19 +0200
    http://bitbucket.org/pypy/pypy/changeset/7fdab13dc79c/
    
    Log:	merge heads
    
    diff --git a/pypy/module/pyexpat/interp_pyexpat.py b/pypy/module/pyexpat/interp_pyexpat.py
    --- a/pypy/module/pyexpat/interp_pyexpat.py
    +++ b/pypy/module/pyexpat/interp_pyexpat.py
    @@ -305,14 +305,15 @@
                 w_result = space.call_function(handler, %(wargs)s)
                 %(post_code)s
             except OperationError, e:
    -            parser._exc_info = e
    +            if not parser._exc_info: # don't override an existing exception
    +                 parser._exc_info = e
                 XML_StopParser(parser.itself, XML_FALSE)
                 return %(result_error)s
             return %(result_converter)s
         callback = %(name)s_callback
         """ % locals())
     
    -    exec str(src)
    +    exec src.compile()
     
         c_name = 'XML_Set' + name
         callback_type = lltype.Ptr(lltype.FuncType(
    @@ -335,7 +336,8 @@
         try:
             parser.UnknownEncodingHandler(space, name, info)
         except OperationError, e:
    -        parser._exc_info = e
    +        if parser._exc_info:
    +            parser._exc_info = e
             XML_StopParser(parser.itself, XML_FALSE)
             result = 0
         else:
    diff --git a/pypy/module/pyexpat/test/test_parser.py b/pypy/module/pyexpat/test/test_parser.py
    --- a/pypy/module/pyexpat/test/test_parser.py
    +++ b/pypy/module/pyexpat/test/test_parser.py
    @@ -167,3 +167,46 @@
                 p = pyexpat.ParserCreate()
                 p.ParseFile(fake_reader)
                 assert fake_reader.read_count == 4
    +
    +class AppTestPyexpat2:
    +    spaceconfig = dict(usemodules=['pyexpat', 'itertools', '_socket',
    +                                   'rctime', 'struct', 'binascii'])
    +
    +    def test_django_bug(self):
    +        xml_str = ''
    +
    +        from xml.dom import pulldom
    +        from xml.sax import handler
    +        from xml.sax.expatreader import ExpatParser as _ExpatParser
    +        from StringIO import StringIO
    +
    +        class DefusedExpatParser(_ExpatParser):
    +            def start_doctype_decl(self, name, sysid, pubid, has_internal_subset):
    +                raise DTDForbidden(name, sysid, pubid)
    +
    +            def external_entity_ref_handler(self, context, base, sysid, pubid):
    +                raise ExternalReferenceForbidden(context, base, sysid, pubid)
    +
    +            def reset(self):
    +                _ExpatParser.reset(self)
    +                parser = self._parser
    +                parser.StartDoctypeDeclHandler = self.start_doctype_decl
    +                parser.ExternalEntityRefHandler = self.external_entity_ref_handler
    +
    +
    +        class DTDForbidden(ValueError):
    +            pass
    +
    +
    +        class ExternalReferenceForbidden(ValueError):
    +            pass
    +
    +        stream = pulldom.parse(StringIO(xml_str), DefusedExpatParser())
    +
    +        try:
    +            for event, node in stream:
    +                print event, node
    +        except DTDForbidden:
    +            pass
    +        else:
    +            raise Exception("should raise DTDForbidden")
    
    From noreply at buildbot.pypy.org  Fri Apr  5 17:39:41 2013
    From: noreply at buildbot.pypy.org (arigo)
    Date: Fri,  5 Apr 2013 17:39:41 +0200 (CEST)
    Subject: [pypy-commit] pypy default: merge release-2.0-beta2 back into
     "default", to get the updated version number
    Message-ID: <20130405153941.B334E1C0337@cobra.cs.uni-duesseldorf.de>
    
    Author: Armin Rigo 
    Branch: 
    Changeset: r63065:ad65bcfd3efb
    Date: 2013-04-05 17:39 +0200
    http://bitbucket.org/pypy/pypy/changeset/ad65bcfd3efb/
    
    Log:	merge release-2.0-beta2 back into "default", to get the updated
    	version number
    
    diff --git a/pypy/module/cpyext/include/patchlevel.h b/pypy/module/cpyext/include/patchlevel.h
    --- a/pypy/module/cpyext/include/patchlevel.h
    +++ b/pypy/module/cpyext/include/patchlevel.h
    @@ -29,7 +29,7 @@
     #define PY_VERSION		"2.7.3"
     
     /* PyPy version as a string */
    -#define PYPY_VERSION "2.0.0-beta1"
    +#define PYPY_VERSION "2.0.0-beta2"
     
     /* Subversion Revision number of this file (not of the repository).
      * Empty since Mercurial migration. */
    diff --git a/pypy/module/sys/version.py b/pypy/module/sys/version.py
    --- a/pypy/module/sys/version.py
    +++ b/pypy/module/sys/version.py
    @@ -11,7 +11,7 @@
     #XXX # sync CPYTHON_VERSION with patchlevel.h, package.py
     CPYTHON_API_VERSION        = 1013   #XXX # sync with include/modsupport.h
     
    -PYPY_VERSION               = (2, 0, 0, "beta", 1)    #XXX # sync patchlevel.h
    +PYPY_VERSION               = (2, 0, 0, "beta", 2)    #XXX # sync patchlevel.h
     
     if platform.name == 'msvc':
         COMPILER_INFO = 'MSC v.%d 32 bit' % (platform.version * 10 + 600)
    
    From noreply at buildbot.pypy.org  Fri Apr  5 19:38:18 2013
    From: noreply at buildbot.pypy.org (bdkearns)
    Date: Fri,  5 Apr 2013 19:38:18 +0200 (CEST)
    Subject: [pypy-commit] pypy default: fix this copy more simply and in
    	another place
    Message-ID: <20130405173818.93F0A1C0A11@cobra.cs.uni-duesseldorf.de>
    
    Author: Brian Kearns 
    Branch: 
    Changeset: r63066:ffe9f0680418
    Date: 2013-04-05 13:38 -0400
    http://bitbucket.org/pypy/pypy/changeset/ffe9f0680418/
    
    Log:	fix this copy more simply and in another place
    
    diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py
    --- a/lib_pypy/_sqlite3.py
    +++ b/lib_pypy/_sqlite3.py
    @@ -29,7 +29,6 @@
     import string
     import sys
     import weakref
    -import array
     from threading import _get_ident as _thread_get_ident
     try:
         from __pypy__ import newlist_hint
    @@ -959,11 +958,7 @@
                     elif typ == _lib.SQLITE_BLOB:
                         blob = _lib.sqlite3_column_blob(self.__statement._statement, i)
                         blob_len = _lib.sqlite3_column_bytes(self.__statement._statement, i)
    -                    # make a copy of the data into an array, in order to get
    -                    # a read-write buffer in the end, and one that own the
    -                    # memory for a more predictable length of time than 'blob'
    -                    copy = array.array("c", _ffi.buffer(blob, blob_len))
    -                    val = _BLOB_TYPE(copy)
    +                    val = _BLOB_TYPE(_ffi.buffer(blob, blob_len)[:])
                 row.append(val)
             return tuple(row)
     
    @@ -1391,7 +1386,7 @@
             elif typ == _lib.SQLITE_BLOB:
                 blob = _lib.sqlite3_value_blob(params[i])
                 blob_len = _lib.sqlite3_value_bytes(params[i])
    -            val = _BLOB_TYPE(_ffi.buffer(blob, blob_len))
    +            val = _BLOB_TYPE(_ffi.buffer(blob, blob_len)[:])
             else:
                 raise NotImplementedError
             _params.append(val)
    
    From noreply at buildbot.pypy.org  Fri Apr  5 19:43:21 2013
    From: noreply at buildbot.pypy.org (bivab)
    Date: Fri,  5 Apr 2013 19:43:21 +0200 (CEST)
    Subject: [pypy-commit] pypy default: fix test_tabs to check rpython too and
     make the test pass
    Message-ID: <20130405174321.4F6BA1C039A@cobra.cs.uni-duesseldorf.de>
    
    Author: David Schneider 
    Branch: 
    Changeset: r63067:8a5f5f3f1a51
    Date: 2013-04-05 19:36 +0200
    http://bitbucket.org/pypy/pypy/changeset/8a5f5f3f1a51/
    
    Log:	fix test_tabs to check rpython too and make the test pass
    
    diff --git a/pypy/tool/test/test_tab.py b/pypy/tool/test/test_tab.py
    --- a/pypy/tool/test/test_tab.py
    +++ b/pypy/tool/test/test_tab.py
    @@ -5,7 +5,7 @@
     import os
     from pypy.conftest import pypydir
     
    -ROOT = pypydir
    +ROOT = os.path.abspath(os.path.join(pypydir, '..'))
     EXCLUDE = {}
     
     
    diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py
    --- a/rpython/jit/backend/arm/assembler.py
    +++ b/rpython/jit/backend/arm/assembler.py
    @@ -305,7 +305,7 @@
                 self._restore_exception(mc, exc0, exc1)
                 mc.VPOP([vfpr.value for vfpr in r.caller_vfp_resp])
                 assert exc0 is not None
    -	    assert exc1 is not None
    +            assert exc1 is not None
                 mc.POP([gpr.value for gpr in r.caller_resp] +
                                 [exc0.value, exc1.value])
             #
    @@ -1060,8 +1060,7 @@
                 self.mc.PUSH([helper.value], cond=cond)
             self.load_reg(self.mc, loc, r.fp, offset, cond=cond, helper=helper)
             if save_helper:
    -	    self.mc.POP([helper.value], cond=cond)
    -
    +            self.mc.POP([helper.value], cond=cond)
     
         def _mov_imm_float_to_loc(self, prev_loc, loc, cond=c.AL):
             if loc.is_vfp_reg():
    diff --git a/rpython/jit/backend/arm/test/test_calling_convention.py b/rpython/jit/backend/arm/test/test_calling_convention.py
    --- a/rpython/jit/backend/arm/test/test_calling_convention.py
    +++ b/rpython/jit/backend/arm/test/test_calling_convention.py
    @@ -72,7 +72,7 @@
             callargs = []
             def func(f0, f1, f2, f3, f4, f5, f6, i0, f7, i1, f8, f9):
                 callargs.append(zip(range(12),
    -			[f0, f1, f2, f3, f4, f5, f6, i0, f7, i1, f8, f9]))
    +                        [f0, f1, f2, f3, f4, f5, f6, i0, f7, i1, f8, f9]))
                 return f0 + f1 + f2 + f3 + f4 + f5 + f6 + float(i0 + i1) + f7 + f8 + f9
             F = lltype.Float
             I = lltype.Signed
    @@ -103,7 +103,7 @@
             callargs = []
             def func(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9):
                 callargs.append(zip(range(10),
    -			[f0, f1, f2, f3, f4, f5, f6, f7, f8, f9]))
    +                        [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9]))
                 return f0 + f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8 + f9
             F = lltype.Float
             FUNC = self.FuncType([F] * 10, F)
    @@ -125,7 +125,7 @@
             callargs = []
             def func(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9):
                 callargs.append(zip(range(10),
    -			[f0, f1, f2, f3, f4, f5, f6, f7, f8, f9]))
    +                        [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9]))
                 return f0 + f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8 + f9
     
             I = lltype.Signed
    diff --git a/rpython/jit/backend/test/calling_convention_test.py b/rpython/jit/backend/test/calling_convention_test.py
    --- a/rpython/jit/backend/test/calling_convention_test.py
    +++ b/rpython/jit/backend/test/calling_convention_test.py
    @@ -384,7 +384,7 @@
     
         def test_call_aligned_explicit_check(self):
             if (not platform.machine().startswith('arm') and
    -		sys.maxint == 2 ** 31 - 1): # XXX is still necessary on x86?
    +                sys.maxint == 2 ** 31 - 1): # XXX is still necessary on x86?
                 py.test.skip("libffi on 32bit is broken")
             cpu = self.cpu
             if not cpu.supports_floats:
    diff --git a/rpython/jit/backend/x86/runner.py b/rpython/jit/backend/x86/runner.py
    --- a/rpython/jit/backend/x86/runner.py
    +++ b/rpython/jit/backend/x86/runner.py
    @@ -58,10 +58,10 @@
             self.assembler = Assembler386(self, self.translate_support_code)
     
         def build_regalloc(self):
    -	''' for tests'''
    -	from rpython.jit.backend.x86.regalloc import RegAlloc
    -	assert self.assembler is not None
    -	return RegAlloc(self.assembler, False)
    +        ''' for tests'''
    +        from rpython.jit.backend.x86.regalloc import RegAlloc
    +        assert self.assembler is not None
    +        return RegAlloc(self.assembler, False)
     
         def setup_once(self):
             self.profile_agent.startup()
    diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
    --- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
    +++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
    @@ -4282,9 +4282,9 @@
             self.optimize_loop(ops, expected)
     
         def test_add_sub_ovf_second_operation_regular(self):
    -	py.test.skip("Smalltalk would like this to pass")
    -	# This situation occurs in Smalltalk because it uses 1-based indexing.
    -	# The below code is equivalent to a loop over an array.
    +        py.test.skip("Smalltalk would like this to pass")
    +        # This situation occurs in Smalltalk because it uses 1-based indexing.
    +        # The below code is equivalent to a loop over an array.
             ops = """
             [i1]
             i2 = int_sub(i1, 1)
    
    From noreply at buildbot.pypy.org  Fri Apr  5 19:43:22 2013
    From: noreply at buildbot.pypy.org (bivab)
    Date: Fri,  5 Apr 2013 19:43:22 +0200 (CEST)
    Subject: [pypy-commit] pypy default: merge heads
    Message-ID: <20130405174322.96D621C039A@cobra.cs.uni-duesseldorf.de>
    
    Author: David Schneider 
    Branch: 
    Changeset: r63068:e06dbffccdc6
    Date: 2013-04-05 19:43 +0200
    http://bitbucket.org/pypy/pypy/changeset/e06dbffccdc6/
    
    Log:	merge heads
    
    diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py
    --- a/lib_pypy/_sqlite3.py
    +++ b/lib_pypy/_sqlite3.py
    @@ -29,7 +29,6 @@
     import string
     import sys
     import weakref
    -import array
     from threading import _get_ident as _thread_get_ident
     try:
         from __pypy__ import newlist_hint
    @@ -959,11 +958,7 @@
                     elif typ == _lib.SQLITE_BLOB:
                         blob = _lib.sqlite3_column_blob(self.__statement._statement, i)
                         blob_len = _lib.sqlite3_column_bytes(self.__statement._statement, i)
    -                    # make a copy of the data into an array, in order to get
    -                    # a read-write buffer in the end, and one that own the
    -                    # memory for a more predictable length of time than 'blob'
    -                    copy = array.array("c", _ffi.buffer(blob, blob_len))
    -                    val = _BLOB_TYPE(copy)
    +                    val = _BLOB_TYPE(_ffi.buffer(blob, blob_len)[:])
                 row.append(val)
             return tuple(row)
     
    @@ -1391,7 +1386,7 @@
             elif typ == _lib.SQLITE_BLOB:
                 blob = _lib.sqlite3_value_blob(params[i])
                 blob_len = _lib.sqlite3_value_bytes(params[i])
    -            val = _BLOB_TYPE(_ffi.buffer(blob, blob_len))
    +            val = _BLOB_TYPE(_ffi.buffer(blob, blob_len)[:])
             else:
                 raise NotImplementedError
             _params.append(val)
    
    From noreply at buildbot.pypy.org  Fri Apr  5 22:39:28 2013
    From: noreply at buildbot.pypy.org (bdkearns)
    Date: Fri,  5 Apr 2013 22:39:28 +0200 (CEST)
    Subject: [pypy-commit] pypy default: more cleanups for sqlite
    Message-ID: <20130405203928.642EC1C039A@cobra.cs.uni-duesseldorf.de>
    
    Author: Brian Kearns 
    Branch: 
    Changeset: r63069:f09e57516642
    Date: 2013-04-05 16:32 -0400
    http://bitbucket.org/pypy/pypy/changeset/f09e57516642/
    
    Log:	more cleanups for sqlite
    
    diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py
    --- a/lib_pypy/_sqlite3.py
    +++ b/lib_pypy/_sqlite3.py
    @@ -852,7 +852,7 @@
             self._reset = False
             self.__locked = False
             self.__closed = False
    -        self.__description = None
    +        self.__lastrowid = None
             self.__rowcount = -1
     
             con._check_thread()
    @@ -972,20 +972,24 @@
             try:
                 if not isinstance(sql, basestring):
                     raise ValueError("operation parameter must be str or unicode")
    -            self.__description = None
    +            try:
    +                del self.__description
    +            except AttributeError:
    +                pass
                 self.__rowcount = -1
                 self.__statement = self.__connection._statement_cache.get(sql)
     
                 if self.__connection._isolation_level is not None:
    -                if self.__statement._kind == Statement._DDL:
    +                if self.__statement._type in ("UPDATE", "DELETE", "INSERT", "REPLACE"):
    +                    if not self.__connection._in_transaction:
    +                        self.__connection._begin()
    +                elif self.__statement._type == "OTHER":
                         if self.__connection._in_transaction:
                             self.__connection.commit()
    -                elif self.__statement._kind == Statement._DML:
    -                    if not self.__connection._in_transaction:
    -                        self.__connection._begin()
    -
    -            if multiple and self.__statement._kind != Statement._DML:
    -                raise ProgrammingError("executemany is only for DML statements")
    +                elif self.__statement._type == "SELECT":
    +                    if multiple:
    +                        raise ProgrammingError("You cannot execute SELECT "
    +                                               "statements in executemany().")
     
                 for params in many_params:
                     self.__statement._set_params(params)
    @@ -996,17 +1000,26 @@
                         self.__statement._reset()
                         raise self.__connection._get_exception(ret)
     
    -                if self.__statement._kind == Statement._DML:
    +                if ret == _lib.SQLITE_ROW:
    +                    if multiple:
    +                        raise ProgrammingError("executemany() can only execute DML statements.")
    +                    self.__build_row_cast_map()
    +                    self.__next_row = self.__fetch_one_row()
    +                elif ret == _lib.SQLITE_DONE and not multiple:
                         self.__statement._reset()
     
    -                if ret == _lib.SQLITE_ROW:
    -                    self.__build_row_cast_map()
    -                    self.__next_row = self.__fetch_one_row()
    -
    -                if self.__statement._kind == Statement._DML:
    +                if self.__statement._type in ("UPDATE", "DELETE", "INSERT", "REPLACE"):
                         if self.__rowcount == -1:
                             self.__rowcount = 0
                         self.__rowcount += _lib.sqlite3_changes(self.__connection._db)
    +
    +                if not multiple and self.__statement._type == "INSERT":
    +                    self.__lastrowid = _lib.sqlite3_last_insert_rowid(self.__connection._db)
    +                else:
    +                    self.__lastrowid = None
    +
    +                if multiple:
    +                    self.__statement._reset()
             finally:
                 self.__connection._in_transaction = \
                     not _lib.sqlite3_get_autocommit(self.__connection._db)
    @@ -1118,13 +1131,15 @@
         rowcount = property(__get_rowcount)
     
         def __get_description(self):
    -        if self.__description is None:
    +        try:
    +            return self.__description
    +        except AttributeError:
                 self.__description = self.__statement._get_description()
    -        return self.__description
    +            return self.__description
         description = property(__get_description)
     
         def __get_lastrowid(self):
    -        return _lib.sqlite3_last_insert_rowid(self.__connection._db)
    +        return self.__lastrowid
         lastrowid = property(__get_lastrowid)
     
         def setinputsizes(self, *args):
    @@ -1135,8 +1150,6 @@
     
     
     class Statement(object):
    -    _DML, _DQL, _DDL = range(3)
    -
         _statement = None
     
         def __init__(self, connection, sql):
    @@ -1147,13 +1160,14 @@
     
             if not isinstance(sql, basestring):
                 raise Warning("SQL is of wrong type. Must be string or unicode.")
    -        first_word = self._statement_kind = sql.lstrip().split(" ")[0].upper()
    -        if first_word in ("INSERT", "UPDATE", "DELETE", "REPLACE"):
    -            self._kind = Statement._DML
    -        elif first_word in ("SELECT", "PRAGMA"):
    -            self._kind = Statement._DQL
    +
    +        first_word = sql.lstrip().split(" ")[0].upper()
    +        if first_word == "":
    +            self._type = "INVALID"
    +        elif first_word in ("SELECT", "INSERT", "UPDATE", "DELETE", "REPLACE"):
    +            self._type = first_word
             else:
    -            self._kind = Statement._DDL
    +            self._type = "OTHER"
     
             if isinstance(sql, unicode):
                 sql = sql.encode('utf-8')
    @@ -1166,11 +1180,12 @@
     
             if ret == _lib.SQLITE_OK and not self._statement:
                 # an empty statement, work around that, as it's the least trouble
    +            self._type = "SELECT"
                 c_sql = _ffi.new("char[]", b"select 42")
                 ret = _lib.sqlite3_prepare_v2(self.__con._db, c_sql, -1,
                                               statement_star, next_char)
                 self._statement = statement_star[0]
    -            self._kind = Statement._DQL
    +
             if ret != _lib.SQLITE_OK:
                 raise self.__con._get_exception(ret)
     
    @@ -1281,7 +1296,7 @@
                 raise ValueError("parameters are of unsupported type")
     
         def _get_description(self):
    -        if self._kind == Statement._DML:
    +        if self._type in ("INSERT", "UPDATE", "DELETE", "REPLACE"):
                 return None
             desc = []
             for i in xrange(_lib.sqlite3_column_count(self._statement)):
    diff --git a/pypy/module/test_lib_pypy/test_sqlite3.py b/pypy/module/test_lib_pypy/test_sqlite3.py
    --- a/pypy/module/test_lib_pypy/test_sqlite3.py
    +++ b/pypy/module/test_lib_pypy/test_sqlite3.py
    @@ -216,3 +216,10 @@
         cur = con.cursor()
         cur.execute("select 42").fetchall()
         assert cur.description is not None
    +
    +def test_executemany_lastrowid():
    +    con = _sqlite3.connect(':memory:')
    +    cur = con.cursor()
    +    cur.execute("create table test(a)")
    +    cur.executemany("insert into test values (?)", [[1], [2], [3]])
    +    assert cur.lastrowid is None
    
    From noreply at buildbot.pypy.org  Fri Apr  5 23:36:15 2013
    From: noreply at buildbot.pypy.org (arigo)
    Date: Fri,  5 Apr 2013 23:36:15 +0200 (CEST)
    Subject: [pypy-commit] pypy default: Issue #1435: Add a failing test
    Message-ID: <20130405213615.4D7031C0A11@cobra.cs.uni-duesseldorf.de>
    
    Author: Armin Rigo 
    Branch: 
    Changeset: r63070:ba3fbbd1e5ba
    Date: 2013-04-05 23:35 +0200
    http://bitbucket.org/pypy/pypy/changeset/ba3fbbd1e5ba/
    
    Log:	Issue #1435: Add a failing test
    
    diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
    --- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
    +++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
    @@ -7609,6 +7609,26 @@
             """
             self.optimize_loop(ops, ops)
     
    +    def test_setarrayitem_followed_by_arraycopy_2(self):
    +        ops = """
    +        [i1, i2]
    +        p1 = new_array(i1, descr=arraydescr)
    +        setarrayitem_gc(p1, 0, i2, descr=arraydescr)
    +        p3 = new_array(5, descr=arraydescr)
    +        call(0, p1, p3, 0, 1, 1, descr=arraycopydescr)
    +        i4 = getarrayitem_gc(p3, 1, descr=arraydescr)
    +        jump(i1, i4)
    +        """
    +        expected = """
    +        [i1, i2]
    +        p1 = new_array(i1, descr=arraydescr)
    +        # operations are not all removed because this new_array() is var-sized
    +        # unsure exactly which operations should be left, but right now it's
    +        # really buggy
    +        jump(i1, i2)
    +        """
    +        self.optimize_loop(ops, expected)
    +
         def test_heap_cache_virtuals_forced_by_delayed_setfield(self):
             py.test.skip('not yet supoprted')
             ops = """
    
    From noreply at buildbot.pypy.org  Fri Apr  5 23:36:47 2013
    From: noreply at buildbot.pypy.org (wlav)
    Date: Fri,  5 Apr 2013 23:36:47 +0200 (CEST)
    Subject: [pypy-commit] pypy reflex-support: doh,
    	don't touch memory after free-ing it ...
    Message-ID: <20130405213647.7E4571C0A11@cobra.cs.uni-duesseldorf.de>
    
    Author: Wim Lavrijsen 
    Branch: reflex-support
    Changeset: r63071:7b2dc9dd0300
    Date: 2013-04-05 14:33 -0700
    http://bitbucket.org/pypy/pypy/changeset/7b2dc9dd0300/
    
    Log:	doh, don't touch memory after free-ing it ...
    
    diff --git a/pypy/module/cppyy/capi/loadable_capi.py b/pypy/module/cppyy/capi/loadable_capi.py
    --- a/pypy/module/cppyy/capi/loadable_capi.py
    +++ b/pypy/module/cppyy/capi/loadable_capi.py
    @@ -1,10 +1,11 @@
     from rpython.rtyper.lltypesystem import rffi, lltype
     from rpython.rlib import jit, jit_libffi, libffi, rdynload, objectmodel
    +from rpython.rlib.rarithmetic import r_singlefloat
     from rpython.tool import leakfinder
     
     from pypy.interpreter.error import OperationError
     
    -from pypy.module._cffi_backend import ctypefunc, ctypeprim, ctypeptr, misc
    +from pypy.module._cffi_backend import ctypefunc, ctypeprim, cdataobj, misc
     
     from pypy.module.cppyy.capi.capi_types import C_SCOPE, C_TYPE, C_OBJECT,\
        C_METHOD, C_INDEX, C_INDEX_ARRAY, WLAVC_INDEX, C_METHPTRGETTER_PTR
    @@ -72,11 +73,14 @@
                                         buffer)
     
                 resultdata = rffi.ptradd(buffer, cif_descr.exchange_result)
    +            # this wrapping is unnecessary, but the assumption is that given the
    +            # immediate unwrapping, the round-trip is removed
    +            w_res = self.ctitem.copy_and_convert_to_object(resultdata)
             finally:
                 if raw_string != rffi.cast(rffi.CCHARP, 0):
                     rffi.free_charp(raw_string)
                 lltype.free(buffer, flavor='raw')
    -        return rffi.cast(rffi.LONGP, resultdata)
    +        return w_res
     
     class State(object):
         def __init__(self, space):
    @@ -107,7 +111,7 @@
             c_double = nt.new_primitive_type(space, 'double')
     
             c_ccharp = nt.new_pointer_type(space, c_char)
    -        c_index_array = nt.new_primitive_type(space, 'unsigned long')     # likewise ...
    +        c_index_array = nt.new_pointer_type(space, c_void)
     
             c_voidp  = nt.new_pointer_type(space, c_void)
             c_size_t = nt.new_primitive_type(space, 'size_t')
    @@ -247,16 +251,22 @@
             state.capi_calls[name] = c_call
         return c_call.ctype.rcall(c_call._cdata, args)
     
    -def _longptr_to_int(longptr):
    -    # TODO: not understanding why this should be rffi.LONGP instead of rffi.INTP ??
    -    return int(rffi.cast(rffi.LONGP, longptr)[0])
    +def _cdata_to_cobject(space, w_cdata):
    +    return rffi.cast(C_OBJECT, space.int_w(w_cdata))
    +
    +def _cdata_to_size_t(space, w_cdata):
    +    return rffi.cast(rffi.SIZE_T, space.int_w(w_cdata))
    +
    +def _cdata_to_ptr(space, w_cdata): # TODO: this is both a hack and dreadfully slow
    +    return rffi.cast(rffi.VOIDP,
    +        space.interp_w(cdataobj.W_CData, w_cdata, can_be_None=False)._cdata)
     
     def c_load_dictionary(name):
         return libffi.CDLL(name)
     
     # name to opaque C++ scope representation ------------------------------------
     def c_num_scopes(space, cppscope):
    -    return call_capi(space, 'num_scopes', [_Arg(l=cppscope.handle)])[0]
    +    return space.int_w(call_capi(space, 'num_scopes', [_Arg(l=cppscope.handle)]))
     def c_scope_name(space, cppscope, iscope):
         args = [_Arg(l=cppscope.handle), _Arg(l=iscope)]
         return charp2str_free(space, call_capi(space, 'scope_name', args))
    @@ -264,16 +274,16 @@
     def c_resolve_name(space, name):
         return charp2str_free(space, call_capi(space, 'resolve_name', [_Arg(s=name)]))
     def c_get_scope_opaque(space, name):
    -    return rffi.cast(C_SCOPE, call_capi(space, 'get_scope', [_Arg(s=name)])[0])
    +    return rffi.cast(C_SCOPE, space.int_w(call_capi(space, 'get_scope', [_Arg(s=name)])))
     def c_get_template(space, name):
    -    return rffi.cast(C_TYPE, call_capi(space, 'get_template', [_Arg(s=name)])[0])
    +    return rffi.cast(C_TYPE, space.int_w(call_capi(space, 'get_template', [_Arg(s=name)])))
     def c_actual_class(space, cppclass, cppobj):
         args = [_Arg(l=cppclass.handle), _Arg(l=cppobj)]
    -    return rffi.cast(C_TYPE, call_capi(space, 'actual_class', args)[0])
    +    return rffi.cast(C_TYPE, space.int_w(call_capi(space, 'actual_class', args)))
     
     # memory management ----------------------------------------------------------
     def c_allocate(space, cppclass):
    -    return rffi.cast(C_OBJECT, call_capi(space, 'allocate', [_Arg(l=cppclass.handle)])[0])
    +    return _cdata_to_cobject(space, call_capi(space, 'allocate', [_Arg(l=cppclass.handle)]))
     def c_deallocate(space, cppclass, cppobject):
         call_capi(space, 'deallocate', [_Arg(l=cppclass.handle), _Arg(l=cppobject)])
     def c_destruct(space, cppclass, cppobject):
    @@ -285,65 +295,66 @@
         call_capi(space, 'call_v', args)
     def c_call_b(space, cppmethod, cppobject, nargs, cargs):
         args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)]
    -    return rffi.cast(rffi.UCHARP, call_capi(space, 'call_b', args))[0]
    +    return rffi.cast(rffi.UCHAR, space.c_int_w(call_capi(space, 'call_b', args)))
     def c_call_c(space, cppmethod, cppobject, nargs, cargs):
         args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)]
    -    return rffi.cast(rffi.CCHARP, call_capi(space, 'call_c', args))[0]
    +    return rffi.cast(rffi.CHAR, space.str_w(call_capi(space, 'call_c', args))[0])
     def c_call_h(space, cppmethod, cppobject, nargs, cargs):
         args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)]
    -    return rffi.cast(rffi.SHORTP, call_capi(space, 'call_h', args))[0]
    +    return rffi.cast(rffi.SHORT, space.int_w(call_capi(space, 'call_h', args)))
     def c_call_i(space, cppmethod, cppobject, nargs, cargs):
         args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)]
    -    return rffi.cast(rffi.INTP, call_capi(space, 'call_i', args))[0]  # TODO: should this be LONGP, too?
    +    return rffi.cast(rffi.INT, space.c_int_w(call_capi(space, 'call_i', args)))
     def c_call_l(space, cppmethod, cppobject, nargs, cargs):
         args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)]
    -    return rffi.cast(rffi.LONGP, call_capi(space, 'call_l', args))[0]
    +    return rffi.cast(rffi.LONG, space.int_w(call_capi(space, 'call_l', args)))
     def c_call_ll(space, cppmethod, cppobject, nargs, cargs):
         args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)]
    -    return rffi.cast(rffi.LONGLONGP, call_capi(space, 'call_ll', args))[0]
    +    return rffi.cast(rffi.LONGLONG, space.r_longlong_w(call_capi(space, 'call_ll', args)))
     def c_call_f(space, cppmethod, cppobject, nargs, cargs):
         args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)]
    -    return rffi.cast(rffi.FLOATP, call_capi(space, 'call_f', args))[0]
    +    return rffi.cast(rffi.FLOAT, r_singlefloat(space.float_w(call_capi(space, 'call_f', args))))
     def c_call_d(space, cppmethod, cppobject, nargs, cargs):
         args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)]
    -    return rffi.cast(rffi.DOUBLEP, call_capi(space, 'call_d', args))[0]
    +    return rffi.cast(rffi.DOUBLE, space.float_w(call_capi(space, 'call_d', args)))
     
     def c_call_r(space, cppmethod, cppobject, nargs, cargs):
         args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)]
    -    return rffi.cast(rffi.VOIDPP, call_capi(space, 'call_r', args))[0]
    +    return _cdata_to_ptr(space, call_capi(space, 'call_r', args))
     def c_call_s(space, cppmethod, cppobject, nargs, cargs):
         args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)]
         return call_capi(space, 'call_s', args)
     
     def c_constructor(space, cppmethod, cppobject, nargs, cargs):
         args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)]
    -    return rffi.cast(C_OBJECT, call_capi(space, 'constructor', args)[0])
    +    return _cdata_to_cobject(space, call_capi(space, 'constructor', args))
     def c_call_o(space, cppmethod, cppobject, nargs, cargs, cppclass):
         args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs), _Arg(l=cppclass.handle)]
    -    return rffi.cast(C_OBJECT, call_capi(space, 'call_o', args)[0])
    +    return _cdata_to_cobject(space, call_capi(space, 'call_o', args))
     
     @jit.elidable_promote()
     def c_get_methptr_getter(space, cppscope, index):
         args = [_Arg(l=cppscope.handle), _Arg(l=index)]
    -    return rffi.cast(C_METHPTRGETTER_PTR, call_capi(space, 'get_methptr_getter', args)[0])
    +    return rffi.cast(C_METHPTRGETTER_PTR,
    +        _cdata_to_ptr(space, call_capi(space, 'get_methptr_getter', args)))
     
     # handling of function argument buffer ---------------------------------------
     def c_allocate_function_args(space, size):
    -    return rffi.cast(rffi.VOIDP, call_capi(space, 'allocate_function_args', [_Arg(l=size)])[0])
    +    return _cdata_to_ptr(space, call_capi(space, 'allocate_function_args', [_Arg(l=size)]))
     def c_deallocate_function_args(space, cargs):
         call_capi(space, 'deallocate_function_args', [_Arg(vp=cargs)])
     @jit.elidable_promote()
     def c_function_arg_sizeof(space):
    -    return rffi.cast(rffi.SIZE_T, call_capi(space, 'function_arg_sizeof', [])[0])
    +    return _cdata_to_size_t(space, call_capi(space, 'function_arg_sizeof', []))
     @jit.elidable_promote()
     def c_function_arg_typeoffset(space):
    -    return rffi.cast(rffi.SIZE_T, call_capi(space, 'function_arg_typeoffset', [])[0])
    +    return _cdata_to_size_t(space, call_capi(space, 'function_arg_typeoffset', []))
     
     # scope reflection information -----------------------------------------------
     def c_is_namespace(space, scope):
    -    return _longptr_to_int(call_capi(space, 'is_namespace', [_Arg(l=scope)]))
    +    return space.bool_w(call_capi(space, 'is_namespace', [_Arg(l=scope)]))
     def c_is_enum(space, name):
    -    return _longptr_to_int(call_capi(space, 'is_enum', [_Arg(s=name)]))
    +    return space.bool_w(call_capi(space, 'is_enum', [_Arg(s=name)]))
     
     # type/class reflection information ------------------------------------------
     def c_final_name(space, cpptype):
    @@ -351,26 +362,26 @@
     def c_scoped_final_name(space, cpptype):
         return charp2str_free(space, call_capi(space, 'scoped_final_name', [_Arg(l=cpptype)]))
     def c_has_complex_hierarchy(space, handle):
    -    return _longptr_to_int(call_capi(space, 'has_complex_hierarchy', [_Arg(l=handle)]))
    +    return space.bool_w(call_capi(space, 'has_complex_hierarchy', [_Arg(l=handle)]))
     def c_num_bases(space, cppclass):
    -    return _longptr_to_int(call_capi(space, 'num_bases', [_Arg(l=cppclass.handle)]))
    +    return space.int_w(call_capi(space, 'num_bases', [_Arg(l=cppclass.handle)]))
     def c_base_name(space, cppclass, base_index):
         args = [_Arg(l=cppclass.handle), _Arg(l=base_index)]
         return charp2str_free(space, call_capi(space, 'base_name', args))
     @jit.elidable_promote()
     def c_is_subtype(space, derived, base):
         if derived == base:
    -        return 1
    -    return _longptr_to_int(call_capi(space, 'is_subtype', [_Arg(l=derived.handle), _Arg(l=base.handle)]))
    +        return bool(1)
    +    return space.bool_w(call_capi(space, 'is_subtype', [_Arg(l=derived.handle), _Arg(l=base.handle)]))
     
     @jit.elidable_promote()
     def _c_base_offset(space, derived_h, base_h, address, direction):
         args = [_Arg(l=derived_h), _Arg(l=base_h), _Arg(l=address), _Arg(l=direction)]
    -    return rffi.cast(rffi.SIZE_T, rffi.cast(rffi.ULONGP, call_capi(space, 'base_offset', args))[0])
    +    return _cdata_to_size_t(space, call_capi(space, 'base_offset', args))
     @jit.elidable_promote()
     def c_base_offset(space, derived, base, address, direction):
         if derived == base:
    -        return 0
    +        return rffi.cast(rffi.SIZE_T, 0)
         return _c_base_offset(space, derived.handle, base.handle, address, direction)
     @jit.elidable_promote()
     def c_base_offset1(space, derived_h, base, address, direction):
    @@ -379,13 +390,14 @@
     # method/function reflection information -------------------------------------
     def c_num_methods(space, cppscope):
         args = [_Arg(l=cppscope.handle)]
    -    return _longptr_to_int(call_capi(space, 'num_methods', args))
    +    return space.int_w(call_capi(space, 'num_methods', args))
     def c_method_index_at(space, cppscope, imethod):
         args = [_Arg(l=cppscope.handle), _Arg(l=imethod)]
    -    return call_capi(space, 'method_index_at', args)[0]
    +    return space.int_w(call_capi(space, 'method_index_at', args))
     def c_method_indices_from_name(space, cppscope, name):
         args = [_Arg(l=cppscope.handle), _Arg(s=name)]
    -    indices = rffi.cast(C_INDEX_ARRAY, call_capi(space, 'method_indices_from_name', args)[0])
    +    indices = rffi.cast(C_INDEX_ARRAY,
    +                        _cdata_to_ptr(space, call_capi(space, 'method_indices_from_name', args)))
         if not indices:
             return []
         py_indices = []
    @@ -406,10 +418,10 @@
         return charp2str_free(space, call_capi(space, 'method_result_type', args))
     def c_method_num_args(space, cppscope, index):
         args = [_Arg(l=cppscope.handle), _Arg(l=index)]
    -    return _longptr_to_int(call_capi(space, 'method_num_args', args))
    +    return space.int_w(call_capi(space, 'method_num_args', args))
     def c_method_req_args(space, cppscope, index):
         args = [_Arg(l=cppscope.handle), _Arg(l=index)]
    -    return _longptr_to_int(call_capi(space, 'method_req_args', args))
    +    return space.int_w(call_capi(space, 'method_req_args', args))
     def c_method_arg_type(space, cppscope, index, arg_index):
         args = [_Arg(l=cppscope.handle), _Arg(l=index), _Arg(l=arg_index)]
         return charp2str_free(space, call_capi(space, 'method_arg_type', args))
    @@ -422,10 +434,10 @@
     
     def c_method_is_template(space, cppscope, index):
         args = [_Arg(l=cppscope.handle), _Arg(l=index)]
    -    return _longptr_to_int(call_capi(space, 'method_is_template', args))
    +    return space.bool_w(call_capi(space, 'method_is_template', args))
     def _c_method_num_template_args(space, cppscope, index):
         args = [_Arg(l=cppscope.handle), _Arg(l=index)]
    -    return _longptr_to_int(call_capi(space, 'method_num_template_args', args)) 
    +    return space.int_w(call_capi(space, 'method_num_template_args', args)) 
     def c_template_args(space, cppscope, index):
         nargs = _c_method_num_template_args(space, cppscope, index)
         arg1 = _Arg(l=cppscope.handle)
    @@ -437,69 +449,69 @@
     
     def c_get_method(space, cppscope, index):
         args = [_Arg(l=cppscope.handle), _Arg(l=index)]
    -    return rffi.cast(C_METHOD, call_capi(space, 'get_method', args)[0])
    +    return rffi.cast(C_METHOD, space.int_w(call_capi(space, 'get_method', args)))
     def c_get_global_operator(space, nss, lc, rc, op):
         if nss is not None:
             args = [_Arg(l=nss.handle), _Arg(l=lc.handle), _Arg(l=rc.handle), _Arg(s=op)]
    -        return rffi.cast(WLAVC_INDEX, call_capi(space, 'get_global_operator', args)[0])
    +        return rffi.cast(WLAVC_INDEX, space.int_w(call_capi(space, 'get_global_operator', args)))
         return rffi.cast(WLAVC_INDEX, -1)
     
     # method properties ----------------------------------------------------------
     def c_is_constructor(space, cppclass, index):
         args = [_Arg(l=cppclass.handle), _Arg(l=index)]
    -    return _longptr_to_int(call_capi(space, 'is_constructor', args))
    +    return space.bool_w(call_capi(space, 'is_constructor', args))
     def c_is_staticmethod(space, cppclass, index):
         args = [_Arg(l=cppclass.handle), _Arg(l=index)]
    -    return _longptr_to_int(call_capi(space, 'is_staticmethod', args))
    +    return space.bool_w(call_capi(space, 'is_staticmethod', args))
     
     # data member reflection information -----------------------------------------
     def c_num_datamembers(space, cppscope):
    -    return _longptr_to_int(call_capi(space, 'num_datamembers', [_Arg(l=cppscope.handle)]))
    +    return space.int_w(call_capi(space, 'num_datamembers', [_Arg(l=cppscope.handle)]))
     def c_datamember_name(space, cppscope, datamember_index):
         args = [_Arg(l=cppscope.handle), _Arg(l=datamember_index)]
         return charp2str_free(space, call_capi(space, 'datamember_name', args))
     def c_datamember_type(space, cppscope, datamember_index):
         args = [_Arg(l=cppscope.handle), _Arg(l=datamember_index)]
    -    return charp2str_free(space, call_capi(space, 'datamember_type', args))
    +    return  charp2str_free(space, call_capi(space, 'datamember_type', args))
     def c_datamember_offset(space, cppscope, datamember_index):
         args = [_Arg(l=cppscope.handle), _Arg(l=datamember_index)]
    -    return rffi.cast(rffi.SIZE_T, rffi.cast(rffi.ULONGP, call_capi(space, 'datamember_offset', args))[0])
    +    return _cdata_to_size_t(space, call_capi(space, 'datamember_offset', args))
     
     def c_datamember_index(space, cppscope, name):
         args = [_Arg(l=cppscope.handle), _Arg(s=name)]
    -    return _longptr_to_int(call_capi(space, 'datamember_index', args))
    +    return space.int_w(call_capi(space, 'datamember_index', args))
     
     # data member properties -----------------------------------------------------
     def c_is_publicdata(space, cppscope, datamember_index):
         args = [_Arg(l=cppscope.handle), _Arg(l=datamember_index)]
    -    return _longptr_to_int(call_capi(space, 'is_publicdata', args))
    +    return space.bool_w(call_capi(space, 'is_publicdata', args))
     def c_is_staticdata(space, cppscope, datamember_index):
         args = [_Arg(l=cppscope.handle), _Arg(l=datamember_index)]
    -    return _longptr_to_int(call_capi(space, 'is_staticdata', args))
    +    return space.bool_w(call_capi(space, 'is_staticdata', args))
     
     # misc helpers ---------------------------------------------------------------
     def c_strtoll(space, svalue):
    -    return rffi.cast(rffi.LONGLONGP, call_capi(space, 'strtoll', [_Arg(s=svalue)]))[0]
    +    return space.r_longlong_w(call_capi(space, 'strtoll', [_Arg(s=svalue)]))
     def c_strtoull(space, svalue):
    -    return rffi.cast(rffi.ULONGLONGP, call_capi(space, 'strtoull', [_Arg(s=svalue)]))[0]
    +    return space.r_ulonglong_w(call_capi(space, 'strtoull', [_Arg(s=svalue)]))
     def c_free(space, voidp):
         call_capi(space, 'free', [_Arg(vp=voidp)])
     
     def charp2str_free(space, cdata):
    -    charp = rffi.cast(rffi.CCHARPP, cdata)[0]
    +    charp = rffi.cast(rffi.CCHARP, _cdata_to_ptr(space, cdata))
         pystr = rffi.charp2str(charp)
         c_free(space, rffi.cast(rffi.VOIDP, charp))
         return pystr
     
     def c_charp2stdstring(space, svalue):
    -    return rffi.cast(C_OBJECT, call_capi(space, 'charp2stdstring', [_Arg(s=svalue)])[0])
    +    return _cdata_to_cobject(space, call_capi(space, 'charp2stdstring', [_Arg(s=svalue)]))
     def c_stdstring2stdstring(space, cppobject):
    -    return rffi.cast(C_OBJECT, call_capi(space, 'stdstring2stdstring', [_Arg(l=cppobject)])[0])
    +    return _cdata_to_cobject(space, call_capi(space, 'stdstring2stdstring', [_Arg(l=cppobject)]))
     def c_assign2stdstring(space, cppobject, svalue):
         args = [_Arg(l=cppobject), _Arg(s=svalue)]
    -    return rffi.cast(C_OBJECT, call_capi(space, 'assign2stdstring', args)[0])
    +    call_capi(space, 'assign2stdstring', args)
     def c_free_stdstring(space, cppobject):
    -    call_capi(space, 'free_stdstring', [_Arg(l=cppobject)])[0]
    +    call_capi(space, 'free_stdstring', [_Arg(l=cppobject)])
     
     # loadable-capi-specific pythonizations (none, as the capi isn't known until runtime)
     def register_pythonizations(space):
    diff --git a/pypy/module/cppyy/executor.py b/pypy/module/cppyy/executor.py
    --- a/pypy/module/cppyy/executor.py
    +++ b/pypy/module/cppyy/executor.py
    @@ -91,7 +91,6 @@
             return self._wrap_object(space, rffi.cast(self.c_type, result))
     
         def execute_libffi(self, space, cif_descr, funcaddr, buffer):
    -        data = rffi.ptradd(buffer, cif_descr.exchange_args[1])
             jit_libffi.jit_ffi_call(cif_descr, funcaddr, buffer)
             result = rffi.ptradd(buffer, cif_descr.exchange_result)
             return self._wrap_object(space, rffi.cast(self.c_ptrtype, result)[0])
    
    From noreply at buildbot.pypy.org  Sat Apr  6 01:29:02 2013
    From: noreply at buildbot.pypy.org (wlav)
    Date: Sat,  6 Apr 2013 01:29:02 +0200 (CEST)
    Subject: [pypy-commit] pypy reflex-support: merge default into branch
    Message-ID: <20130405232902.B6F891C0A11@cobra.cs.uni-duesseldorf.de>
    
    Author: Wim Lavrijsen 
    Branch: reflex-support
    Changeset: r63072:607168b3bbc0
    Date: 2013-04-05 15:18 -0700
    http://bitbucket.org/pypy/pypy/changeset/607168b3bbc0/
    
    Log:	merge default into branch
    
    diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py
    --- a/lib_pypy/_sqlite3.py
    +++ b/lib_pypy/_sqlite3.py
    @@ -48,13 +48,7 @@
     
     from cffi import FFI as _FFI
     
    -if '__pypy__' not in sys.builtin_module_names:
    -    from cffi.backend_ctypes import CTypesBackend
    -    backend = CTypesBackend()
    -else:
    -    backend = None
    -
    -_ffi = _FFI(backend=backend)
    +_ffi = _FFI()
     
     _ffi.cdef("""
     #define SQLITE_OK ...
    @@ -224,7 +218,7 @@
         const char **pzTail     /* OUT: Pointer to unused portion of zSql */
     );
     
    -void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*));
    +void sqlite3_result_blob(sqlite3_context*, const char*, int, void(*)(void*));
     void sqlite3_result_double(sqlite3_context*, double);
     void sqlite3_result_error(sqlite3_context*, const char*, int);
     void sqlite3_result_error16(sqlite3_context*, const void*, int);
    @@ -257,7 +251,7 @@
     
     def _has_load_extension():
         """Only available since 3.3.6"""
    -    unverified_ffi = _FFI(backend=backend)
    +    unverified_ffi = _FFI()
         unverified_ffi.cdef("""
         typedef ... sqlite3;
         int sqlite3_enable_load_extension(sqlite3 *db, int onoff);
    @@ -858,7 +852,7 @@
             self._reset = False
             self.__locked = False
             self.__closed = False
    -        self.__description = None
    +        self.__lastrowid = None
             self.__rowcount = -1
     
             con._check_thread()
    @@ -964,7 +958,7 @@
                     elif typ == _lib.SQLITE_BLOB:
                         blob = _lib.sqlite3_column_blob(self.__statement._statement, i)
                         blob_len = _lib.sqlite3_column_bytes(self.__statement._statement, i)
    -                    val = _BLOB_TYPE(_ffi.buffer(blob, blob_len))
    +                    val = _BLOB_TYPE(_ffi.buffer(blob, blob_len)[:])
                 row.append(val)
             return tuple(row)
     
    @@ -978,20 +972,24 @@
             try:
                 if not isinstance(sql, basestring):
                     raise ValueError("operation parameter must be str or unicode")
    -            self.__description = None
    +            try:
    +                del self.__description
    +            except AttributeError:
    +                pass
                 self.__rowcount = -1
                 self.__statement = self.__connection._statement_cache.get(sql)
     
                 if self.__connection._isolation_level is not None:
    -                if self.__statement._kind == Statement._DDL:
    +                if self.__statement._type in ("UPDATE", "DELETE", "INSERT", "REPLACE"):
    +                    if not self.__connection._in_transaction:
    +                        self.__connection._begin()
    +                elif self.__statement._type == "OTHER":
                         if self.__connection._in_transaction:
                             self.__connection.commit()
    -                elif self.__statement._kind == Statement._DML:
    -                    if not self.__connection._in_transaction:
    -                        self.__connection._begin()
    -
    -            if multiple and self.__statement._kind != Statement._DML:
    -                raise ProgrammingError("executemany is only for DML statements")
    +                elif self.__statement._type == "SELECT":
    +                    if multiple:
    +                        raise ProgrammingError("You cannot execute SELECT "
    +                                               "statements in executemany().")
     
                 for params in many_params:
                     self.__statement._set_params(params)
    @@ -1002,17 +1000,26 @@
                         self.__statement._reset()
                         raise self.__connection._get_exception(ret)
     
    -                if self.__statement._kind == Statement._DML:
    +                if ret == _lib.SQLITE_ROW:
    +                    if multiple:
    +                        raise ProgrammingError("executemany() can only execute DML statements.")
    +                    self.__build_row_cast_map()
    +                    self.__next_row = self.__fetch_one_row()
    +                elif ret == _lib.SQLITE_DONE and not multiple:
                         self.__statement._reset()
     
    -                if ret == _lib.SQLITE_ROW:
    -                    self.__build_row_cast_map()
    -                    self.__next_row = self.__fetch_one_row()
    -
    -                if self.__statement._kind == Statement._DML:
    +                if self.__statement._type in ("UPDATE", "DELETE", "INSERT", "REPLACE"):
                         if self.__rowcount == -1:
                             self.__rowcount = 0
                         self.__rowcount += _lib.sqlite3_changes(self.__connection._db)
    +
    +                if not multiple and self.__statement._type == "INSERT":
    +                    self.__lastrowid = _lib.sqlite3_last_insert_rowid(self.__connection._db)
    +                else:
    +                    self.__lastrowid = None
    +
    +                if multiple:
    +                    self.__statement._reset()
             finally:
                 self.__connection._in_transaction = \
                     not _lib.sqlite3_get_autocommit(self.__connection._db)
    @@ -1081,7 +1088,6 @@
                 next_row = self.__next_row
             except AttributeError:
                 self.__statement._reset()
    -            self.__statement = None
                 raise StopIteration
             del self.__next_row
     
    @@ -1125,13 +1131,15 @@
         rowcount = property(__get_rowcount)
     
         def __get_description(self):
    -        if self.__description is None:
    +        try:
    +            return self.__description
    +        except AttributeError:
                 self.__description = self.__statement._get_description()
    -        return self.__description
    +            return self.__description
         description = property(__get_description)
     
         def __get_lastrowid(self):
    -        return _lib.sqlite3_last_insert_rowid(self.__connection._db)
    +        return self.__lastrowid
         lastrowid = property(__get_lastrowid)
     
         def setinputsizes(self, *args):
    @@ -1142,8 +1150,6 @@
     
     
     class Statement(object):
    -    _DML, _DQL, _DDL = range(3)
    -
         _statement = None
     
         def __init__(self, connection, sql):
    @@ -1154,13 +1160,14 @@
     
             if not isinstance(sql, basestring):
                 raise Warning("SQL is of wrong type. Must be string or unicode.")
    -        first_word = self._statement_kind = sql.lstrip().split(" ")[0].upper()
    -        if first_word in ("INSERT", "UPDATE", "DELETE", "REPLACE"):
    -            self._kind = Statement._DML
    -        elif first_word in ("SELECT", "PRAGMA"):
    -            self._kind = Statement._DQL
    +
    +        first_word = sql.lstrip().split(" ")[0].upper()
    +        if first_word == "":
    +            self._type = "INVALID"
    +        elif first_word in ("SELECT", "INSERT", "UPDATE", "DELETE", "REPLACE"):
    +            self._type = first_word
             else:
    -            self._kind = Statement._DDL
    +            self._type = "OTHER"
     
             if isinstance(sql, unicode):
                 sql = sql.encode('utf-8')
    @@ -1173,11 +1180,12 @@
     
             if ret == _lib.SQLITE_OK and not self._statement:
                 # an empty statement, work around that, as it's the least trouble
    +            self._type = "SELECT"
                 c_sql = _ffi.new("char[]", b"select 42")
                 ret = _lib.sqlite3_prepare_v2(self.__con._db, c_sql, -1,
                                               statement_star, next_char)
                 self._statement = statement_star[0]
    -            self._kind = Statement._DQL
    +
             if ret != _lib.SQLITE_OK:
                 raise self.__con._get_exception(ret)
     
    @@ -1288,7 +1296,7 @@
                 raise ValueError("parameters are of unsupported type")
     
         def _get_description(self):
    -        if self._kind == Statement._DML:
    +        if self._type in ("INSERT", "UPDATE", "DELETE", "REPLACE"):
                 return None
             desc = []
             for i in xrange(_lib.sqlite3_column_count(self._statement)):
    @@ -1393,7 +1401,7 @@
             elif typ == _lib.SQLITE_BLOB:
                 blob = _lib.sqlite3_value_blob(params[i])
                 blob_len = _lib.sqlite3_value_bytes(params[i])
    -            val = _BLOB_TYPE(_ffi.buffer(blob, blob_len))
    +            val = _BLOB_TYPE(_ffi.buffer(blob, blob_len)[:])
             else:
                 raise NotImplementedError
             _params.append(val)
    diff --git a/lib_pypy/cffi/api.py b/lib_pypy/cffi/api.py
    --- a/lib_pypy/cffi/api.py
    +++ b/lib_pypy/cffi/api.py
    @@ -25,6 +25,7 @@
                 line = ''
             return '%s%s' % (line, self.args[0])
     
    +
     class FFI(object):
         r'''
         The main top-level class that you instantiate once, or once per module.
    @@ -220,7 +221,7 @@
             it as a string or unicode string.
     
             If 'cdata' is an enum, returns the value of the enumerator as a
    -        string, or '#NUMBER' if the value is out of range.
    +        string, or 'NUMBER' if the value is out of range.
             """
             return self._backend.string(cdata, maxlen)
     
    diff --git a/pypy/doc/getting-started-python.rst b/pypy/doc/getting-started-python.rst
    --- a/pypy/doc/getting-started-python.rst
    +++ b/pypy/doc/getting-started-python.rst
    @@ -46,14 +46,14 @@
     2. Install build-time dependencies.  On a Debian box these are::
     
          [user at debian-box ~]$ sudo apt-get install \
    -     gcc make python-dev libffi-dev pkg-config \
    +     gcc make python-dev libffi-dev lib-sqlite3-dev pkg-config \
          libz-dev libbz2-dev libncurses-dev libexpat1-dev \
          libssl-dev libgc-dev python-sphinx python-greenlet
     
        On a Fedora-16 box these are::
     
          [user at fedora-or-rh-box ~]$ sudo yum install \
    -     gcc make python-devel libffi-devel pkgconfig \
    +     gcc make python-devel libffi-devel lib-sqlite3-devel pkgconfig \
          zlib-devel bzip2-devel ncurses-devel expat-devel \
          openssl-devel gc-devel python-sphinx python-greenlet
     
    @@ -62,6 +62,7 @@
        * ``pkg-config`` (to help us locate libffi files)
        * ``libz-dev`` (for the optional ``zlib`` module)
        * ``libbz2-dev`` (for the optional ``bz2`` module)
    +   * ``libsqlite3-dev`` (for the optional ``sqlite3`` module via cffi)
        * ``libncurses-dev`` (for the optional ``_minimal_curses`` module)
        * ``libexpat1-dev`` (for the optional ``pyexpat`` module)
        * ``libssl-dev`` (for the optional ``_ssl`` module)
    diff --git a/pypy/doc/index.rst b/pypy/doc/index.rst
    --- a/pypy/doc/index.rst
    +++ b/pypy/doc/index.rst
    @@ -15,7 +15,7 @@
     
     * `FAQ`_: some frequently asked questions.
     
    -* `Release 2.0 beta 1`_: the latest official release
    +* `Release 2.0 beta 2`_: the latest official release
     
     * `PyPy Blog`_: news and status info about PyPy 
     
    @@ -75,7 +75,7 @@
     .. _`Getting Started`: getting-started.html
     .. _`Papers`: extradoc.html
     .. _`Videos`: video-index.html
    -.. _`Release 2.0 beta 1`: http://pypy.org/download.html
    +.. _`Release 2.0 beta 2`: http://pypy.org/download.html
     .. _`speed.pypy.org`: http://speed.pypy.org
     .. _`RPython toolchain`: translation.html
     .. _`potential project ideas`: project-ideas.html
    diff --git a/pypy/doc/release-2.0.0-beta2.rst b/pypy/doc/release-2.0.0-beta2.rst
    new file mode 100644
    --- /dev/null
    +++ b/pypy/doc/release-2.0.0-beta2.rst
    @@ -0,0 +1,84 @@
    +===============
    +PyPy 2.0 beta 2
    +===============
    +
    +We're pleased to announce the 2.0 beta 2 release of PyPy. This is a major
    +release of PyPy and we're getting very close to 2.0 final, however it includes
    +quite a few new features that require further testing. Please test and report
    +issues, so we can have a rock-solid 2.0 final. It also includes a performance
    +regression of about 5% compared to 2.0 beta 1 that we hope to fix before
    +2.0 final. The ARM support is not working yet and we're working hard to
    +make it happen before the 2.0 final. The new major features are:
    +
    +* JIT now supports stackless features, that is greenlets and stacklets. This
    +  means that JIT can now optimize the code that switches the context. It enables
    +  running `eventlet`_ and `gevent`_ on PyPy (although gevent requires some
    +  special support that's not quite finished, read below).
    +
    +* This is the first PyPy release that includes `cffi`_ as a core library.
    +  Version 0.6 comes included in the PyPy library. cffi has seen a lot of
    +  adoption among library authors and we believe it's the best way to wrap
    +  C libaries. You can see examples of cffi usage in `_curses.py`_ and
    +  `_sqlite3.py`_ in the PyPy source code.
    +
    +You can download the PyPy 2.0 beta 2 release here:
    +
    +    http://pypy.org/download.html 
    +
    +What is PyPy?
    +=============
    +
    +PyPy is a very compliant Python interpreter, almost a drop-in replacement for
    +CPython 2.7.3. It's fast (`pypy 2.0 beta 2 and cpython 2.7.3`_
    +performance comparison) due to its integrated tracing JIT compiler.
    +
    +This release supports x86 machines running Linux 32/64, Mac OS X 64 or
    +Windows 32. It also supports ARM machines running Linux, however this is
    +disabled for the beta 2 release.
    +Windows 64 work is still stalling, we would welcome a volunteer
    +to handle that.
    +
    +.. _`pypy 2.0 beta 2 and cpython 2.7.3`: http://bit.ly/USXqpP
    +
    +How to use PyPy?
    +================
    +
    +We suggest using PyPy from a `virtualenv`_. Once you have a virtualenv
    +installed, you can follow instructions from `pypy documentation`_ on how
    +to proceed. This document also covers other `installation schemes`_.
    +
    +.. _`pypy documentation`: http://doc.pypy.org/en/latest/getting-started.html#installing-using-virtualenv
    +.. _`virtualenv`: http://www.virtualenv.org/en/latest/
    +.. _`installation schemes`: http://doc.pypy.org/en/latest/getting-started.html#installing-pypy
    +
    +Highlights
    +==========
    +
    +* ``cffi`` is officially supported by PyPy. It comes included in the standard
    +  library, just use ``import cffi``
    +
    +* stackless support - `eventlet`_ just works and `gevent`_ requires `pypycore`_
    +  and `pypy-hacks`_ branch of gevent (which mostly disables cython-based
    +  modules)
    +
    +* callbacks from C are now much faster. pyexpat is about 3x faster, cffi
    +  callbacks around the same
    +
    +* ``__length_hint__`` is implemented (PEP 424)
    +
    +* a lot of numpy improvements
    +
    +Improvements since 1.9
    +======================
    +
    +* `JIT hooks`_ are now a powerful tool to introspect the JITting process that
    +  PyPy performs
    +
    +* various performance improvements compared to 1.9 and 2.0 beta 1
    +
    +* operations on ``long`` objects are now as fast as in CPython (from
    +  roughly 2x slower)
    +
    +* we now have special strategies for ``dict``/``set``/``list`` which contain
    +  unicode strings, which means that now such collections will be both faster
    +  and more compact.
    diff --git a/pypy/doc/windows.rst b/pypy/doc/windows.rst
    --- a/pypy/doc/windows.rst
    +++ b/pypy/doc/windows.rst
    @@ -111,6 +111,18 @@
         cd bzip2-1.0.5
         nmake -f makefile.msc
         
    +The sqlite3 database library
    +~~~~~~~~~~~~~~~~~~~~
    +
    +Download http://www.sqlite.org/2013/sqlite-amalgamation-3071601.zip and extract
    +it into a directory under the base directory. Also get 
    +http://www.sqlite.org/2013/sqlite-dll-win32-x86-3071601.zip and extract the dll
    +into the bin directory, and the sqlite3.def into the sources directory.
    +Now build the import library so cffi can use the header and dll::
    +    lib /DEF:sqlite3.def" /OUT:sqlite3.lib"
    +    copy sqlite3.lib path\to\libs
    +
    +
     The expat XML parser
     ~~~~~~~~~~~~~~~~~~~~
     
    diff --git a/pypy/module/cpyext/include/patchlevel.h b/pypy/module/cpyext/include/patchlevel.h
    --- a/pypy/module/cpyext/include/patchlevel.h
    +++ b/pypy/module/cpyext/include/patchlevel.h
    @@ -29,7 +29,7 @@
     #define PY_VERSION		"2.7.3"
     
     /* PyPy version as a string */
    -#define PYPY_VERSION "2.0.0-beta1"
    +#define PYPY_VERSION "2.0.0-beta2"
     
     /* Subversion Revision number of this file (not of the repository).
      * Empty since Mercurial migration. */
    diff --git a/pypy/module/pyexpat/interp_pyexpat.py b/pypy/module/pyexpat/interp_pyexpat.py
    --- a/pypy/module/pyexpat/interp_pyexpat.py
    +++ b/pypy/module/pyexpat/interp_pyexpat.py
    @@ -305,14 +305,15 @@
                 w_result = space.call_function(handler, %(wargs)s)
                 %(post_code)s
             except OperationError, e:
    -            parser._exc_info = e
    +            if not parser._exc_info: # don't override an existing exception
    +                 parser._exc_info = e
                 XML_StopParser(parser.itself, XML_FALSE)
                 return %(result_error)s
             return %(result_converter)s
         callback = %(name)s_callback
         """ % locals())
     
    -    exec str(src)
    +    exec src.compile()
     
         c_name = 'XML_Set' + name
         callback_type = lltype.Ptr(lltype.FuncType(
    @@ -335,7 +336,8 @@
         try:
             parser.UnknownEncodingHandler(space, name, info)
         except OperationError, e:
    -        parser._exc_info = e
    +        if parser._exc_info:
    +            parser._exc_info = e
             XML_StopParser(parser.itself, XML_FALSE)
             result = 0
         else:
    diff --git a/pypy/module/pyexpat/test/test_parser.py b/pypy/module/pyexpat/test/test_parser.py
    --- a/pypy/module/pyexpat/test/test_parser.py
    +++ b/pypy/module/pyexpat/test/test_parser.py
    @@ -167,3 +167,46 @@
                 p = pyexpat.ParserCreate()
                 p.ParseFile(fake_reader)
                 assert fake_reader.read_count == 4
    +
    +class AppTestPyexpat2:
    +    spaceconfig = dict(usemodules=['pyexpat', 'itertools', '_socket',
    +                                   'rctime', 'struct', 'binascii'])
    +
    +    def test_django_bug(self):
    +        xml_str = ''
    +
    +        from xml.dom import pulldom
    +        from xml.sax import handler
    +        from xml.sax.expatreader import ExpatParser as _ExpatParser
    +        from StringIO import StringIO
    +
    +        class DefusedExpatParser(_ExpatParser):
    +            def start_doctype_decl(self, name, sysid, pubid, has_internal_subset):
    +                raise DTDForbidden(name, sysid, pubid)
    +
    +            def external_entity_ref_handler(self, context, base, sysid, pubid):
    +                raise ExternalReferenceForbidden(context, base, sysid, pubid)
    +
    +            def reset(self):
    +                _ExpatParser.reset(self)
    +                parser = self._parser
    +                parser.StartDoctypeDeclHandler = self.start_doctype_decl
    +                parser.ExternalEntityRefHandler = self.external_entity_ref_handler
    +
    +
    +        class DTDForbidden(ValueError):
    +            pass
    +
    +
    +        class ExternalReferenceForbidden(ValueError):
    +            pass
    +
    +        stream = pulldom.parse(StringIO(xml_str), DefusedExpatParser())
    +
    +        try:
    +            for event, node in stream:
    +                print event, node
    +        except DTDForbidden:
    +            pass
    +        else:
    +            raise Exception("should raise DTDForbidden")
    diff --git a/pypy/module/sys/version.py b/pypy/module/sys/version.py
    --- a/pypy/module/sys/version.py
    +++ b/pypy/module/sys/version.py
    @@ -11,7 +11,7 @@
     #XXX # sync CPYTHON_VERSION with patchlevel.h, package.py
     CPYTHON_API_VERSION        = 1013   #XXX # sync with include/modsupport.h
     
    -PYPY_VERSION               = (2, 0, 0, "beta", 1)    #XXX # sync patchlevel.h
    +PYPY_VERSION               = (2, 0, 0, "beta", 2)    #XXX # sync patchlevel.h
     
     if platform.name == 'msvc':
         COMPILER_INFO = 'MSC v.%d 32 bit' % (platform.version * 10 + 600)
    diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/setup.py
    --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/setup.py
    +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/setup.py
    @@ -1,3 +1,4 @@
    +# Generated by pypy/tool/import_cffi.py
     
     from distutils.core import setup
     import snip_basic_verify
    diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/snip_basic_verify.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/snip_basic_verify.py
    --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/snip_basic_verify.py
    +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/snip_basic_verify.py
    @@ -1,3 +1,4 @@
    +# Generated by pypy/tool/import_cffi.py
     
     from cffi import FFI
     import sys
    diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/setup.py
    --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/setup.py
    +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/setup.py
    @@ -1,3 +1,4 @@
    +# Generated by pypy/tool/import_cffi.py
     
     from distutils.core import setup
     import snip_basic_verify1
    diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/snip_basic_verify1/__init__.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/snip_basic_verify1/__init__.py
    --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/snip_basic_verify1/__init__.py
    +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/snip_basic_verify1/__init__.py
    @@ -1,3 +1,4 @@
    +# Generated by pypy/tool/import_cffi.py
     
     from cffi import FFI
     import sys
    diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/setup.py
    --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/setup.py
    +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/setup.py
    @@ -1,3 +1,4 @@
    +# Generated by pypy/tool/import_cffi.py
     
     from distutils.core import setup
     import snip_basic_verify2
    diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/snip_basic_verify2/__init__.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/snip_basic_verify2/__init__.py
    --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/snip_basic_verify2/__init__.py
    +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/snip_basic_verify2/__init__.py
    @@ -1,3 +1,4 @@
    +# Generated by pypy/tool/import_cffi.py
     
     from cffi import FFI
     import sys
    diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/setup.py
    --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/setup.py
    +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/setup.py
    @@ -1,3 +1,4 @@
    +# Generated by pypy/tool/import_cffi.py
     
     from distutils.core import setup
     
    diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/snip_infrastructure/__init__.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/snip_infrastructure/__init__.py
    --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/snip_infrastructure/__init__.py
    +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/snip_infrastructure/__init__.py
    @@ -1,3 +1,4 @@
    +# Generated by pypy/tool/import_cffi.py
     
     def func():
         return 42
    diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/setup.py
    --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/setup.py
    +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/setup.py
    @@ -1,3 +1,4 @@
    +# Generated by pypy/tool/import_cffi.py
     
     from setuptools import setup
     import snip_setuptools_verify
    diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/snip_setuptools_verify.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/snip_setuptools_verify.py
    --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/snip_setuptools_verify.py
    +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/snip_setuptools_verify.py
    @@ -1,3 +1,4 @@
    +# Generated by pypy/tool/import_cffi.py
     
     from cffi import FFI
     import sys
    diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/setup.py
    --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/setup.py
    +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/setup.py
    @@ -1,3 +1,4 @@
    +# Generated by pypy/tool/import_cffi.py
     
     from setuptools import setup
     import snip_setuptools_verify1
    diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/snip_setuptools_verify1/__init__.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/snip_setuptools_verify1/__init__.py
    --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/snip_setuptools_verify1/__init__.py
    +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/snip_setuptools_verify1/__init__.py
    @@ -1,3 +1,4 @@
    +# Generated by pypy/tool/import_cffi.py
     
     from cffi import FFI
     import sys
    diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/setup.py
    --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/setup.py
    +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/setup.py
    @@ -1,3 +1,4 @@
    +# Generated by pypy/tool/import_cffi.py
     
     from setuptools import setup
     import snip_setuptools_verify2
    diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/snip_setuptools_verify2/__init__.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/snip_setuptools_verify2/__init__.py
    --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/snip_setuptools_verify2/__init__.py
    +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/snip_setuptools_verify2/__init__.py
    @@ -1,3 +1,4 @@
    +# Generated by pypy/tool/import_cffi.py
     
     from cffi import FFI
     import sys
    diff --git a/pypy/module/test_lib_pypy/test_sqlite3.py b/pypy/module/test_lib_pypy/test_sqlite3.py
    --- a/pypy/module/test_lib_pypy/test_sqlite3.py
    +++ b/pypy/module/test_lib_pypy/test_sqlite3.py
    @@ -198,3 +198,28 @@
         con = _sqlite3.connect(':memory:')
         con.row_factory = 42
         con.execute('select 1')
    +
    +def test_returning_blob_must_own_memory():
    +    import gc
    +    con = _sqlite3.connect(":memory:")
    +    con.create_function("returnblob", 0, lambda: buffer("blob"))
    +    cur = con.cursor()
    +    cur.execute("select returnblob()")
    +    val = cur.fetchone()[0]
    +    for i in range(5):
    +        gc.collect()
    +        got = (val[0], val[1], val[2], val[3])
    +        assert got == ('b', 'l', 'o', 'b')
    +
    +def test_description_after_fetchall():
    +    con = _sqlite3.connect(":memory:")
    +    cur = con.cursor()
    +    cur.execute("select 42").fetchall()
    +    assert cur.description is not None
    +
    +def test_executemany_lastrowid():
    +    con = _sqlite3.connect(':memory:')
    +    cur = con.cursor()
    +    cur.execute("create table test(a)")
    +    cur.executemany("insert into test values (?)", [[1], [2], [3]])
    +    assert cur.lastrowid is None
    diff --git a/pypy/tool/release/package.py b/pypy/tool/release/package.py
    --- a/pypy/tool/release/package.py
    +++ b/pypy/tool/release/package.py
    @@ -43,6 +43,7 @@
     def fix_permissions(basedir):
         if sys.platform != 'win32':
             os.system("chmod -R a+rX %s" % basedir)
    +        os.system("chmod -R g-w %s" % basedir)
     
     def package(basedir, name='pypy-nightly', rename_pypy_c='pypy',
                 copy_to_dir = None, override_pypy_c = None, nostrip=False):
    diff --git a/pypy/tool/test/test_tab.py b/pypy/tool/test/test_tab.py
    --- a/pypy/tool/test/test_tab.py
    +++ b/pypy/tool/test/test_tab.py
    @@ -5,7 +5,7 @@
     import os
     from pypy.conftest import pypydir
     
    -ROOT = pypydir
    +ROOT = os.path.abspath(os.path.join(pypydir, '..'))
     EXCLUDE = {}
     
     
    diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py
    --- a/rpython/jit/backend/arm/assembler.py
    +++ b/rpython/jit/backend/arm/assembler.py
    @@ -305,7 +305,7 @@
                 self._restore_exception(mc, exc0, exc1)
                 mc.VPOP([vfpr.value for vfpr in r.caller_vfp_resp])
                 assert exc0 is not None
    -	    assert exc1 is not None
    +            assert exc1 is not None
                 mc.POP([gpr.value for gpr in r.caller_resp] +
                                 [exc0.value, exc1.value])
             #
    @@ -526,9 +526,7 @@
                 self.gen_shadowstack_header(gcrootmap)
     
         def gen_shadowstack_header(self, gcrootmap):
    -        # we need to put two words into the shadowstack: the MARKER_FRAME
    -        # and the address of the frame (fp, actually)
    -        # lr = rst addr
    +        # lr = shadow stack top addr
             # ip = *lr
             rst = gcrootmap.get_root_stack_top_addr()
             self.mc.gen_load_int(r.lr.value, rst)
    @@ -1062,8 +1060,7 @@
                 self.mc.PUSH([helper.value], cond=cond)
             self.load_reg(self.mc, loc, r.fp, offset, cond=cond, helper=helper)
             if save_helper:
    -	    self.mc.POP([helper.value], cond=cond)
    -
    +            self.mc.POP([helper.value], cond=cond)
     
         def _mov_imm_float_to_loc(self, prev_loc, loc, cond=c.AL):
             if loc.is_vfp_reg():
    diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py
    --- a/rpython/jit/backend/arm/opassembler.py
    +++ b/rpython/jit/backend/arm/opassembler.py
    @@ -628,12 +628,14 @@
                                         bool(self._regalloc.vfprm.reg_bindings))
                 assert self.wb_slowpath[helper_num] != 0
             #
    -        if not is_frame and loc_base is not r.r0:
    +        if loc_base is not r.r0:
                 # push two registers to keep stack aligned
                 mc.PUSH([r.r0.value, loc_base.value])
    -            remap_frame_layout(self, [loc_base], [r.r0], r.ip)
    +            mc.MOV_rr(r.r0.value, loc_base.value)
    +            if is_frame:
    +                assert loc_base is r.fp
             mc.BL(self.wb_slowpath[helper_num])
    -        if not is_frame and loc_base is not r.r0:
    +        if loc_base is not r.r0:
                 mc.POP([r.r0.value, loc_base.value])
     
             if card_marking:
    diff --git a/rpython/jit/backend/arm/runner.py b/rpython/jit/backend/arm/runner.py
    --- a/rpython/jit/backend/arm/runner.py
    +++ b/rpython/jit/backend/arm/runner.py
    @@ -120,7 +120,7 @@
         """ARM v7 uses hardfp ABI, requires vfp"""
         hf_abi = True
         backend_name = "armv7hf"
    -    supports_floats = False
    +    supports_floats = True
         supports_singlefloats = False
     
     
    @@ -129,5 +129,5 @@
         hf_abi = True
         arch_version = 6
         backend_name = "armv6hf"
    -    supports_floats = False
    +    supports_floats = True
         supports_singlefloats = False
    diff --git a/rpython/jit/backend/arm/test/test_calling_convention.py b/rpython/jit/backend/arm/test/test_calling_convention.py
    --- a/rpython/jit/backend/arm/test/test_calling_convention.py
    +++ b/rpython/jit/backend/arm/test/test_calling_convention.py
    @@ -72,7 +72,7 @@
             callargs = []
             def func(f0, f1, f2, f3, f4, f5, f6, i0, f7, i1, f8, f9):
                 callargs.append(zip(range(12),
    -			[f0, f1, f2, f3, f4, f5, f6, i0, f7, i1, f8, f9]))
    +                        [f0, f1, f2, f3, f4, f5, f6, i0, f7, i1, f8, f9]))
                 return f0 + f1 + f2 + f3 + f4 + f5 + f6 + float(i0 + i1) + f7 + f8 + f9
             F = lltype.Float
             I = lltype.Signed
    @@ -103,7 +103,7 @@
             callargs = []
             def func(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9):
                 callargs.append(zip(range(10),
    -			[f0, f1, f2, f3, f4, f5, f6, f7, f8, f9]))
    +                        [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9]))
                 return f0 + f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8 + f9
             F = lltype.Float
             FUNC = self.FuncType([F] * 10, F)
    @@ -125,7 +125,7 @@
             callargs = []
             def func(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9):
                 callargs.append(zip(range(10),
    -			[f0, f1, f2, f3, f4, f5, f6, f7, f8, f9]))
    +                        [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9]))
                 return f0 + f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8 + f9
     
             I = lltype.Signed
    diff --git a/rpython/jit/backend/llsupport/test/test_gc_integration.py b/rpython/jit/backend/llsupport/test/test_gc_integration.py
    --- a/rpython/jit/backend/llsupport/test/test_gc_integration.py
    +++ b/rpython/jit/backend/llsupport/test/test_gc_integration.py
    @@ -256,7 +256,9 @@
                 if self.cpu.IS_64_BIT:
                     assert frame.jf_gcmap[idx] == (1<<29) | (1 << 30)
                 else:
    -                assert frame.jf_gcmap[idx] == (1<<24) | (1 << 23)
    +                assert frame.jf_gcmap[idx]
    +                exp_idx = self.cpu.JITFRAME_FIXED_SIZE - 32 * idx + 1 # +1 from i0
    +                assert frame.jf_gcmap[idx] == (1 << (exp_idx + 1)) | (1 << exp_idx)
     
             self.cpu = self.getcpu(check)
             ops = '''
    @@ -680,7 +682,7 @@
     
             def f(frame, x):
                 # all the gc pointers are alive p1 -> p7 (but not p0)
    -            assert bin(frame.jf_gcmap[0]).count('1') == 7
    +            assert getmap(frame).count('1') == 7 #
                 assert x == 1
                 return 2
             
    @@ -713,7 +715,7 @@
             def f(frame, arg, x):
                 assert not arg
                 assert frame.jf_gcmap[0] & 31 == 0
    -            assert bin(frame.jf_gcmap[0]).count('1') == 3 # p1, p2, p3, but
    +            assert getmap(frame).count('1') == 3 # p1, p2, p3, but
                 # not in registers
                 frame.jf_descr = frame.jf_force_descr # make guard_not_forced fail
                 assert x == 1
    @@ -749,7 +751,8 @@
             cpu.compile_loop(loop.inputargs, loop.operations, token)
             frame = lltype.cast_opaque_ptr(JITFRAMEPTR,
                                            cpu.execute_token(token, 1, a))
    -        assert bin(frame.jf_gcmap[0]).count('1') == 4
    +        
    +        assert getmap(frame).count('1') == 4
     
         def test_call_gcmap_no_guard(self):
             cpu = self.cpu
    @@ -757,7 +760,7 @@
             def f(frame, arg, x):
                 assert not arg
                 assert frame.jf_gcmap[0] & 31 == 0
    -            assert bin(frame.jf_gcmap[0]).count('1') == 3 # p1, p2, p3
    +            assert getmap(frame).count('1') == 3 # p1, p2, p3
                 frame.jf_descr = frame.jf_force_descr # make guard_not_forced fail
                 assert x == 1
                 return lltype.nullptr(llmemory.GCREF.TO)
    @@ -792,4 +795,5 @@
             cpu.compile_loop(loop.inputargs, loop.operations, token)
             frame = lltype.cast_opaque_ptr(JITFRAMEPTR,
                                            cpu.execute_token(token, 1, a))
    -        assert bin(frame.jf_gcmap[0]).count('1') == 4
    +        assert getmap(frame).count('1') == 4
    +
    diff --git a/rpython/jit/backend/test/calling_convention_test.py b/rpython/jit/backend/test/calling_convention_test.py
    --- a/rpython/jit/backend/test/calling_convention_test.py
    +++ b/rpython/jit/backend/test/calling_convention_test.py
    @@ -384,7 +384,7 @@
     
         def test_call_aligned_explicit_check(self):
             if (not platform.machine().startswith('arm') and
    -		sys.maxint == 2 ** 31 - 1): # XXX is still necessary on x86?
    +                sys.maxint == 2 ** 31 - 1): # XXX is still necessary on x86?
                 py.test.skip("libffi on 32bit is broken")
             cpu = self.cpu
             if not cpu.supports_floats:
    diff --git a/rpython/jit/backend/x86/runner.py b/rpython/jit/backend/x86/runner.py
    --- a/rpython/jit/backend/x86/runner.py
    +++ b/rpython/jit/backend/x86/runner.py
    @@ -58,10 +58,10 @@
             self.assembler = Assembler386(self, self.translate_support_code)
     
         def build_regalloc(self):
    -	''' for tests'''
    -	from rpython.jit.backend.x86.regalloc import RegAlloc
    -	assert self.assembler is not None
    -	return RegAlloc(self.assembler, False)
    +        ''' for tests'''
    +        from rpython.jit.backend.x86.regalloc import RegAlloc
    +        assert self.assembler is not None
    +        return RegAlloc(self.assembler, False)
     
         def setup_once(self):
             self.profile_agent.startup()
    diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
    --- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
    +++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
    @@ -4282,9 +4282,9 @@
             self.optimize_loop(ops, expected)
     
         def test_add_sub_ovf_second_operation_regular(self):
    -	py.test.skip("Smalltalk would like this to pass")
    -	# This situation occurs in Smalltalk because it uses 1-based indexing.
    -	# The below code is equivalent to a loop over an array.
    +        py.test.skip("Smalltalk would like this to pass")
    +        # This situation occurs in Smalltalk because it uses 1-based indexing.
    +        # The below code is equivalent to a loop over an array.
             ops = """
             [i1]
             i2 = int_sub(i1, 1)
    @@ -7609,6 +7609,26 @@
             """
             self.optimize_loop(ops, ops)
     
    +    def test_setarrayitem_followed_by_arraycopy_2(self):
    +        ops = """
    +        [i1, i2]
    +        p1 = new_array(i1, descr=arraydescr)
    +        setarrayitem_gc(p1, 0, i2, descr=arraydescr)
    +        p3 = new_array(5, descr=arraydescr)
    +        call(0, p1, p3, 0, 1, 1, descr=arraycopydescr)
    +        i4 = getarrayitem_gc(p3, 1, descr=arraydescr)
    +        jump(i1, i4)
    +        """
    +        expected = """
    +        [i1, i2]
    +        p1 = new_array(i1, descr=arraydescr)
    +        # operations are not all removed because this new_array() is var-sized
    +        # unsure exactly which operations should be left, but right now it's
    +        # really buggy
    +        jump(i1, i2)
    +        """
    +        self.optimize_loop(ops, expected)
    +
         def test_heap_cache_virtuals_forced_by_delayed_setfield(self):
             py.test.skip('not yet supoprted')
             ops = """
    diff --git a/rpython/rlib/rsocket.py b/rpython/rlib/rsocket.py
    --- a/rpython/rlib/rsocket.py
    +++ b/rpython/rlib/rsocket.py
    @@ -80,7 +80,7 @@
     
         def __del__(self):
             if self.addr_p:
    -            lltype.free(self.addr_p, flavor='raw')
    +            lltype.free(self.addr_p, flavor='raw', track_allocation=False)
     
         def setdata(self, addr, addrlen):
             # initialize self.addr and self.addrlen.  'addr' can be a different
    @@ -271,7 +271,8 @@
             result = instantiate(INETAddress)
             # store the malloc'ed data into 'result' as soon as possible
             # to avoid leaks if an exception occurs inbetween
    -        sin = lltype.malloc(_c.sockaddr_in, flavor='raw', zero=True)
    +        sin = lltype.malloc(_c.sockaddr_in, flavor='raw', zero=True,
    +                            track_allocation=False)
             result.setdata(sin, sizeof(_c.sockaddr_in))
             # PLAT sin_len
             rffi.setintfield(sin, 'c_sin_family', AF_INET)
    @@ -337,7 +338,8 @@
             result = instantiate(INET6Address)
             # store the malloc'ed data into 'result' as soon as possible
             # to avoid leaks if an exception occurs inbetween
    -        sin = lltype.malloc(_c.sockaddr_in6, flavor='raw', zero=True)
    +        sin = lltype.malloc(_c.sockaddr_in6, flavor='raw', zero=True,
    +                            track_allocation=False)
             result.setdata(sin, sizeof(_c.sockaddr_in6))
             rffi.setintfield(sin, 'c_sin6_family', AF_INET6)
             rffi.structcopy(sin.c_sin6_addr, in6_addr)
    @@ -360,7 +362,8 @@
             maxlen = sizeof(struct)
     
             def __init__(self, path):
    -            sun = lltype.malloc(_c.sockaddr_un, flavor='raw', zero=True)
    +            sun = lltype.malloc(_c.sockaddr_un, flavor='raw', zero=True,
    +                                track_allocation=False)
                 baseofs = offsetof(_c.sockaddr_un, 'c_sun_path')
                 self.setdata(sun, baseofs + len(path))
                 rffi.setintfield(sun, 'c_sun_family', AF_UNIX)
    @@ -409,7 +412,8 @@
             maxlen = minlen = sizeof(struct)
     
             def __init__(self, pid, groups):
    -            addr = lltype.malloc(_c.sockaddr_nl, flavor='raw', zero=True)
    +            addr = lltype.malloc(_c.sockaddr_nl, flavor='raw', zero=True,
    +                                 track_allocation=False)
                 self.setdata(addr, NETLINKAddress.maxlen)
                 rffi.setintfield(addr, 'c_nl_family', AF_NETLINK)
                 rffi.setintfield(addr, 'c_nl_pid', pid)
    @@ -444,7 +448,8 @@
             raise RSocketError("address family mismatched")
         # copy into a new buffer the address that 'addrptr' points to
         addrlen = rffi.cast(lltype.Signed, addrlen)
    -    buf = lltype.malloc(rffi.CCHARP.TO, addrlen, flavor='raw')
    +    buf = lltype.malloc(rffi.CCHARP.TO, addrlen, flavor='raw',
    +                        track_allocation=False)
         src = rffi.cast(rffi.CCHARP, addrptr)
         for i in range(addrlen):
             buf[i] = src[i]
    @@ -456,7 +461,8 @@
             result = instantiate(INETAddress)
         elif result.family != AF_INET:
             raise RSocketError("address family mismatched")
    -    sin = lltype.malloc(_c.sockaddr_in, flavor='raw', zero=True)
    +    sin = lltype.malloc(_c.sockaddr_in, flavor='raw', zero=True,
    +                        track_allocation=False)
         result.setdata(sin, sizeof(_c.sockaddr_in))
         rffi.setintfield(sin, 'c_sin_family', AF_INET)   # PLAT sin_len
         rffi.setintfield(sin.c_sin_addr, 'c_s_addr', s_addr)
    @@ -465,7 +471,8 @@
     def make_null_address(family):
         klass = familyclass(family)
         result = instantiate(klass)
    -    buf = lltype.malloc(rffi.CCHARP.TO, klass.maxlen, flavor='raw', zero=True)
    +    buf = lltype.malloc(rffi.CCHARP.TO, klass.maxlen, flavor='raw', zero=True,
    +                        track_allocation=False)
         # Initialize the family to the correct value.  Avoids surprizes on
         # Windows when calling a function that unexpectedly does not set
         # the output address (e.g. recvfrom() on a connected IPv4 socket).
    diff --git a/rpython/rtyper/lltypesystem/rffi.py b/rpython/rtyper/lltypesystem/rffi.py
    --- a/rpython/rtyper/lltypesystem/rffi.py
    +++ b/rpython/rtyper/lltypesystem/rffi.py
    @@ -934,10 +934,8 @@
         if tp is lltype.SingleFloat:
             return 4
         if tp is lltype.LongFloat:
    -        if globals()['r_void*'].BITS == 32:
    -            return 12
    -        else:
    -            return 16
    +        import ctypes    # :-/
    +        return ctypes.sizeof(ctypes.c_longdouble)
         assert isinstance(tp, lltype.Number)
         if tp is lltype.Signed:
             return LONG_BIT/8
    
    From noreply at buildbot.pypy.org  Sat Apr  6 01:29:04 2013
    From: noreply at buildbot.pypy.org (wlav)
    Date: Sat,  6 Apr 2013 01:29:04 +0200 (CEST)
    Subject: [pypy-commit] pypy reflex-support: coding convention fix
    Message-ID: <20130405232904.0710C1C0A11@cobra.cs.uni-duesseldorf.de>
    
    Author: Wim Lavrijsen 
    Branch: reflex-support
    Changeset: r63073:b440e97a9581
    Date: 2013-04-05 15:39 -0700
    http://bitbucket.org/pypy/pypy/changeset/b440e97a9581/
    
    Log:	coding convention fix
    
    diff --git a/pypy/module/cppyy/src/reflexcwrapper.cxx b/pypy/module/cppyy/src/reflexcwrapper.cxx
    --- a/pypy/module/cppyy/src/reflexcwrapper.cxx
    +++ b/pypy/module/cppyy/src/reflexcwrapper.cxx
    @@ -620,7 +620,7 @@
     }
     
     void cppyy_assign2stdstring(cppyy_object_t ptr, const char* str) {
    -   *((std::string*)ptr) = str;
    +    *((std::string*)ptr) = str;
     }
     
     void cppyy_free_stdstring(cppyy_object_t ptr) {
    
    From noreply at buildbot.pypy.org  Sat Apr  6 01:29:05 2013
    From: noreply at buildbot.pypy.org (wlav)
    Date: Sat,  6 Apr 2013 01:29:05 +0200 (CEST)
    Subject: [pypy-commit] pypy reflex-support: stubs use placement new
    Message-ID: <20130405232905.3A3E31C0A11@cobra.cs.uni-duesseldorf.de>
    
    Author: Wim Lavrijsen 
    Branch: reflex-support
    Changeset: r63074:7159a9b97251
    Date: 2013-04-05 16:18 -0700
    http://bitbucket.org/pypy/pypy/changeset/7159a9b97251/
    
    Log:	stubs use placement new
    
    diff --git a/pypy/module/cppyy/src/reflexcwrapper.cxx b/pypy/module/cppyy/src/reflexcwrapper.cxx
    --- a/pypy/module/cppyy/src/reflexcwrapper.cxx
    +++ b/pypy/module/cppyy/src/reflexcwrapper.cxx
    @@ -170,11 +170,13 @@
     }
     
     char* cppyy_call_s(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
    -    std::string result("");
    +    std::string* cppresult = (std::string*)malloc(sizeof(std::string));
         std::vector arguments = build_args(nargs, args);
         Reflex::StubFunction stub = (Reflex::StubFunction)method;
    -    stub(&result, (void*)self, arguments, NULL /* stub context */);
    -    return cppstring_to_cstring(result);
    +    stub(cppresult, (void*)self, arguments, NULL /* stub context */);
    +    char* cstr = cppstring_to_cstring(*cppresult);
    +    delete cppresult;         // the stub will have performed a placement-new
    +    return cstr;
     }
     
     cppyy_object_t cppyy_constructor(cppyy_method_t method, cppyy_type_t handle, int nargs, void* args) {
    
    From noreply at buildbot.pypy.org  Sat Apr  6 01:29:06 2013
    From: noreply at buildbot.pypy.org (wlav)
    Date: Sat,  6 Apr 2013 01:29:06 +0200 (CEST)
    Subject: [pypy-commit] pypy reflex-support: fix check: cif_descr is
     initialized to null ptr, not to None
    Message-ID: <20130405232906.66C6D1C0A11@cobra.cs.uni-duesseldorf.de>
    
    Author: Wim Lavrijsen 
    Branch: reflex-support
    Changeset: r63075:4ae8555bbb2c
    Date: 2013-04-05 16:28 -0700
    http://bitbucket.org/pypy/pypy/changeset/4ae8555bbb2c/
    
    Log:	fix check: cif_descr is initialized to null ptr, not to None
    
    diff --git a/pypy/module/cppyy/interp_cppyy.py b/pypy/module/cppyy/interp_cppyy.py
    --- a/pypy/module/cppyy/interp_cppyy.py
    +++ b/pypy/module/cppyy/interp_cppyy.py
    @@ -204,7 +204,7 @@
     
         @jit.unroll_safe
         def do_fast_call(self, cppthis, args_w, call_local):
    -        if self.cif_descr is None:
    +        if self.cif_descr == lltype.nullptr(jit_libffi.CIF_DESCRIPTION):
                 raise FastCallNotPossible
             cif_descr = self.cif_descr
             buffer = lltype.malloc(rffi.CCHARP.TO, cif_descr.exchange_size, flavor='raw')
    
    From noreply at buildbot.pypy.org  Sat Apr  6 02:23:11 2013
    From: noreply at buildbot.pypy.org (bdkearns)
    Date: Sat,  6 Apr 2013 02:23:11 +0200 (CEST)
    Subject: [pypy-commit] pypy default: fix whatsnew
    Message-ID: <20130406002311.E5DC71C039A@cobra.cs.uni-duesseldorf.de>
    
    Author: Brian Kearns 
    Branch: 
    Changeset: r63076:d34ad891ac19
    Date: 2013-04-05 20:22 -0400
    http://bitbucket.org/pypy/pypy/changeset/d34ad891ac19/
    
    Log:	fix whatsnew
    
    diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
    --- a/pypy/doc/whatsnew-head.rst
    +++ b/pypy/doc/whatsnew-head.rst
    @@ -115,9 +115,9 @@
     .. branch: remove-list-smm
     .. branch: bridge-logging
     .. branch: curses_cffi
    -
     cffi implementation of _curses
     
     .. branch: sqlite-cffi
    +cffi implementation of sqlite3
     
    -cffi implementation of sqlite3
    +.. branch: release-2.0-beta2
    
    From noreply at buildbot.pypy.org  Sat Apr  6 02:27:35 2013
    From: noreply at buildbot.pypy.org (pjenvey)
    Date: Sat,  6 Apr 2013 02:27:35 +0200 (CEST)
    Subject: [pypy-commit] pypy py3k: this is text
    Message-ID: <20130406002735.692141C039A@cobra.cs.uni-duesseldorf.de>
    
    Author: Philip Jenvey 
    Branch: py3k
    Changeset: r63077:5b7c09b8a1af
    Date: 2013-04-05 17:24 -0700
    http://bitbucket.org/pypy/pypy/changeset/5b7c09b8a1af/
    
    Log:	this is text
    
    diff --git a/lib_pypy/_curses.py b/lib_pypy/_curses.py
    --- a/lib_pypy/_curses.py
    +++ b/lib_pypy/_curses.py
    @@ -359,9 +359,10 @@
         if not lib._m_NetBSD:
             for key in range(lib.KEY_MIN, lib.KEY_MAX):
                 key_n = lib.keyname(key)
    -            if key_n == ffi.NULL or ffi.string(key_n) == "UNKNOWN KEY":
    +            if key_n == ffi.NULL or ffi.string(key_n) == b"UNKNOWN KEY":
                     continue
    -            key_n = ffi.string(key_n).replace('(', '').replace(')', '')
    +            key_n = ffi.string(key_n).decode()
    +            key_n = key_n.replace('(', '').replace(')', '')
                 globals()[key_n] = key
     
     _setup()
    
    From noreply at buildbot.pypy.org  Sat Apr  6 02:27:36 2013
    From: noreply at buildbot.pypy.org (pjenvey)
    Date: Sat,  6 Apr 2013 02:27:36 +0200 (CEST)
    Subject: [pypy-commit] pypy py3k: int is W_LongObject
    Message-ID: <20130406002736.8B84E1C039A@cobra.cs.uni-duesseldorf.de>
    
    Author: Philip Jenvey 
    Branch: py3k
    Changeset: r63078:727a7454acb0
    Date: 2013-04-05 17:25 -0700
    http://bitbucket.org/pypy/pypy/changeset/727a7454acb0/
    
    Log:	int is W_LongObject
    
    diff --git a/pypy/objspace/std/test/test_stdobjspace.py b/pypy/objspace/std/test/test_stdobjspace.py
    --- a/pypy/objspace/std/test/test_stdobjspace.py
    +++ b/pypy/objspace/std/test/test_stdobjspace.py
    @@ -51,13 +51,13 @@
     
         def test_fastpath_isinstance(self):
             from pypy.objspace.std.stringobject import W_StringObject
    -        from pypy.objspace.std.intobject import W_AbstractIntObject
    +        from pypy.objspace.std.longobject import W_LongObject
             from pypy.objspace.std.iterobject import W_AbstractSeqIterObject
             from pypy.objspace.std.iterobject import W_SeqIterObject
     
             space = self.space
             assert space._get_interplevel_cls(space.w_str) is W_StringObject
    -        assert space._get_interplevel_cls(space.w_int) is W_AbstractIntObject
    +        assert space._get_interplevel_cls(space.w_int) is W_LongObject
             class X(W_StringObject):
                 def __init__(self):
                     pass
    
    From noreply at buildbot.pypy.org  Sat Apr  6 02:27:37 2013
    From: noreply at buildbot.pypy.org (pjenvey)
    Date: Sat,  6 Apr 2013 02:27:37 +0200 (CEST)
    Subject: [pypy-commit] pypy py3k: match cpython's stricter handling of
    	extended unpacking
    Message-ID: <20130406002737.BC98E1C039A@cobra.cs.uni-duesseldorf.de>
    
    Author: Philip Jenvey 
    Branch: py3k
    Changeset: r63079:6cded36a0209
    Date: 2013-04-05 17:25 -0700
    http://bitbucket.org/pypy/pypy/changeset/6cded36a0209/
    
    Log:	match cpython's stricter handling of extended unpacking
    
    diff --git a/pypy/interpreter/astcompiler/codegen.py b/pypy/interpreter/astcompiler/codegen.py
    --- a/pypy/interpreter/astcompiler/codegen.py
    +++ b/pypy/interpreter/astcompiler/codegen.py
    @@ -6,6 +6,7 @@
     # help the annotator.  To it, unfortunately, everything is not so obvious.  If
     # you figure out a way to remove them, great, but try a translation first,
     # please.
    +import struct
     
     from pypy.interpreter.astcompiler import ast, assemble, symtable, consts, misc
     from pypy.interpreter.astcompiler import optimize # For side effects
    @@ -13,6 +14,7 @@
     from pypy.tool import stdlib_opcode as ops
     from pypy.interpreter.error import OperationError
     
    +C_INT_MAX = (2 ** (struct.calcsize('i') * 8)) / 2 - 1
     
     def compile_ast(space, module, info):
         """Generate a code object from AST."""
    @@ -771,6 +773,9 @@
                 return False
             for target in targets:
                 if not isinstance(target, ast.Name):
    +                if isinstance(target, ast.Starred):
    +                    # these require extra checks
    +                    return False
                     break
             else:
                 self.visit_sequence(values)
    @@ -935,28 +940,24 @@
     
         def _visit_list_or_tuple(self, node, elts, ctx, op):
             elt_count = len(elts) if elts else 0
    -        star_pos = -1
             if ctx == ast.Store:
    -            if elt_count > 0:
    -                for i, elt in enumerate(elts):
    -                    if isinstance(elt, ast.Starred):
    -                        if star_pos != -1:
    -                            msg = "too many starred expressions in assignment"
    -                            self.error(msg, node)
    -                        star_pos = i
    -            if star_pos != -1:
    -                self.emit_op_arg(ops.UNPACK_EX, star_pos | (elt_count-star_pos-1)<<8)
    -            else:
    +            seen_star = False
    +            for i in range(elt_count):
    +                elt = elts[i]
    +                is_starred = isinstance(elt, ast.Starred)
    +                if is_starred and not seen_star:
    +                    if i >= 1 << 8 or elt_count - i - 1 >= (C_INT_MAX >> 8):
    +                        self.error("too many expressions in star-unpacking "
    +                                   "assignment", node)
    +                    self.emit_op_arg(ops.UNPACK_EX,
    +                                     i + ((elt_count - i - 1) << 8))
    +                    seen_star = True
    +                    elts[i] = elt.value
    +                elif is_starred:
    +                    self.error("two starred expressions in assignment", node)
    +            if not seen_star:
                     self.emit_op_arg(ops.UNPACK_SEQUENCE, elt_count)
    -        if elt_count > 0:
    -            if star_pos != -1:
    -                for elt in elts:
    -                    if isinstance(elt, ast.Starred):
    -                        elt.value.walkabout(self)
    -                    else:
    -                        elt.walkabout(self)
    -            else:
    -                self.visit_sequence(elts)
    +        self.visit_sequence(elts)
             if ctx == ast.Load:
                 self.emit_op_arg(op, elt_count)
     
    diff --git a/pypy/interpreter/astcompiler/test/test_compiler.py b/pypy/interpreter/astcompiler/test/test_compiler.py
    --- a/pypy/interpreter/astcompiler/test/test_compiler.py
    +++ b/pypy/interpreter/astcompiler/test/test_compiler.py
    @@ -884,12 +884,30 @@
                     return a, b, c
             """
             yield self.st, func, "f()", (1, [2, 3], 4)
    -        py.test.raises(SyntaxError, self.simple_test, "*a, *b = [1, 2]",
    -                       None, None)
    -        py.test.raises(SyntaxError, self.simple_test, "a = [*b, c]",
    -                       None, None)
    -        py.test.raises(SyntaxError, self.simple_test, "for *a in x: pass",
    -                       None, None)
    +
    +    def test_extended_unpacking_fail(self):
    +        exc = py.test.raises(SyntaxError, self.simple_test, "*a, *b = [1, 2]",
    +                             None, None).value
    +        assert exc.msg == "two starred expressions in assignment"
    +        exc = py.test.raises(SyntaxError, self.simple_test,
    +                             "[*b, *c] = range(10)", None, None).value
    +        assert exc.msg == "two starred expressions in assignment"
    +
    +        exc = py.test.raises(SyntaxError, self.simple_test, "a = [*b, c]",
    +                             None, None).value
    +        assert exc.msg == "can use starred expression only as assignment target"
    +        exc = py.test.raises(SyntaxError, self.simple_test, "for *a in x: pass",
    +                             None, None).value
    +        assert exc.msg == "starred assignment target must be in a list or tuple"
    +
    +        s = ", ".join("a%d" % i for i in range(1<<8)) + ", *rest = range(1<<8 + 1)"
    +        exc = py.test.raises(SyntaxError, self.simple_test, s, None,
    +                             None).value
    +        assert exc.msg == "too many expressions in star-unpacking assignment"
    +        s = ", ".join("a%d" % i for i in range(1<<8 + 1)) + ", *rest = range(1<<8 + 2)"
    +        exc = py.test.raises(SyntaxError, self.simple_test, s, None,
    +                             None).value
    +        assert exc.msg == "too many expressions in star-unpacking assignment"
     
     
     class AppTestCompiler:
    
    From noreply at buildbot.pypy.org  Sat Apr  6 02:27:39 2013
    From: noreply at buildbot.pypy.org (pjenvey)
    Date: Sat,  6 Apr 2013 02:27:39 +0200 (CEST)
    Subject: [pypy-commit] pypy py3k: correct UNPACK_EX's counting
    Message-ID: <20130406002739.010971C039A@cobra.cs.uni-duesseldorf.de>
    
    Author: Philip Jenvey 
    Branch: py3k
    Changeset: r63080:db0c22afb498
    Date: 2013-04-05 17:25 -0700
    http://bitbucket.org/pypy/pypy/changeset/db0c22afb498/
    
    Log:	correct UNPACK_EX's counting
    
    diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
    --- a/pypy/interpreter/pyopcode.py
    +++ b/pypy/interpreter/pyopcode.py
    @@ -604,15 +604,15 @@
             w_iterable = self.popvalue()
             items = self.space.fixedview(w_iterable)
             itemcount = len(items)
    -        if right > itemcount:
    -            count = left + right
    +        count = left + right
    +        if count > itemcount:
                 if count == 1:
                     plural = ''
                 else:
                     plural = 's'
                 raise operationerrfmt(self.space.w_ValueError,
                                       "need more than %d value%s to unpack",
    -                                  left + right, plural)
    +                                  itemcount, plural)
             right = itemcount - right
             assert right >= 0
             # push values in reverse order
    diff --git a/pypy/interpreter/test/test_interpreter.py b/pypy/interpreter/test/test_interpreter.py
    --- a/pypy/interpreter/test/test_interpreter.py
    +++ b/pypy/interpreter/test/test_interpreter.py
    @@ -346,3 +346,17 @@
             assert l(1, 2) == 1 + 2 + 20
             assert l(1, 2, k=10) == 1 + 2 + 10
             """
    +
    +    def test_extended_unpacking_short(self):
    +        """
    +        class Seq:
    +            def __getitem__(self, i):
    +                if i >= 0 and i < 3: return i
    +                raise IndexError
    +        try:
    +            a, *b, c, d, e = Seq()
    +        except ValueError as e:
    +            assert str(e) == "need more than 3 values to unpack"
    +        else:
    +            assert False, "Expected ValueError"
    +            """
    
    From noreply at buildbot.pypy.org  Sat Apr  6 02:27:40 2013
    From: noreply at buildbot.pypy.org (pjenvey)
    Date: Sat,  6 Apr 2013 02:27:40 +0200 (CEST)
    Subject: [pypy-commit] pypy py3k: ints are always PyLongs
    Message-ID: <20130406002740.2A2851C039A@cobra.cs.uni-duesseldorf.de>
    
    Author: Philip Jenvey 
    Branch: py3k
    Changeset: r63081:7ecf4bccf4c9
    Date: 2013-04-05 17:26 -0700
    http://bitbucket.org/pypy/pypy/changeset/7ecf4bccf4c9/
    
    Log:	ints are always PyLongs
    
    diff --git a/pypy/module/cpyext/test/test_longobject.py b/pypy/module/cpyext/test/test_longobject.py
    --- a/pypy/module/cpyext/test/test_longobject.py
    +++ b/pypy/module/cpyext/test/test_longobject.py
    @@ -50,11 +50,11 @@
             assert api.PyLong_CheckExact(w_l)
     
             w_i = space.wrap(sys.maxint)
    -        assert not api.PyLong_Check(w_i)
    -        assert not api.PyLong_CheckExact(w_i)
    +        assert api.PyLong_Check(w_i)
    +        assert api.PyLong_CheckExact(w_i)
     
             L = space.appexec([], """():
    -            class L(long):
    +            class L(int):
                     pass
                 return L
             """)
    
    From noreply at buildbot.pypy.org  Sat Apr  6 02:31:06 2013
    From: noreply at buildbot.pypy.org (bdkearns)
    Date: Sat,  6 Apr 2013 02:31:06 +0200 (CEST)
    Subject: [pypy-commit] pypy default: not sure why this was changed in
    	a163d0d435d5
    Message-ID: <20130406003106.BFC231C039A@cobra.cs.uni-duesseldorf.de>
    
    Author: Brian Kearns 
    Branch: 
    Changeset: r63082:d801b8e5feac
    Date: 2013-04-05 20:30 -0400
    http://bitbucket.org/pypy/pypy/changeset/d801b8e5feac/
    
    Log:	not sure why this was changed in a163d0d435d5
    
    diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py
    --- a/lib_pypy/_sqlite3.py
    +++ b/lib_pypy/_sqlite3.py
    @@ -218,7 +218,7 @@
         const char **pzTail     /* OUT: Pointer to unused portion of zSql */
     );
     
    -void sqlite3_result_blob(sqlite3_context*, const char*, int, void(*)(void*));
    +void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*));
     void sqlite3_result_double(sqlite3_context*, double);
     void sqlite3_result_error(sqlite3_context*, const char*, int);
     void sqlite3_result_error16(sqlite3_context*, const void*, int);
    
    From noreply at buildbot.pypy.org  Sat Apr  6 02:43:18 2013
    From: noreply at buildbot.pypy.org (bdkearns)
    Date: Sat,  6 Apr 2013 02:43:18 +0200 (CEST)
    Subject: [pypy-commit] pypy default: transplant 5b7c09b8a1af and improve to
     only call ffi.string once
    Message-ID: <20130406004318.BACA51C0337@cobra.cs.uni-duesseldorf.de>
    
    Author: Brian Kearns 
    Branch: 
    Changeset: r63083:3e8013bc9ef3
    Date: 2013-04-05 20:43 -0400
    http://bitbucket.org/pypy/pypy/changeset/3e8013bc9ef3/
    
    Log:	transplant 5b7c09b8a1af and improve to only call ffi.string once
    
    diff --git a/lib_pypy/_curses.py b/lib_pypy/_curses.py
    --- a/lib_pypy/_curses.py
    +++ b/lib_pypy/_curses.py
    @@ -359,9 +359,12 @@
         if not lib._m_NetBSD:
             for key in range(lib.KEY_MIN, lib.KEY_MAX):
                 key_n = lib.keyname(key)
    -            if key_n == ffi.NULL or ffi.string(key_n) == "UNKNOWN KEY":
    +            if key_n == ffi.NULL:
                     continue
    -            key_n = ffi.string(key_n).replace('(', '').replace(')', '')
    +            key_n = ffi.string(key_n)
    +            if key_n == b"UNKNOWN KEY":
    +                continue
    +            key_n = key_n.decode().replace('(', '').replace(')', '')
                 globals()[key_n] = key
     
     _setup()
    
    From noreply at buildbot.pypy.org  Sat Apr  6 02:57:18 2013
    From: noreply at buildbot.pypy.org (bdkearns)
    Date: Sat,  6 Apr 2013 02:57:18 +0200 (CEST)
    Subject: [pypy-commit] pypy default: pep8/whitespace
    Message-ID: <20130406005718.8A5E21C06BD@cobra.cs.uni-duesseldorf.de>
    
    Author: Brian Kearns 
    Branch: 
    Changeset: r63084:49a3f33a88d1
    Date: 2013-04-05 20:57 -0400
    http://bitbucket.org/pypy/pypy/changeset/49a3f33a88d1/
    
    Log:	pep8/whitespace
    
    diff --git a/lib-python/conftest.py b/lib-python/conftest.py
    --- a/lib-python/conftest.py
    +++ b/lib-python/conftest.py
    @@ -1,91 +1,89 @@
     """
     
     test configuration(s) for running CPython's regression
    -test suite on top of PyPy 
    +test suite on top of PyPy
     
     """
     import py
     import sys
     import pypy
     import re
    -from pypy.interpreter.gateway import ApplevelClass 
    +from pypy.interpreter.gateway import ApplevelClass
     from pypy.interpreter.error import OperationError
    -from pypy.interpreter.module import Module as PyPyModule 
    +from pypy.interpreter.module import Module as PyPyModule
     from pypy.interpreter.main import run_string, run_file
     
    -# the following adds command line options as a side effect! 
    -from pypy.conftest import option as pypy_option 
    +# the following adds command line options as a side effect!
    +from pypy.conftest import option as pypy_option
     
    -from pypy.tool.pytest import appsupport 
    +from pypy.tool.pytest import appsupport
     from pypy.tool.pytest.confpath import pypydir, rpythondir, testdir, testresultdir
     from rpython.config.parse import parse_info
     
     pytest_plugins = "resultlog",
     rsyncdirs = ['.', '../pypy/']
     
    -# 
    -# Interfacing/Integrating with py.test's collection process 
    +#
    +# Interfacing/Integrating with py.test's collection process
     #
     
     def pytest_addoption(parser):
    -    group = parser.getgroup("complicance testing options") 
    -    group.addoption('-T', '--timeout', action="store", type="string", 
    -       default="1000", dest="timeout", 
    -       help="fail a test module after the given timeout. "
    -            "specify in seconds or 'NUMmp' aka Mega-Pystones")
    -    group.addoption('--pypy', action="store", type="string",
    -       dest="pypy",  help="use given pypy executable to run lib-python tests. "
    -                          "This will run the tests directly (i.e. not through py.py)")
    +    group = parser.getgroup("complicance testing options")
    +    group.addoption('-T', '--timeout', action="store", type="string",
    +                    default="1000", dest="timeout",
    +                    help="fail a test module after the given timeout. "
    +                         "specify in seconds or 'NUMmp' aka Mega-Pystones")
    +    group.addoption('--pypy', action="store", type="string", dest="pypy",
    +                    help="use given pypy executable to run lib-python tests. "
    +                         "This will run the tests directly (i.e. not through py.py)")
         group.addoption('--filter', action="store", type="string", default=None,
    -                    dest="unittest_filter",  help="Similar to -k, XXX")
    +                    dest="unittest_filter", help="Similar to -k, XXX")
     
    -def gettimeout(timeout): 
    +def gettimeout(timeout):
         from rpython.translator.test import rpystone
    -    if timeout.endswith('mp'): 
    +    if timeout.endswith('mp'):
             megapystone = float(timeout[:-2])
             t, stone = pystone.Proc0(10000)
    -        pystonetime = t/stone 
    -        seconds = megapystone  * 1000000 * pystonetime
    -        return seconds 
    -    return float(timeout) 
    +        pystonetime = t/stone
    +        seconds = megapystone * 1000000 * pystonetime
    +        return seconds
    +    return float(timeout)
     
     # ________________________________________________________________________
     #
    -# classification of all tests files (this is ongoing work) 
    +# classification of all tests files (this is ongoing work)
     #
     
    -class RegrTest: 
    -    """ Regression Test Declaration.""" 
    -    def __init__(self, basename, core=False,
    -                                 compiler=None, 
    -                                 usemodules = '',
    -                                 skip=None): 
    -        self.basename = basename 
    +class RegrTest:
    +    """ Regression Test Declaration."""
    +    def __init__(self, basename, core=False, compiler=None, usemodules='',
    +                 skip=None):
    +        self.basename = basename
             self._usemodules = usemodules.split() + ['signal', 'rctime', 'itertools', '_socket']
    -        self._compiler = compiler 
    +        self._compiler = compiler
             self.core = core
             self.skip = skip
             assert self.getfspath().check(), "%r not found!" % (basename,)
     
         def usemodules(self):
    -        return self._usemodules #+ pypy_option.usemodules
    +        return self._usemodules  # + pypy_option.usemodules
         usemodules = property(usemodules)
     
    -    def compiler(self): 
    -        return self._compiler #or pypy_option.compiler 
    +    def compiler(self):
    +        return self._compiler  # or pypy_option.compiler
         compiler = property(compiler)
     
    -    def ismodified(self): 
    +    def ismodified(self):
             #XXX: ask hg
             return None
     
    -    def getfspath(self): 
    +    def getfspath(self):
             return testdir.join(self.basename)
     
    -    def run_file(self, space): 
    +    def run_file(self, space):
             fspath = self.getfspath()
             assert fspath.check()
    -        modname = fspath.purebasename 
    +        modname = fspath.purebasename
             space.appexec([], '''():
                 from test import %(modname)s
                 m = %(modname)s
    @@ -424,7 +422,7 @@
         RegrTest('test_textwrap.py'),
         RegrTest('test_thread.py', usemodules="thread", core=True),
         RegrTest('test_threaded_import.py', usemodules="thread", core=True),
    -    RegrTest('test_threadedtempfile.py', 
    +    RegrTest('test_threadedtempfile.py',
                  usemodules="thread", core=False),
         RegrTest('test_threading.py', usemodules="thread", core=True),
         RegrTest('test_threading_local.py', usemodules="thread", core=True),
    @@ -504,7 +502,7 @@
     
     def pytest_configure(config):
         config._basename2spec = cache = {}
    -    for x in testmap: 
    +    for x in testmap:
             cache[x.basename] = x
     
     def pytest_collect_file(path, parent, __multicall__):
    @@ -520,33 +518,33 @@
         return RunFileExternal(path.basename, parent=parent, regrtest=regrtest)
     
     class RunFileExternal(py.test.collect.File):
    -    def __init__(self, name, parent, regrtest): 
    -        super(RunFileExternal, self).__init__(name, parent) 
    -        self.regrtest = regrtest 
    +    def __init__(self, name, parent, regrtest):
    +        super(RunFileExternal, self).__init__(name, parent)
    +        self.regrtest = regrtest
             self.fspath = regrtest.getfspath()
     
    -    def collect(self): 
    -        if self.regrtest.ismodified(): 
    +    def collect(self):
    +        if self.regrtest.ismodified():
                 name = 'modified'
             else:
                 name = 'unmodified'
    -        return [ReallyRunFileExternal(name, parent=self)] 
    +        return [ReallyRunFileExternal(name, parent=self)]
     
     #
    -# testmethod: 
    +# testmethod:
     # invoking in a separate process: py.py TESTFILE
     #
     import os
     import time
     import getpass
     
    -class ReallyRunFileExternal(py.test.collect.Item): 
    +class ReallyRunFileExternal(py.test.collect.Item):
         class ExternalFailure(Exception):
             """Failure in running subprocess"""
     
    -    def getinvocation(self, regrtest): 
    -        fspath = regrtest.getfspath() 
    -        python = sys.executable 
    +    def getinvocation(self, regrtest):
    +        fspath = regrtest.getfspath()
    +        python = sys.executable
             pypy_script = pypydir.join('bin', 'pyinteractive.py')
             alarm_script = pypydir.join('tool', 'alarm.py')
             if sys.platform == 'win32':
    @@ -555,9 +553,9 @@
                 watchdog_name = 'watchdog.py'
             watchdog_script = rpythondir.join('tool', watchdog_name)
     
    -        regr_script = pypydir.join('tool', 'pytest', 
    +        regr_script = pypydir.join('tool', 'pytest',
                                        'run-script', 'regrverbose.py')
    -        
    +
             regrrun = str(regr_script)
             option = self.config.option
             TIMEOUT = gettimeout(option.timeout.lower())
    @@ -566,8 +564,7 @@
                 if not execpath.check():
                     execpath = py.path.local.sysfind(option.pypy)
                 if not execpath:
    -                raise LookupError("could not find executable %r" %
    -                                  (option.pypy,))
    +                raise LookupError("could not find executable %r" % option.pypy)
     
                 # check modules
                 info = py.process.cmdexec("%s --info" % execpath)
    @@ -576,34 +573,29 @@
                     if info.get('objspace.usemodules.%s' % mod) is not True:
                         py.test.skip("%s module not included in %s" % (mod,
                                                                        execpath))
    -                    
    -            cmd = "%s %s %s" %(
    -                execpath, 
    -                regrrun, fspath.purebasename)
     
    +            cmd = "%s %s %s" % (execpath, regrrun, fspath.purebasename)
                 # add watchdog for timing out
    -            cmd = "%s %s %s %s" %(
    -                python, watchdog_script, TIMEOUT,
    -                cmd)
    +            cmd = "%s %s %s %s" % (python, watchdog_script, TIMEOUT, cmd)
             else:
                 pypy_options = []
                 pypy_options.extend(
                     ['--withmod-%s' % mod for mod in regrtest.usemodules])
    -            sopt = " ".join(pypy_options) 
    -            cmd = "%s %s %d %s -S %s %s %s -v" %(
    -                python, alarm_script, TIMEOUT, 
    -                pypy_script, sopt, 
    +            sopt = " ".join(pypy_options)
    +            cmd = "%s %s %d %s -S %s %s %s -v" % (
    +                python, alarm_script, TIMEOUT,
    +                pypy_script, sopt,
                     regrrun, fspath.purebasename)
    -        return cmd 
    +        return cmd
     
    -    def runtest(self): 
    -        """ invoke a subprocess running the test file via PyPy. 
    -            record its output into the 'result/user at host' subdirectory. 
    -            (we might want to create subdirectories for 
    -            each user, because we will probably all produce 
    +    def runtest(self):
    +        """ invoke a subprocess running the test file via PyPy.
    +            record its output into the 'result/user at host' subdirectory.
    +            (we might want to create subdirectories for
    +            each user, because we will probably all produce
                 such result runs and they will not be the same
    -            i am afraid. 
    -        """ 
    +            i am afraid.
    +        """
             regrtest = self.parent.regrtest
             if regrtest.skip:
                 if regrtest.skip is True:
    @@ -611,8 +603,8 @@
                 else:
                     msg = regrtest.skip
                 py.test.skip(msg)
    -        (skipped, exit_status, test_stdout,
    -                               test_stderr) = self.getresult(regrtest)
    +        (skipped, exit_status, test_stdout, test_stderr) = \
    +            self.getresult(regrtest)
             if skipped:
                 py.test.skip(test_stderr.splitlines()[-1])
             if exit_status:
    @@ -624,13 +616,13 @@
             out, err = excinfo.value.args
             return out + err
     
    -    def getstatusouterr(self, cmd): 
    +    def getstatusouterr(self, cmd):
             tempdir = py.test.ensuretemp(self.fspath.basename)
             stdout = tempdir.join(self.fspath.basename) + '.out'
             stderr = tempdir.join(self.fspath.basename) + '.err'
             if sys.platform == 'win32':
    -            status = os.system("%s >%s 2>%s" %(cmd, stdout, stderr))
    -            if status>=0:
    +            status = os.system("%s >%s 2>%s" % (cmd, stdout, stderr))
    +            if status >= 0:
                     status = status
                 else:
                     status = 'abnormal termination 0x%x' % status
    @@ -644,22 +636,22 @@
                     stdout.write('')
                     stderr.write('')
                 else:
    -                status = os.system("%s >>%s 2>>%s" %(cmd, stdout, stderr))
    +                status = os.system("%s >>%s 2>>%s" % (cmd, stdout, stderr))
                 if os.WIFEXITED(status):
                     status = os.WEXITSTATUS(status)
                 else:
                     status = 'abnormal termination 0x%x' % status
             return status, stdout.read(mode='rU'), stderr.read(mode='rU')
     
    -    def getresult(self, regrtest): 
    +    def getresult(self, regrtest):
             cmd = self.getinvocation(regrtest)
             tempdir = py.test.ensuretemp(self.fspath.basename)
             oldcwd = tempdir.chdir()
             exit_status, test_stdout, test_stderr = self.getstatusouterr(cmd)
             oldcwd.chdir()
             skipped = False
    -        timedout = test_stderr.rfind(26*"=" + "timedout" + 26*"=") != -1 
    -        if not timedout: 
    +        timedout = test_stderr.rfind(26*"=" + "timedout" + 26*"=") != -1
    +        if not timedout:
                 timedout = test_stderr.rfind("KeyboardInterrupt") != -1
             if test_stderr.rfind(26*"=" + "skipped" + 26*"=") != -1:
                 skipped = True
    @@ -669,12 +661,12 @@
                 # test in test_zipimport_support.py
                 if re.search(r'\bFAIL\b', test_stdout) or re.search('[^:]ERROR', test_stderr):
                     outcome = 'FAIL'
    -                exit_status = 2  
    -        elif timedout: 
    -            outcome = "T/O"    
    -        else: 
    +                exit_status = 2
    +        elif timedout:
    +            outcome = "T/O"
    +        else:
                 outcome = "ERR"
    -        
    +
             return skipped, exit_status, test_stdout, test_stderr
     
         def _keywords(self):
    @@ -683,4 +675,3 @@
             if regrtest.core:
                 lst.append('core')
             return lst
    -
    
    From noreply at buildbot.pypy.org  Sat Apr  6 03:29:53 2013
    From: noreply at buildbot.pypy.org (bdkearns)
    Date: Sat,  6 Apr 2013 03:29:53 +0200 (CEST)
    Subject: [pypy-commit] pypy default: fix this test after c2e8c09de077
    Message-ID: <20130406012953.5466D1C1481@cobra.cs.uni-duesseldorf.de>
    
    Author: Brian Kearns 
    Branch: 
    Changeset: r63085:80ab72ab0def
    Date: 2013-04-05 21:29 -0400
    http://bitbucket.org/pypy/pypy/changeset/80ab72ab0def/
    
    Log:	fix this test after c2e8c09de077
    
    diff --git a/pypy/module/_socket/test/test_sock_app.py b/pypy/module/_socket/test/test_sock_app.py
    --- a/pypy/module/_socket/test/test_sock_app.py
    +++ b/pypy/module/_socket/test/test_sock_app.py
    @@ -233,7 +233,7 @@
     
     def test_unknown_addr_as_object():
         from pypy.module._socket.interp_socket import addr_as_object
    -    c_addr = lltype.malloc(rsocket._c.sockaddr, flavor='raw')
    +    c_addr = lltype.malloc(rsocket._c.sockaddr, flavor='raw', track_allocation=False)
         c_addr.c_sa_data[0] = 'c'
         rffi.setintfield(c_addr, 'c_sa_family', 15)
         # XXX what size to pass here? for the purpose of this test it has
    
    From noreply at buildbot.pypy.org  Sat Apr  6 05:26:44 2013
    From: noreply at buildbot.pypy.org (bdkearns)
    Date: Sat,  6 Apr 2013 05:26:44 +0200 (CEST)
    Subject: [pypy-commit] pypy default: fix test_package when faking pypy_c
    Message-ID: <20130406032644.28CB01C0337@cobra.cs.uni-duesseldorf.de>
    
    Author: Brian Kearns 
    Branch: 
    Changeset: r63086:086df98954ff
    Date: 2013-04-05 23:26 -0400
    http://bitbucket.org/pypy/pypy/changeset/086df98954ff/
    
    Log:	fix test_package when faking pypy_c
    
    diff --git a/pypy/tool/release/test/test_package.py b/pypy/tool/release/test/test_package.py
    --- a/pypy/tool/release/test/test_package.py
    +++ b/pypy/tool/release/test/test_package.py
    @@ -17,7 +17,7 @@
             exe_name_in_archive = 'bin/pypy'
         pypy_c = py.path.local(pypydir).join('goal', basename)
         if not pypy_c.check():
    -        os.system("echo faked_pypy_c> %s" % (pypy_c,))
    +        pypy_c.write("#!/bin/sh")
             pypy_c.chmod(0755)
             fake_pypy_c = True
         else:
    
    From noreply at buildbot.pypy.org  Sat Apr  6 06:05:37 2013
    From: noreply at buildbot.pypy.org (bdkearns)
    Date: Sat,  6 Apr 2013 06:05:37 +0200 (CEST)
    Subject: [pypy-commit] pypy default: cleanups in lib_pypy
    Message-ID: <20130406040537.D7BCF1C039A@cobra.cs.uni-duesseldorf.de>
    
    Author: Brian Kearns 
    Branch: 
    Changeset: r63087:f0e3b9fc043a
    Date: 2013-04-06 00:01 -0400
    http://bitbucket.org/pypy/pypy/changeset/f0e3b9fc043a/
    
    Log:	cleanups in lib_pypy
    
    diff --git a/lib_pypy/_collections.py b/lib_pypy/_collections.py
    --- a/lib_pypy/_collections.py
    +++ b/lib_pypy/_collections.py
    @@ -8,7 +8,6 @@
     # Note that PyPy also contains a built-in module '_collections' which will hide
     # this one if compiled in.
     
    -import operator
     try:
         from threading import _get_ident as _thread_ident
     except ImportError:
    diff --git a/lib_pypy/_pypy_interact.py b/lib_pypy/_pypy_interact.py
    --- a/lib_pypy/_pypy_interact.py
    +++ b/lib_pypy/_pypy_interact.py
    @@ -74,7 +74,6 @@
     # ____________________________________________________________
     
     if __name__ == '__main__':    # for testing
    -    import os
         if os.getenv('PYTHONSTARTUP'):
             execfile(os.getenv('PYTHONSTARTUP'))
         interactive_console()
    diff --git a/lib_pypy/_sha512.py b/lib_pypy/_sha512.py
    --- a/lib_pypy/_sha512.py
    +++ b/lib_pypy/_sha512.py
    @@ -30,23 +30,23 @@
     
     def sha_transform(sha_info):
         W = []
    -    
    +
         d = sha_info['data']
         for i in xrange(0,16):
             W.append( (d[8*i]<<56) + (d[8*i+1]<<48) + (d[8*i+2]<<40) + (d[8*i+3]<<32) + (d[8*i+4]<<24) + (d[8*i+5]<<16) + (d[8*i+6]<<8) + d[8*i+7])
    -    
    +
         for i in xrange(16,80):
             W.append( (Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]) & 0xffffffffffffffff )
    -    
    +
         ss = sha_info['digest'][:]
    -    
    +
         def RND(a,b,c,d,e,f,g,h,i,ki):
             t0 = (h + Sigma1(e) + Ch(e, f, g) + ki + W[i]) & 0xffffffffffffffff
             t1 = (Sigma0(a) + Maj(a, b, c)) & 0xffffffffffffffff
             d = (d + t0) & 0xffffffffffffffff
             h = (t0 + t1) & 0xffffffffffffffff
             return d & 0xffffffffffffffff, h & 0xffffffffffffffff
    -    
    +
         ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],0,0x428a2f98d728ae22)
         ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],1,0x7137449123ef65cd)
         ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],2,0xb5c0fbcfec4d3b2f)
    @@ -127,8 +127,7 @@
         ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],77,0x597f299cfc657e2a)
         ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],78,0x5fcb6fab3ad6faec)
         ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],79,0x6c44198c4a475817)
    -    
    -    
    +
         dig = []
         for i, x in enumerate(sha_info['digest']):
             dig.append( (x + ss[i]) & 0xffffffffffffffff )
    @@ -167,36 +166,35 @@
         if clo < sha_info['count_lo']:
             sha_info['count_hi'] += 1
         sha_info['count_lo'] = clo
    -    
    +
         sha_info['count_hi'] += (count >> 29)
    -    
    +
         if sha_info['local']:
             i = SHA_BLOCKSIZE - sha_info['local']
             if i > count:
                 i = count
    -        
    +
             # copy buffer
             for x in enumerate(buffer[buffer_idx:buffer_idx+i]):
                 sha_info['data'][sha_info['local']+x[0]] = struct.unpack('B', x[1])[0]
    -        
    +
             count -= i
             buffer_idx += i
    -        
    +
             sha_info['local'] += i
             if sha_info['local'] == SHA_BLOCKSIZE:
                 sha_transform(sha_info)
                 sha_info['local'] = 0
             else:
                 return
    -    
    +
         while count >= SHA_BLOCKSIZE:
             # copy buffer
             sha_info['data'] = [struct.unpack('B',c)[0] for c in buffer[buffer_idx:buffer_idx + SHA_BLOCKSIZE]]
             count -= SHA_BLOCKSIZE
             buffer_idx += SHA_BLOCKSIZE
             sha_transform(sha_info)
    -    
    -    
    +
         # copy buffer
         pos = sha_info['local']
         sha_info['data'][pos:pos+count] = [struct.unpack('B',c)[0] for c in buffer[buffer_idx:buffer_idx + count]]
    @@ -216,7 +214,7 @@
             sha_info['data'] = [0] * SHA_BLOCKSIZE
         else:
             sha_info['data'] = sha_info['data'][:count] + ([0] * (SHA_BLOCKSIZE - count))
    -    
    +
         sha_info['data'][112] = 0;
         sha_info['data'][113] = 0;
         sha_info['data'][114] = 0;
    @@ -225,7 +223,7 @@
         sha_info['data'][117] = 0;
         sha_info['data'][118] = 0;
         sha_info['data'][119] = 0;
    -    
    +
         sha_info['data'][120] = (hi_bit_count >> 24) & 0xff
         sha_info['data'][121] = (hi_bit_count >> 16) & 0xff
         sha_info['data'][122] = (hi_bit_count >>  8) & 0xff
    @@ -234,9 +232,9 @@
         sha_info['data'][125] = (lo_bit_count >> 16) & 0xff
         sha_info['data'][126] = (lo_bit_count >>  8) & 0xff
         sha_info['data'][127] = (lo_bit_count >>  0) & 0xff
    -    
    +
         sha_transform(sha_info)
    -    
    +
         dig = []
         for i in sha_info['digest']:
             dig.extend([ ((i>>56) & 0xff), ((i>>48) & 0xff), ((i>>40) & 0xff), ((i>>32) & 0xff), ((i>>24) & 0xff), ((i>>16) & 0xff), ((i>>8) & 0xff), (i & 0xff) ])
    @@ -250,13 +248,13 @@
             self._sha = sha_init()
             if s:
                 sha_update(self._sha, getbuf(s))
    -    
    +
         def update(self, s):
             sha_update(self._sha, getbuf(s))
    -    
    +
         def digest(self):
             return sha_final(self._sha.copy())[:self._sha['digestsize']]
    -    
    +
         def hexdigest(self):
             return ''.join(['%.2x' % ord(i) for i in self.digest()])
     
    @@ -279,12 +277,14 @@
             return new
     
     def test():
    +    import _sha512
    +
         a_str = "just a test string"
    -    
    +
         assert _sha512.sha512().hexdigest() == sha512().hexdigest()
         assert _sha512.sha512(a_str).hexdigest() == sha512(a_str).hexdigest()
         assert _sha512.sha512(a_str*7).hexdigest() == sha512(a_str*7).hexdigest()
    -    
    +
         s = sha512(a_str)
         s.update(a_str)
         assert _sha512.sha512(a_str+a_str).hexdigest() == s.hexdigest()
    diff --git a/lib_pypy/dbm.py b/lib_pypy/dbm.py
    --- a/lib_pypy/dbm.py
    +++ b/lib_pypy/dbm.py
    @@ -168,7 +168,7 @@
                 'c': os.O_RDWR | os.O_CREAT,
                 'n': os.O_RDWR | os.O_CREAT | os.O_TRUNC,
                 }[flag]
    -    except KeyError, e:
    +    except KeyError:
             raise error("arg 2 to open should be 'r', 'w', 'c', or 'n'")
     
         a_db = getattr(lib, funcs['open'])(filename, openflag, mode)
    diff --git a/lib_pypy/greenlet.py b/lib_pypy/greenlet.py
    --- a/lib_pypy/greenlet.py
    +++ b/lib_pypy/greenlet.py
    @@ -1,4 +1,4 @@
    -import _continuation, sys
    +import _continuation
     
     __version__ = "0.4.0"
     
    
    From noreply at buildbot.pypy.org  Sat Apr  6 06:13:33 2013
    From: noreply at buildbot.pypy.org (bdkearns)
    Date: Sat,  6 Apr 2013 06:13:33 +0200 (CEST)
    Subject: [pypy-commit] pypy py3k: merge default
    Message-ID: <20130406041333.A24461C039A@cobra.cs.uni-duesseldorf.de>
    
    Author: Brian Kearns 
    Branch: py3k
    Changeset: r63088:1b3e654752cc
    Date: 2013-04-06 00:13 -0400
    http://bitbucket.org/pypy/pypy/changeset/1b3e654752cc/
    
    Log:	merge default
    
    diff --git a/lib-python/conftest.py b/lib-python/conftest.py
    --- a/lib-python/conftest.py
    +++ b/lib-python/conftest.py
    @@ -1,92 +1,90 @@
     """
     
     test configuration(s) for running CPython's regression
    -test suite on top of PyPy 
    +test suite on top of PyPy
     
     """
     import py
     import sys
     import pypy
     import re
    -from pypy.interpreter.gateway import ApplevelClass 
    +from pypy.interpreter.gateway import ApplevelClass
     from pypy.interpreter.error import OperationError
    -from pypy.interpreter.module import Module as PyPyModule 
    +from pypy.interpreter.module import Module as PyPyModule
     from pypy.interpreter.main import run_string, run_file
     
    -# the following adds command line options as a side effect! 
    -from pypy.conftest import option as pypy_option 
    +# the following adds command line options as a side effect!
    +from pypy.conftest import option as pypy_option
     
    -from pypy.tool.pytest import appsupport 
    +from pypy.tool.pytest import appsupport
     from pypy.tool.pytest.confpath import pypydir, rpythondir, testdir, testresultdir
     from rpython.config.parse import parse_info
     
     pytest_plugins = "resultlog",
     rsyncdirs = ['.', '../pypy/']
     
    -# 
    -# Interfacing/Integrating with py.test's collection process 
    +#
    +# Interfacing/Integrating with py.test's collection process
     #
     
     def pytest_addoption(parser):
    -    group = parser.getgroup("complicance testing options") 
    -    group.addoption('-T', '--timeout', action="store", type="string", 
    -       default="1000", dest="timeout", 
    -       help="fail a test module after the given timeout. "
    -            "specify in seconds or 'NUMmp' aka Mega-Pystones")
    -    group.addoption('--pypy', action="store", type="string",
    -       dest="pypy",  help="use given pypy executable to run lib-python tests. "
    -                          "This will run the tests directly (i.e. not through py.py)")
    +    group = parser.getgroup("complicance testing options")
    +    group.addoption('-T', '--timeout', action="store", type="string",
    +                    default="1000", dest="timeout",
    +                    help="fail a test module after the given timeout. "
    +                         "specify in seconds or 'NUMmp' aka Mega-Pystones")
    +    group.addoption('--pypy', action="store", type="string", dest="pypy",
    +                    help="use given pypy executable to run lib-python tests. "
    +                         "This will run the tests directly (i.e. not through py.py)")
         group.addoption('--filter', action="store", type="string", default=None,
    -                    dest="unittest_filter",  help="Similar to -k, XXX")
    +                    dest="unittest_filter", help="Similar to -k, XXX")
     
    -def gettimeout(timeout): 
    +def gettimeout(timeout):
         from rpython.translator.test import rpystone
    -    if timeout.endswith('mp'): 
    +    if timeout.endswith('mp'):
             megapystone = float(timeout[:-2])
             t, stone = pystone.Proc0(10000)
    -        pystonetime = t/stone 
    -        seconds = megapystone  * 1000000 * pystonetime
    -        return seconds 
    -    return float(timeout) 
    +        pystonetime = t/stone
    +        seconds = megapystone * 1000000 * pystonetime
    +        return seconds
    +    return float(timeout)
     
     # ________________________________________________________________________
     #
    -# classification of all tests files (this is ongoing work) 
    +# classification of all tests files (this is ongoing work)
     #
     
    -class RegrTest: 
    -    """ Regression Test Declaration.""" 
    -    def __init__(self, basename, core=False,
    -                                 compiler=None, 
    -                                 usemodules = '',
    -                                 skip=None): 
    -        self.basename = basename 
    +class RegrTest:
    +    """ Regression Test Declaration."""
    +    def __init__(self, basename, core=False, compiler=None, usemodules='',
    +                 skip=None):
    +        self.basename = basename
             self._usemodules = usemodules.split() + ['signal', 'rctime', 'binascii', '_socket',
                     'select', 'fcntl', '_posixsubprocess']
    -        self._compiler = compiler 
    +        self._compiler = compiler
             self.core = core
             self.skip = skip
             assert self.getfspath().check(), "%r not found!" % (basename,)
     
         def usemodules(self):
    -        return self._usemodules #+ pypy_option.usemodules
    +        return self._usemodules  # + pypy_option.usemodules
         usemodules = property(usemodules)
     
    -    def compiler(self): 
    -        return self._compiler #or pypy_option.compiler 
    +    def compiler(self):
    +        return self._compiler  # or pypy_option.compiler
         compiler = property(compiler)
     
    -    def ismodified(self): 
    +    def ismodified(self):
             #XXX: ask hg
             return None
     
    -    def getfspath(self): 
    +    def getfspath(self):
             return testdir.join(self.basename)
     
    -    def run_file(self, space): 
    +    def run_file(self, space):
             fspath = self.getfspath()
             assert fspath.check()
    -        modname = fspath.purebasename 
    +        modname = fspath.purebasename
             space.appexec([], '''():
                 from test import %(modname)s
                 m = %(modname)s
    @@ -392,7 +390,7 @@
         RegrTest('test_textwrap.py'),
         RegrTest('test_thread.py', usemodules="thread", core=True),
         RegrTest('test_threaded_import.py', usemodules="thread", core=True),
    -    RegrTest('test_threadedtempfile.py', 
    +    RegrTest('test_threadedtempfile.py',
                  usemodules="thread", core=False),
         RegrTest('test_threading.py', usemodules="thread", core=True),
         RegrTest('test_threading_local.py', usemodules="thread", core=True),
    @@ -469,7 +467,7 @@
     
     def pytest_configure(config):
         config._basename2spec = cache = {}
    -    for x in testmap: 
    +    for x in testmap:
             cache[x.basename] = x
     
     def pytest_collect_file(path, parent, __multicall__):
    @@ -485,33 +483,33 @@
         return RunFileExternal(path.basename, parent=parent, regrtest=regrtest)
     
     class RunFileExternal(py.test.collect.File):
    -    def __init__(self, name, parent, regrtest): 
    -        super(RunFileExternal, self).__init__(name, parent) 
    -        self.regrtest = regrtest 
    +    def __init__(self, name, parent, regrtest):
    +        super(RunFileExternal, self).__init__(name, parent)
    +        self.regrtest = regrtest
             self.fspath = regrtest.getfspath()
     
    -    def collect(self): 
    -        if self.regrtest.ismodified(): 
    +    def collect(self):
    +        if self.regrtest.ismodified():
                 name = 'modified'
             else:
                 name = 'unmodified'
    -        return [ReallyRunFileExternal(name, parent=self)] 
    +        return [ReallyRunFileExternal(name, parent=self)]
     
     #
    -# testmethod: 
    +# testmethod:
     # invoking in a separate process: py.py TESTFILE
     #
     import os
     import time
     import getpass
     
    -class ReallyRunFileExternal(py.test.collect.Item): 
    +class ReallyRunFileExternal(py.test.collect.Item):
         class ExternalFailure(Exception):
             """Failure in running subprocess"""
     
    -    def getinvocation(self, regrtest): 
    -        fspath = regrtest.getfspath() 
    -        python = sys.executable 
    +    def getinvocation(self, regrtest):
    +        fspath = regrtest.getfspath()
    +        python = sys.executable
             pypy_script = pypydir.join('bin', 'pyinteractive.py')
             alarm_script = pypydir.join('tool', 'alarm.py')
             if sys.platform == 'win32':
    @@ -520,9 +518,9 @@
                 watchdog_name = 'watchdog.py'
             watchdog_script = rpythondir.join('tool', watchdog_name)
     
    -        regr_script = pypydir.join('tool', 'pytest', 
    +        regr_script = pypydir.join('tool', 'pytest',
                                        'run-script', 'regrverbose.py')
    -        
    +
             regrrun = str(regr_script)
             option = self.config.option
             TIMEOUT = gettimeout(option.timeout.lower())
    @@ -531,8 +529,7 @@
                 if not execpath.check():
                     execpath = py.path.local.sysfind(option.pypy)
                 if not execpath:
    -                raise LookupError("could not find executable %r" %
    -                                  (option.pypy,))
    +                raise LookupError("could not find executable %r" % option.pypy)
     
                 # check modules
                 info = py.process.cmdexec("%s --info" % execpath)
    @@ -541,34 +538,29 @@
                     if info.get('objspace.usemodules.%s' % mod) is not True:
                         py.test.skip("%s module not included in %s" % (mod,
                                                                        execpath))
    -                    
    -            cmd = "%s %s %s" %(
    -                execpath, 
    -                regrrun, fspath.purebasename)
     
    +            cmd = "%s %s %s" % (execpath, regrrun, fspath.purebasename)
                 # add watchdog for timing out
    -            cmd = "%s %s %s %s" %(
    -                python, watchdog_script, TIMEOUT,
    -                cmd)
    +            cmd = "%s %s %s %s" % (python, watchdog_script, TIMEOUT, cmd)
             else:
                 pypy_options = []
                 pypy_options.extend(
                     ['--withmod-%s' % mod for mod in regrtest.usemodules])
    -            sopt = " ".join(pypy_options) 
    -            cmd = "%s %s %d %s -S %s %s %s -v" %(
    -                python, alarm_script, TIMEOUT, 
    -                pypy_script, sopt, 
    +            sopt = " ".join(pypy_options)
    +            cmd = "%s %s %d %s -S %s %s %s -v" % (
    +                python, alarm_script, TIMEOUT,
    +                pypy_script, sopt,
                     regrrun, fspath.purebasename)
    -        return cmd 
    +        return cmd
     
    -    def runtest(self): 
    -        """ invoke a subprocess running the test file via PyPy. 
    -            record its output into the 'result/user at host' subdirectory. 
    -            (we might want to create subdirectories for 
    -            each user, because we will probably all produce 
    +    def runtest(self):
    +        """ invoke a subprocess running the test file via PyPy.
    +            record its output into the 'result/user at host' subdirectory.
    +            (we might want to create subdirectories for
    +            each user, because we will probably all produce
                 such result runs and they will not be the same
    -            i am afraid. 
    -        """ 
    +            i am afraid.
    +        """
             regrtest = self.parent.regrtest
             if regrtest.skip:
                 if regrtest.skip is True:
    @@ -576,8 +568,8 @@
                 else:
                     msg = regrtest.skip
                 py.test.skip(msg)
    -        (skipped, exit_status, test_stdout,
    -                               test_stderr) = self.getresult(regrtest)
    +        (skipped, exit_status, test_stdout, test_stderr) = \
    +            self.getresult(regrtest)
             if skipped:
                 py.test.skip(test_stderr.splitlines()[-1])
             if exit_status:
    @@ -589,13 +581,13 @@
             out, err = excinfo.value.args
             return out + err
     
    -    def getstatusouterr(self, cmd): 
    +    def getstatusouterr(self, cmd):
             tempdir = py.test.ensuretemp(self.fspath.basename)
             stdout = tempdir.join(self.fspath.basename) + '.out'
             stderr = tempdir.join(self.fspath.basename) + '.err'
             if sys.platform == 'win32':
    -            status = os.system("%s >%s 2>%s" %(cmd, stdout, stderr))
    -            if status>=0:
    +            status = os.system("%s >%s 2>%s" % (cmd, stdout, stderr))
    +            if status >= 0:
                     status = status
                 else:
                     status = 'abnormal termination 0x%x' % status
    @@ -609,22 +601,22 @@
                     stdout.write('')
                     stderr.write('')
                 else:
    -                status = os.system("%s >>%s 2>>%s" %(cmd, stdout, stderr))
    +                status = os.system("%s >>%s 2>>%s" % (cmd, stdout, stderr))
                 if os.WIFEXITED(status):
                     status = os.WEXITSTATUS(status)
                 else:
                     status = 'abnormal termination 0x%x' % status
             return status, stdout.read(mode='rU'), stderr.read(mode='rU')
     
    -    def getresult(self, regrtest): 
    +    def getresult(self, regrtest):
             cmd = self.getinvocation(regrtest)
             tempdir = py.test.ensuretemp(self.fspath.basename)
             oldcwd = tempdir.chdir()
             exit_status, test_stdout, test_stderr = self.getstatusouterr(cmd)
             oldcwd.chdir()
             skipped = False
    -        timedout = test_stderr.rfind(26*"=" + "timedout" + 26*"=") != -1 
    -        if not timedout: 
    +        timedout = test_stderr.rfind(26*"=" + "timedout" + 26*"=") != -1
    +        if not timedout:
                 timedout = test_stderr.rfind("KeyboardInterrupt") != -1
             if test_stderr.rfind(26*"=" + "skipped" + 26*"=") != -1:
                 skipped = True
    @@ -634,12 +626,12 @@
                 # test in test_zipimport_support.py
                 if re.search(r'\bFAIL\b', test_stdout) or re.search('[^:]ERROR', test_stderr):
                     outcome = 'FAIL'
    -                exit_status = 2  
    -        elif timedout: 
    -            outcome = "T/O"    
    -        else: 
    +                exit_status = 2
    +        elif timedout:
    +            outcome = "T/O"
    +        else:
                 outcome = "ERR"
    -        
    +
             return skipped, exit_status, test_stdout, test_stderr
     
         def _keywords(self):
    @@ -648,4 +640,3 @@
             if regrtest.core:
                 lst.append('core')
             return lst
    -
    diff --git a/lib_pypy/_collections.py b/lib_pypy/_collections.py
    --- a/lib_pypy/_collections.py
    +++ b/lib_pypy/_collections.py
    @@ -8,7 +8,6 @@
     # Note that PyPy also contains a built-in module '_collections' which will hide
     # this one if compiled in.
     
    -import operator
     try:
         from _thread import _get_ident as _thread_ident
     except ImportError:
    diff --git a/lib_pypy/_curses.py b/lib_pypy/_curses.py
    --- a/lib_pypy/_curses.py
    +++ b/lib_pypy/_curses.py
    @@ -359,10 +359,12 @@
         if not lib._m_NetBSD:
             for key in range(lib.KEY_MIN, lib.KEY_MAX):
                 key_n = lib.keyname(key)
    -            if key_n == ffi.NULL or ffi.string(key_n) == b"UNKNOWN KEY":
    +            if key_n == ffi.NULL:
                     continue
    -            key_n = ffi.string(key_n).decode()
    -            key_n = key_n.replace('(', '').replace(')', '')
    +            key_n = ffi.string(key_n)
    +            if key_n == b"UNKNOWN KEY":
    +                continue
    +            key_n = key_n.decode().replace('(', '').replace(')', '')
                 globals()[key_n] = key
     
     _setup()
    diff --git a/lib_pypy/_dbm.py b/lib_pypy/_dbm.py
    --- a/lib_pypy/_dbm.py
    +++ b/lib_pypy/_dbm.py
    @@ -172,7 +172,7 @@
                 'c': os.O_RDWR | os.O_CREAT,
                 'n': os.O_RDWR | os.O_CREAT | os.O_TRUNC,
                 }[flag]
    -    except KeyError as e:
    +    except KeyError:
             raise error("arg 2 to open should be 'r', 'w', 'c', or 'n'")
     
         a_db = getattr(lib, funcs['open'])(filename, openflag, mode)
    diff --git a/lib_pypy/_pypy_interact.py b/lib_pypy/_pypy_interact.py
    --- a/lib_pypy/_pypy_interact.py
    +++ b/lib_pypy/_pypy_interact.py
    @@ -73,7 +73,6 @@
     # ____________________________________________________________
     
     if __name__ == '__main__':    # for testing
    -    import os
         if os.getenv('PYTHONSTARTUP'):
             exec(compile(open(os.getenv('PYTHONSTARTUP')).read(), os.getenv('PYTHONSTARTUP'), 'exec'))
         interactive_console()
    diff --git a/lib_pypy/_sha512.py b/lib_pypy/_sha512.py
    --- a/lib_pypy/_sha512.py
    +++ b/lib_pypy/_sha512.py
    @@ -28,23 +28,23 @@
     
     def sha_transform(sha_info):
         W = []
    -    
    +
         d = sha_info['data']
         for i in range(0,16):
             W.append( (d[8*i]<<56) + (d[8*i+1]<<48) + (d[8*i+2]<<40) + (d[8*i+3]<<32) + (d[8*i+4]<<24) + (d[8*i+5]<<16) + (d[8*i+6]<<8) + d[8*i+7])
    -    
    +
         for i in range(16,80):
             W.append( (Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]) & 0xffffffffffffffff )
    -    
    +
         ss = sha_info['digest'][:]
    -    
    +
         def RND(a,b,c,d,e,f,g,h,i,ki):
             t0 = (h + Sigma1(e) + Ch(e, f, g) + ki + W[i]) & 0xffffffffffffffff
             t1 = (Sigma0(a) + Maj(a, b, c)) & 0xffffffffffffffff
             d = (d + t0) & 0xffffffffffffffff
             h = (t0 + t1) & 0xffffffffffffffff
             return d & 0xffffffffffffffff, h & 0xffffffffffffffff
    -    
    +
         ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],0,0x428a2f98d728ae22)
         ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],1,0x7137449123ef65cd)
         ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],2,0xb5c0fbcfec4d3b2f)
    @@ -125,8 +125,7 @@
         ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],77,0x597f299cfc657e2a)
         ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],78,0x5fcb6fab3ad6faec)
         ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],79,0x6c44198c4a475817)
    -    
    -    
    +
         dig = []
         for i, x in enumerate(sha_info['digest']):
             dig.append( (x + ss[i]) & 0xffffffffffffffff )
    @@ -159,35 +158,34 @@
         if clo < sha_info['count_lo']:
             sha_info['count_hi'] += 1
         sha_info['count_lo'] = clo
    -    
    +
         sha_info['count_hi'] += (count >> 29)
    -    
    +
         if sha_info['local']:
             i = SHA_BLOCKSIZE - sha_info['local']
             if i > count:
                 i = count
    -        
    +
             # copy buffer
             sha_info['data'][sha_info['local']:sha_info['local']+i] = buffer[buffer_idx:buffer_idx+i]
    -        
    +
             count -= i
             buffer_idx += i
    -        
    +
             sha_info['local'] += i
             if sha_info['local'] == SHA_BLOCKSIZE:
                 sha_transform(sha_info)
                 sha_info['local'] = 0
             else:
                 return
    -    
    +
         while count >= SHA_BLOCKSIZE:
             # copy buffer
             sha_info['data'] = list(buffer[buffer_idx:buffer_idx + SHA_BLOCKSIZE])
             count -= SHA_BLOCKSIZE
             buffer_idx += SHA_BLOCKSIZE
             sha_transform(sha_info)
    -    
    -    
    +
         # copy buffer
         pos = sha_info['local']
         sha_info['data'][pos:pos+count] = buffer[buffer_idx:buffer_idx + count]
    @@ -207,7 +205,7 @@
             sha_info['data'] = [0] * SHA_BLOCKSIZE
         else:
             sha_info['data'] = sha_info['data'][:count] + ([0] * (SHA_BLOCKSIZE - count))
    -    
    +
         sha_info['data'][112] = 0;
         sha_info['data'][113] = 0;
         sha_info['data'][114] = 0;
    @@ -216,7 +214,7 @@
         sha_info['data'][117] = 0;
         sha_info['data'][118] = 0;
         sha_info['data'][119] = 0;
    -    
    +
         sha_info['data'][120] = (hi_bit_count >> 24) & 0xff
         sha_info['data'][121] = (hi_bit_count >> 16) & 0xff
         sha_info['data'][122] = (hi_bit_count >>  8) & 0xff
    @@ -225,9 +223,9 @@
         sha_info['data'][125] = (lo_bit_count >> 16) & 0xff
         sha_info['data'][126] = (lo_bit_count >>  8) & 0xff
         sha_info['data'][127] = (lo_bit_count >>  0) & 0xff
    -    
    +
         sha_transform(sha_info)
    -    
    +
         dig = []
         for i in sha_info['digest']:
             dig.extend([ ((i>>56) & 0xff), ((i>>48) & 0xff), ((i>>40) & 0xff), ((i>>32) & 0xff), ((i>>24) & 0xff), ((i>>16) & 0xff), ((i>>8) & 0xff), (i & 0xff) ])
    @@ -241,13 +239,13 @@
             self._sha = sha_init()
             if s:
                 sha_update(self._sha, s)
    -    
    +
         def update(self, s):
             sha_update(self._sha, s)
    -    
    +
         def digest(self):
             return sha_final(self._sha.copy())[:self._sha['digestsize']]
    -    
    +
         def hexdigest(self):
             return ''.join(['%.2x' % i for i in self.digest()])
     
    @@ -270,12 +268,14 @@
             return new
     
     def test():
    +    import _sha512
    +
         a_str = "just a test string"
    -    
    +
         assert _sha512.sha512().hexdigest() == sha512().hexdigest()
         assert _sha512.sha512(a_str).hexdigest() == sha512(a_str).hexdigest()
         assert _sha512.sha512(a_str*7).hexdigest() == sha512(a_str*7).hexdigest()
    -    
    +
         s = sha512(a_str)
         s.update(a_str)
         assert _sha512.sha512(a_str+a_str).hexdigest() == s.hexdigest()
    diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py
    --- a/lib_pypy/_sqlite3.py
    +++ b/lib_pypy/_sqlite3.py
    @@ -852,7 +852,7 @@
             self._reset = False
             self.__locked = False
             self.__closed = False
    -        self.__description = None
    +        self.__lastrowid = None
             self.__rowcount = -1
     
             con._check_thread()
    @@ -958,7 +958,7 @@
                     elif typ == _lib.SQLITE_BLOB:
                         blob = _lib.sqlite3_column_blob(self.__statement._statement, i)
                         blob_len = _lib.sqlite3_column_bytes(self.__statement._statement, i)
    -                    val = _BLOB_TYPE(_ffi.buffer(blob, blob_len))
    +                    val = _BLOB_TYPE(_ffi.buffer(blob, blob_len)[:])
                 row.append(val)
             return tuple(row)
     
    @@ -972,20 +972,24 @@
             try:
                 if not isinstance(sql, basestring):
                     raise ValueError("operation parameter must be str or unicode")
    -            self.__description = None
    +            try:
    +                del self.__description
    +            except AttributeError:
    +                pass
                 self.__rowcount = -1
                 self.__statement = self.__connection._statement_cache.get(sql)
     
                 if self.__connection._isolation_level is not None:
    -                if self.__statement._kind == Statement._DDL:
    +                if self.__statement._type in ("UPDATE", "DELETE", "INSERT", "REPLACE"):
    +                    if not self.__connection._in_transaction:
    +                        self.__connection._begin()
    +                elif self.__statement._type == "OTHER":
                         if self.__connection._in_transaction:
                             self.__connection.commit()
    -                elif self.__statement._kind == Statement._DML:
    -                    if not self.__connection._in_transaction:
    -                        self.__connection._begin()
    -
    -            if multiple and self.__statement._kind != Statement._DML:
    -                raise ProgrammingError("executemany is only for DML statements")
    +                elif self.__statement._type == "SELECT":
    +                    if multiple:
    +                        raise ProgrammingError("You cannot execute SELECT "
    +                                               "statements in executemany().")
     
                 for params in many_params:
                     self.__statement._set_params(params)
    @@ -996,17 +1000,26 @@
                         self.__statement._reset()
                         raise self.__connection._get_exception(ret)
     
    -                if self.__statement._kind == Statement._DML:
    +                if ret == _lib.SQLITE_ROW:
    +                    if multiple:
    +                        raise ProgrammingError("executemany() can only execute DML statements.")
    +                    self.__build_row_cast_map()
    +                    self.__next_row = self.__fetch_one_row()
    +                elif ret == _lib.SQLITE_DONE and not multiple:
                         self.__statement._reset()
     
    -                if ret == _lib.SQLITE_ROW:
    -                    self.__build_row_cast_map()
    -                    self.__next_row = self.__fetch_one_row()
    -
    -                if self.__statement._kind == Statement._DML:
    +                if self.__statement._type in ("UPDATE", "DELETE", "INSERT", "REPLACE"):
                         if self.__rowcount == -1:
                             self.__rowcount = 0
                         self.__rowcount += _lib.sqlite3_changes(self.__connection._db)
    +
    +                if not multiple and self.__statement._type == "INSERT":
    +                    self.__lastrowid = _lib.sqlite3_last_insert_rowid(self.__connection._db)
    +                else:
    +                    self.__lastrowid = None
    +
    +                if multiple:
    +                    self.__statement._reset()
             finally:
                 self.__connection._in_transaction = \
                     not _lib.sqlite3_get_autocommit(self.__connection._db)
    @@ -1075,7 +1088,6 @@
                 next_row = self.__next_row
             except AttributeError:
                 self.__statement._reset()
    -            self.__statement = None
                 raise StopIteration
             del self.__next_row
     
    @@ -1119,13 +1131,15 @@
         rowcount = property(__get_rowcount)
     
         def __get_description(self):
    -        if self.__description is None:
    +        try:
    +            return self.__description
    +        except AttributeError:
                 self.__description = self.__statement._get_description()
    -        return self.__description
    +            return self.__description
         description = property(__get_description)
     
         def __get_lastrowid(self):
    -        return _lib.sqlite3_last_insert_rowid(self.__connection._db)
    +        return self.__lastrowid
         lastrowid = property(__get_lastrowid)
     
         def setinputsizes(self, *args):
    @@ -1136,8 +1150,6 @@
     
     
     class Statement(object):
    -    _DML, _DQL, _DDL = range(3)
    -
         _statement = None
     
         def __init__(self, connection, sql):
    @@ -1148,13 +1160,14 @@
     
             if not isinstance(sql, basestring):
                 raise Warning("SQL is of wrong type. Must be string or unicode.")
    -        first_word = self._statement_kind = sql.lstrip().split(" ")[0].upper()
    -        if first_word in ("INSERT", "UPDATE", "DELETE", "REPLACE"):
    -            self._kind = Statement._DML
    -        elif first_word in ("SELECT", "PRAGMA"):
    -            self._kind = Statement._DQL
    +
    +        first_word = sql.lstrip().split(" ")[0].upper()
    +        if first_word == "":
    +            self._type = "INVALID"
    +        elif first_word in ("SELECT", "INSERT", "UPDATE", "DELETE", "REPLACE"):
    +            self._type = first_word
             else:
    -            self._kind = Statement._DDL
    +            self._type = "OTHER"
     
             if isinstance(sql, unicode):
                 sql = sql.encode('utf-8')
    @@ -1167,11 +1180,12 @@
     
             if ret == _lib.SQLITE_OK and not self._statement:
                 # an empty statement, work around that, as it's the least trouble
    +            self._type = "SELECT"
                 c_sql = _ffi.new("char[]", b"select 42")
                 ret = _lib.sqlite3_prepare_v2(self.__con._db, c_sql, -1,
                                               statement_star, next_char)
                 self._statement = statement_star[0]
    -            self._kind = Statement._DQL
    +
             if ret != _lib.SQLITE_OK:
                 raise self.__con._get_exception(ret)
     
    @@ -1282,7 +1296,7 @@
                 raise ValueError("parameters are of unsupported type")
     
         def _get_description(self):
    -        if self._kind == Statement._DML:
    +        if self._type in ("INSERT", "UPDATE", "DELETE", "REPLACE"):
                 return None
             desc = []
             for i in xrange(_lib.sqlite3_column_count(self._statement)):
    @@ -1387,7 +1401,7 @@
             elif typ == _lib.SQLITE_BLOB:
                 blob = _lib.sqlite3_value_blob(params[i])
                 blob_len = _lib.sqlite3_value_bytes(params[i])
    -            val = _BLOB_TYPE(_ffi.buffer(blob, blob_len))
    +            val = _BLOB_TYPE(_ffi.buffer(blob, blob_len)[:])
             else:
                 raise NotImplementedError
             _params.append(val)
    diff --git a/lib_pypy/cffi/api.py b/lib_pypy/cffi/api.py
    --- a/lib_pypy/cffi/api.py
    +++ b/lib_pypy/cffi/api.py
    @@ -25,6 +25,7 @@
                 line = ''
             return '%s%s' % (line, self.args[0])
     
    +
     class FFI(object):
         r'''
         The main top-level class that you instantiate once, or once per module.
    @@ -220,7 +221,7 @@
             it as a string or unicode string.
     
             If 'cdata' is an enum, returns the value of the enumerator as a
    -        string, or '#NUMBER' if the value is out of range.
    +        string, or 'NUMBER' if the value is out of range.
             """
             return self._backend.string(cdata, maxlen)
     
    diff --git a/lib_pypy/cffi/cparser.py b/lib_pypy/cffi/cparser.py
    --- a/lib_pypy/cffi/cparser.py
    +++ b/lib_pypy/cffi/cparser.py
    @@ -2,7 +2,7 @@
     from . import api, model
     from .commontypes import COMMON_TYPES, resolve_common_type
     try:
    -    from cffi import _pycparser as pycparser
    +    from . import _pycparser as pycparser
     except ImportError:
         import pycparser
     import weakref, re, sys
    diff --git a/lib_pypy/greenlet.py b/lib_pypy/greenlet.py
    --- a/lib_pypy/greenlet.py
    +++ b/lib_pypy/greenlet.py
    @@ -1,4 +1,4 @@
    -import _continuation, sys
    +import _continuation
     
     __version__ = "0.4.0"
     
    diff --git a/pypy/doc/getting-started-python.rst b/pypy/doc/getting-started-python.rst
    --- a/pypy/doc/getting-started-python.rst
    +++ b/pypy/doc/getting-started-python.rst
    @@ -46,14 +46,14 @@
     2. Install build-time dependencies.  On a Debian box these are::
     
          [user at debian-box ~]$ sudo apt-get install \
    -     gcc make python-dev libffi-dev pkg-config \
    +     gcc make python-dev libffi-dev lib-sqlite3-dev pkg-config \
          libz-dev libbz2-dev libncurses-dev libexpat1-dev \
          libssl-dev libgc-dev python-sphinx python-greenlet
     
        On a Fedora-16 box these are::
     
          [user at fedora-or-rh-box ~]$ sudo yum install \
    -     gcc make python-devel libffi-devel pkgconfig \
    +     gcc make python-devel libffi-devel lib-sqlite3-devel pkgconfig \
          zlib-devel bzip2-devel ncurses-devel expat-devel \
          openssl-devel gc-devel python-sphinx python-greenlet
     
    @@ -62,6 +62,7 @@
        * ``pkg-config`` (to help us locate libffi files)
        * ``libz-dev`` (for the optional ``zlib`` module)
        * ``libbz2-dev`` (for the optional ``bz2`` module)
    +   * ``libsqlite3-dev`` (for the optional ``sqlite3`` module via cffi)
        * ``libncurses-dev`` (for the optional ``_minimal_curses`` module)
        * ``libexpat1-dev`` (for the optional ``pyexpat`` module)
        * ``libssl-dev`` (for the optional ``_ssl`` module)
    diff --git a/pypy/doc/index.rst b/pypy/doc/index.rst
    --- a/pypy/doc/index.rst
    +++ b/pypy/doc/index.rst
    @@ -15,7 +15,7 @@
     
     * `FAQ`_: some frequently asked questions.
     
    -* `Release 2.0 beta 1`_: the latest official release
    +* `Release 2.0 beta 2`_: the latest official release
     
     * `PyPy Blog`_: news and status info about PyPy 
     
    @@ -75,7 +75,7 @@
     .. _`Getting Started`: getting-started.html
     .. _`Papers`: extradoc.html
     .. _`Videos`: video-index.html
    -.. _`Release 2.0 beta 1`: http://pypy.org/download.html
    +.. _`Release 2.0 beta 2`: http://pypy.org/download.html
     .. _`speed.pypy.org`: http://speed.pypy.org
     .. _`RPython toolchain`: translation.html
     .. _`potential project ideas`: project-ideas.html
    diff --git a/pypy/doc/release-2.0.0-beta2.rst b/pypy/doc/release-2.0.0-beta2.rst
    new file mode 100644
    --- /dev/null
    +++ b/pypy/doc/release-2.0.0-beta2.rst
    @@ -0,0 +1,84 @@
    +===============
    +PyPy 2.0 beta 2
    +===============
    +
    +We're pleased to announce the 2.0 beta 2 release of PyPy. This is a major
    +release of PyPy and we're getting very close to 2.0 final, however it includes
    +quite a few new features that require further testing. Please test and report
    +issues, so we can have a rock-solid 2.0 final. It also includes a performance
    +regression of about 5% compared to 2.0 beta 1 that we hope to fix before
    +2.0 final. The ARM support is not working yet and we're working hard to
    +make it happen before the 2.0 final. The new major features are:
    +
    +* JIT now supports stackless features, that is greenlets and stacklets. This
    +  means that JIT can now optimize the code that switches the context. It enables
    +  running `eventlet`_ and `gevent`_ on PyPy (although gevent requires some
    +  special support that's not quite finished, read below).
    +
    +* This is the first PyPy release that includes `cffi`_ as a core library.
    +  Version 0.6 comes included in the PyPy library. cffi has seen a lot of
    +  adoption among library authors and we believe it's the best way to wrap
    +  C libaries. You can see examples of cffi usage in `_curses.py`_ and
    +  `_sqlite3.py`_ in the PyPy source code.
    +
    +You can download the PyPy 2.0 beta 2 release here:
    +
    +    http://pypy.org/download.html 
    +
    +What is PyPy?
    +=============
    +
    +PyPy is a very compliant Python interpreter, almost a drop-in replacement for
    +CPython 2.7.3. It's fast (`pypy 2.0 beta 2 and cpython 2.7.3`_
    +performance comparison) due to its integrated tracing JIT compiler.
    +
    +This release supports x86 machines running Linux 32/64, Mac OS X 64 or
    +Windows 32. It also supports ARM machines running Linux, however this is
    +disabled for the beta 2 release.
    +Windows 64 work is still stalling, we would welcome a volunteer
    +to handle that.
    +
    +.. _`pypy 2.0 beta 2 and cpython 2.7.3`: http://bit.ly/USXqpP
    +
    +How to use PyPy?
    +================
    +
    +We suggest using PyPy from a `virtualenv`_. Once you have a virtualenv
    +installed, you can follow instructions from `pypy documentation`_ on how
    +to proceed. This document also covers other `installation schemes`_.
    +
    +.. _`pypy documentation`: http://doc.pypy.org/en/latest/getting-started.html#installing-using-virtualenv
    +.. _`virtualenv`: http://www.virtualenv.org/en/latest/
    +.. _`installation schemes`: http://doc.pypy.org/en/latest/getting-started.html#installing-pypy
    +
    +Highlights
    +==========
    +
    +* ``cffi`` is officially supported by PyPy. It comes included in the standard
    +  library, just use ``import cffi``
    +
    +* stackless support - `eventlet`_ just works and `gevent`_ requires `pypycore`_
    +  and `pypy-hacks`_ branch of gevent (which mostly disables cython-based
    +  modules)
    +
    +* callbacks from C are now much faster. pyexpat is about 3x faster, cffi
    +  callbacks around the same
    +
    +* ``__length_hint__`` is implemented (PEP 424)
    +
    +* a lot of numpy improvements
    +
    +Improvements since 1.9
    +======================
    +
    +* `JIT hooks`_ are now a powerful tool to introspect the JITting process that
    +  PyPy performs
    +
    +* various performance improvements compared to 1.9 and 2.0 beta 1
    +
    +* operations on ``long`` objects are now as fast as in CPython (from
    +  roughly 2x slower)
    +
    +* we now have special strategies for ``dict``/``set``/``list`` which contain
    +  unicode strings, which means that now such collections will be both faster
    +  and more compact.
    diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
    --- a/pypy/doc/whatsnew-head.rst
    +++ b/pypy/doc/whatsnew-head.rst
    @@ -115,9 +115,9 @@
     .. branch: remove-list-smm
     .. branch: bridge-logging
     .. branch: curses_cffi
    -
     cffi implementation of _curses
     
     .. branch: sqlite-cffi
    +cffi implementation of sqlite3
     
    -cffi implementation of sqlite3
    +.. branch: release-2.0-beta2
    diff --git a/pypy/doc/windows.rst b/pypy/doc/windows.rst
    --- a/pypy/doc/windows.rst
    +++ b/pypy/doc/windows.rst
    @@ -111,6 +111,18 @@
         cd bzip2-1.0.5
         nmake -f makefile.msc
         
    +The sqlite3 database library
    +~~~~~~~~~~~~~~~~~~~~
    +
    +Download http://www.sqlite.org/2013/sqlite-amalgamation-3071601.zip and extract
    +it into a directory under the base directory. Also get 
    +http://www.sqlite.org/2013/sqlite-dll-win32-x86-3071601.zip and extract the dll
    +into the bin directory, and the sqlite3.def into the sources directory.
    +Now build the import library so cffi can use the header and dll::
    +    lib /DEF:sqlite3.def" /OUT:sqlite3.lib"
    +    copy sqlite3.lib path\to\libs
    +
    +
     The expat XML parser
     ~~~~~~~~~~~~~~~~~~~~
     
    diff --git a/pypy/module/_socket/test/test_sock_app.py b/pypy/module/_socket/test/test_sock_app.py
    --- a/pypy/module/_socket/test/test_sock_app.py
    +++ b/pypy/module/_socket/test/test_sock_app.py
    @@ -217,7 +217,7 @@
     
     def test_unknown_addr_as_object():
         from pypy.module._socket.interp_socket import addr_as_object
    -    c_addr = lltype.malloc(rsocket._c.sockaddr, flavor='raw')
    +    c_addr = lltype.malloc(rsocket._c.sockaddr, flavor='raw', track_allocation=False)
         c_addr.c_sa_data[0] = 'c'
         rffi.setintfield(c_addr, 'c_sa_family', 15)
         # XXX what size to pass here? for the purpose of this test it has
    diff --git a/pypy/module/cpyext/include/patchlevel.h b/pypy/module/cpyext/include/patchlevel.h
    --- a/pypy/module/cpyext/include/patchlevel.h
    +++ b/pypy/module/cpyext/include/patchlevel.h
    @@ -29,7 +29,7 @@
     #define PY_VERSION		"3.2.2"
     
     /* PyPy version as a string */
    -#define PYPY_VERSION "2.0.0-beta1"
    +#define PYPY_VERSION "2.0.0-beta2"
     
     /* Subversion Revision number of this file (not of the repository).
      * Empty since Mercurial migration. */
    diff --git a/pypy/module/pyexpat/interp_pyexpat.py b/pypy/module/pyexpat/interp_pyexpat.py
    --- a/pypy/module/pyexpat/interp_pyexpat.py
    +++ b/pypy/module/pyexpat/interp_pyexpat.py
    @@ -305,14 +305,15 @@
                 w_result = space.call_function(handler, %(wargs)s)
                 %(post_code)s
             except OperationError, e:
    -            parser._exc_info = e
    +            if not parser._exc_info: # don't override an existing exception
    +                 parser._exc_info = e
                 XML_StopParser(parser.itself, XML_FALSE)
                 return %(result_error)s
             return %(result_converter)s
         callback = %(name)s_callback
         """ % locals())
     
    -    exec str(src)
    +    exec src.compile()
     
         c_name = 'XML_Set' + name
         callback_type = lltype.Ptr(lltype.FuncType(
    @@ -335,7 +336,8 @@
         try:
             parser.UnknownEncodingHandler(space, name, info)
         except OperationError, e:
    -        parser._exc_info = e
    +        if parser._exc_info:
    +            parser._exc_info = e
             XML_StopParser(parser.itself, XML_FALSE)
             result = 0
         else:
    diff --git a/pypy/module/pyexpat/test/test_parser.py b/pypy/module/pyexpat/test/test_parser.py
    --- a/pypy/module/pyexpat/test/test_parser.py
    +++ b/pypy/module/pyexpat/test/test_parser.py
    @@ -181,3 +181,46 @@
                 p = pyexpat.ParserCreate()
                 p.ParseFile(fake_reader)
                 assert fake_reader.read_count == 4
    +
    +class AppTestPyexpat2:
    +    spaceconfig = dict(usemodules=['pyexpat', 'itertools', '_socket',
    +                                   'rctime', 'struct', 'binascii'])
    +
    +    def test_django_bug(self):
    +        xml_str = ''
    +
    +        from xml.dom import pulldom
    +        from xml.sax import handler
    +        from xml.sax.expatreader import ExpatParser as _ExpatParser
    +        from StringIO import StringIO
    +
    +        class DefusedExpatParser(_ExpatParser):
    +            def start_doctype_decl(self, name, sysid, pubid, has_internal_subset):
    +                raise DTDForbidden(name, sysid, pubid)
    +
    +            def external_entity_ref_handler(self, context, base, sysid, pubid):
    +                raise ExternalReferenceForbidden(context, base, sysid, pubid)
    +
    +            def reset(self):
    +                _ExpatParser.reset(self)
    +                parser = self._parser
    +                parser.StartDoctypeDeclHandler = self.start_doctype_decl
    +                parser.ExternalEntityRefHandler = self.external_entity_ref_handler
    +
    +
    +        class DTDForbidden(ValueError):
    +            pass
    +
    +
    +        class ExternalReferenceForbidden(ValueError):
    +            pass
    +
    +        stream = pulldom.parse(StringIO(xml_str), DefusedExpatParser())
    +
    +        try:
    +            for event, node in stream:
    +                print event, node
    +        except DTDForbidden:
    +            pass
    +        else:
    +            raise Exception("should raise DTDForbidden")
    diff --git a/pypy/module/sys/version.py b/pypy/module/sys/version.py
    --- a/pypy/module/sys/version.py
    +++ b/pypy/module/sys/version.py
    @@ -11,7 +11,7 @@
     #XXX # sync CPYTHON_VERSION with patchlevel.h, package.py
     CPYTHON_API_VERSION        = 1013   #XXX # sync with include/modsupport.h
     
    -PYPY_VERSION               = (2, 0, 0, "beta", 1)    #XXX # sync patchlevel.h
    +PYPY_VERSION               = (2, 0, 0, "beta", 2)    #XXX # sync patchlevel.h
     
     if platform.name == 'msvc':
         COMPILER_INFO = 'MSC v.%d 32 bit' % (platform.version * 10 + 600)
    diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/setup.py
    --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/setup.py
    +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/setup.py
    @@ -1,3 +1,4 @@
    +# Generated by pypy/tool/import_cffi.py
     
     from distutils.core import setup
     import snip_basic_verify
    diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/snip_basic_verify.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/snip_basic_verify.py
    --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/snip_basic_verify.py
    +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_module/snip_basic_verify.py
    @@ -1,3 +1,4 @@
    +# Generated by pypy/tool/import_cffi.py
     
     from cffi import FFI
     import sys
    diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/setup.py
    --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/setup.py
    +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/setup.py
    @@ -1,3 +1,4 @@
    +# Generated by pypy/tool/import_cffi.py
     
     from distutils.core import setup
     import snip_basic_verify1
    diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/snip_basic_verify1/__init__.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/snip_basic_verify1/__init__.py
    --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/snip_basic_verify1/__init__.py
    +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_1/snip_basic_verify1/__init__.py
    @@ -1,3 +1,4 @@
    +# Generated by pypy/tool/import_cffi.py
     
     from cffi import FFI
     import sys
    diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/setup.py
    --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/setup.py
    +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/setup.py
    @@ -1,3 +1,4 @@
    +# Generated by pypy/tool/import_cffi.py
     
     from distutils.core import setup
     import snip_basic_verify2
    diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/snip_basic_verify2/__init__.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/snip_basic_verify2/__init__.py
    --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/snip_basic_verify2/__init__.py
    +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/distutils_package_2/snip_basic_verify2/__init__.py
    @@ -1,3 +1,4 @@
    +# Generated by pypy/tool/import_cffi.py
     
     from cffi import FFI
     import sys
    diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/setup.py
    --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/setup.py
    +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/setup.py
    @@ -1,3 +1,4 @@
    +# Generated by pypy/tool/import_cffi.py
     
     from distutils.core import setup
     
    diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/snip_infrastructure/__init__.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/snip_infrastructure/__init__.py
    --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/snip_infrastructure/__init__.py
    +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/infrastructure/snip_infrastructure/__init__.py
    @@ -1,3 +1,4 @@
    +# Generated by pypy/tool/import_cffi.py
     
     def func():
         return 42
    diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/setup.py
    --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/setup.py
    +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/setup.py
    @@ -1,3 +1,4 @@
    +# Generated by pypy/tool/import_cffi.py
     
     from setuptools import setup
     import snip_setuptools_verify
    diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/snip_setuptools_verify.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/snip_setuptools_verify.py
    --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/snip_setuptools_verify.py
    +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_module/snip_setuptools_verify.py
    @@ -1,3 +1,4 @@
    +# Generated by pypy/tool/import_cffi.py
     
     from cffi import FFI
     import sys
    diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/setup.py
    --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/setup.py
    +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/setup.py
    @@ -1,3 +1,4 @@
    +# Generated by pypy/tool/import_cffi.py
     
     from setuptools import setup
     import snip_setuptools_verify1
    diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/snip_setuptools_verify1/__init__.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/snip_setuptools_verify1/__init__.py
    --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/snip_setuptools_verify1/__init__.py
    +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_1/snip_setuptools_verify1/__init__.py
    @@ -1,3 +1,4 @@
    +# Generated by pypy/tool/import_cffi.py
     
     from cffi import FFI
     import sys
    diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/setup.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/setup.py
    --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/setup.py
    +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/setup.py
    @@ -1,3 +1,4 @@
    +# Generated by pypy/tool/import_cffi.py
     
     from setuptools import setup
     import snip_setuptools_verify2
    diff --git a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/snip_setuptools_verify2/__init__.py b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/snip_setuptools_verify2/__init__.py
    --- a/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/snip_setuptools_verify2/__init__.py
    +++ b/pypy/module/test_lib_pypy/cffi_tests/snippets/setuptools_package_2/snip_setuptools_verify2/__init__.py
    @@ -1,3 +1,4 @@
    +# Generated by pypy/tool/import_cffi.py
     
     from cffi import FFI
     import sys
    diff --git a/pypy/module/test_lib_pypy/test_sqlite3.py b/pypy/module/test_lib_pypy/test_sqlite3.py
    --- a/pypy/module/test_lib_pypy/test_sqlite3.py
    +++ b/pypy/module/test_lib_pypy/test_sqlite3.py
    @@ -198,3 +198,28 @@
         con = _sqlite3.connect(':memory:')
         con.row_factory = 42
         con.execute('select 1')
    +
    +def test_returning_blob_must_own_memory():
    +    import gc
    +    con = _sqlite3.connect(":memory:")
    +    con.create_function("returnblob", 0, lambda: buffer("blob"))
    +    cur = con.cursor()
    +    cur.execute("select returnblob()")
    +    val = cur.fetchone()[0]
    +    for i in range(5):
    +        gc.collect()
    +        got = (val[0], val[1], val[2], val[3])
    +        assert got == ('b', 'l', 'o', 'b')
    +
    +def test_description_after_fetchall():
    +    con = _sqlite3.connect(":memory:")
    +    cur = con.cursor()
    +    cur.execute("select 42").fetchall()
    +    assert cur.description is not None
    +
    +def test_executemany_lastrowid():
    +    con = _sqlite3.connect(':memory:')
    +    cur = con.cursor()
    +    cur.execute("create table test(a)")
    +    cur.executemany("insert into test values (?)", [[1], [2], [3]])
    +    assert cur.lastrowid is None
    diff --git a/pypy/tool/release/package.py b/pypy/tool/release/package.py
    --- a/pypy/tool/release/package.py
    +++ b/pypy/tool/release/package.py
    @@ -43,6 +43,7 @@
     def fix_permissions(basedir):
         if sys.platform != 'win32':
             os.system("chmod -R a+rX %s" % basedir)
    +        os.system("chmod -R g-w %s" % basedir)
     
     def package(basedir, name='pypy-nightly', rename_pypy_c='pypy',
                 copy_to_dir = None, override_pypy_c = None, nostrip=False):
    diff --git a/pypy/tool/release/test/test_package.py b/pypy/tool/release/test/test_package.py
    --- a/pypy/tool/release/test/test_package.py
    +++ b/pypy/tool/release/test/test_package.py
    @@ -17,7 +17,7 @@
             exe_name_in_archive = 'bin/pypy'
         pypy_c = py.path.local(pypydir).join('goal', basename)
         if not pypy_c.check():
    -        os.system("echo faked_pypy_c> %s" % (pypy_c,))
    +        pypy_c.write("#!/bin/sh")
             pypy_c.chmod(0755)
             fake_pypy_c = True
         else:
    diff --git a/pypy/tool/test/test_tab.py b/pypy/tool/test/test_tab.py
    --- a/pypy/tool/test/test_tab.py
    +++ b/pypy/tool/test/test_tab.py
    @@ -5,7 +5,7 @@
     import os
     from pypy.conftest import pypydir
     
    -ROOT = pypydir
    +ROOT = os.path.abspath(os.path.join(pypydir, '..'))
     EXCLUDE = {}
     
     
    diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py
    --- a/rpython/jit/backend/arm/assembler.py
    +++ b/rpython/jit/backend/arm/assembler.py
    @@ -305,7 +305,7 @@
                 self._restore_exception(mc, exc0, exc1)
                 mc.VPOP([vfpr.value for vfpr in r.caller_vfp_resp])
                 assert exc0 is not None
    -	    assert exc1 is not None
    +            assert exc1 is not None
                 mc.POP([gpr.value for gpr in r.caller_resp] +
                                 [exc0.value, exc1.value])
             #
    @@ -526,9 +526,7 @@
                 self.gen_shadowstack_header(gcrootmap)
     
         def gen_shadowstack_header(self, gcrootmap):
    -        # we need to put two words into the shadowstack: the MARKER_FRAME
    -        # and the address of the frame (fp, actually)
    -        # lr = rst addr
    +        # lr = shadow stack top addr
             # ip = *lr
             rst = gcrootmap.get_root_stack_top_addr()
             self.mc.gen_load_int(r.lr.value, rst)
    @@ -1062,8 +1060,7 @@
                 self.mc.PUSH([helper.value], cond=cond)
             self.load_reg(self.mc, loc, r.fp, offset, cond=cond, helper=helper)
             if save_helper:
    -	    self.mc.POP([helper.value], cond=cond)
    -
    +            self.mc.POP([helper.value], cond=cond)
     
         def _mov_imm_float_to_loc(self, prev_loc, loc, cond=c.AL):
             if loc.is_vfp_reg():
    diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py
    --- a/rpython/jit/backend/arm/opassembler.py
    +++ b/rpython/jit/backend/arm/opassembler.py
    @@ -628,12 +628,14 @@
                                         bool(self._regalloc.vfprm.reg_bindings))
                 assert self.wb_slowpath[helper_num] != 0
             #
    -        if not is_frame and loc_base is not r.r0:
    +        if loc_base is not r.r0:
                 # push two registers to keep stack aligned
                 mc.PUSH([r.r0.value, loc_base.value])
    -            remap_frame_layout(self, [loc_base], [r.r0], r.ip)
    +            mc.MOV_rr(r.r0.value, loc_base.value)
    +            if is_frame:
    +                assert loc_base is r.fp
             mc.BL(self.wb_slowpath[helper_num])
    -        if not is_frame and loc_base is not r.r0:
    +        if loc_base is not r.r0:
                 mc.POP([r.r0.value, loc_base.value])
     
             if card_marking:
    diff --git a/rpython/jit/backend/arm/runner.py b/rpython/jit/backend/arm/runner.py
    --- a/rpython/jit/backend/arm/runner.py
    +++ b/rpython/jit/backend/arm/runner.py
    @@ -120,7 +120,7 @@
         """ARM v7 uses hardfp ABI, requires vfp"""
         hf_abi = True
         backend_name = "armv7hf"
    -    supports_floats = False
    +    supports_floats = True
         supports_singlefloats = False
     
     
    @@ -129,5 +129,5 @@
         hf_abi = True
         arch_version = 6
         backend_name = "armv6hf"
    -    supports_floats = False
    +    supports_floats = True
         supports_singlefloats = False
    diff --git a/rpython/jit/backend/arm/test/test_calling_convention.py b/rpython/jit/backend/arm/test/test_calling_convention.py
    --- a/rpython/jit/backend/arm/test/test_calling_convention.py
    +++ b/rpython/jit/backend/arm/test/test_calling_convention.py
    @@ -72,7 +72,7 @@
             callargs = []
             def func(f0, f1, f2, f3, f4, f5, f6, i0, f7, i1, f8, f9):
                 callargs.append(zip(range(12),
    -			[f0, f1, f2, f3, f4, f5, f6, i0, f7, i1, f8, f9]))
    +                        [f0, f1, f2, f3, f4, f5, f6, i0, f7, i1, f8, f9]))
                 return f0 + f1 + f2 + f3 + f4 + f5 + f6 + float(i0 + i1) + f7 + f8 + f9
             F = lltype.Float
             I = lltype.Signed
    @@ -103,7 +103,7 @@
             callargs = []
             def func(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9):
                 callargs.append(zip(range(10),
    -			[f0, f1, f2, f3, f4, f5, f6, f7, f8, f9]))
    +                        [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9]))
                 return f0 + f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8 + f9
             F = lltype.Float
             FUNC = self.FuncType([F] * 10, F)
    @@ -125,7 +125,7 @@
             callargs = []
             def func(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9):
                 callargs.append(zip(range(10),
    -			[f0, f1, f2, f3, f4, f5, f6, f7, f8, f9]))
    +                        [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9]))
                 return f0 + f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8 + f9
     
             I = lltype.Signed
    diff --git a/rpython/jit/backend/llsupport/test/test_gc_integration.py b/rpython/jit/backend/llsupport/test/test_gc_integration.py
    --- a/rpython/jit/backend/llsupport/test/test_gc_integration.py
    +++ b/rpython/jit/backend/llsupport/test/test_gc_integration.py
    @@ -256,7 +256,9 @@
                 if self.cpu.IS_64_BIT:
                     assert frame.jf_gcmap[idx] == (1<<29) | (1 << 30)
                 else:
    -                assert frame.jf_gcmap[idx] == (1<<24) | (1 << 23)
    +                assert frame.jf_gcmap[idx]
    +                exp_idx = self.cpu.JITFRAME_FIXED_SIZE - 32 * idx + 1 # +1 from i0
    +                assert frame.jf_gcmap[idx] == (1 << (exp_idx + 1)) | (1 << exp_idx)
     
             self.cpu = self.getcpu(check)
             ops = '''
    @@ -680,7 +682,7 @@
     
             def f(frame, x):
                 # all the gc pointers are alive p1 -> p7 (but not p0)
    -            assert bin(frame.jf_gcmap[0]).count('1') == 7
    +            assert getmap(frame).count('1') == 7 #
                 assert x == 1
                 return 2
             
    @@ -713,7 +715,7 @@
             def f(frame, arg, x):
                 assert not arg
                 assert frame.jf_gcmap[0] & 31 == 0
    -            assert bin(frame.jf_gcmap[0]).count('1') == 3 # p1, p2, p3, but
    +            assert getmap(frame).count('1') == 3 # p1, p2, p3, but
                 # not in registers
                 frame.jf_descr = frame.jf_force_descr # make guard_not_forced fail
                 assert x == 1
    @@ -749,7 +751,8 @@
             cpu.compile_loop(loop.inputargs, loop.operations, token)
             frame = lltype.cast_opaque_ptr(JITFRAMEPTR,
                                            cpu.execute_token(token, 1, a))
    -        assert bin(frame.jf_gcmap[0]).count('1') == 4
    +        
    +        assert getmap(frame).count('1') == 4
     
         def test_call_gcmap_no_guard(self):
             cpu = self.cpu
    @@ -757,7 +760,7 @@
             def f(frame, arg, x):
                 assert not arg
                 assert frame.jf_gcmap[0] & 31 == 0
    -            assert bin(frame.jf_gcmap[0]).count('1') == 3 # p1, p2, p3
    +            assert getmap(frame).count('1') == 3 # p1, p2, p3
                 frame.jf_descr = frame.jf_force_descr # make guard_not_forced fail
                 assert x == 1
                 return lltype.nullptr(llmemory.GCREF.TO)
    @@ -792,4 +795,5 @@
             cpu.compile_loop(loop.inputargs, loop.operations, token)
             frame = lltype.cast_opaque_ptr(JITFRAMEPTR,
                                            cpu.execute_token(token, 1, a))
    -        assert bin(frame.jf_gcmap[0]).count('1') == 4
    +        assert getmap(frame).count('1') == 4
    +
    diff --git a/rpython/jit/backend/test/calling_convention_test.py b/rpython/jit/backend/test/calling_convention_test.py
    --- a/rpython/jit/backend/test/calling_convention_test.py
    +++ b/rpython/jit/backend/test/calling_convention_test.py
    @@ -384,7 +384,7 @@
     
         def test_call_aligned_explicit_check(self):
             if (not platform.machine().startswith('arm') and
    -		sys.maxint == 2 ** 31 - 1): # XXX is still necessary on x86?
    +                sys.maxint == 2 ** 31 - 1): # XXX is still necessary on x86?
                 py.test.skip("libffi on 32bit is broken")
             cpu = self.cpu
             if not cpu.supports_floats:
    diff --git a/rpython/jit/backend/x86/runner.py b/rpython/jit/backend/x86/runner.py
    --- a/rpython/jit/backend/x86/runner.py
    +++ b/rpython/jit/backend/x86/runner.py
    @@ -58,10 +58,10 @@
             self.assembler = Assembler386(self, self.translate_support_code)
     
         def build_regalloc(self):
    -	''' for tests'''
    -	from rpython.jit.backend.x86.regalloc import RegAlloc
    -	assert self.assembler is not None
    -	return RegAlloc(self.assembler, False)
    +        ''' for tests'''
    +        from rpython.jit.backend.x86.regalloc import RegAlloc
    +        assert self.assembler is not None
    +        return RegAlloc(self.assembler, False)
     
         def setup_once(self):
             self.profile_agent.startup()
    diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
    --- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
    +++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
    @@ -4282,9 +4282,9 @@
             self.optimize_loop(ops, expected)
     
         def test_add_sub_ovf_second_operation_regular(self):
    -	py.test.skip("Smalltalk would like this to pass")
    -	# This situation occurs in Smalltalk because it uses 1-based indexing.
    -	# The below code is equivalent to a loop over an array.
    +        py.test.skip("Smalltalk would like this to pass")
    +        # This situation occurs in Smalltalk because it uses 1-based indexing.
    +        # The below code is equivalent to a loop over an array.
             ops = """
             [i1]
             i2 = int_sub(i1, 1)
    @@ -7609,6 +7609,26 @@
             """
             self.optimize_loop(ops, ops)
     
    +    def test_setarrayitem_followed_by_arraycopy_2(self):
    +        ops = """
    +        [i1, i2]
    +        p1 = new_array(i1, descr=arraydescr)
    +        setarrayitem_gc(p1, 0, i2, descr=arraydescr)
    +        p3 = new_array(5, descr=arraydescr)
    +        call(0, p1, p3, 0, 1, 1, descr=arraycopydescr)
    +        i4 = getarrayitem_gc(p3, 1, descr=arraydescr)
    +        jump(i1, i4)
    +        """
    +        expected = """
    +        [i1, i2]
    +        p1 = new_array(i1, descr=arraydescr)
    +        # operations are not all removed because this new_array() is var-sized
    +        # unsure exactly which operations should be left, but right now it's
    +        # really buggy
    +        jump(i1, i2)
    +        """
    +        self.optimize_loop(ops, expected)
    +
         def test_heap_cache_virtuals_forced_by_delayed_setfield(self):
             py.test.skip('not yet supoprted')
             ops = """
    diff --git a/rpython/rlib/rsocket.py b/rpython/rlib/rsocket.py
    --- a/rpython/rlib/rsocket.py
    +++ b/rpython/rlib/rsocket.py
    @@ -80,7 +80,7 @@
     
         def __del__(self):
             if self.addr_p:
    -            lltype.free(self.addr_p, flavor='raw')
    +            lltype.free(self.addr_p, flavor='raw', track_allocation=False)
     
         def setdata(self, addr, addrlen):
             # initialize self.addr and self.addrlen.  'addr' can be a different
    @@ -271,7 +271,8 @@
             result = instantiate(INETAddress)
             # store the malloc'ed data into 'result' as soon as possible
             # to avoid leaks if an exception occurs inbetween
    -        sin = lltype.malloc(_c.sockaddr_in, flavor='raw', zero=True)
    +        sin = lltype.malloc(_c.sockaddr_in, flavor='raw', zero=True,
    +                            track_allocation=False)
             result.setdata(sin, sizeof(_c.sockaddr_in))
             # PLAT sin_len
             rffi.setintfield(sin, 'c_sin_family', AF_INET)
    @@ -337,7 +338,8 @@
             result = instantiate(INET6Address)
             # store the malloc'ed data into 'result' as soon as possible
             # to avoid leaks if an exception occurs inbetween
    -        sin = lltype.malloc(_c.sockaddr_in6, flavor='raw', zero=True)
    +        sin = lltype.malloc(_c.sockaddr_in6, flavor='raw', zero=True,
    +                            track_allocation=False)
             result.setdata(sin, sizeof(_c.sockaddr_in6))
             rffi.setintfield(sin, 'c_sin6_family', AF_INET6)
             rffi.structcopy(sin.c_sin6_addr, in6_addr)
    @@ -360,7 +362,8 @@
             maxlen = sizeof(struct)
     
             def __init__(self, path):
    -            sun = lltype.malloc(_c.sockaddr_un, flavor='raw', zero=True)
    +            sun = lltype.malloc(_c.sockaddr_un, flavor='raw', zero=True,
    +                                track_allocation=False)
                 baseofs = offsetof(_c.sockaddr_un, 'c_sun_path')
                 self.setdata(sun, baseofs + len(path))
                 rffi.setintfield(sun, 'c_sun_family', AF_UNIX)
    @@ -409,7 +412,8 @@
             maxlen = minlen = sizeof(struct)
     
             def __init__(self, pid, groups):
    -            addr = lltype.malloc(_c.sockaddr_nl, flavor='raw', zero=True)
    +            addr = lltype.malloc(_c.sockaddr_nl, flavor='raw', zero=True,
    +                                 track_allocation=False)
                 self.setdata(addr, NETLINKAddress.maxlen)
                 rffi.setintfield(addr, 'c_nl_family', AF_NETLINK)
                 rffi.setintfield(addr, 'c_nl_pid', pid)
    @@ -444,7 +448,8 @@
             raise RSocketError("address family mismatched")
         # copy into a new buffer the address that 'addrptr' points to
         addrlen = rffi.cast(lltype.Signed, addrlen)
    -    buf = lltype.malloc(rffi.CCHARP.TO, addrlen, flavor='raw')
    +    buf = lltype.malloc(rffi.CCHARP.TO, addrlen, flavor='raw',
    +                        track_allocation=False)
         src = rffi.cast(rffi.CCHARP, addrptr)
         for i in range(addrlen):
             buf[i] = src[i]
    @@ -456,7 +461,8 @@
             result = instantiate(INETAddress)
         elif result.family != AF_INET:
             raise RSocketError("address family mismatched")
    -    sin = lltype.malloc(_c.sockaddr_in, flavor='raw', zero=True)
    +    sin = lltype.malloc(_c.sockaddr_in, flavor='raw', zero=True,
    +                        track_allocation=False)
         result.setdata(sin, sizeof(_c.sockaddr_in))
         rffi.setintfield(sin, 'c_sin_family', AF_INET)   # PLAT sin_len
         rffi.setintfield(sin.c_sin_addr, 'c_s_addr', s_addr)
    @@ -465,7 +471,8 @@
     def make_null_address(family):
         klass = familyclass(family)
         result = instantiate(klass)
    -    buf = lltype.malloc(rffi.CCHARP.TO, klass.maxlen, flavor='raw', zero=True)
    +    buf = lltype.malloc(rffi.CCHARP.TO, klass.maxlen, flavor='raw', zero=True,
    +                        track_allocation=False)
         # Initialize the family to the correct value.  Avoids surprizes on
         # Windows when calling a function that unexpectedly does not set
         # the output address (e.g. recvfrom() on a connected IPv4 socket).
    diff --git a/rpython/rtyper/lltypesystem/rffi.py b/rpython/rtyper/lltypesystem/rffi.py
    --- a/rpython/rtyper/lltypesystem/rffi.py
    +++ b/rpython/rtyper/lltypesystem/rffi.py
    @@ -934,10 +934,8 @@
         if tp is lltype.SingleFloat:
             return 4
         if tp is lltype.LongFloat:
    -        if globals()['r_void*'].BITS == 32:
    -            return 12
    -        else:
    -            return 16
    +        import ctypes    # :-/
    +        return ctypes.sizeof(ctypes.c_longdouble)
         assert isinstance(tp, lltype.Number)
         if tp is lltype.Signed:
             return LONG_BIT/8
    
    From noreply at buildbot.pypy.org  Sat Apr  6 06:53:20 2013
    From: noreply at buildbot.pypy.org (bdkearns)
    Date: Sat,  6 Apr 2013 06:53:20 +0200 (CEST)
    Subject: [pypy-commit] pypy default: remove conditional skip,
    	this was a ctypes limitation
    Message-ID: <20130406045320.060DF1C00EF@cobra.cs.uni-duesseldorf.de>
    
    Author: Brian Kearns 
    Branch: 
    Changeset: r63089:53926a2ab1b9
    Date: 2013-04-06 00:28 -0400
    http://bitbucket.org/pypy/pypy/changeset/53926a2ab1b9/
    
    Log:	remove conditional skip, this was a ctypes limitation
    
    diff --git a/pypy/module/test_lib_pypy/test_sqlite3.py b/pypy/module/test_lib_pypy/test_sqlite3.py
    --- a/pypy/module/test_lib_pypy/test_sqlite3.py
    +++ b/pypy/module/test_lib_pypy/test_sqlite3.py
    @@ -1,9 +1,5 @@
     """Tests for _sqlite3.py"""
     
    -import sys
    -if sys.version_info < (2, 7):
    -    skip("lib_pypy._sqlite3 doesn't work with python < 2.7")
    -
     import pytest
     from lib_pypy import _sqlite3
     
    
    From noreply at buildbot.pypy.org  Sat Apr  6 06:53:21 2013
    From: noreply at buildbot.pypy.org (bdkearns)
    Date: Sat,  6 Apr 2013 06:53:21 +0200 (CEST)
    Subject: [pypy-commit] pypy default: simplify sqlite tests by providing a
     funcarg that automatically connects/closes
    Message-ID: <20130406045321.492961C00EF@cobra.cs.uni-duesseldorf.de>
    
    Author: Brian Kearns 
    Branch: 
    Changeset: r63090:3b60aa181915
    Date: 2013-04-06 00:45 -0400
    http://bitbucket.org/pypy/pypy/changeset/3b60aa181915/
    
    Log:	simplify sqlite tests by providing a funcarg that automatically
    	connects/closes
    
    diff --git a/pypy/module/test_lib_pypy/test_sqlite3.py b/pypy/module/test_lib_pypy/test_sqlite3.py
    --- a/pypy/module/test_lib_pypy/test_sqlite3.py
    +++ b/pypy/module/test_lib_pypy/test_sqlite3.py
    @@ -3,10 +3,14 @@
     import pytest
     from lib_pypy import _sqlite3
     
    -def test_list_ddl():
    +def pytest_funcarg__con(request):
    +    con = _sqlite3.connect(':memory:')
    +    request.addfinalizer(lambda: con.close())
    +    return con
    +
    +def test_list_ddl(con):
         """From issue996.  Mostly just looking for lack of exceptions."""
    -    connection = _sqlite3.connect(':memory:')
    -    cursor = connection.cursor()
    +    cursor = con.cursor()
         cursor.execute('CREATE TABLE foo (bar INTEGER)')
         result = list(cursor)
         assert result == []
    @@ -17,8 +21,7 @@
         result = list(cursor)
         assert result == [(42,)]
     
    -def test_total_changes_after_close():
    -    con = _sqlite3.connect(':memory:')
    +def test_total_changes_after_close(con):
         con.close()
         pytest.raises(_sqlite3.ProgrammingError, "con.total_changes")
     
    @@ -31,25 +34,22 @@
         e = pytest.raises(_sqlite3.ProgrammingError, "con.cursor()")
         assert '__init__' in e.value.message
     
    -def test_cursor_check_init():
    +def test_cursor_check_init(con):
         class Cursor(_sqlite3.Cursor):
             def __init__(self, name):
                 pass
     
    -    con = _sqlite3.connect(":memory:")
         cur = Cursor(con)
         e = pytest.raises(_sqlite3.ProgrammingError, "cur.execute('select 1')")
         assert '__init__' in e.value.message
     
    -def test_connection_after_close():
    -    con = _sqlite3.connect(':memory:')
    +def test_connection_after_close(con):
         pytest.raises(TypeError, "con()")
         con.close()
         # raises ProgrammingError because should check closed before check args
         pytest.raises(_sqlite3.ProgrammingError, "con()")
     
    -def test_cursor_iter():
    -    con = _sqlite3.connect(':memory:')
    +def test_cursor_iter(con):
         cur = con.cursor()
         with pytest.raises(StopIteration):
             next(cur)
    @@ -81,8 +81,7 @@
         with pytest.raises(StopIteration):
             next(cur)
     
    -def test_cursor_after_close():
    -     con = _sqlite3.connect(':memory:')
    +def test_cursor_after_close(con):
          cur = con.execute('select 1')
          cur.close()
          con.close()
    @@ -127,11 +126,10 @@
         finally:
             resource.setrlimit(resource.RLIMIT_NOFILE, limit)
     
    -def test_on_conflict_rollback_executemany():
    +def test_on_conflict_rollback_executemany(con):
         major, minor, micro = _sqlite3.sqlite_version.split('.')
         if (int(major), int(minor), int(micro)) < (3, 2, 2):
             pytest.skip("requires sqlite3 version >= 3.2.2")
    -    con = _sqlite3.connect(":memory:")
         con.execute("create table foo(x, unique(x) on conflict rollback)")
         con.execute("insert into foo(x) values (1)")
         try:
    @@ -143,10 +141,8 @@
             con.commit()
         except _sqlite3.OperationalError:
             pytest.fail("_sqlite3 knew nothing about the implicit ROLLBACK")
    -    con.close()
     
    -def test_statement_arg_checking():
    -    con = _sqlite3.connect(':memory:')
    +def test_statement_arg_checking(con):
         with pytest.raises(_sqlite3.Warning) as e:
             con(123)
         assert str(e.value) == 'SQL is of wrong type. Must be string or unicode.'
    @@ -160,8 +156,7 @@
             con.executescript(123)
         assert str(e.value) == 'script argument must be unicode or string.'
     
    -def test_statement_param_checking():
    -    con = _sqlite3.connect(':memory:')
    +def test_statement_param_checking(con):
         con.execute('create table foo(x)')
         con.execute('insert into foo(x) values (?)', [2])
         con.execute('insert into foo(x) values (?)', (2,))
    @@ -179,10 +174,8 @@
         with pytest.raises(ValueError) as e:
             con.execute('insert into foo(x) values (?)', 2)
         assert str(e.value) == 'parameters are of unsupported type'
    -    con.close()
     
    -def test_explicit_begin():
    -    con = _sqlite3.connect(':memory:')
    +def test_explicit_begin(con):
         con.execute('BEGIN')
         con.execute('BEGIN ')
         con.execute('BEGIN')
    @@ -190,31 +183,26 @@
         con.execute('BEGIN')
         con.commit()
     
    -def test_row_factory_use():
    -    con = _sqlite3.connect(':memory:')
    +def test_row_factory_use(con):
         con.row_factory = 42
         con.execute('select 1')
     
    -def test_returning_blob_must_own_memory():
    +def test_returning_blob_must_own_memory(con):
         import gc
    -    con = _sqlite3.connect(":memory:")
         con.create_function("returnblob", 0, lambda: buffer("blob"))
    -    cur = con.cursor()
    -    cur.execute("select returnblob()")
    +    cur = con.execute("select returnblob()")
         val = cur.fetchone()[0]
         for i in range(5):
             gc.collect()
             got = (val[0], val[1], val[2], val[3])
             assert got == ('b', 'l', 'o', 'b')
     
    -def test_description_after_fetchall():
    -    con = _sqlite3.connect(":memory:")
    +def test_description_after_fetchall(con):
         cur = con.cursor()
         cur.execute("select 42").fetchall()
         assert cur.description is not None
     
    -def test_executemany_lastrowid():
    -    con = _sqlite3.connect(':memory:')
    +def test_executemany_lastrowid(con):
         cur = con.cursor()
         cur.execute("create table test(a)")
         cur.executemany("insert into test values (?)", [[1], [2], [3]])
    
    From noreply at buildbot.pypy.org  Sat Apr  6 07:39:50 2013
    From: noreply at buildbot.pypy.org (mattip)
    Date: Sat,  6 Apr 2013 07:39:50 +0200 (CEST)
    Subject: [pypy-commit] pypy default: no ncurses on windowss
    Message-ID: <20130406053950.A846A1C00EF@cobra.cs.uni-duesseldorf.de>
    
    Author: mattip
    Branch: 
    Changeset: r63091:79414fd8306a
    Date: 2013-04-06 07:41 +0200
    http://bitbucket.org/pypy/pypy/changeset/79414fd8306a/
    
    Log:	no ncurses on windowss
    
    diff --git a/pypy/tool/release/package.py b/pypy/tool/release/package.py
    --- a/pypy/tool/release/package.py
    +++ b/pypy/tool/release/package.py
    @@ -67,7 +67,8 @@
                     'Bogus path: %r does not exist (see docstring for more info)'
                     % (os.path.dirname(str(pypy_c)),))
         subprocess.check_call([str(pypy_c), '-c', 'import _sqlite3'])
    -    subprocess.check_call([str(pypy_c), '-c', 'import _curses'])
    +    if not sys.platform == 'win32':
    +        subprocess.check_call([str(pypy_c), '-c', 'import _curses'])
         if sys.platform == 'win32' and not rename_pypy_c.lower().endswith('.exe'):
             rename_pypy_c += '.exe'
         binaries = [(pypy_c, rename_pypy_c)]
    
    From noreply at buildbot.pypy.org  Sat Apr  6 10:52:26 2013
    From: noreply at buildbot.pypy.org (arigo)
    Date: Sat,  6 Apr 2013 10:52:26 +0200 (CEST)
    Subject: [pypy-commit] pypy default: Bug fix: don't use
     self.optimizer.propagate_forward(newop). It's
    Message-ID: <20130406085226.D460A1C06E1@cobra.cs.uni-duesseldorf.de>
    
    Author: Armin Rigo 
    Branch: 
    Changeset: r63093:2ec1ac5c5ef1
    Date: 2013-04-06 10:52 +0200
    http://bitbucket.org/pypy/pypy/changeset/2ec1ac5c5ef1/
    
    Log:	Bug fix: don't use self.optimizer.propagate_forward(newop). It's
    	.send_extra_operation() that is meant here...
    
    diff --git a/rpython/jit/metainterp/optimizeopt/rewrite.py b/rpython/jit/metainterp/optimizeopt/rewrite.py
    --- a/rpython/jit/metainterp/optimizeopt/rewrite.py
    +++ b/rpython/jit/metainterp/optimizeopt/rewrite.py
    @@ -456,7 +456,7 @@
                                           [op.getarg(1),
                                            ConstInt(index + source_start)], resbox,
                                            descr=arraydescr)
    -                    self.optimizer.propagate_forward(newop)
    +                    self.optimizer.send_extra_operation(newop)
                         val = self.getvalue(resbox)
                     if dest_value.is_virtual():
                         dest_value.setitem(index + dest_start, val)
    diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
    --- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
    +++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
    @@ -7621,10 +7621,9 @@
             """
             expected = """
             [i1, i2]
    +        # operations are not all removed because this new_array() is var-sized
             p1 = new_array(i1, descr=arraydescr)
    -        # operations are not all removed because this new_array() is var-sized
    -        # unsure exactly which operations should be left, but right now it's
    -        # really buggy
    +        setarrayitem_gc(p1, 0, i2, descr=arraydescr)
             jump(i1, i2)
             """
             self.optimize_loop(ops, expected)
    
    From noreply at buildbot.pypy.org  Sat Apr  6 11:17:49 2013
    From: noreply at buildbot.pypy.org (arigo)
    Date: Sat,  6 Apr 2013 11:17:49 +0200 (CEST)
    Subject: [pypy-commit] pypy default: Add a skipped test about why it was
     done with array.array in the first place
    Message-ID: <20130406091749.B28251C00EF@cobra.cs.uni-duesseldorf.de>
    
    Author: Armin Rigo 
    Branch: 
    Changeset: r63094:fe06ba47d82a
    Date: 2013-04-06 11:16 +0200
    http://bitbucket.org/pypy/pypy/changeset/fe06ba47d82a/
    
    Log:	Add a skipped test about why it was done with array.array in the
    	first place
    
    diff --git a/pypy/module/test_lib_pypy/test_sqlite3.py b/pypy/module/test_lib_pypy/test_sqlite3.py
    --- a/pypy/module/test_lib_pypy/test_sqlite3.py
    +++ b/pypy/module/test_lib_pypy/test_sqlite3.py
    @@ -196,6 +196,11 @@
             gc.collect()
             got = (val[0], val[1], val[2], val[3])
             assert got == ('b', 'l', 'o', 'b')
    +    # in theory 'val' should be a read-write buffer
    +    # but it's not right now
    +    pytest.skip("in theory 'val' should be a read-write buffer")
    +    val[1] = 'X'
    +    assert got == ('b', 'X', 'o', 'b')
     
     def test_description_after_fetchall(con):
         cur = con.cursor()
    
    From noreply at buildbot.pypy.org  Sat Apr  6 11:17:50 2013
    From: noreply at buildbot.pypy.org (arigo)
    Date: Sat,  6 Apr 2013 11:17:50 +0200 (CEST)
    Subject: [pypy-commit] pypy default: hg backout d801b8e5feac
    Message-ID: <20130406091750.D78F31C00EF@cobra.cs.uni-duesseldorf.de>
    
    Author: Armin Rigo 
    Branch: 
    Changeset: r63095:039f6e85a7a6
    Date: 2013-04-06 11:17 +0200
    http://bitbucket.org/pypy/pypy/changeset/039f6e85a7a6/
    
    Log:	hg backout d801b8e5feac
    
    	This was changed in the first place because of some minor difference
    	between CPython's and PyPy's CFFI. I guess it should be fixed in
    	CPython's CFFI too, but too late: 0.6 is out.
    
    diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py
    --- a/lib_pypy/_sqlite3.py
    +++ b/lib_pypy/_sqlite3.py
    @@ -218,7 +218,7 @@
         const char **pzTail     /* OUT: Pointer to unused portion of zSql */
     );
     
    -void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*));
    +void sqlite3_result_blob(sqlite3_context*, const char*, int, void(*)(void*));
     void sqlite3_result_double(sqlite3_context*, double);
     void sqlite3_result_error(sqlite3_context*, const char*, int);
     void sqlite3_result_error16(sqlite3_context*, const void*, int);
    
    From noreply at buildbot.pypy.org  Sat Apr  6 11:22:30 2013
    From: noreply at buildbot.pypy.org (arigo)
    Date: Sat,  6 Apr 2013 11:22:30 +0200 (CEST)
    Subject: [pypy-commit] pypy default: Backed out changeset 039f6e85a7a6
    Message-ID: <20130406092230.11CE71C00EF@cobra.cs.uni-duesseldorf.de>
    
    Author: Armin Rigo 
    Branch: 
    Changeset: r63096:c333f91a0074
    Date: 2013-04-06 11:22 +0200
    http://bitbucket.org/pypy/pypy/changeset/c333f91a0074/
    
    Log:	Backed out changeset 039f6e85a7a6
    
    	Ah, re-re-revert that change. It works with CPython too; the issue
    	is only in the ctypes backend, which used to be used by _sqlite3.py.
    
    diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py
    --- a/lib_pypy/_sqlite3.py
    +++ b/lib_pypy/_sqlite3.py
    @@ -218,7 +218,7 @@
         const char **pzTail     /* OUT: Pointer to unused portion of zSql */
     );
     
    -void sqlite3_result_blob(sqlite3_context*, const char*, int, void(*)(void*));
    +void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*));
     void sqlite3_result_double(sqlite3_context*, double);
     void sqlite3_result_error(sqlite3_context*, const char*, int);
     void sqlite3_result_error16(sqlite3_context*, const void*, int);
    
    From noreply at buildbot.pypy.org  Sat Apr  6 11:32:37 2013
    From: noreply at buildbot.pypy.org (arigo)
    Date: Sat,  6 Apr 2013 11:32:37 +0200 (CEST)
    Subject: [pypy-commit] cffi default: Test and fix in the ctypes backend for
     calling "void *" functions with a
    Message-ID: <20130406093237.4CC9D1C06E1@cobra.cs.uni-duesseldorf.de>
    
    Author: Armin Rigo 
    Branch: 
    Changeset: r1239:557412448032
    Date: 2013-04-06 11:32 +0200
    http://bitbucket.org/cffi/cffi/changeset/557412448032/
    
    Log:	Test and fix in the ctypes backend for calling "void *" functions
    	with a Python string argument.
    
    diff --git a/cffi/backend_ctypes.py b/cffi/backend_ctypes.py
    --- a/cffi/backend_ctypes.py
    +++ b/cffi/backend_ctypes.py
    @@ -491,6 +491,8 @@
             elif BItem in (getbtype(model.PrimitiveType('signed char')),
                            getbtype(model.PrimitiveType('unsigned char'))):
                 kind = 'bytep'
    +        elif BItem is getbtype(model.void_type):
    +            kind = 'voidp'
             else:
                 kind = 'generic'
             #
    @@ -546,13 +548,13 @@
                 def __setitem__(self, index, value):
                     self._as_ctype_ptr[index] = BItem._to_ctypes(value)
     
    -            if kind == 'charp':
    +            if kind == 'charp' or kind == 'voidp':
                     @classmethod
    -                def _arg_to_ctypes(cls, value):
    -                    if isinstance(value, bytes):
    -                        return ctypes.c_char_p(value)
    +                def _arg_to_ctypes(cls, *value):
    +                    if value and isinstance(value[0], bytes):
    +                        return ctypes.c_char_p(value[0])
                         else:
    -                        return super(CTypesPtr, cls)._arg_to_ctypes(value)
    +                        return super(CTypesPtr, cls)._arg_to_ctypes(*value)
     
                 if kind == 'charp' or kind == 'bytep':
                     def _to_string(self, maxlen):
    diff --git a/testing/test_function.py b/testing/test_function.py
    --- a/testing/test_function.py
    +++ b/testing/test_function.py
    @@ -345,3 +345,28 @@
             assert lib.DD == 6
             assert lib.EE == -5
             assert lib.FF == -4
    +
    +    def test_void_star_accepts_string(self):
    +        ffi = FFI(backend=self.Backend())
    +        ffi.cdef("""int strlen(const void *);""")
    +        lib = ffi.dlopen(None)
    +        res = lib.strlen(b"hello")
    +        assert res == 5
    +
    +    def test_signed_char_star_accepts_string(self):
    +        if self.Backend is CTypesBackend:
    +            py.test.skip("not supported by the ctypes backend")
    +        ffi = FFI(backend=self.Backend())
    +        ffi.cdef("""int strlen(signed char *);""")
    +        lib = ffi.dlopen(None)
    +        res = lib.strlen(b"hello")
    +        assert res == 5
    +
    +    def test_unsigned_char_star_accepts_string(self):
    +        if self.Backend is CTypesBackend:
    +            py.test.skip("not supported by the ctypes backend")
    +        ffi = FFI(backend=self.Backend())
    +        ffi.cdef("""int strlen(unsigned char *);""")
    +        lib = ffi.dlopen(None)
    +        res = lib.strlen(b"hello")
    +        assert res == 5
    
    From noreply at buildbot.pypy.org  Sat Apr  6 11:42:23 2013
    From: noreply at buildbot.pypy.org (arigo)
    Date: Sat,  6 Apr 2013 11:42:23 +0200 (CEST)
    Subject: [pypy-commit] pypy default: Missing import.
    Message-ID: <20130406094223.8C91B1C0337@cobra.cs.uni-duesseldorf.de>
    
    Author: Armin Rigo 
    Branch: 
    Changeset: r63097:c3744e8e1a14
    Date: 2013-04-06 11:42 +0200
    http://bitbucket.org/pypy/pypy/changeset/c3744e8e1a14/
    
    Log:	Missing import.
    
    diff --git a/lib_pypy/_ctypes/function.py b/lib_pypy/_ctypes/function.py
    --- a/lib_pypy/_ctypes/function.py
    +++ b/lib_pypy/_ctypes/function.py
    @@ -342,6 +342,7 @@
             if not outargs:
                 return result
     
    +        from ctypes import c_void_p
             simple_cdata = type(c_void_p()).__bases__[0]
             outargs = [x.value if type(x).__bases__[0] is simple_cdata else x
                        for x in outargs]
    
    From noreply at buildbot.pypy.org  Sat Apr  6 11:45:32 2013
    From: noreply at buildbot.pypy.org (arigo)
    Date: Sat,  6 Apr 2013 11:45:32 +0200 (CEST)
    Subject: [pypy-commit] pypy default: Disable the PyPy-only warning in ctypes
    	for now.
    Message-ID: <20130406094532.3B6F41C06BD@cobra.cs.uni-duesseldorf.de>
    
    Author: Armin Rigo 
    Branch: 
    Changeset: r63098:17f9426edda9
    Date: 2013-04-06 11:45 +0200
    http://bitbucket.org/pypy/pypy/changeset/17f9426edda9/
    
    Log:	Disable the PyPy-only warning in ctypes for now.
    
    diff --git a/lib_pypy/_ctypes/function.py b/lib_pypy/_ctypes/function.py
    --- a/lib_pypy/_ctypes/function.py
    +++ b/lib_pypy/_ctypes/function.py
    @@ -8,7 +8,6 @@
     import _ffi
     import sys
     import traceback
    -import warnings
     
     try: from __pypy__ import builtinify
     except ImportError: builtinify = lambda f: f
    @@ -315,8 +314,12 @@
                 return
     
             if argtypes is None:
    -            warnings.warn('C function without declared arguments called',
    -                          RuntimeWarning, stacklevel=2)
    +            # XXX this warning was originally meaning "it's going to be
    +            # really slow".  Now we don't worry that much about slowness
    +            # of ctypes, and it's strange to get warnings for perfectly-
    +            # legal code.
    +            #warnings.warn('C function without declared arguments called',
    +            #              RuntimeWarning, stacklevel=2)
                 argtypes = []
     
             if self._com_index:
    diff --git a/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py b/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py
    --- a/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py
    +++ b/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py
    @@ -510,6 +510,7 @@
             assert seen == ["yadda"]
     
         def test_warnings(self):
    +        py.test.skip("warnings are disabled")
             import warnings
             warnings.simplefilter("always")
             with warnings.catch_warnings(record=True) as w:
    
    From noreply at buildbot.pypy.org  Sat Apr  6 11:48:42 2013
    From: noreply at buildbot.pypy.org (arigo)
    Date: Sat,  6 Apr 2013 11:48:42 +0200 (CEST)
    Subject: [pypy-commit] pypy release-2.0-beta2: hg merge default
    Message-ID: <20130406094842.3324C1C0337@cobra.cs.uni-duesseldorf.de>
    
    Author: Armin Rigo 
    Branch: release-2.0-beta2
    Changeset: r63099:3eef596df459
    Date: 2013-04-06 11:48 +0200
    http://bitbucket.org/pypy/pypy/changeset/3eef596df459/
    
    Log:	hg merge default
    
    diff --git a/.hgignore b/.hgignore
    --- a/.hgignore
    +++ b/.hgignore
    @@ -70,6 +70,7 @@
     ^rpython/translator/cli/src/pypylib\.dll$
     ^rpython/translator/cli/src/query\.exe$
     ^rpython/translator/cli/src/main\.exe$
    +^lib_pypy/__pycache__$
     ^lib_pypy/ctypes_config_cache/_.+_cache\.py$
     ^lib_pypy/ctypes_config_cache/_.+_.+_\.py$
     ^rpython/translator/cli/query-descriptions$
    diff --git a/lib-python/conftest.py b/lib-python/conftest.py
    --- a/lib-python/conftest.py
    +++ b/lib-python/conftest.py
    @@ -1,91 +1,89 @@
     """
     
     test configuration(s) for running CPython's regression
    -test suite on top of PyPy 
    +test suite on top of PyPy
     
     """
     import py
     import sys
     import pypy
     import re
    -from pypy.interpreter.gateway import ApplevelClass 
    +from pypy.interpreter.gateway import ApplevelClass
     from pypy.interpreter.error import OperationError
    -from pypy.interpreter.module import Module as PyPyModule 
    +from pypy.interpreter.module import Module as PyPyModule
     from pypy.interpreter.main import run_string, run_file
     
    -# the following adds command line options as a side effect! 
    -from pypy.conftest import option as pypy_option 
    +# the following adds command line options as a side effect!
    +from pypy.conftest import option as pypy_option
     
    -from pypy.tool.pytest import appsupport 
    +from pypy.tool.pytest import appsupport
     from pypy.tool.pytest.confpath import pypydir, rpythondir, testdir, testresultdir
     from rpython.config.parse import parse_info
     
     pytest_plugins = "resultlog",
     rsyncdirs = ['.', '../pypy/']
     
    -# 
    -# Interfacing/Integrating with py.test's collection process 
    +#
    +# Interfacing/Integrating with py.test's collection process
     #
     
     def pytest_addoption(parser):
    -    group = parser.getgroup("complicance testing options") 
    -    group.addoption('-T', '--timeout', action="store", type="string", 
    -       default="1000", dest="timeout", 
    -       help="fail a test module after the given timeout. "
    -            "specify in seconds or 'NUMmp' aka Mega-Pystones")
    -    group.addoption('--pypy', action="store", type="string",
    -       dest="pypy",  help="use given pypy executable to run lib-python tests. "
    -                          "This will run the tests directly (i.e. not through py.py)")
    +    group = parser.getgroup("complicance testing options")
    +    group.addoption('-T', '--timeout', action="store", type="string",
    +                    default="1000", dest="timeout",
    +                    help="fail a test module after the given timeout. "
    +                         "specify in seconds or 'NUMmp' aka Mega-Pystones")
    +    group.addoption('--pypy', action="store", type="string", dest="pypy",
    +                    help="use given pypy executable to run lib-python tests. "
    +                         "This will run the tests directly (i.e. not through py.py)")
         group.addoption('--filter', action="store", type="string", default=None,
    -                    dest="unittest_filter",  help="Similar to -k, XXX")
    +                    dest="unittest_filter", help="Similar to -k, XXX")
     
    -def gettimeout(timeout): 
    +def gettimeout(timeout):
         from rpython.translator.test import rpystone
    -    if timeout.endswith('mp'): 
    +    if timeout.endswith('mp'):
             megapystone = float(timeout[:-2])
             t, stone = pystone.Proc0(10000)
    -        pystonetime = t/stone 
    -        seconds = megapystone  * 1000000 * pystonetime
    -        return seconds 
    -    return float(timeout) 
    +        pystonetime = t/stone
    +        seconds = megapystone * 1000000 * pystonetime
    +        return seconds
    +    return float(timeout)
     
     # ________________________________________________________________________
     #
    -# classification of all tests files (this is ongoing work) 
    +# classification of all tests files (this is ongoing work)
     #
     
    -class RegrTest: 
    -    """ Regression Test Declaration.""" 
    -    def __init__(self, basename, core=False,
    -                                 compiler=None, 
    -                                 usemodules = '',
    -                                 skip=None): 
    -        self.basename = basename 
    +class RegrTest:
    +    """ Regression Test Declaration."""
    +    def __init__(self, basename, core=False, compiler=None, usemodules='',
    +                 skip=None):
    +        self.basename = basename
             self._usemodules = usemodules.split() + ['signal', 'rctime', 'itertools', '_socket']
    -        self._compiler = compiler 
    +        self._compiler = compiler
             self.core = core
             self.skip = skip
             assert self.getfspath().check(), "%r not found!" % (basename,)
     
         def usemodules(self):
    -        return self._usemodules #+ pypy_option.usemodules
    +        return self._usemodules  # + pypy_option.usemodules
         usemodules = property(usemodules)
     
    -    def compiler(self): 
    -        return self._compiler #or pypy_option.compiler 
    +    def compiler(self):
    +        return self._compiler  # or pypy_option.compiler
         compiler = property(compiler)
     
    -    def ismodified(self): 
    +    def ismodified(self):
             #XXX: ask hg
             return None
     
    -    def getfspath(self): 
    +    def getfspath(self):
             return testdir.join(self.basename)
     
    -    def run_file(self, space): 
    +    def run_file(self, space):
             fspath = self.getfspath()
             assert fspath.check()
    -        modname = fspath.purebasename 
    +        modname = fspath.purebasename
             space.appexec([], '''():
                 from test import %(modname)s
                 m = %(modname)s
    @@ -424,7 +422,7 @@
         RegrTest('test_textwrap.py'),
         RegrTest('test_thread.py', usemodules="thread", core=True),
         RegrTest('test_threaded_import.py', usemodules="thread", core=True),
    -    RegrTest('test_threadedtempfile.py', 
    +    RegrTest('test_threadedtempfile.py',
                  usemodules="thread", core=False),
         RegrTest('test_threading.py', usemodules="thread", core=True),
         RegrTest('test_threading_local.py', usemodules="thread", core=True),
    @@ -504,7 +502,7 @@
     
     def pytest_configure(config):
         config._basename2spec = cache = {}
    -    for x in testmap: 
    +    for x in testmap:
             cache[x.basename] = x
     
     def pytest_collect_file(path, parent, __multicall__):
    @@ -520,33 +518,33 @@
         return RunFileExternal(path.basename, parent=parent, regrtest=regrtest)
     
     class RunFileExternal(py.test.collect.File):
    -    def __init__(self, name, parent, regrtest): 
    -        super(RunFileExternal, self).__init__(name, parent) 
    -        self.regrtest = regrtest 
    +    def __init__(self, name, parent, regrtest):
    +        super(RunFileExternal, self).__init__(name, parent)
    +        self.regrtest = regrtest
             self.fspath = regrtest.getfspath()
     
    -    def collect(self): 
    -        if self.regrtest.ismodified(): 
    +    def collect(self):
    +        if self.regrtest.ismodified():
                 name = 'modified'
             else:
                 name = 'unmodified'
    -        return [ReallyRunFileExternal(name, parent=self)] 
    +        return [ReallyRunFileExternal(name, parent=self)]
     
     #
    -# testmethod: 
    +# testmethod:
     # invoking in a separate process: py.py TESTFILE
     #
     import os
     import time
     import getpass
     
    -class ReallyRunFileExternal(py.test.collect.Item): 
    +class ReallyRunFileExternal(py.test.collect.Item):
         class ExternalFailure(Exception):
             """Failure in running subprocess"""
     
    -    def getinvocation(self, regrtest): 
    -        fspath = regrtest.getfspath() 
    -        python = sys.executable 
    +    def getinvocation(self, regrtest):
    +        fspath = regrtest.getfspath()
    +        python = sys.executable
             pypy_script = pypydir.join('bin', 'pyinteractive.py')
             alarm_script = pypydir.join('tool', 'alarm.py')
             if sys.platform == 'win32':
    @@ -555,9 +553,9 @@
                 watchdog_name = 'watchdog.py'
             watchdog_script = rpythondir.join('tool', watchdog_name)
     
    -        regr_script = pypydir.join('tool', 'pytest', 
    +        regr_script = pypydir.join('tool', 'pytest',
                                        'run-script', 'regrverbose.py')
    -        
    +
             regrrun = str(regr_script)
             option = self.config.option
             TIMEOUT = gettimeout(option.timeout.lower())
    @@ -566,8 +564,7 @@
                 if not execpath.check():
                     execpath = py.path.local.sysfind(option.pypy)
                 if not execpath:
    -                raise LookupError("could not find executable %r" %
    -                                  (option.pypy,))
    +                raise LookupError("could not find executable %r" % option.pypy)
     
                 # check modules
                 info = py.process.cmdexec("%s --info" % execpath)
    @@ -576,34 +573,29 @@
                     if info.get('objspace.usemodules.%s' % mod) is not True:
                         py.test.skip("%s module not included in %s" % (mod,
                                                                        execpath))
    -                    
    -            cmd = "%s %s %s" %(
    -                execpath, 
    -                regrrun, fspath.purebasename)
     
    +            cmd = "%s %s %s" % (execpath, regrrun, fspath.purebasename)
                 # add watchdog for timing out
    -            cmd = "%s %s %s %s" %(
    -                python, watchdog_script, TIMEOUT,
    -                cmd)
    +            cmd = "%s %s %s %s" % (python, watchdog_script, TIMEOUT, cmd)
             else:
                 pypy_options = []
                 pypy_options.extend(
                     ['--withmod-%s' % mod for mod in regrtest.usemodules])
    -            sopt = " ".join(pypy_options) 
    -            cmd = "%s %s %d %s -S %s %s %s -v" %(
    -                python, alarm_script, TIMEOUT, 
    -                pypy_script, sopt, 
    +            sopt = " ".join(pypy_options)
    +            cmd = "%s %s %d %s -S %s %s %s -v" % (
    +                python, alarm_script, TIMEOUT,
    +                pypy_script, sopt,
                     regrrun, fspath.purebasename)
    -        return cmd 
    +        return cmd
     
    -    def runtest(self): 
    -        """ invoke a subprocess running the test file via PyPy. 
    -            record its output into the 'result/user at host' subdirectory. 
    -            (we might want to create subdirectories for 
    -            each user, because we will probably all produce 
    +    def runtest(self):
    +        """ invoke a subprocess running the test file via PyPy.
    +            record its output into the 'result/user at host' subdirectory.
    +            (we might want to create subdirectories for
    +            each user, because we will probably all produce
                 such result runs and they will not be the same
    -            i am afraid. 
    -        """ 
    +            i am afraid.
    +        """
             regrtest = self.parent.regrtest
             if regrtest.skip:
                 if regrtest.skip is True:
    @@ -611,8 +603,8 @@
                 else:
                     msg = regrtest.skip
                 py.test.skip(msg)
    -        (skipped, exit_status, test_stdout,
    -                               test_stderr) = self.getresult(regrtest)
    +        (skipped, exit_status, test_stdout, test_stderr) = \
    +            self.getresult(regrtest)
             if skipped:
                 py.test.skip(test_stderr.splitlines()[-1])
             if exit_status:
    @@ -624,13 +616,13 @@
             out, err = excinfo.value.args
             return out + err
     
    -    def getstatusouterr(self, cmd): 
    +    def getstatusouterr(self, cmd):
             tempdir = py.test.ensuretemp(self.fspath.basename)
             stdout = tempdir.join(self.fspath.basename) + '.out'
             stderr = tempdir.join(self.fspath.basename) + '.err'
             if sys.platform == 'win32':
    -            status = os.system("%s >%s 2>%s" %(cmd, stdout, stderr))
    -            if status>=0:
    +            status = os.system("%s >%s 2>%s" % (cmd, stdout, stderr))
    +            if status >= 0:
                     status = status
                 else:
                     status = 'abnormal termination 0x%x' % status
    @@ -644,22 +636,22 @@
                     stdout.write('')
                     stderr.write('')
                 else:
    -                status = os.system("%s >>%s 2>>%s" %(cmd, stdout, stderr))
    +                status = os.system("%s >>%s 2>>%s" % (cmd, stdout, stderr))
                 if os.WIFEXITED(status):
                     status = os.WEXITSTATUS(status)
                 else:
                     status = 'abnormal termination 0x%x' % status
             return status, stdout.read(mode='rU'), stderr.read(mode='rU')
     
    -    def getresult(self, regrtest): 
    +    def getresult(self, regrtest):
             cmd = self.getinvocation(regrtest)
             tempdir = py.test.ensuretemp(self.fspath.basename)
             oldcwd = tempdir.chdir()
             exit_status, test_stdout, test_stderr = self.getstatusouterr(cmd)
             oldcwd.chdir()
             skipped = False
    -        timedout = test_stderr.rfind(26*"=" + "timedout" + 26*"=") != -1 
    -        if not timedout: 
    +        timedout = test_stderr.rfind(26*"=" + "timedout" + 26*"=") != -1
    +        if not timedout:
                 timedout = test_stderr.rfind("KeyboardInterrupt") != -1
             if test_stderr.rfind(26*"=" + "skipped" + 26*"=") != -1:
                 skipped = True
    @@ -669,12 +661,12 @@
                 # test in test_zipimport_support.py
                 if re.search(r'\bFAIL\b', test_stdout) or re.search('[^:]ERROR', test_stderr):
                     outcome = 'FAIL'
    -                exit_status = 2  
    -        elif timedout: 
    -            outcome = "T/O"    
    -        else: 
    +                exit_status = 2
    +        elif timedout:
    +            outcome = "T/O"
    +        else:
                 outcome = "ERR"
    -        
    +
             return skipped, exit_status, test_stdout, test_stderr
     
         def _keywords(self):
    @@ -683,4 +675,3 @@
             if regrtest.core:
                 lst.append('core')
             return lst
    -
    diff --git a/lib_pypy/_collections.py b/lib_pypy/_collections.py
    --- a/lib_pypy/_collections.py
    +++ b/lib_pypy/_collections.py
    @@ -8,7 +8,6 @@
     # Note that PyPy also contains a built-in module '_collections' which will hide
     # this one if compiled in.
     
    -import operator
     try:
         from threading import _get_ident as _thread_ident
     except ImportError:
    diff --git a/lib_pypy/_ctypes/function.py b/lib_pypy/_ctypes/function.py
    --- a/lib_pypy/_ctypes/function.py
    +++ b/lib_pypy/_ctypes/function.py
    @@ -8,7 +8,6 @@
     import _ffi
     import sys
     import traceback
    -import warnings
     
     try: from __pypy__ import builtinify
     except ImportError: builtinify = lambda f: f
    @@ -315,8 +314,12 @@
                 return
     
             if argtypes is None:
    -            warnings.warn('C function without declared arguments called',
    -                          RuntimeWarning, stacklevel=2)
    +            # XXX this warning was originally meaning "it's going to be
    +            # really slow".  Now we don't worry that much about slowness
    +            # of ctypes, and it's strange to get warnings for perfectly-
    +            # legal code.
    +            #warnings.warn('C function without declared arguments called',
    +            #              RuntimeWarning, stacklevel=2)
                 argtypes = []
     
             if self._com_index:
    @@ -342,6 +345,7 @@
             if not outargs:
                 return result
     
    +        from ctypes import c_void_p
             simple_cdata = type(c_void_p()).__bases__[0]
             outargs = [x.value if type(x).__bases__[0] is simple_cdata else x
                        for x in outargs]
    diff --git a/lib_pypy/_curses.py b/lib_pypy/_curses.py
    --- a/lib_pypy/_curses.py
    +++ b/lib_pypy/_curses.py
    @@ -359,9 +359,12 @@
         if not lib._m_NetBSD:
             for key in range(lib.KEY_MIN, lib.KEY_MAX):
                 key_n = lib.keyname(key)
    -            if key_n == ffi.NULL or ffi.string(key_n) == "UNKNOWN KEY":
    +            if key_n == ffi.NULL:
                     continue
    -            key_n = ffi.string(key_n).replace('(', '').replace(')', '')
    +            key_n = ffi.string(key_n)
    +            if key_n == b"UNKNOWN KEY":
    +                continue
    +            key_n = key_n.decode().replace('(', '').replace(')', '')
                 globals()[key_n] = key
     
     _setup()
    diff --git a/lib_pypy/_pypy_interact.py b/lib_pypy/_pypy_interact.py
    --- a/lib_pypy/_pypy_interact.py
    +++ b/lib_pypy/_pypy_interact.py
    @@ -74,7 +74,6 @@
     # ____________________________________________________________
     
     if __name__ == '__main__':    # for testing
    -    import os
         if os.getenv('PYTHONSTARTUP'):
             execfile(os.getenv('PYTHONSTARTUP'))
         interactive_console()
    diff --git a/lib_pypy/_sha512.py b/lib_pypy/_sha512.py
    --- a/lib_pypy/_sha512.py
    +++ b/lib_pypy/_sha512.py
    @@ -30,23 +30,23 @@
     
     def sha_transform(sha_info):
         W = []
    -    
    +
         d = sha_info['data']
         for i in xrange(0,16):
             W.append( (d[8*i]<<56) + (d[8*i+1]<<48) + (d[8*i+2]<<40) + (d[8*i+3]<<32) + (d[8*i+4]<<24) + (d[8*i+5]<<16) + (d[8*i+6]<<8) + d[8*i+7])
    -    
    +
         for i in xrange(16,80):
             W.append( (Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]) & 0xffffffffffffffff )
    -    
    +
         ss = sha_info['digest'][:]
    -    
    +
         def RND(a,b,c,d,e,f,g,h,i,ki):
             t0 = (h + Sigma1(e) + Ch(e, f, g) + ki + W[i]) & 0xffffffffffffffff
             t1 = (Sigma0(a) + Maj(a, b, c)) & 0xffffffffffffffff
             d = (d + t0) & 0xffffffffffffffff
             h = (t0 + t1) & 0xffffffffffffffff
             return d & 0xffffffffffffffff, h & 0xffffffffffffffff
    -    
    +
         ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],0,0x428a2f98d728ae22)
         ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],1,0x7137449123ef65cd)
         ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],2,0xb5c0fbcfec4d3b2f)
    @@ -127,8 +127,7 @@
         ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],77,0x597f299cfc657e2a)
         ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],78,0x5fcb6fab3ad6faec)
         ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],79,0x6c44198c4a475817)
    -    
    -    
    +
         dig = []
         for i, x in enumerate(sha_info['digest']):
             dig.append( (x + ss[i]) & 0xffffffffffffffff )
    @@ -167,36 +166,35 @@
         if clo < sha_info['count_lo']:
             sha_info['count_hi'] += 1
         sha_info['count_lo'] = clo
    -    
    +
         sha_info['count_hi'] += (count >> 29)
    -    
    +
         if sha_info['local']:
             i = SHA_BLOCKSIZE - sha_info['local']
             if i > count:
                 i = count
    -        
    +
             # copy buffer
             for x in enumerate(buffer[buffer_idx:buffer_idx+i]):
                 sha_info['data'][sha_info['local']+x[0]] = struct.unpack('B', x[1])[0]
    -        
    +
             count -= i
             buffer_idx += i
    -        
    +
             sha_info['local'] += i
             if sha_info['local'] == SHA_BLOCKSIZE:
                 sha_transform(sha_info)
                 sha_info['local'] = 0
             else:
                 return
    -    
    +
         while count >= SHA_BLOCKSIZE:
             # copy buffer
             sha_info['data'] = [struct.unpack('B',c)[0] for c in buffer[buffer_idx:buffer_idx + SHA_BLOCKSIZE]]
             count -= SHA_BLOCKSIZE
             buffer_idx += SHA_BLOCKSIZE
             sha_transform(sha_info)
    -    
    -    
    +
         # copy buffer
         pos = sha_info['local']
         sha_info['data'][pos:pos+count] = [struct.unpack('B',c)[0] for c in buffer[buffer_idx:buffer_idx + count]]
    @@ -216,7 +214,7 @@
             sha_info['data'] = [0] * SHA_BLOCKSIZE
         else:
             sha_info['data'] = sha_info['data'][:count] + ([0] * (SHA_BLOCKSIZE - count))
    -    
    +
         sha_info['data'][112] = 0;
         sha_info['data'][113] = 0;
         sha_info['data'][114] = 0;
    @@ -225,7 +223,7 @@
         sha_info['data'][117] = 0;
         sha_info['data'][118] = 0;
         sha_info['data'][119] = 0;
    -    
    +
         sha_info['data'][120] = (hi_bit_count >> 24) & 0xff
         sha_info['data'][121] = (hi_bit_count >> 16) & 0xff
         sha_info['data'][122] = (hi_bit_count >>  8) & 0xff
    @@ -234,9 +232,9 @@
         sha_info['data'][125] = (lo_bit_count >> 16) & 0xff
         sha_info['data'][126] = (lo_bit_count >>  8) & 0xff
         sha_info['data'][127] = (lo_bit_count >>  0) & 0xff
    -    
    +
         sha_transform(sha_info)
    -    
    +
         dig = []
         for i in sha_info['digest']:
             dig.extend([ ((i>>56) & 0xff), ((i>>48) & 0xff), ((i>>40) & 0xff), ((i>>32) & 0xff), ((i>>24) & 0xff), ((i>>16) & 0xff), ((i>>8) & 0xff), (i & 0xff) ])
    @@ -250,13 +248,13 @@
             self._sha = sha_init()
             if s:
                 sha_update(self._sha, getbuf(s))
    -    
    +
         def update(self, s):
             sha_update(self._sha, getbuf(s))
    -    
    +
         def digest(self):
             return sha_final(self._sha.copy())[:self._sha['digestsize']]
    -    
    +
         def hexdigest(self):
             return ''.join(['%.2x' % ord(i) for i in self.digest()])
     
    @@ -279,12 +277,14 @@
             return new
     
     def test():
    +    import _sha512
    +
         a_str = "just a test string"
    -    
    +
         assert _sha512.sha512().hexdigest() == sha512().hexdigest()
         assert _sha512.sha512(a_str).hexdigest() == sha512(a_str).hexdigest()
         assert _sha512.sha512(a_str*7).hexdigest() == sha512(a_str*7).hexdigest()
    -    
    +
         s = sha512(a_str)
         s.update(a_str)
         assert _sha512.sha512(a_str+a_str).hexdigest() == s.hexdigest()
    diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py
    --- a/lib_pypy/_sqlite3.py
    +++ b/lib_pypy/_sqlite3.py
    @@ -29,7 +29,6 @@
     import string
     import sys
     import weakref
    -import array
     from threading import _get_ident as _thread_get_ident
     try:
         from __pypy__ import newlist_hint
    @@ -219,7 +218,7 @@
         const char **pzTail     /* OUT: Pointer to unused portion of zSql */
     );
     
    -void sqlite3_result_blob(sqlite3_context*, const char*, int, void(*)(void*));
    +void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*));
     void sqlite3_result_double(sqlite3_context*, double);
     void sqlite3_result_error(sqlite3_context*, const char*, int);
     void sqlite3_result_error16(sqlite3_context*, const void*, int);
    @@ -853,7 +852,7 @@
             self._reset = False
             self.__locked = False
             self.__closed = False
    -        self.__description = None
    +        self.__lastrowid = None
             self.__rowcount = -1
     
             con._check_thread()
    @@ -959,11 +958,7 @@
                     elif typ == _lib.SQLITE_BLOB:
                         blob = _lib.sqlite3_column_blob(self.__statement._statement, i)
                         blob_len = _lib.sqlite3_column_bytes(self.__statement._statement, i)
    -                    # make a copy of the data into an array, in order to get
    -                    # a read-write buffer in the end, and one that own the
    -                    # memory for a more predictable length of time than 'blob'
    -                    copy = array.array("c", _ffi.buffer(blob, blob_len))
    -                    val = _BLOB_TYPE(copy)
    +                    val = _BLOB_TYPE(_ffi.buffer(blob, blob_len)[:])
                 row.append(val)
             return tuple(row)
     
    @@ -977,20 +972,24 @@
             try:
                 if not isinstance(sql, basestring):
                     raise ValueError("operation parameter must be str or unicode")
    -            self.__description = None
    +            try:
    +                del self.__description
    +            except AttributeError:
    +                pass
                 self.__rowcount = -1
                 self.__statement = self.__connection._statement_cache.get(sql)
     
                 if self.__connection._isolation_level is not None:
    -                if self.__statement._kind == Statement._DDL:
    +                if self.__statement._type in ("UPDATE", "DELETE", "INSERT", "REPLACE"):
    +                    if not self.__connection._in_transaction:
    +                        self.__connection._begin()
    +                elif self.__statement._type == "OTHER":
                         if self.__connection._in_transaction:
                             self.__connection.commit()
    -                elif self.__statement._kind == Statement._DML:
    -                    if not self.__connection._in_transaction:
    -                        self.__connection._begin()
    -
    -            if multiple and self.__statement._kind != Statement._DML:
    -                raise ProgrammingError("executemany is only for DML statements")
    +                elif self.__statement._type == "SELECT":
    +                    if multiple:
    +                        raise ProgrammingError("You cannot execute SELECT "
    +                                               "statements in executemany().")
     
                 for params in many_params:
                     self.__statement._set_params(params)
    @@ -1001,17 +1000,26 @@
                         self.__statement._reset()
                         raise self.__connection._get_exception(ret)
     
    -                if self.__statement._kind == Statement._DML:
    +                if ret == _lib.SQLITE_ROW:
    +                    if multiple:
    +                        raise ProgrammingError("executemany() can only execute DML statements.")
    +                    self.__build_row_cast_map()
    +                    self.__next_row = self.__fetch_one_row()
    +                elif ret == _lib.SQLITE_DONE and not multiple:
                         self.__statement._reset()
     
    -                if ret == _lib.SQLITE_ROW:
    -                    self.__build_row_cast_map()
    -                    self.__next_row = self.__fetch_one_row()
    -
    -                if self.__statement._kind == Statement._DML:
    +                if self.__statement._type in ("UPDATE", "DELETE", "INSERT", "REPLACE"):
                         if self.__rowcount == -1:
                             self.__rowcount = 0
                         self.__rowcount += _lib.sqlite3_changes(self.__connection._db)
    +
    +                if not multiple and self.__statement._type == "INSERT":
    +                    self.__lastrowid = _lib.sqlite3_last_insert_rowid(self.__connection._db)
    +                else:
    +                    self.__lastrowid = None
    +
    +                if multiple:
    +                    self.__statement._reset()
             finally:
                 self.__connection._in_transaction = \
                     not _lib.sqlite3_get_autocommit(self.__connection._db)
    @@ -1123,13 +1131,15 @@
         rowcount = property(__get_rowcount)
     
         def __get_description(self):
    -        if self.__description is None:
    +        try:
    +            return self.__description
    +        except AttributeError:
                 self.__description = self.__statement._get_description()
    -        return self.__description
    +            return self.__description
         description = property(__get_description)
     
         def __get_lastrowid(self):
    -        return _lib.sqlite3_last_insert_rowid(self.__connection._db)
    +        return self.__lastrowid
         lastrowid = property(__get_lastrowid)
     
         def setinputsizes(self, *args):
    @@ -1140,8 +1150,6 @@
     
     
     class Statement(object):
    -    _DML, _DQL, _DDL = range(3)
    -
         _statement = None
     
         def __init__(self, connection, sql):
    @@ -1152,13 +1160,14 @@
     
             if not isinstance(sql, basestring):
                 raise Warning("SQL is of wrong type. Must be string or unicode.")
    -        first_word = self._statement_kind = sql.lstrip().split(" ")[0].upper()
    -        if first_word in ("INSERT", "UPDATE", "DELETE", "REPLACE"):
    -            self._kind = Statement._DML
    -        elif first_word in ("SELECT", "PRAGMA"):
    -            self._kind = Statement._DQL
    +
    +        first_word = sql.lstrip().split(" ")[0].upper()
    +        if first_word == "":
    +            self._type = "INVALID"
    +        elif first_word in ("SELECT", "INSERT", "UPDATE", "DELETE", "REPLACE"):
    +            self._type = first_word
             else:
    -            self._kind = Statement._DDL
    +            self._type = "OTHER"
     
             if isinstance(sql, unicode):
                 sql = sql.encode('utf-8')
    @@ -1171,11 +1180,12 @@
     
             if ret == _lib.SQLITE_OK and not self._statement:
                 # an empty statement, work around that, as it's the least trouble
    +            self._type = "SELECT"
                 c_sql = _ffi.new("char[]", b"select 42")
                 ret = _lib.sqlite3_prepare_v2(self.__con._db, c_sql, -1,
                                               statement_star, next_char)
                 self._statement = statement_star[0]
    -            self._kind = Statement._DQL
    +
             if ret != _lib.SQLITE_OK:
                 raise self.__con._get_exception(ret)
     
    @@ -1286,7 +1296,7 @@
                 raise ValueError("parameters are of unsupported type")
     
         def _get_description(self):
    -        if self._kind == Statement._DML:
    +        if self._type in ("INSERT", "UPDATE", "DELETE", "REPLACE"):
                 return None
             desc = []
             for i in xrange(_lib.sqlite3_column_count(self._statement)):
    @@ -1391,7 +1401,7 @@
             elif typ == _lib.SQLITE_BLOB:
                 blob = _lib.sqlite3_value_blob(params[i])
                 blob_len = _lib.sqlite3_value_bytes(params[i])
    -            val = _BLOB_TYPE(_ffi.buffer(blob, blob_len))
    +            val = _BLOB_TYPE(_ffi.buffer(blob, blob_len)[:])
             else:
                 raise NotImplementedError
             _params.append(val)
    diff --git a/lib_pypy/dbm.py b/lib_pypy/dbm.py
    --- a/lib_pypy/dbm.py
    +++ b/lib_pypy/dbm.py
    @@ -168,7 +168,7 @@
                 'c': os.O_RDWR | os.O_CREAT,
                 'n': os.O_RDWR | os.O_CREAT | os.O_TRUNC,
                 }[flag]
    -    except KeyError, e:
    +    except KeyError:
             raise error("arg 2 to open should be 'r', 'w', 'c', or 'n'")
     
         a_db = getattr(lib, funcs['open'])(filename, openflag, mode)
    diff --git a/lib_pypy/greenlet.py b/lib_pypy/greenlet.py
    --- a/lib_pypy/greenlet.py
    +++ b/lib_pypy/greenlet.py
    @@ -1,4 +1,4 @@
    -import _continuation, sys
    +import _continuation
     
     __version__ = "0.4.0"
     
    diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
    --- a/pypy/doc/whatsnew-head.rst
    +++ b/pypy/doc/whatsnew-head.rst
    @@ -115,9 +115,9 @@
     .. branch: remove-list-smm
     .. branch: bridge-logging
     .. branch: curses_cffi
    -
     cffi implementation of _curses
     
     .. branch: sqlite-cffi
    +cffi implementation of sqlite3
     
    -cffi implementation of sqlite3
    +.. branch: release-2.0-beta2
    diff --git a/pypy/module/_socket/test/test_sock_app.py b/pypy/module/_socket/test/test_sock_app.py
    --- a/pypy/module/_socket/test/test_sock_app.py
    +++ b/pypy/module/_socket/test/test_sock_app.py
    @@ -233,7 +233,7 @@
     
     def test_unknown_addr_as_object():
         from pypy.module._socket.interp_socket import addr_as_object
    -    c_addr = lltype.malloc(rsocket._c.sockaddr, flavor='raw')
    +    c_addr = lltype.malloc(rsocket._c.sockaddr, flavor='raw', track_allocation=False)
         c_addr.c_sa_data[0] = 'c'
         rffi.setintfield(c_addr, 'c_sa_family', 15)
         # XXX what size to pass here? for the purpose of this test it has
    diff --git a/pypy/module/pyexpat/interp_pyexpat.py b/pypy/module/pyexpat/interp_pyexpat.py
    --- a/pypy/module/pyexpat/interp_pyexpat.py
    +++ b/pypy/module/pyexpat/interp_pyexpat.py
    @@ -305,14 +305,15 @@
                 w_result = space.call_function(handler, %(wargs)s)
                 %(post_code)s
             except OperationError, e:
    -            parser._exc_info = e
    +            if not parser._exc_info: # don't override an existing exception
    +                 parser._exc_info = e
                 XML_StopParser(parser.itself, XML_FALSE)
                 return %(result_error)s
             return %(result_converter)s
         callback = %(name)s_callback
         """ % locals())
     
    -    exec str(src)
    +    exec src.compile()
     
         c_name = 'XML_Set' + name
         callback_type = lltype.Ptr(lltype.FuncType(
    @@ -335,7 +336,8 @@
         try:
             parser.UnknownEncodingHandler(space, name, info)
         except OperationError, e:
    -        parser._exc_info = e
    +        if parser._exc_info:
    +            parser._exc_info = e
             XML_StopParser(parser.itself, XML_FALSE)
             result = 0
         else:
    diff --git a/pypy/module/pyexpat/test/test_parser.py b/pypy/module/pyexpat/test/test_parser.py
    --- a/pypy/module/pyexpat/test/test_parser.py
    +++ b/pypy/module/pyexpat/test/test_parser.py
    @@ -167,3 +167,46 @@
                 p = pyexpat.ParserCreate()
                 p.ParseFile(fake_reader)
                 assert fake_reader.read_count == 4
    +
    +class AppTestPyexpat2:
    +    spaceconfig = dict(usemodules=['pyexpat', 'itertools', '_socket',
    +                                   'rctime', 'struct', 'binascii'])
    +
    +    def test_django_bug(self):
    +        xml_str = ''
    +
    +        from xml.dom import pulldom
    +        from xml.sax import handler
    +        from xml.sax.expatreader import ExpatParser as _ExpatParser
    +        from StringIO import StringIO
    +
    +        class DefusedExpatParser(_ExpatParser):
    +            def start_doctype_decl(self, name, sysid, pubid, has_internal_subset):
    +                raise DTDForbidden(name, sysid, pubid)
    +
    +            def external_entity_ref_handler(self, context, base, sysid, pubid):
    +                raise ExternalReferenceForbidden(context, base, sysid, pubid)
    +
    +            def reset(self):
    +                _ExpatParser.reset(self)
    +                parser = self._parser
    +                parser.StartDoctypeDeclHandler = self.start_doctype_decl
    +                parser.ExternalEntityRefHandler = self.external_entity_ref_handler
    +
    +
    +        class DTDForbidden(ValueError):
    +            pass
    +
    +
    +        class ExternalReferenceForbidden(ValueError):
    +            pass
    +
    +        stream = pulldom.parse(StringIO(xml_str), DefusedExpatParser())
    +
    +        try:
    +            for event, node in stream:
    +                print event, node
    +        except DTDForbidden:
    +            pass
    +        else:
    +            raise Exception("should raise DTDForbidden")
    diff --git a/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py b/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py
    --- a/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py
    +++ b/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py
    @@ -510,6 +510,7 @@
             assert seen == ["yadda"]
     
         def test_warnings(self):
    +        py.test.skip("warnings are disabled")
             import warnings
             warnings.simplefilter("always")
             with warnings.catch_warnings(record=True) as w:
    diff --git a/pypy/module/test_lib_pypy/test_sqlite3.py b/pypy/module/test_lib_pypy/test_sqlite3.py
    --- a/pypy/module/test_lib_pypy/test_sqlite3.py
    +++ b/pypy/module/test_lib_pypy/test_sqlite3.py
    @@ -1,16 +1,16 @@
     """Tests for _sqlite3.py"""
     
    -import sys
    -if sys.version_info < (2, 7):
    -    skip("lib_pypy._sqlite3 doesn't work with python < 2.7")
    -
     import pytest
     from lib_pypy import _sqlite3
     
    -def test_list_ddl():
    +def pytest_funcarg__con(request):
    +    con = _sqlite3.connect(':memory:')
    +    request.addfinalizer(lambda: con.close())
    +    return con
    +
    +def test_list_ddl(con):
         """From issue996.  Mostly just looking for lack of exceptions."""
    -    connection = _sqlite3.connect(':memory:')
    -    cursor = connection.cursor()
    +    cursor = con.cursor()
         cursor.execute('CREATE TABLE foo (bar INTEGER)')
         result = list(cursor)
         assert result == []
    @@ -21,8 +21,7 @@
         result = list(cursor)
         assert result == [(42,)]
     
    -def test_total_changes_after_close():
    -    con = _sqlite3.connect(':memory:')
    +def test_total_changes_after_close(con):
         con.close()
         pytest.raises(_sqlite3.ProgrammingError, "con.total_changes")
     
    @@ -35,25 +34,22 @@
         e = pytest.raises(_sqlite3.ProgrammingError, "con.cursor()")
         assert '__init__' in e.value.message
     
    -def test_cursor_check_init():
    +def test_cursor_check_init(con):
         class Cursor(_sqlite3.Cursor):
             def __init__(self, name):
                 pass
     
    -    con = _sqlite3.connect(":memory:")
         cur = Cursor(con)
         e = pytest.raises(_sqlite3.ProgrammingError, "cur.execute('select 1')")
         assert '__init__' in e.value.message
     
    -def test_connection_after_close():
    -    con = _sqlite3.connect(':memory:')
    +def test_connection_after_close(con):
         pytest.raises(TypeError, "con()")
         con.close()
         # raises ProgrammingError because should check closed before check args
         pytest.raises(_sqlite3.ProgrammingError, "con()")
     
    -def test_cursor_iter():
    -    con = _sqlite3.connect(':memory:')
    +def test_cursor_iter(con):
         cur = con.cursor()
         with pytest.raises(StopIteration):
             next(cur)
    @@ -85,8 +81,7 @@
         with pytest.raises(StopIteration):
             next(cur)
     
    -def test_cursor_after_close():
    -     con = _sqlite3.connect(':memory:')
    +def test_cursor_after_close(con):
          cur = con.execute('select 1')
          cur.close()
          con.close()
    @@ -131,11 +126,10 @@
         finally:
             resource.setrlimit(resource.RLIMIT_NOFILE, limit)
     
    -def test_on_conflict_rollback_executemany():
    +def test_on_conflict_rollback_executemany(con):
         major, minor, micro = _sqlite3.sqlite_version.split('.')
         if (int(major), int(minor), int(micro)) < (3, 2, 2):
             pytest.skip("requires sqlite3 version >= 3.2.2")
    -    con = _sqlite3.connect(":memory:")
         con.execute("create table foo(x, unique(x) on conflict rollback)")
         con.execute("insert into foo(x) values (1)")
         try:
    @@ -147,10 +141,8 @@
             con.commit()
         except _sqlite3.OperationalError:
             pytest.fail("_sqlite3 knew nothing about the implicit ROLLBACK")
    -    con.close()
     
    -def test_statement_arg_checking():
    -    con = _sqlite3.connect(':memory:')
    +def test_statement_arg_checking(con):
         with pytest.raises(_sqlite3.Warning) as e:
             con(123)
         assert str(e.value) == 'SQL is of wrong type. Must be string or unicode.'
    @@ -164,8 +156,7 @@
             con.executescript(123)
         assert str(e.value) == 'script argument must be unicode or string.'
     
    -def test_statement_param_checking():
    -    con = _sqlite3.connect(':memory:')
    +def test_statement_param_checking(con):
         con.execute('create table foo(x)')
         con.execute('insert into foo(x) values (?)', [2])
         con.execute('insert into foo(x) values (?)', (2,))
    @@ -183,10 +174,8 @@
         with pytest.raises(ValueError) as e:
             con.execute('insert into foo(x) values (?)', 2)
         assert str(e.value) == 'parameters are of unsupported type'
    -    con.close()
     
    -def test_explicit_begin():
    -    con = _sqlite3.connect(':memory:')
    +def test_explicit_begin(con):
         con.execute('BEGIN')
         con.execute('BEGIN ')
         con.execute('BEGIN')
    @@ -194,25 +183,32 @@
         con.execute('BEGIN')
         con.commit()
     
    -def test_row_factory_use():
    -    con = _sqlite3.connect(':memory:')
    +def test_row_factory_use(con):
         con.row_factory = 42
         con.execute('select 1')
     
    -def test_returning_blob_must_own_memory():
    +def test_returning_blob_must_own_memory(con):
         import gc
    -    con = _sqlite3.connect(":memory:")
         con.create_function("returnblob", 0, lambda: buffer("blob"))
    -    cur = con.cursor()
    -    cur.execute("select returnblob()")
    +    cur = con.execute("select returnblob()")
         val = cur.fetchone()[0]
         for i in range(5):
             gc.collect()
             got = (val[0], val[1], val[2], val[3])
             assert got == ('b', 'l', 'o', 'b')
    +    # in theory 'val' should be a read-write buffer
    +    # but it's not right now
    +    pytest.skip("in theory 'val' should be a read-write buffer")
    +    val[1] = 'X'
    +    assert got == ('b', 'X', 'o', 'b')
     
    -def test_description_after_fetchall():
    -    con = _sqlite3.connect(":memory:")
    +def test_description_after_fetchall(con):
         cur = con.cursor()
         cur.execute("select 42").fetchall()
         assert cur.description is not None
    +
    +def test_executemany_lastrowid(con):
    +    cur = con.cursor()
    +    cur.execute("create table test(a)")
    +    cur.executemany("insert into test values (?)", [[1], [2], [3]])
    +    assert cur.lastrowid is None
    diff --git a/pypy/tool/release/package.py b/pypy/tool/release/package.py
    --- a/pypy/tool/release/package.py
    +++ b/pypy/tool/release/package.py
    @@ -67,7 +67,8 @@
                     'Bogus path: %r does not exist (see docstring for more info)'
                     % (os.path.dirname(str(pypy_c)),))
         subprocess.check_call([str(pypy_c), '-c', 'import _sqlite3'])
    -    subprocess.check_call([str(pypy_c), '-c', 'import _curses'])
    +    if not sys.platform == 'win32':
    +        subprocess.check_call([str(pypy_c), '-c', 'import _curses'])
         if sys.platform == 'win32' and not rename_pypy_c.lower().endswith('.exe'):
             rename_pypy_c += '.exe'
         binaries = [(pypy_c, rename_pypy_c)]
    diff --git a/pypy/tool/release/test/test_package.py b/pypy/tool/release/test/test_package.py
    --- a/pypy/tool/release/test/test_package.py
    +++ b/pypy/tool/release/test/test_package.py
    @@ -17,7 +17,7 @@
             exe_name_in_archive = 'bin/pypy'
         pypy_c = py.path.local(pypydir).join('goal', basename)
         if not pypy_c.check():
    -        os.system("echo faked_pypy_c> %s" % (pypy_c,))
    +        pypy_c.write("#!/bin/sh")
             pypy_c.chmod(0755)
             fake_pypy_c = True
         else:
    diff --git a/pypy/tool/test/test_tab.py b/pypy/tool/test/test_tab.py
    --- a/pypy/tool/test/test_tab.py
    +++ b/pypy/tool/test/test_tab.py
    @@ -5,7 +5,7 @@
     import os
     from pypy.conftest import pypydir
     
    -ROOT = pypydir
    +ROOT = os.path.abspath(os.path.join(pypydir, '..'))
     EXCLUDE = {}
     
     
    diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py
    --- a/rpython/jit/backend/arm/assembler.py
    +++ b/rpython/jit/backend/arm/assembler.py
    @@ -305,7 +305,7 @@
                 self._restore_exception(mc, exc0, exc1)
                 mc.VPOP([vfpr.value for vfpr in r.caller_vfp_resp])
                 assert exc0 is not None
    -	    assert exc1 is not None
    +            assert exc1 is not None
                 mc.POP([gpr.value for gpr in r.caller_resp] +
                                 [exc0.value, exc1.value])
             #
    @@ -526,9 +526,7 @@
                 self.gen_shadowstack_header(gcrootmap)
     
         def gen_shadowstack_header(self, gcrootmap):
    -        # we need to put two words into the shadowstack: the MARKER_FRAME
    -        # and the address of the frame (fp, actually)
    -        # lr = rst addr
    +        # lr = shadow stack top addr
             # ip = *lr
             rst = gcrootmap.get_root_stack_top_addr()
             self.mc.gen_load_int(r.lr.value, rst)
    @@ -1062,8 +1060,7 @@
                 self.mc.PUSH([helper.value], cond=cond)
             self.load_reg(self.mc, loc, r.fp, offset, cond=cond, helper=helper)
             if save_helper:
    -	    self.mc.POP([helper.value], cond=cond)
    -
    +            self.mc.POP([helper.value], cond=cond)
     
         def _mov_imm_float_to_loc(self, prev_loc, loc, cond=c.AL):
             if loc.is_vfp_reg():
    diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py
    --- a/rpython/jit/backend/arm/opassembler.py
    +++ b/rpython/jit/backend/arm/opassembler.py
    @@ -628,12 +628,14 @@
                                         bool(self._regalloc.vfprm.reg_bindings))
                 assert self.wb_slowpath[helper_num] != 0
             #
    -        if not is_frame and loc_base is not r.r0:
    +        if loc_base is not r.r0:
                 # push two registers to keep stack aligned
                 mc.PUSH([r.r0.value, loc_base.value])
    -            remap_frame_layout(self, [loc_base], [r.r0], r.ip)
    +            mc.MOV_rr(r.r0.value, loc_base.value)
    +            if is_frame:
    +                assert loc_base is r.fp
             mc.BL(self.wb_slowpath[helper_num])
    -        if not is_frame and loc_base is not r.r0:
    +        if loc_base is not r.r0:
                 mc.POP([r.r0.value, loc_base.value])
     
             if card_marking:
    diff --git a/rpython/jit/backend/arm/runner.py b/rpython/jit/backend/arm/runner.py
    --- a/rpython/jit/backend/arm/runner.py
    +++ b/rpython/jit/backend/arm/runner.py
    @@ -120,7 +120,7 @@
         """ARM v7 uses hardfp ABI, requires vfp"""
         hf_abi = True
         backend_name = "armv7hf"
    -    supports_floats = False
    +    supports_floats = True
         supports_singlefloats = False
     
     
    @@ -129,5 +129,5 @@
         hf_abi = True
         arch_version = 6
         backend_name = "armv6hf"
    -    supports_floats = False
    +    supports_floats = True
         supports_singlefloats = False
    diff --git a/rpython/jit/backend/arm/test/test_calling_convention.py b/rpython/jit/backend/arm/test/test_calling_convention.py
    --- a/rpython/jit/backend/arm/test/test_calling_convention.py
    +++ b/rpython/jit/backend/arm/test/test_calling_convention.py
    @@ -72,7 +72,7 @@
             callargs = []
             def func(f0, f1, f2, f3, f4, f5, f6, i0, f7, i1, f8, f9):
                 callargs.append(zip(range(12),
    -			[f0, f1, f2, f3, f4, f5, f6, i0, f7, i1, f8, f9]))
    +                        [f0, f1, f2, f3, f4, f5, f6, i0, f7, i1, f8, f9]))
                 return f0 + f1 + f2 + f3 + f4 + f5 + f6 + float(i0 + i1) + f7 + f8 + f9
             F = lltype.Float
             I = lltype.Signed
    @@ -103,7 +103,7 @@
             callargs = []
             def func(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9):
                 callargs.append(zip(range(10),
    -			[f0, f1, f2, f3, f4, f5, f6, f7, f8, f9]))
    +                        [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9]))
                 return f0 + f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8 + f9
             F = lltype.Float
             FUNC = self.FuncType([F] * 10, F)
    @@ -125,7 +125,7 @@
             callargs = []
             def func(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9):
                 callargs.append(zip(range(10),
    -			[f0, f1, f2, f3, f4, f5, f6, f7, f8, f9]))
    +                        [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9]))
                 return f0 + f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8 + f9
     
             I = lltype.Signed
    diff --git a/rpython/jit/backend/llsupport/test/test_gc_integration.py b/rpython/jit/backend/llsupport/test/test_gc_integration.py
    --- a/rpython/jit/backend/llsupport/test/test_gc_integration.py
    +++ b/rpython/jit/backend/llsupport/test/test_gc_integration.py
    @@ -256,7 +256,9 @@
                 if self.cpu.IS_64_BIT:
                     assert frame.jf_gcmap[idx] == (1<<29) | (1 << 30)
                 else:
    -                assert frame.jf_gcmap[idx] == (1<<24) | (1 << 23)
    +                assert frame.jf_gcmap[idx]
    +                exp_idx = self.cpu.JITFRAME_FIXED_SIZE - 32 * idx + 1 # +1 from i0
    +                assert frame.jf_gcmap[idx] == (1 << (exp_idx + 1)) | (1 << exp_idx)
     
             self.cpu = self.getcpu(check)
             ops = '''
    @@ -680,7 +682,7 @@
     
             def f(frame, x):
                 # all the gc pointers are alive p1 -> p7 (but not p0)
    -            assert bin(frame.jf_gcmap[0]).count('1') == 7
    +            assert getmap(frame).count('1') == 7 #
                 assert x == 1
                 return 2
             
    @@ -713,7 +715,7 @@
             def f(frame, arg, x):
                 assert not arg
                 assert frame.jf_gcmap[0] & 31 == 0
    -            assert bin(frame.jf_gcmap[0]).count('1') == 3 # p1, p2, p3, but
    +            assert getmap(frame).count('1') == 3 # p1, p2, p3, but
                 # not in registers
                 frame.jf_descr = frame.jf_force_descr # make guard_not_forced fail
                 assert x == 1
    @@ -749,7 +751,8 @@
             cpu.compile_loop(loop.inputargs, loop.operations, token)
             frame = lltype.cast_opaque_ptr(JITFRAMEPTR,
                                            cpu.execute_token(token, 1, a))
    -        assert bin(frame.jf_gcmap[0]).count('1') == 4
    +        
    +        assert getmap(frame).count('1') == 4
     
         def test_call_gcmap_no_guard(self):
             cpu = self.cpu
    @@ -757,7 +760,7 @@
             def f(frame, arg, x):
                 assert not arg
                 assert frame.jf_gcmap[0] & 31 == 0
    -            assert bin(frame.jf_gcmap[0]).count('1') == 3 # p1, p2, p3
    +            assert getmap(frame).count('1') == 3 # p1, p2, p3
                 frame.jf_descr = frame.jf_force_descr # make guard_not_forced fail
                 assert x == 1
                 return lltype.nullptr(llmemory.GCREF.TO)
    @@ -792,4 +795,5 @@
             cpu.compile_loop(loop.inputargs, loop.operations, token)
             frame = lltype.cast_opaque_ptr(JITFRAMEPTR,
                                            cpu.execute_token(token, 1, a))
    -        assert bin(frame.jf_gcmap[0]).count('1') == 4
    +        assert getmap(frame).count('1') == 4
    +
    diff --git a/rpython/jit/backend/test/calling_convention_test.py b/rpython/jit/backend/test/calling_convention_test.py
    --- a/rpython/jit/backend/test/calling_convention_test.py
    +++ b/rpython/jit/backend/test/calling_convention_test.py
    @@ -384,7 +384,7 @@
     
         def test_call_aligned_explicit_check(self):
             if (not platform.machine().startswith('arm') and
    -		sys.maxint == 2 ** 31 - 1): # XXX is still necessary on x86?
    +                sys.maxint == 2 ** 31 - 1): # XXX is still necessary on x86?
                 py.test.skip("libffi on 32bit is broken")
             cpu = self.cpu
             if not cpu.supports_floats:
    diff --git a/rpython/jit/backend/x86/runner.py b/rpython/jit/backend/x86/runner.py
    --- a/rpython/jit/backend/x86/runner.py
    +++ b/rpython/jit/backend/x86/runner.py
    @@ -58,10 +58,10 @@
             self.assembler = Assembler386(self, self.translate_support_code)
     
         def build_regalloc(self):
    -	''' for tests'''
    -	from rpython.jit.backend.x86.regalloc import RegAlloc
    -	assert self.assembler is not None
    -	return RegAlloc(self.assembler, False)
    +        ''' for tests'''
    +        from rpython.jit.backend.x86.regalloc import RegAlloc
    +        assert self.assembler is not None
    +        return RegAlloc(self.assembler, False)
     
         def setup_once(self):
             self.profile_agent.startup()
    diff --git a/rpython/jit/metainterp/optimizeopt/rewrite.py b/rpython/jit/metainterp/optimizeopt/rewrite.py
    --- a/rpython/jit/metainterp/optimizeopt/rewrite.py
    +++ b/rpython/jit/metainterp/optimizeopt/rewrite.py
    @@ -456,7 +456,7 @@
                                           [op.getarg(1),
                                            ConstInt(index + source_start)], resbox,
                                            descr=arraydescr)
    -                    self.optimizer.propagate_forward(newop)
    +                    self.optimizer.send_extra_operation(newop)
                         val = self.getvalue(resbox)
                     if dest_value.is_virtual():
                         dest_value.setitem(index + dest_start, val)
    diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
    --- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
    +++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
    @@ -4282,9 +4282,9 @@
             self.optimize_loop(ops, expected)
     
         def test_add_sub_ovf_second_operation_regular(self):
    -	py.test.skip("Smalltalk would like this to pass")
    -	# This situation occurs in Smalltalk because it uses 1-based indexing.
    -	# The below code is equivalent to a loop over an array.
    +        py.test.skip("Smalltalk would like this to pass")
    +        # This situation occurs in Smalltalk because it uses 1-based indexing.
    +        # The below code is equivalent to a loop over an array.
             ops = """
             [i1]
             i2 = int_sub(i1, 1)
    @@ -7609,6 +7609,25 @@
             """
             self.optimize_loop(ops, ops)
     
    +    def test_setarrayitem_followed_by_arraycopy_2(self):
    +        ops = """
    +        [i1, i2]
    +        p1 = new_array(i1, descr=arraydescr)
    +        setarrayitem_gc(p1, 0, i2, descr=arraydescr)
    +        p3 = new_array(5, descr=arraydescr)
    +        call(0, p1, p3, 0, 1, 1, descr=arraycopydescr)
    +        i4 = getarrayitem_gc(p3, 1, descr=arraydescr)
    +        jump(i1, i4)
    +        """
    +        expected = """
    +        [i1, i2]
    +        # operations are not all removed because this new_array() is var-sized
    +        p1 = new_array(i1, descr=arraydescr)
    +        setarrayitem_gc(p1, 0, i2, descr=arraydescr)
    +        jump(i1, i2)
    +        """
    +        self.optimize_loop(ops, expected)
    +
         def test_heap_cache_virtuals_forced_by_delayed_setfield(self):
             py.test.skip('not yet supoprted')
             ops = """
    
    From noreply at buildbot.pypy.org  Sat Apr  6 12:14:28 2013
    From: noreply at buildbot.pypy.org (bivab)
    Date: Sat,  6 Apr 2013 12:14:28 +0200 (CEST)
    Subject: [pypy-commit] buildbot default: kill the unused ppc64 builders for
    	now
    Message-ID: <20130406101428.8B2DA1C039A@cobra.cs.uni-duesseldorf.de>
    
    Author: David Schneider 
    Branch: 
    Changeset: r767:57bf5255cfdf
    Date: 2013-04-06 12:13 +0200
    http://bitbucket.org/pypy/buildbot/changeset/57bf5255cfdf/
    
    Log:	kill the unused ppc64 builders for now
    
    diff --git a/bot2/pypybuildbot/master.py b/bot2/pypybuildbot/master.py
    --- a/bot2/pypybuildbot/master.py
    +++ b/bot2/pypybuildbot/master.py
    @@ -75,13 +75,6 @@
                                                                 app_tests=False,
                                                                 platform='linux64')
     
    -
    -pypyTranslatedAppLevelTestFactoryPPC64 = pypybuilds.Translated(
    -        lib_python=True,
    -        app_tests=True,
    -        platform='linux-ppc64',
    -        interpreter='python')
    -
     pypyTranslatedAppLevelTestFactoryWin = pypybuilds.Translated(
         platform="win32",
         lib_python=True,
    @@ -108,16 +101,6 @@
         platform='linux64',
         )
     
    -pypyJITTranslatedTestFactoryPPC64 = pypybuilds.Translated(
    -    translationArgs=jit_translation_args,
    -    targetArgs=[],
    -    lib_python=True,
    -    pypyjit=True,
    -    app_tests=True,
    -    platform='linux-ppc64',
    -    interpreter='python',
    -    )
    -
     pypyJITTranslatedTestFactoryIndiana = pypybuilds.Translated(
         translationArgs=jit_translation_args,
         targetArgs=[],
    @@ -229,7 +212,6 @@
     
     LINUX32 = "own-linux-x86-32"
     LINUX64 = "own-linux-x86-64"
    -LINUXPPC64 = "own-linux-ppc-64"
     INDIANA32 = "own-indiana-x86-32"
     
     MACOSX32 = "own-macosx-x86-32"
    @@ -238,7 +220,6 @@
     APPLVLLINUX32 = "pypy-c-app-level-linux-x86-32"
     APPLVLLINUX64 = "pypy-c-app-level-linux-x86-64"
     APPLVLLINUXARM = "pypy-c-app-level-linux-armel"
    -APPLVLLINUXPPC64 = "pypy-c-app-level-linux-ppc-64"
     APPLVLWIN32 = "pypy-c-app-level-win-x86-32"
     
     LIBPYTHON_LINUX32 = "pypy-c-lib-python-linux-x86-32"
    @@ -247,7 +228,6 @@
     JITLINUX32 = "pypy-c-jit-linux-x86-32"
     JITLINUX64 = "pypy-c-jit-linux-x86-64"
     JITLINUXARM = "pypy-c-jit-linux-armel"
    -JITLINUXPPC64 = "pypy-c-jit-linux-ppc-64"
     JITMACOSX64 = "pypy-c-jit-macosx-x86-64"
     JITWIN32 = "pypy-c-jit-win-x86-32"
     JITWIN64 = "pypy-c-jit-win-x86-64"
    @@ -474,30 +454,12 @@
                        "category": 'freebsd64'
                        },
                       # PPC
    -                  {"name": LINUXPPC64,
    -                   "slavenames": ["gcc1"],
    -                   "builddir": LINUXPPC64,
    -                   "factory": pypyOwnTestFactory,
    -                   "category": 'linux-ppc64',
    -                   },
                       {"name": JITONLYLINUXPPC64,
                        "slavenames": ['gcc1'],
                        "builddir": JITONLYLINUXPPC64,
                        "factory": pypyJitOnlyOwnTestFactory,
                        "category": 'linux-ppc64',
                        },
    -                  {"name": APPLVLLINUXPPC64,
    -                   "slavenames": ["gcc1"],
    -                   "builddir": APPLVLLINUXPPC64,
    -                   "factory": pypyTranslatedAppLevelTestFactoryPPC64,
    -                   "category": "linux-ppc64",
    -                   },
    -                  {'name': JITLINUXPPC64,
    -                   'slavenames': ['gcc1'],
    -                   'builddir': JITLINUXPPC64,
    -                   'factory': pypyJITTranslatedTestFactoryPPC64,
    -                   'category': 'linux-ppc64',
    -                   },
                       # openindiana
                       {'name': JITINDIANA32,
                        'slavenames': ['jcea-openindiana-32'],
    
    From noreply at buildbot.pypy.org  Sat Apr  6 12:14:27 2013
    From: noreply at buildbot.pypy.org (bivab)
    Date: Sat,  6 Apr 2013 12:14:27 +0200 (CEST)
    Subject: [pypy-commit] buildbot default: kill the ARM xdist based builder
    Message-ID: <20130406101427.8A74E1C0337@cobra.cs.uni-duesseldorf.de>
    
    Author: David Schneider 
    Branch: 
    Changeset: r766:f83a18b2639d
    Date: 2013-04-06 12:12 +0200
    http://bitbucket.org/pypy/buildbot/changeset/f83a18b2639d/
    
    Log:	kill the ARM xdist based builder
    
    diff --git a/bot2/pypybuildbot/builds.py b/bot2/pypybuildbot/builds.py
    --- a/bot2/pypybuildbot/builds.py
    +++ b/bot2/pypybuildbot/builds.py
    @@ -26,9 +26,6 @@
     ARMCrossLock = locks.SlaveLock('arm_cpu', maxCount=2)
     # while the boards can only run one job at the same time
     ARMBoardLock = locks.SlaveLock('arm_boards', maxCount=1)
    -# and the builder using xdist uses both boards and needs exclusive access to this lock
    -ARMXdistLock = locks.MasterLock('arm_xdist', maxCount=2)
    -
     
     
     # XXX monkey patch Trigger class, there are to issues with the list of renderables
    diff --git a/bot2/pypybuildbot/master.py b/bot2/pypybuildbot/master.py
    --- a/bot2/pypybuildbot/master.py
    +++ b/bot2/pypybuildbot/master.py
    @@ -51,7 +51,6 @@
     #WinLockCPU = pypybuilds.WinLockCPU
     ARMCrossLock = pypybuilds.ARMCrossLock
     ARMBoardLock = pypybuilds.ARMBoardLock
    -ARMXdistLock = pypybuilds.ARMXdistLock
     
     pypyOwnTestFactory = pypybuilds.Own()
     pypyOwnTestFactoryWin = pypybuilds.Own(platform="win32")
    @@ -257,7 +256,6 @@
     JITINDIANA32 = "pypy-c-jit-indiana-x86-32"
     
     JITBACKENDONLYLINUXARMEL = "jitbackendonly-own-linux-armel"
    -JITBACKENDONLYLINUXARMELXDIST = "jitbackendonly-own-linux-armel-xdist"
     JITONLYLINUXPPC64 = "jitonly-own-linux-ppc-64"
     JITBENCH = "jit-benchmark-linux-x86-32"
     JITBENCH64 = "jit-benchmark-linux-x86-64"
    @@ -515,19 +513,13 @@
                        },
                       # ARM
                       # armel
    -                  {"name": JITBACKENDONLYLINUXARMELXDIST,
    -                   "slavenames": ['hhu-arm'],
    -                   "builddir": JITBACKENDONLYLINUXARMELXDIST ,
    -                   "factory": pypyJitBackendOnlyOwnTestFactoryARM,
    -                   "category": 'linux-armel',
    -                   "locks": [ARMXdistLock.access('exclusive'), ARMBoardLock.access('counting')],
    -                   },
                       {"name": JITBACKENDONLYLINUXARMEL,
                        "slavenames": ['hhu-i.mx53'],
                        "builddir": JITBACKENDONLYLINUXARMEL,
                        "factory": pypyJitBackendOnlyOwnTestFactoryARM,
                        "category": 'linux-armel',
    -                   "locks": [ARMXdistLock.access('counting'), ARMBoardLock.access('counting')],
    +                   "locks": [ARMBoardLock.access('counting')],
    +                   },
                        },
                       # app level builders
                       {"name": APPLVLLINUXARM,
    @@ -535,14 +527,14 @@
                        "builddir": APPLVLLINUXARM,
                        "factory": pypyARMTranslatedAppLevelTestFactory,
                        "category": "linux-armel",
    -                   "locks": [ARMXdistLock.access('counting'), ARMBoardLock.access('counting')],
    +                   "locks": [ARMBoardLock.access('counting')],
                        },
                       {"name": JITLINUXARM,
                        "slavenames": ["hhu-beagleboard"],
                        'builddir': JITLINUXARM,
                        'factory': pypyARMJITTranslatedTestFactory ,
                        'category': 'linux-armel',
    -                   "locks": [ARMXdistLock.access('counting'), ARMBoardLock.access('counting')],
    +                   "locks": [ARMBoardLock.access('counting')],
                        },
                       # Translation Builders for ARM
                       {"name": BUILDLINUXARM,
    
    From noreply at buildbot.pypy.org  Sat Apr  6 12:14:29 2013
    From: noreply at buildbot.pypy.org (bivab)
    Date: Sat,  6 Apr 2013 12:14:29 +0200 (CEST)
    Subject: [pypy-commit] buildbot default: add an ARMHF builder to run backend
    	tests
    Message-ID: <20130406101429.8C76F1C0337@cobra.cs.uni-duesseldorf.de>
    
    Author: David Schneider 
    Branch: 
    Changeset: r768:7ee98683dcf0
    Date: 2013-04-06 12:13 +0200
    http://bitbucket.org/pypy/buildbot/changeset/7ee98683dcf0/
    
    Log:	add an ARMHF builder to run backend tests
    
    diff --git a/bot2/pypybuildbot/master.py b/bot2/pypybuildbot/master.py
    --- a/bot2/pypybuildbot/master.py
    +++ b/bot2/pypybuildbot/master.py
    @@ -236,6 +236,7 @@
     JITINDIANA32 = "pypy-c-jit-indiana-x86-32"
     
     JITBACKENDONLYLINUXARMEL = "jitbackendonly-own-linux-armel"
    +JITBACKENDONLYLINUXARMHF = "jitbackendonly-own-linux-armhf"
     JITONLYLINUXPPC64 = "jitonly-own-linux-ppc-64"
     JITBENCH = "jit-benchmark-linux-x86-32"
     JITBENCH64 = "jit-benchmark-linux-x86-64"
    @@ -293,15 +294,16 @@
             Nightly("nighly-arm-0-00", [
                 BUILDLINUXARM,                 # on hhu-cross-armel, uses 1 core
                 BUILDJITLINUXARM,              # on hhu-cross-armel, uses 1 core
    -            JITBACKENDONLYLINUXARMEL,      # on hhu-beagleboard or hhu-imx.53
    +            JITBACKENDONLYLINUXARMEL,      # on hhu-imx.53
    +            JITBACKENDONLYLINUXARMHF,      # on hhu-raspberry-pi
                 ], branch=None, hour=0, minute=0),
     
             Triggerable("APPLVLLINUXARM_scheduler", [
    -            APPLVLLINUXARM,            # triggered by BUILDLINUXARM, on hhu-beagleboard or hhu-imx.53
    +            APPLVLLINUXARM,            # triggered by BUILDLINUXARM, on hhu-beagleboard
             ]),
     
             Triggerable("JITLINUXARM_scheduler", [
    -            JITLINUXARM,               # triggered by BUILDJITLINUXARM, on hhu-beagleboard or hhu-imx.53
    +            JITLINUXARM,               # triggered by BUILDJITLINUXARM, on hhu-beagleboard
             ]),
         ],
     
    @@ -482,6 +484,13 @@
                        "category": 'linux-armel',
                        "locks": [ARMBoardLock.access('counting')],
                        },
    +                  # armhf
    +                  {"name": JITBACKENDONLYLINUXARMHF,
    +                   "slavenames": ['hhu-raspberry-pi'],
    +                   "builddir": JITBACKENDONLYLINUXARMHF,
    +                   "factory": pypyJitBackendOnlyOwnTestFactoryARM,
    +                   "category": 'linux-armhf',
    +                   "locks": [ARMBoardLock.access('counting')],
                        },
                       # app level builders
                       {"name": APPLVLLINUXARM,
    
    From noreply at buildbot.pypy.org  Sat Apr  6 12:15:14 2013
    From: noreply at buildbot.pypy.org (arigo)
    Date: Sat,  6 Apr 2013 12:15:14 +0200 (CEST)
    Subject: [pypy-commit] pypy default: Remove MANGLE_LEN,
     the artificial limit which was removed from CPython
    Message-ID: <20130406101514.CC7CA1C0337@cobra.cs.uni-duesseldorf.de>
    
    Author: Armin Rigo 
    Branch: 
    Changeset: r63100:daab686f929a
    Date: 2013-04-06 12:14 +0200
    http://bitbucket.org/pypy/pypy/changeset/daab686f929a/
    
    Log:	Remove MANGLE_LEN, the artificial limit which was removed from
    	CPython at least as early as 2.5. Add tests and avoid code
    	duplication.
    
    diff --git a/pypy/interpreter/astcompiler/misc.py b/pypy/interpreter/astcompiler/misc.py
    --- a/pypy/interpreter/astcompiler/misc.py
    +++ b/pypy/interpreter/astcompiler/misc.py
    @@ -1,5 +1,4 @@
     from pypy.interpreter import gateway
    -from pypy.interpreter.astcompiler import ast
     from rpython.rlib.objectmodel import we_are_translated
     from rpython.rlib.unroll import unrolling_iterable
     
    @@ -28,6 +27,7 @@
     
     
     def parse_future(tree, feature_flags):
    +    from pypy.interpreter.astcompiler import ast
         future_lineno = 0
         future_column = 0
         flags = 0
    @@ -91,13 +91,9 @@
         return lookup
     
     
    -MANGLE_LEN = 256 # magic constant from compile.c
    -
     def mangle(name, klass):
         if not name.startswith('__'):
             return name
    -    if len(name) + 2 >= MANGLE_LEN:
    -        return name
         # Don't mangle __id__ or names with dots. The only time a name with a dot
         # can occur is when we are compiling an import statement that has a package
         # name.
    @@ -109,14 +105,4 @@
                 i = i + 1
         except IndexError:
             return name
    -    klass = klass[i:]
    -
    -    tlen = len(klass) + len(name)
    -    if tlen > MANGLE_LEN:
    -        end = len(klass) + MANGLE_LEN-tlen
    -        if end < 0:
    -            klass = ''     # slices of negative length are invalid in RPython
    -        else:
    -            klass = klass[:end]
    -
    -    return "_%s%s" % (klass, name)
    +    return "_%s%s" % (klass[i:], name)
    diff --git a/pypy/interpreter/astcompiler/test/test_misc.py b/pypy/interpreter/astcompiler/test/test_misc.py
    new file mode 100644
    --- /dev/null
    +++ b/pypy/interpreter/astcompiler/test/test_misc.py
    @@ -0,0 +1,14 @@
    +from pypy.interpreter.astcompiler.misc import mangle
    +
    +def test_mangle():
    +    assert mangle("foo", "Bar") == "foo"
    +    assert mangle("__foo__", "Bar") == "__foo__"
    +    assert mangle("foo.baz", "Bar") == "foo.baz"
    +    assert mangle("__", "Bar") == "__"
    +    assert mangle("___", "Bar") == "___"
    +    assert mangle("____", "Bar") == "____"
    +    assert mangle("__foo", "Bar") == "_Bar__foo"
    +    assert mangle("__foo", "_Bar") == "_Bar__foo"
    +    assert mangle("__foo", "__Bar") == "_Bar__foo"
    +    assert mangle("__foo", "___") == "__foo"
    +    assert mangle("___foo", "__Bar") == "_Bar___foo"
    diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py
    --- a/pypy/objspace/std/typeobject.py
    +++ b/pypy/objspace/std/typeobject.py
    @@ -4,6 +4,7 @@
     from pypy.interpreter.function import Function, StaticMethod
     from pypy.interpreter.typedef import weakref_descr, GetSetProperty,\
          descr_get_dict
    +from pypy.interpreter.astcompiler.misc import mangle
     from pypy.objspace.std.model import W_Object
     from pypy.objspace.std.register_all import register_all
     from pypy.objspace.std.stdtypedef import std_dict_descr, issubtypedef, Member
    @@ -26,34 +27,6 @@
             return w_value.w_value
         return w_value
     
    -# from compiler/misc.py
    -
    -MANGLE_LEN = 256 # magic constant from compile.c
    -
    -def _mangle(name, klass):
    -    if not name.startswith('__'):
    -        return name
    -    if len(name) + 2 >= MANGLE_LEN:
    -        return name
    -    if name.endswith('__'):
    -        return name
    -    try:
    -        i = 0
    -        while klass[i] == '_':
    -            i = i + 1
    -    except IndexError:
    -        return name
    -    klass = klass[i:]
    -
    -    tlen = len(klass) + len(name)
    -    if tlen > MANGLE_LEN:
    -        end = len(klass) + MANGLE_LEN-tlen
    -        if end < 0:
    -            klass = ''     # annotator hint
    -        else:
    -            klass = klass[:end]
    -
    -    return "_%s%s" % (klass, name)
     
     class VersionTag(object):
         pass
    @@ -987,7 +960,7 @@
             raise OperationError(space.w_TypeError,
                                  space.wrap('__slots__ must be identifiers'))
         # create member
    -    slot_name = _mangle(slot_name, w_self.name)
    +    slot_name = mangle(slot_name, w_self.name)
         if slot_name not in w_self.dict_w:
             # Force interning of slot names.
             slot_name = space.str_w(space.new_interned_str(slot_name))
    
    From noreply at buildbot.pypy.org  Sat Apr  6 12:36:58 2013
    From: noreply at buildbot.pypy.org (pjenvey)
    Date: Sat,  6 Apr 2013 12:36:58 +0200 (CEST)
    Subject: [pypy-commit] cffi default: py3 compat
    Message-ID: <20130406103658.EE2E41C3069@cobra.cs.uni-duesseldorf.de>
    
    Author: Philip Jenvey 
    Branch: 
    Changeset: r1240:95eb1111a1b0
    Date: 2013-04-05 11:57 -0700
    http://bitbucket.org/cffi/cffi/changeset/95eb1111a1b0/
    
    Log:	py3 compat
    
    diff --git a/testing/test_verify.py b/testing/test_verify.py
    --- a/testing/test_verify.py
    +++ b/testing/test_verify.py
    @@ -7,7 +7,7 @@
     if sys.platform == 'win32':
         pass      # no obvious -Werror equivalent on MSVC
     elif (sys.platform == 'darwin' and
    -      map(int, os.uname()[2].split('.')) >= [11, 0, 0]):
    +      [int(x) for x in os.uname()[2].split('.')] >= [11, 0, 0]):
         pass      # recent MacOSX come with clang by default, and passing some
                   # flags from the interpreter (-mno-fused-madd) generates a
                   # warning --- which is interpreted as an error with -Werror
    
    From noreply at buildbot.pypy.org  Sat Apr  6 12:37:00 2013
    From: noreply at buildbot.pypy.org (pjenvey)
    Date: Sat,  6 Apr 2013 12:37:00 +0200 (CEST)
    Subject: [pypy-commit] cffi default: fix handling w/ py3 hasattr,
     which only swallows AttributeErrors
    Message-ID: <20130406103700.0EF4D1C3069@cobra.cs.uni-duesseldorf.de>
    
    Author: Philip Jenvey 
    Branch: 
    Changeset: r1241:e2b9db908b90
    Date: 2013-04-05 12:01 -0700
    http://bitbucket.org/cffi/cffi/changeset/e2b9db908b90/
    
    Log:	fix handling w/ py3 hasattr, which only swallows AttributeErrors
    
    diff --git a/cffi/api.py b/cffi/api.py
    --- a/cffi/api.py
    +++ b/cffi/api.py
    @@ -370,7 +370,10 @@
             if key in ffi._parser._declarations:
                 tp = ffi._parser._declarations[key]
                 BType = ffi._get_cached_btype(tp)
    -            value = backendlib.load_function(BType, name)
    +            try:
    +                value = backendlib.load_function(BType, name)
    +            except KeyError:
    +                raise AttributeError(name)
                 library.__dict__[name] = value
                 return
             #
    diff --git a/testing/test_function.py b/testing/test_function.py
    --- a/testing/test_function.py
    +++ b/testing/test_function.py
    @@ -345,3 +345,11 @@
             assert lib.DD == 6
             assert lib.EE == -5
             assert lib.FF == -4
    +
    +    def test_missing_function(self):
    +        ffi = FFI(backend=self.Backend())
    +        ffi.cdef("""
    +            int nonexistent();
    +        """)
    +        m = ffi.dlopen("m")
    +        assert not hasattr(m, 'nonexistent')
    
    From noreply at buildbot.pypy.org  Sat Apr  6 12:37:01 2013
    From: noreply at buildbot.pypy.org (arigo)
    Date: Sat,  6 Apr 2013 12:37:01 +0200 (CEST)
    Subject: [pypy-commit] cffi default: Merged in pjenvey/cffi (pull request
    	#13)
    Message-ID: <20130406103701.1D09A1C3069@cobra.cs.uni-duesseldorf.de>
    
    Author: Armin Rigo 
    Branch: 
    Changeset: r1242:c2550687121c
    Date: 2013-04-06 12:35 +0200
    http://bitbucket.org/cffi/cffi/changeset/c2550687121c/
    
    Log:	Merged in pjenvey/cffi (pull request #13)
    
    diff --git a/cffi/api.py b/cffi/api.py
    --- a/cffi/api.py
    +++ b/cffi/api.py
    @@ -370,7 +370,10 @@
             if key in ffi._parser._declarations:
                 tp = ffi._parser._declarations[key]
                 BType = ffi._get_cached_btype(tp)
    -            value = backendlib.load_function(BType, name)
    +            try:
    +                value = backendlib.load_function(BType, name)
    +            except KeyError:
    +                raise AttributeError(name)
                 library.__dict__[name] = value
                 return
             #
    diff --git a/testing/test_function.py b/testing/test_function.py
    --- a/testing/test_function.py
    +++ b/testing/test_function.py
    @@ -370,3 +370,11 @@
             lib = ffi.dlopen(None)
             res = lib.strlen(b"hello")
             assert res == 5
    +
    +    def test_missing_function(self):
    +        ffi = FFI(backend=self.Backend())
    +        ffi.cdef("""
    +            int nonexistent();
    +        """)
    +        m = ffi.dlopen("m")
    +        assert not hasattr(m, 'nonexistent')
    diff --git a/testing/test_verify.py b/testing/test_verify.py
    --- a/testing/test_verify.py
    +++ b/testing/test_verify.py
    @@ -7,7 +7,7 @@
     if sys.platform == 'win32':
         pass      # no obvious -Werror equivalent on MSVC
     elif (sys.platform == 'darwin' and
    -      map(int, os.uname()[2].split('.')) >= [11, 0, 0]):
    +      [int(x) for x in os.uname()[2].split('.')] >= [11, 0, 0]):
         pass      # recent MacOSX come with clang by default, and passing some
                   # flags from the interpreter (-mno-fused-madd) generates a
                   # warning --- which is interpreted as an error with -Werror
    
    From noreply at buildbot.pypy.org  Sat Apr  6 13:18:25 2013
    From: noreply at buildbot.pypy.org (arigo)
    Date: Sat,  6 Apr 2013 13:18:25 +0200 (CEST)
    Subject: [pypy-commit] pypy default: Skip this test if the underlying
     modules are not installed
    Message-ID: <20130406111825.2BB601C305F@cobra.cs.uni-duesseldorf.de>
    
    Author: Armin Rigo 
    Branch: 
    Changeset: r63101:d67f1882c9ed
    Date: 2013-04-06 13:18 +0200
    http://bitbucket.org/pypy/pypy/changeset/d67f1882c9ed/
    
    Log:	Skip this test if the underlying modules are not installed
    
    diff --git a/pypy/module/test_lib_pypy/test_sqlite3.py b/pypy/module/test_lib_pypy/test_sqlite3.py
    --- a/pypy/module/test_lib_pypy/test_sqlite3.py
    +++ b/pypy/module/test_lib_pypy/test_sqlite3.py
    @@ -1,6 +1,15 @@
     """Tests for _sqlite3.py"""
     
    -import pytest
    +import pytest, sys
    +
    +if sys.version_info < (2, 7):
    +    pytest.skip("_sqlite3 requires Python 2.7")
    +try:
    +    import _cffi_backend
    +except ImportError:
    +    # On CPython, "pip install cffi".  On old PyPy's, no chance
    +    pytest.skip("_sqlite3 requires _cffi_backend to be installed")
    +
     from lib_pypy import _sqlite3
     
     def pytest_funcarg__con(request):
    
    From noreply at buildbot.pypy.org  Sat Apr  6 14:26:43 2013
    From: noreply at buildbot.pypy.org (bivab)
    Date: Sat,  6 Apr 2013 14:26:43 +0200 (CEST)
    Subject: [pypy-commit] pypy default: merge heads
    Message-ID: <20130406122643.DFF4F1C039A@cobra.cs.uni-duesseldorf.de>
    
    Author: David Schneider 
    Branch: 
    Changeset: r63103:7d116d0b63bf
    Date: 2013-04-06 13:32 +0200
    http://bitbucket.org/pypy/pypy/changeset/7d116d0b63bf/
    
    Log:	merge heads
    
    diff --git a/pypy/module/test_lib_pypy/test_sqlite3.py b/pypy/module/test_lib_pypy/test_sqlite3.py
    --- a/pypy/module/test_lib_pypy/test_sqlite3.py
    +++ b/pypy/module/test_lib_pypy/test_sqlite3.py
    @@ -1,6 +1,15 @@
     """Tests for _sqlite3.py"""
     
    -import pytest
    +import pytest, sys
    +
    +if sys.version_info < (2, 7):
    +    pytest.skip("_sqlite3 requires Python 2.7")
    +try:
    +    import _cffi_backend
    +except ImportError:
    +    # On CPython, "pip install cffi".  On old PyPy's, no chance
    +    pytest.skip("_sqlite3 requires _cffi_backend to be installed")
    +
     from lib_pypy import _sqlite3
     
     def pytest_funcarg__con(request):
    
    From noreply at buildbot.pypy.org  Sat Apr  6 14:26:42 2013
    From: noreply at buildbot.pypy.org (bivab)
    Date: Sat,  6 Apr 2013 14:26:42 +0200 (CEST)
    Subject: [pypy-commit] pypy default: fix test_compile_asmlen on ARMv6 by
     introducing a * marker in checkops to skip checking instructions (for
     inline constants)
    Message-ID: <20130406122642.BE8151C0337@cobra.cs.uni-duesseldorf.de>
    
    Author: David Schneider 
    Branch: 
    Changeset: r63102:c6892e8a418f
    Date: 2013-04-06 13:30 +0200
    http://bitbucket.org/pypy/pypy/changeset/c6892e8a418f/
    
    Log:	fix test_compile_asmlen on ARMv6 by introducing a * marker in
    	checkops to skip checking instructions (for inline constants)
    
    diff --git a/rpython/jit/backend/arm/test/test_runner.py b/rpython/jit/backend/arm/test/test_runner.py
    --- a/rpython/jit/backend/arm/test/test_runner.py
    +++ b/rpython/jit/backend/arm/test/test_runner.py
    @@ -34,11 +34,11 @@
         else:
             bridge_loop_instructions = ['ldr', 'mov', 'nop', 'nop', 'nop', 'cmp', 'bge',
                                   'push', 'ldr', 'mov',
    -                              '', # inline constant
    +                              '*', # inline constant
                                   'push', 'ldr', 'mov',
    -                              'ldrsblt', #inline constant (decodes as instruction)
    +                              '*', # inline constant
                                   'blx', 'ldr', 'mov',
    -                              '', # inline constant
    +                              '*', # inline constant
                                   'bx']
     
         def get_cpu(self):
    diff --git a/rpython/jit/backend/test/runner_test.py b/rpython/jit/backend/test/runner_test.py
    --- a/rpython/jit/backend/test/runner_test.py
    +++ b/rpython/jit/backend/test/runner_test.py
    @@ -3475,6 +3475,8 @@
             def checkops(mc, ops):
                 assert len(mc) == len(ops)
                 for i in range(len(mc)):
    +                if ops[i] == '*':
    +                    continue # ingore ops marked as '*', i.e. inline constants
                     assert mc[i].split("\t")[2].startswith(ops[i])
     
             data = ctypes.string_at(info.asmaddr, info.asmlen)
    
    From noreply at buildbot.pypy.org  Sat Apr  6 17:59:18 2013
    From: noreply at buildbot.pypy.org (bivab)
    Date: Sat,  6 Apr 2013 17:59:18 +0200 (CEST)
    Subject: [pypy-commit] buildbot default: add a prefix parameter to the
     crosstranslation builds to run the packaging in a chroot (needed for cffi)
    Message-ID: <20130406155918.84F871C00EF@cobra.cs.uni-duesseldorf.de>
    
    Author: David Schneider 
    Branch: 
    Changeset: r769:767583db1da9
    Date: 2013-04-06 17:58 +0200
    http://bitbucket.org/pypy/buildbot/changeset/767583db1da9/
    
    Log:	add a prefix parameter to the crosstranslation builds to run the
    	packaging in a chroot (needed for cffi)
    
    diff --git a/bot2/pypybuildbot/master.py b/bot2/pypybuildbot/master.py
    --- a/bot2/pypybuildbot/master.py
    +++ b/bot2/pypybuildbot/master.py
    @@ -178,11 +178,12 @@
                                 ]),
             timeout=6 * 3600)
     pypyJitOnlyOwnTestFactoryARM = pypybuilds.Own(cherrypick="jit", timeout=2 * 3600)
    -pypyOwnTestFactoryARM = pypybuilds.Own(timeout=2*3600)
    +pypyOwnTestFactoryARM = pypybuilds.Own(timeout=2 * 3600)
     pypyCrossTranslationFactoryARM = pypybuilds.NightlyBuild(
    -    translationArgs=crosstranslationargs+['-O2'],
    +    translationArgs=crosstranslationargs + ['-O2'],
         platform='linux-armel',
         interpreter='pypy',
    +    prefix='schroot -c armel',
         trigger='APPLVLLINUXARM_scheduler')
     
     pypyJITCrossTranslationFactoryARM = pypybuilds.NightlyBuild(
    @@ -191,6 +192,7 @@
                             + crosstranslationjitargs),
         platform='linux-armel',
         interpreter='pypy',
    +    prefix='schroot -c armel',
         trigger='JITLINUXARM_scheduler')
     
     pypyARMJITTranslatedTestFactory = pypybuilds.TranslatedTests(
    
    From noreply at buildbot.pypy.org  Sat Apr  6 18:35:45 2013
    From: noreply at buildbot.pypy.org (arigo)
    Date: Sat,  6 Apr 2013 18:35:45 +0200 (CEST)
    Subject: [pypy-commit] pypy default: Fix the skipped part of the test (it
    	was bogus)
    Message-ID: <20130406163545.E40E91C0337@cobra.cs.uni-duesseldorf.de>
    
    Author: Armin Rigo 
    Branch: 
    Changeset: r63104:83bc72e8e482
    Date: 2013-04-06 18:35 +0200
    http://bitbucket.org/pypy/pypy/changeset/83bc72e8e482/
    
    Log:	Fix the skipped part of the test (it was bogus)
    
    diff --git a/pypy/module/test_lib_pypy/test_sqlite3.py b/pypy/module/test_lib_pypy/test_sqlite3.py
    --- a/pypy/module/test_lib_pypy/test_sqlite3.py
    +++ b/pypy/module/test_lib_pypy/test_sqlite3.py
    @@ -209,6 +209,7 @@
         # but it's not right now
         pytest.skip("in theory 'val' should be a read-write buffer")
         val[1] = 'X'
    +    got = (val[0], val[1], val[2], val[3])
         assert got == ('b', 'X', 'o', 'b')
     
     def test_description_after_fetchall(con):
    
    From noreply at buildbot.pypy.org  Sat Apr  6 21:19:50 2013
    From: noreply at buildbot.pypy.org (bivab)
    Date: Sat,  6 Apr 2013 21:19:50 +0200 (CEST)
    Subject: [pypy-commit] pypy default: update arm platform libffi configuration
    Message-ID: <20130406191951.025141C0337@cobra.cs.uni-duesseldorf.de>
    
    Author: David Schneider 
    Branch: 
    Changeset: r63105:8bfec0fa1e69
    Date: 2013-04-06 21:19 +0200
    http://bitbucket.org/pypy/pypy/changeset/8bfec0fa1e69/
    
    Log:	update arm platform libffi configuration
    
    diff --git a/rpython/jit/tl/tla/tla_assembler.py b/rpython/jit/tl/tla/tla_assembler.py
    --- a/rpython/jit/tl/tla/tla_assembler.py
    +++ b/rpython/jit/tl/tla/tla_assembler.py
    @@ -2,8 +2,8 @@
     
     import sys
     import py
    +from rpython.jit.tl.tla.test_tla import assemble
     py.path.local(__file__)
    -from rpython.jit.tl.tla.test_tla import assemble
     
     def usage():
         print >> sys.stderr, 'Usage: tla_assembler.py filename.tla.py'
    diff --git a/rpython/translator/platform/arm.py b/rpython/translator/platform/arm.py
    --- a/rpython/translator/platform/arm.py
    +++ b/rpython/translator/platform/arm.py
    @@ -47,11 +47,12 @@
             return ExecutionResult(returncode, stdout, stderr)
     
         def include_dirs_for_libffi(self):
    -        return [SB2 + '/usr/include/arm-linux-gnueabi/']
    +        return [SB2 + '/usr/include/arm-linux-gnueabi/',
    +		SB2 + '/usr/include/arm-linux-gnueabihf/']
     
         def library_dirs_for_libffi(self):
    -        # on the other hand, library lands in usual place...
    -        return []
    +        return [SB2 + '/usr/lib/arm-linux-gnueabi/',
    +		SB2 + '/usr/lib/arm-linux-gnueabihf/']
     
         def execute_makefile(self, path_to_makefile, extra_opts=[]):
             if isinstance(path_to_makefile, GnuMakefile):
    
    From noreply at buildbot.pypy.org  Sat Apr  6 23:59:58 2013
    From: noreply at buildbot.pypy.org (pjenvey)
    Date: Sat,  6 Apr 2013 23:59:58 +0200 (CEST)
    Subject: [pypy-commit] pypy default: fix the maximum recursion depth
     RuntimeErrors under 2.6: avoid
    Message-ID: <20130406215958.16AED1C00EF@cobra.cs.uni-duesseldorf.de>
    
    Author: Philip Jenvey 
    Branch: 
    Changeset: r63106:a271c0002bba
    Date: 2013-04-06 14:59 -0700
    http://bitbucket.org/pypy/pypy/changeset/a271c0002bba/
    
    Log:	fix the maximum recursion depth RuntimeErrors under 2.6: avoid
    	hasattr/__getattr__ crazyness on uninitialized FixedSizeArrays
    
    diff --git a/rpython/rtyper/lltypesystem/lltype.py b/rpython/rtyper/lltypesystem/lltype.py
    --- a/rpython/rtyper/lltypesystem/lltype.py
    +++ b/rpython/rtyper/lltypesystem/lltype.py
    @@ -503,7 +503,7 @@
             return obj
     
         def __init__(self, OF, length, **kwds):
    -        if hasattr(self, '_name'):
    +        if '_name' in self.__dict__:
                 assert self.OF == OF
                 assert self.length == length
                 return
    
    From noreply at buildbot.pypy.org  Sun Apr  7 00:36:17 2013
    From: noreply at buildbot.pypy.org (arigo)
    Date: Sun,  7 Apr 2013 00:36:17 +0200 (CEST)
    Subject: [pypy-commit] pypy stm-gc-2: Write down another TODO
    Message-ID: <20130406223617.A622A1C039A@cobra.cs.uni-duesseldorf.de>
    
    Author: Armin Rigo 
    Branch: stm-gc-2
    Changeset: r63107:53826e16ab29
    Date: 2013-04-06 22:14 +0200
    http://bitbucket.org/pypy/pypy/changeset/53826e16ab29/
    
    Log:	Write down another TODO
    
    diff --git a/TODO b/TODO
    --- a/TODO
    +++ b/TODO
    @@ -1,3 +1,8 @@
    +------------------------------------------------------------
    +
    +kill INEVITABLE in et.c, replace with "global_cur_time & 1" again
    +
    +------------------------------------------------------------
     
     RPyAssert(i < len(lst)): if lst is global this turns into tons of code
     
    
    From noreply at buildbot.pypy.org  Sun Apr  7 00:36:19 2013
    From: noreply at buildbot.pypy.org (arigo)
    Date: Sun,  7 Apr 2013 00:36:19 +0200 (CEST)
    Subject: [pypy-commit] pypy stm-gc-2: hg merge stm-thread-2
    Message-ID: <20130406223619.169971C039A@cobra.cs.uni-duesseldorf.de>
    
    Author: Armin Rigo 
    Branch: stm-gc-2
    Changeset: r63108:88c864764d5f
    Date: 2013-04-06 22:14 +0200
    http://bitbucket.org/pypy/pypy/changeset/88c864764d5f/
    
    Log:	hg merge stm-thread-2
    
    diff --git a/lib_pypy/pypy_test/test_transaction.py b/lib_pypy/pypy_test/test_transaction.py
    --- a/lib_pypy/pypy_test/test_transaction.py
    +++ b/lib_pypy/pypy_test/test_transaction.py
    @@ -76,6 +76,21 @@
             assert num_foos == 1, lsts
     
     
    +def test_number_of_transactions_reported():
    +    transaction.add(lambda: None)
    +    transaction.run()
    +    assert transaction.number_of_transactions_in_last_run() == 1
    +
    +    def add_transactions(l):
    +        if l:
    +            for x in range(l[0]):
    +                transaction.add(add_transactions, l[1:])
    +
    +    transaction.add(add_transactions, [10, 10, 10])
    +    transaction.run()
    +    assert transaction.number_of_transactions_in_last_run() == 1111
    +
    +
     def run_tests():
         for name in sorted(globals().keys()):
             if name.startswith('test_'):
    diff --git a/lib_pypy/transaction.py b/lib_pypy/transaction.py
    --- a/lib_pypy/transaction.py
    +++ b/lib_pypy/transaction.py
    @@ -96,6 +96,9 @@
             tpool.teardown()
         tpool.reraise()
     
    +def number_of_transactions_in_last_run():
    +    return _thread_pool.transactions_run
    +
     # ____________________________________________________________
     
     
    @@ -104,6 +107,7 @@
         def __init__(self):
             self.num_threads = 4    # XXX default value, tweak
             self.in_transaction = False
    +        self.transactions_run = None
     
         def setup(self):
             # a mutex to protect parts of _grab_next_thing_to_do()
    @@ -122,17 +126,20 @@
             _thread_local.pending = None
             #
             self.num_waiting_threads = 0
    +        self.transactions_run = 0
             self.finished = False
             self.got_exception = []
             self.in_transaction = True
     
         def run(self):
             # start the N threads
    -        for i in range(self.num_threads):
    -            thread.start_new_thread(self._run_thread, ())
    +        task_counters = [[0] for i in range(self.num_threads)]
    +        for counter in task_counters:
    +            thread.start_new_thread(self._run_thread, (counter,))
             # now wait.  When we manage to acquire the following lock, then
             # we are finished.
             self.lock_if_released_then_finished.acquire()
    +        self.transactions_run = sum(x[0] for x in task_counters)
     
         def teardown(self):
             self.in_transaction = False
    @@ -148,13 +155,14 @@
             if exc:
                 raise exc[0], exc[1], exc[2]    # exception, value, traceback
     
    -    def _run_thread(self):
    +    def _run_thread(self, counter):
             tloc_pending = _thread_local.pending
             got_exception = self.got_exception
             try:
                 while True:
                     self._do_it(self._grab_next_thing_to_do(tloc_pending),
                                 got_exception)
    +                counter[0] += 1
             except _Done:
                 pass
     
    @@ -249,7 +257,7 @@
         header = info[0]
         f = cStringIO.StringIO()
         if len(info) > 1:
    -        print >> f, 'Traceback from detected conflict:'
    +        print >> f, 'Detected conflict:'
             for tb in info[1:]:
                 filename = tb[0]
                 coname = tb[1]
    diff --git a/rpython/translator/stm/src_stm/et.h b/rpython/translator/stm/src_stm/et.h
    --- a/rpython/translator/stm/src_stm/et.h
    +++ b/rpython/translator/stm/src_stm/et.h
    @@ -93,7 +93,6 @@
     
     //gcptr Allocate(size_t size, int gctid);
     _Bool stm_PtrEq(gcptr P1, gcptr P2);
    -gcptr stm_HashObject(gcptr P);
     
     void *stm_DirectReadBarrier(void *);
     void *stm_DirectReadBarrierFromR(void *, void *, size_t);
    
    From noreply at buildbot.pypy.org  Sun Apr  7 00:36:20 2013
    From: noreply at buildbot.pypy.org (arigo)
    Date: Sun,  7 Apr 2013 00:36:20 +0200 (CEST)
    Subject: [pypy-commit] pypy default: untabbify
    Message-ID: <20130406223620.36E4C1C039A@cobra.cs.uni-duesseldorf.de>
    
    Author: Armin Rigo 
    Branch: 
    Changeset: r63109:1f0c75966429
    Date: 2013-04-07 00:35 +0200
    http://bitbucket.org/pypy/pypy/changeset/1f0c75966429/
    
    Log:	untabbify
    
    diff --git a/rpython/translator/platform/arm.py b/rpython/translator/platform/arm.py
    --- a/rpython/translator/platform/arm.py
    +++ b/rpython/translator/platform/arm.py
    @@ -48,11 +48,11 @@
     
         def include_dirs_for_libffi(self):
             return [SB2 + '/usr/include/arm-linux-gnueabi/',
    -		SB2 + '/usr/include/arm-linux-gnueabihf/']
    +                SB2 + '/usr/include/arm-linux-gnueabihf/']
     
         def library_dirs_for_libffi(self):
             return [SB2 + '/usr/lib/arm-linux-gnueabi/',
    -		SB2 + '/usr/lib/arm-linux-gnueabihf/']
    +                SB2 + '/usr/lib/arm-linux-gnueabihf/']
     
         def execute_makefile(self, path_to_makefile, extra_opts=[]):
             if isinstance(path_to_makefile, GnuMakefile):
    
    From noreply at buildbot.pypy.org  Sun Apr  7 07:44:26 2013
    From: noreply at buildbot.pypy.org (alex_gaynor)
    Date: Sun,  7 Apr 2013 07:44:26 +0200 (CEST)
    Subject: [pypy-commit] pypy default: Convert somethign to use a new-style
     class, as well as make catching an exception more precise.
    Message-ID: <20130407054426.3B4911C15A2@cobra.cs.uni-duesseldorf.de>
    
    Author: Alex Gaynor 
    Branch: 
    Changeset: r63110:a98535f8e486
    Date: 2013-04-06 22:42 -0700
    http://bitbucket.org/pypy/pypy/changeset/a98535f8e486/
    
    Log:	Convert somethign to use a new-style class, as well as make catching
    	an exception more precise.
    
    diff --git a/rpython/flowspace/framestate.py b/rpython/flowspace/framestate.py
    --- a/rpython/flowspace/framestate.py
    +++ b/rpython/flowspace/framestate.py
    @@ -2,7 +2,7 @@
     from rpython.rlib.unroll import SpecTag
     
     
    -class FrameState:
    +class FrameState(object):
         def __init__(self, mergeable, blocklist, next_instr):
             self.mergeable = mergeable
             self.blocklist = blocklist
    @@ -63,6 +63,7 @@
     class UnionError(Exception):
         "The two states should be merged."
     
    +
     def union(w1, w2):
         "Union of two variables or constants."
         if w1 is None or w2 is None:
    @@ -117,7 +118,7 @@
                 key = unroller.__class__, len(vars)
                 try:
                     tag = PICKLE_TAGS[key]
    -            except:
    +            except KeyError:
                     tag = PICKLE_TAGS[key] = Constant(PickleTag())
                     UNPICKLE_TAGS[tag] = key
                 lst[i:i + 1] = [tag] + vars
    
    From noreply at buildbot.pypy.org  Sun Apr  7 07:44:27 2013
    From: noreply at buildbot.pypy.org (alex_gaynor)
    Date: Sun,  7 Apr 2013 07:44:27 +0200 (CEST)
    Subject: [pypy-commit] pypy default: merged upstream
    Message-ID: <20130407054427.8FB031C15A2@cobra.cs.uni-duesseldorf.de>
    
    Author: Alex Gaynor 
    Branch: 
    Changeset: r63111:aefddd47f224
    Date: 2013-04-06 22:44 -0700
    http://bitbucket.org/pypy/pypy/changeset/aefddd47f224/
    
    Log:	merged upstream
    
    diff --git a/rpython/jit/tl/tla/tla_assembler.py b/rpython/jit/tl/tla/tla_assembler.py
    --- a/rpython/jit/tl/tla/tla_assembler.py
    +++ b/rpython/jit/tl/tla/tla_assembler.py
    @@ -2,8 +2,8 @@
     
     import sys
     import py
    +from rpython.jit.tl.tla.test_tla import assemble
     py.path.local(__file__)
    -from rpython.jit.tl.tla.test_tla import assemble
     
     def usage():
         print >> sys.stderr, 'Usage: tla_assembler.py filename.tla.py'
    diff --git a/rpython/rtyper/lltypesystem/lltype.py b/rpython/rtyper/lltypesystem/lltype.py
    --- a/rpython/rtyper/lltypesystem/lltype.py
    +++ b/rpython/rtyper/lltypesystem/lltype.py
    @@ -503,7 +503,7 @@
             return obj
     
         def __init__(self, OF, length, **kwds):
    -        if hasattr(self, '_name'):
    +        if '_name' in self.__dict__:
                 assert self.OF == OF
                 assert self.length == length
                 return
    diff --git a/rpython/translator/platform/arm.py b/rpython/translator/platform/arm.py
    --- a/rpython/translator/platform/arm.py
    +++ b/rpython/translator/platform/arm.py
    @@ -47,11 +47,12 @@
             return ExecutionResult(returncode, stdout, stderr)
     
         def include_dirs_for_libffi(self):
    -        return [SB2 + '/usr/include/arm-linux-gnueabi/']
    +        return [SB2 + '/usr/include/arm-linux-gnueabi/',
    +                SB2 + '/usr/include/arm-linux-gnueabihf/']
     
         def library_dirs_for_libffi(self):
    -        # on the other hand, library lands in usual place...
    -        return []
    +        return [SB2 + '/usr/lib/arm-linux-gnueabi/',
    +                SB2 + '/usr/lib/arm-linux-gnueabihf/']
     
         def execute_makefile(self, path_to_makefile, extra_opts=[]):
             if isinstance(path_to_makefile, GnuMakefile):
    
    From noreply at buildbot.pypy.org  Sun Apr  7 08:50:12 2013
    From: noreply at buildbot.pypy.org (bivab)
    Date: Sun,  7 Apr 2013 08:50:12 +0200 (CEST)
    Subject: [pypy-commit] buildbot default: this should have been a list
    Message-ID: <20130407065012.866B81C010B@cobra.cs.uni-duesseldorf.de>
    
    Author: David Schneider 
    Branch: 
    Changeset: r770:602ef6044151
    Date: 2013-04-07 08:49 +0200
    http://bitbucket.org/pypy/buildbot/changeset/602ef6044151/
    
    Log:	this should have been a list
    
    diff --git a/bot2/pypybuildbot/master.py b/bot2/pypybuildbot/master.py
    --- a/bot2/pypybuildbot/master.py
    +++ b/bot2/pypybuildbot/master.py
    @@ -183,7 +183,7 @@
         translationArgs=crosstranslationargs + ['-O2'],
         platform='linux-armel',
         interpreter='pypy',
    -    prefix='schroot -c armel',
    +    prefix=['schroot', '-c', 'armel'],
         trigger='APPLVLLINUXARM_scheduler')
     
     pypyJITCrossTranslationFactoryARM = pypybuilds.NightlyBuild(
    @@ -192,7 +192,7 @@
                             + crosstranslationjitargs),
         platform='linux-armel',
         interpreter='pypy',
    -    prefix='schroot -c armel',
    +    prefix=['schroot', '-c', 'armel'],
         trigger='JITLINUXARM_scheduler')
     
     pypyARMJITTranslatedTestFactory = pypybuilds.TranslatedTests(
    
    From noreply at buildbot.pypy.org  Sun Apr  7 10:35:28 2013
    From: noreply at buildbot.pypy.org (fijal)
    Date: Sun,  7 Apr 2013 10:35:28 +0200 (CEST)
    Subject: [pypy-commit] pypy.org extradoc: update the website
    Message-ID: <20130407083528.F33CB1C0DCB@cobra.cs.uni-duesseldorf.de>
    
    Author: Maciej Fijalkowski 
    Branch: extradoc
    Changeset: r388:72edaaf283ce
    Date: 2013-04-07 10:17 +0200
    http://bitbucket.org/pypy/pypy.org/changeset/72edaaf283ce/
    
    Log:	update the website
    
    diff --git a/compat.html b/compat.html
    --- a/compat.html
    +++ b/compat.html
    @@ -51,7 +51,7 @@
     already accepted in the main python in newer versions). It supports most
     of the commonly used Python standard library modules; details below.

    PyPy has alpha/beta-level support for the CPython C API, however, as of -2.0 beta1 +2.0 beta2 release this feature is not yet complete. Many libraries will require a bit of effort to work, but there are known success stories. Check out PyPy blog for updates, as well as the Compatibility Wiki.

    diff --git a/download.html b/download.html --- a/download.html +++ b/download.html @@ -49,8 +49,9 @@

    There are nightly binary builds available. Those builds are not always as stable as the release, but they contain numerous bugfixes and performance improvements.

    -

    Here are the binaries of the current release — PyPy 2.0 beta1 — (what's -new in PyPy 2.0 beta1?) for x86 Linux, Mac OS/X, Windows or ARM linux.

    +

    Here are the binaries of the current release — PyPy 2.0 beta2 — (what's +new in PyPy 2.0 beta2?) for x86 Linux, Mac OS/X, Windows or ARM linux +(not available for 2.0 beta 2).

    You can also find here the older 1.9 release.

    • Download
        @@ -69,23 +70,23 @@ x86 CPUs that have the SSE2 instruction set (most of them do, nowadays), or on x86-64 CPUs. They also contain stackless extensions, like greenlets. -(This is the official release 2.0 beta1 and 1.9; +(This is the official release 2.0 beta2 and 1.9; for the most up-to-date version see below.)

        -
        -

        2.0 beta1

        +
        +

        2.0 beta2

        -
        +

        1.9

        • Linux binary (32bit)
        • @@ -138,8 +139,8 @@
        • Get the source code. The following packages contain the source at the same revision as the above binaries:

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

          @@ -151,7 +152,7 @@
        • Enter the goal directory:

          -cd pypy/pypy/translator/goal      # release 2.0-beta-1
          +cd pypy/pypy/translator/goal      # release 2.0-beta-2
           cd pypy/pypy/goal                 # current trunk
           
        • @@ -213,12 +214,10 @@

          Checksums

          Here are the checksums for each of the downloads (md5 and sha1):

          -68d8668299cd5adf4f302eaf882c5b33  pypy-2.0-beta1-linux64-libc2.13.tar.bz2
          -0fde559a7b1a3b98245d6a5ea7f8ebb2  pypy-2.0-beta1-linux64-libc2.15.tar.bz2
          -a1505520c063c591b218e5cd3436b111  pypy-2.0-beta1-linux-armel.tar.bz2
          -5aa2e4eee1c3dab86e5cec237776ced3  pypy-2.0-beta1-linux.tar.bz2
          -2802a06cd19ac86930b63afdd837c32f  pypy-2.0-beta1-osx64.tar.bz2
          -a34dcd53537aaba0bed69d47f492ac73  pypy-2.0-beta1.1-win32.zip
          +99f062eb516d8b6b5614f2350a65adab  pypy-2.0-beta2-linux64-libc2.15.tar.bz2
          +61c2d5873ee62823bcf35b2e7086644f  pypy-2.0-beta2-linux.tar.bz2
          +f7ad21f79c8005b9c00c48e190ec662e  pypy-2.0-beta2-osx64.tar.bz2
          +3b5250872a5e79034bb1a7c209f39391  pypy-2.0-beta2-win32.zip
           201d2cce2557e40c784473b471ee1b6b  pypy-1.9-linux64.tar.bz2
           1a08c88642434fc2e0e4256d351f48db  pypy-1.9-linux.tar.bz2
           aad9c4b7b827583e37fe8ae0f7cfe0ff  pypy-1.9-osx64.tar.bz2
          @@ -227,12 +226,10 @@
           009c970b5fa75754ae4c32a5d108a8d4  pypy-1.8-sandbox-linux.tar.bz2
           4a346df59983e4a5c50e8ee211f80619  release-2.0-beta-1.tar.bz2 (source)
           60270f1b919e75f818028da52ab8c3d3  release-2.0-beta-1.zip (source)
          -720da40e127b6438d6d3ab1164dbf596479984a0  pypy-2.0-beta1-linux64-libc2.13.tar.bz2
          -a406b8b0f8e44c4f3bea0476307c0329a3fde9c2  pypy-2.0-beta1-linux64-libc2.15.tar.bz2
          -5682358c775e90dbc3636dbb0f6158675ecf5357  pypy-2.0-beta1-linux-armel.tar.bz2
          -ede5788f282072bc410019fb26c732f55f0b33ff  pypy-2.0-beta1-linux.tar.bz2
          -e4938fdf33072e457fee6cb22798ec08b5a01978  pypy-2.0-beta1-osx64.tar.bz2
          -152ab10da55ed9f8c8a21b5cb4e67ee2ff4005fa  pypy-2.0-beta1.1-win32.zip
          +699fe12476a1783d6f91de59f48adc01c93c39df  pypy-2.0-beta2-linux64-libc2.15.tar.bz2
          +591e661b091ed4849fdf5aab7e73393dea64016b  pypy-2.0-beta2-linux.tar.bz2
          +ec3d80d7806b0689d9da70ca27c741b1d9cea250  pypy-2.0-beta2-osx64.tar.bz2
          +bb0604f32ba0e2af3c585a1af45dc887e0e95d34  pypy-2.0-beta2-win32.zip
           51be6b7b802a5239a759e04ae9595082e17c4c70  pypy-1.9-linux64.tar.bz2
           1bc5d2467039b954f9b7395b3ee1b8407ce1c057  pypy-1.9-linux.tar.bz2
           825e15724419fbdb6fe215eeea044f9181883c90  pypy-1.9-osx64.tar.bz2
          diff --git a/features.html b/features.html
          --- a/features.html
          +++ b/features.html
          @@ -46,8 +46,9 @@
           

          Features

          -

          PyPy 2.0 beta1 implements Python 2.7.3 and runs on Intel -x86 (IA-32) , x86_64 and ARM platforms, with PPC being underway. +

          PyPy 2.0 beta2 implements Python 2.7.3 and runs on Intel +x86 (IA-32) , x86_64 and ARM platforms (with ARM +being disabled until 2.0 final), with PPC being underway. It supports all of the core language, passing the Python test suite (with minor modifications that were already accepted in the main python in newer versions). It supports most of the commonly used Python @@ -90,10 +91,6 @@

          Stackless

          Support for Stackless and greenlets are now integrated in the normal PyPy. More detailed information is available here.

          -

          Note that there is still an important performance hit for programs using -Stackless features. Also, as of 2.0 beta 1 (and any previous version), -there are known crashes of stackless features. We're working on improving -the situation for 2.0 final and enabling the JIT.

          Other features

          diff --git a/index.html b/index.html --- a/index.html +++ b/index.html @@ -64,7 +64,7 @@
        • As well as other features.
        -

        Download and try out the PyPy release 2.0 beta1!

        +

        Download and try out the PyPy release 2.0 beta2!

        Want to know more? A good place to start is our detailed speed and compatibility reports!

        diff --git a/performance.html b/performance.html --- a/performance.html +++ b/performance.html @@ -195,7 +195,7 @@

    with the admittedly less readable:

    -s = "%(head)%(body)%(maybe)%(tail)" % locals()
    +s = "%(head)s%(body)s%(maybe)s%(tail)s" % locals()
     

    or even:

    diff --git a/source/compat.txt b/source/compat.txt
    --- a/source/compat.txt
    +++ b/source/compat.txt
    @@ -9,7 +9,7 @@
     of the commonly used Python `standard library modules`_; details below.
     
     PyPy has **alpha/beta-level** support for the `CPython C API`_, however, as of
    -2.0 beta1
    +2.0 beta2
     release this feature is not yet complete. Many libraries will require
     a bit of effort to work, but there are known success stories. Check out
     PyPy blog for updates, as well as the `Compatibility Wiki`__.
    diff --git a/source/download.txt b/source/download.txt
    --- a/source/download.txt
    +++ b/source/download.txt
    @@ -12,12 +12,13 @@
       as stable as the release, but they contain numerous bugfixes and 
       performance improvements.
     
    -Here are the binaries of the current release — **PyPy 2.0 beta1** — (`what's
    -new in PyPy 2.0 beta1?`_) for x86 Linux, Mac OS/X, Windows or ARM linux.
    +Here are the binaries of the current release — **PyPy 2.0 beta2** — (`what's
    +new in PyPy 2.0 beta2?`_) for x86 Linux, Mac OS/X, Windows or ARM linux
    +(not available for 2.0 beta 2).
     
     You can also find here the older 1.9 release.
     
    -.. _what's new in PyPy 2.0 beta1?: http://doc.pypy.org/en/latest/release-2.0.0-beta1.html
    +.. _what's new in PyPy 2.0 beta2?: http://doc.pypy.org/en/latest/release-2.0.0-beta2.html
     
     
     .. class:: download_menu
    @@ -41,27 +42,25 @@
     x86 CPUs that have the SSE2_ instruction set (most of
     them do, nowadays), or on x86-64 CPUs. They also contain `stackless`_
     extensions, like `greenlets`_.
    -(This is the official release 2.0 beta1 and 1.9;
    +(This is the official release 2.0 beta2 and 1.9;
     for the most up-to-date version see below.)
     
    -2.0 beta1
    +2.0 beta2
     ---------
     
     * `Linux binary (32bit)`__
     * `Linux binary (64bit) (libc 2.15)`__
    -* `Linux binary (64bit) (libc 2.13)`__
    -* `Linux ARM binary`__
    +* Linux binary (64bit) (libc 2.13) (not available yet)
    +* Linux ARM binary (not available yet)
     * `Mac OS/X binary (64bit)`__
     * `Windows binary (32bit)`__ (you need the `VS 2008 runtime library
       installer vcredist_x86.exe`_.  *Updated again:* the previous version
       required two runtime libs)
     
    -.. __: https://bitbucket.org/pypy/pypy/downloads/pypy-2.0-beta1-linux.tar.bz2
    -.. __: https://bitbucket.org/pypy/pypy/downloads/pypy-2.0-beta1-linux64-libc2.15.tar.bz2
    -.. __: https://bitbucket.org/pypy/pypy/downloads/pypy-2.0-beta1-linux64-libc2.13.tar.bz2
    -.. __: https://bitbucket.org/pypy/pypy/downloads/pypy-2.0-beta1-linux-armel.tar.bz2
    -.. __: https://bitbucket.org/pypy/pypy/downloads/pypy-2.0-beta1-osx64.tar.bz2
    -.. __: https://bitbucket.org/pypy/pypy/downloads/pypy-2.0-beta1.1-win32.zip
    +.. __: https://bitbucket.org/pypy/pypy/downloads/pypy-2.0-beta2-linux.tar.bz2
    +.. __: https://bitbucket.org/pypy/pypy/downloads/pypy-2.0-beta2-linux64-libc2.15.tar.bz2
    +.. __: https://bitbucket.org/pypy/pypy/downloads/pypy-2.0-beta2-osx64.tar.bz2
    +.. __: https://bitbucket.org/pypy/pypy/downloads/pypy-2.0-beta2-win32.zip
     .. _`VS 2008 runtime library installer vcredist_x86.exe`: http://www.microsoft.com/en-us/download/details.aspx?id=5582
     
     1.9
    @@ -139,11 +138,11 @@
     1. Get the source code.  The following packages contain the source at
        the same revision as the above binaries:
     
    -   * `pypy-2.0b1-src.tar.bz2`__ (sources, Unix line endings)
    -   * `pypy-2.0b1-src.zip`__ (sources, Unix line endings too, sorry)
    +   * `pypy-2.0b2-src.tar.bz2`__ (sources, Unix line endings)
    +   * `pypy-2.0b2-src.zip`__ (sources, Unix line endings too, sorry)
     
    -   .. __: https://bitbucket.org/pypy/pypy/get/release-2.0-beta-1.tar.bz2
    -   .. __: https://bitbucket.org/pypy/pypy/get/release-2.0-beta-1.zip
    +   .. __: https://bitbucket.org/pypy/pypy/get/release-2.0-beta-2.tar.bz2
    +   .. __: https://bitbucket.org/pypy/pypy/get/release-2.0-beta-2.zip
     
        Or you can checkout the current trunk using Mercurial_ (the trunk
        usually works and is of course more up-to-date)::
    @@ -156,7 +155,7 @@
     
     3. Enter the ``goal`` directory::
     
    -     cd pypy/pypy/translator/goal      # release 2.0-beta-1
    +     cd pypy/pypy/translator/goal      # release 2.0-beta-2
          cd pypy/pypy/goal                 # current trunk
     
     4. Run the ``translate.py`` script (called ``rpython.py`` in the current
    @@ -225,12 +224,10 @@
     
     Here are the checksums for each of the downloads (md5 and sha1)::
     
    -   68d8668299cd5adf4f302eaf882c5b33  pypy-2.0-beta1-linux64-libc2.13.tar.bz2
    -   0fde559a7b1a3b98245d6a5ea7f8ebb2  pypy-2.0-beta1-linux64-libc2.15.tar.bz2
    -   a1505520c063c591b218e5cd3436b111  pypy-2.0-beta1-linux-armel.tar.bz2
    -   5aa2e4eee1c3dab86e5cec237776ced3  pypy-2.0-beta1-linux.tar.bz2
    -   2802a06cd19ac86930b63afdd837c32f  pypy-2.0-beta1-osx64.tar.bz2
    -   a34dcd53537aaba0bed69d47f492ac73  pypy-2.0-beta1.1-win32.zip
    +   99f062eb516d8b6b5614f2350a65adab  pypy-2.0-beta2-linux64-libc2.15.tar.bz2
    +   61c2d5873ee62823bcf35b2e7086644f  pypy-2.0-beta2-linux.tar.bz2
    +   f7ad21f79c8005b9c00c48e190ec662e  pypy-2.0-beta2-osx64.tar.bz2
    +   3b5250872a5e79034bb1a7c209f39391  pypy-2.0-beta2-win32.zip
        201d2cce2557e40c784473b471ee1b6b  pypy-1.9-linux64.tar.bz2
        1a08c88642434fc2e0e4256d351f48db  pypy-1.9-linux.tar.bz2
        aad9c4b7b827583e37fe8ae0f7cfe0ff  pypy-1.9-osx64.tar.bz2
    @@ -240,12 +237,10 @@
        4a346df59983e4a5c50e8ee211f80619  release-2.0-beta-1.tar.bz2 (source)
        60270f1b919e75f818028da52ab8c3d3  release-2.0-beta-1.zip (source)
     
    -   720da40e127b6438d6d3ab1164dbf596479984a0  pypy-2.0-beta1-linux64-libc2.13.tar.bz2
    -   a406b8b0f8e44c4f3bea0476307c0329a3fde9c2  pypy-2.0-beta1-linux64-libc2.15.tar.bz2
    -   5682358c775e90dbc3636dbb0f6158675ecf5357  pypy-2.0-beta1-linux-armel.tar.bz2
    -   ede5788f282072bc410019fb26c732f55f0b33ff  pypy-2.0-beta1-linux.tar.bz2
    -   e4938fdf33072e457fee6cb22798ec08b5a01978  pypy-2.0-beta1-osx64.tar.bz2
    -   152ab10da55ed9f8c8a21b5cb4e67ee2ff4005fa  pypy-2.0-beta1.1-win32.zip
    +   699fe12476a1783d6f91de59f48adc01c93c39df  pypy-2.0-beta2-linux64-libc2.15.tar.bz2
    +   591e661b091ed4849fdf5aab7e73393dea64016b  pypy-2.0-beta2-linux.tar.bz2
    +   ec3d80d7806b0689d9da70ca27c741b1d9cea250  pypy-2.0-beta2-osx64.tar.bz2
    +   bb0604f32ba0e2af3c585a1af45dc887e0e95d34  pypy-2.0-beta2-win32.zip
        51be6b7b802a5239a759e04ae9595082e17c4c70  pypy-1.9-linux64.tar.bz2
        1bc5d2467039b954f9b7395b3ee1b8407ce1c057  pypy-1.9-linux.tar.bz2
        825e15724419fbdb6fe215eeea044f9181883c90  pypy-1.9-osx64.tar.bz2
    diff --git a/source/features.txt b/source/features.txt
    --- a/source/features.txt
    +++ b/source/features.txt
    @@ -6,8 +6,9 @@
     PyPy features
     ===========================================================
     
    -**PyPy 2.0 beta1** implements **Python 2.7.3** and runs on Intel
    -`x86 (IA-32)`_ , `x86_64`_ and `ARM`_ platforms, with PPC being underway.
    +**PyPy 2.0 beta2** implements **Python 2.7.3** and runs on Intel
    +`x86 (IA-32)`_ , `x86_64`_ and `ARM`_ platforms (with ARM
    +being disabled until 2.0 final), with PPC being underway.
     It supports all of the core language, passing the Python test suite
     (with minor modifications that were already accepted in the main python
     in newer versions). It supports most of the commonly used Python
    @@ -74,11 +75,6 @@
     Support for Stackless_ and greenlets are now integrated in the normal
     PyPy.  More detailed information is available here__.
     
    -Note that there is still an important performance hit for programs using
    -Stackless features. Also, as of 2.0 beta 1 (and any previous version),
    -there are known crashes of stackless features. We're working on improving
    -the situation for 2.0 final and enabling the JIT.
    -
     .. _Stackless: http://www.stackless.com/
     .. __: http://doc.pypy.org/en/latest/stackless.html
     
    diff --git a/source/index.txt b/source/index.txt
    --- a/source/index.txt
    +++ b/source/index.txt
    @@ -26,7 +26,7 @@
     
     .. class:: download
     
    -`Download and try out the PyPy release 2.0 beta1!`__
    +`Download and try out the PyPy release 2.0 beta2!`__
     
     .. __: download.html
     
    
    From noreply at buildbot.pypy.org  Sun Apr  7 10:35:30 2013
    From: noreply at buildbot.pypy.org (fijal)
    Date: Sun,  7 Apr 2013 10:35:30 +0200 (CEST)
    Subject: [pypy-commit] pypy.org extradoc: merge
    Message-ID: <20130407083530.28FAF1C0DCB@cobra.cs.uni-duesseldorf.de>
    
    Author: Maciej Fijalkowski 
    Branch: extradoc
    Changeset: r389:f656fe4becde
    Date: 2013-04-07 10:35 +0200
    http://bitbucket.org/pypy/pypy.org/changeset/f656fe4becde/
    
    Log:	merge
    
    
    From noreply at buildbot.pypy.org  Sun Apr  7 11:27:39 2013
    From: noreply at buildbot.pypy.org (arigo)
    Date: Sun,  7 Apr 2013 11:27:39 +0200 (CEST)
    Subject: [pypy-commit] pypy.org extradoc: regen
    Message-ID: <20130407092739.ED4B11C15A7@cobra.cs.uni-duesseldorf.de>
    
    Author: Armin Rigo 
    Branch: extradoc
    Changeset: r391:403e29079441
    Date: 2013-04-07 11:27 +0200
    http://bitbucket.org/pypy/pypy.org/changeset/403e29079441/
    
    Log:	regen
    
    diff --git a/download.html b/download.html
    --- a/download.html
    +++ b/download.html
    @@ -81,9 +81,8 @@
     
  • Linux binary (64bit) (libc 2.13) (not available yet)
  • Linux ARM binary (not available yet)
  • Mac OS/X binary (64bit)
  • -
  • Windows binary (32bit) (you need the VS 2008 runtime library -installer vcredist_x86.exe. Updated again: the previous version -required two runtime libs)
  • +
  • Windows binary (32bit) (you might need the VS 2008 runtime library +installer vcredist_x86.exe.)
  • From noreply at buildbot.pypy.org Sun Apr 7 11:27:38 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sun, 7 Apr 2013 11:27:38 +0200 (CEST) Subject: [pypy-commit] pypy.org extradoc: Update (thanks janzert) Message-ID: <20130407092738.E12521C0337@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: extradoc Changeset: r390:8f6dcb23166e Date: 2013-04-07 11:27 +0200 http://bitbucket.org/pypy/pypy.org/changeset/8f6dcb23166e/ Log: Update (thanks janzert) diff --git a/source/download.txt b/source/download.txt --- a/source/download.txt +++ b/source/download.txt @@ -53,9 +53,8 @@ * Linux binary (64bit) (libc 2.13) (not available yet) * Linux ARM binary (not available yet) * `Mac OS/X binary (64bit)`__ -* `Windows binary (32bit)`__ (you need the `VS 2008 runtime library - installer vcredist_x86.exe`_. *Updated again:* the previous version - required two runtime libs) +* `Windows binary (32bit)`__ (you might need the `VS 2008 runtime library + installer vcredist_x86.exe`_.) .. __: https://bitbucket.org/pypy/pypy/downloads/pypy-2.0-beta2-linux.tar.bz2 .. __: https://bitbucket.org/pypy/pypy/downloads/pypy-2.0-beta2-linux64-libc2.15.tar.bz2 From noreply at buildbot.pypy.org Sun Apr 7 13:35:20 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sun, 7 Apr 2013 13:35:20 +0200 (CEST) Subject: [pypy-commit] pypy.org extradoc: Typo (thanks tshepang) Message-ID: <20130407113520.619AA1C3100@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: extradoc Changeset: r392:530358f34f23 Date: 2013-04-07 13:35 +0200 http://bitbucket.org/pypy/pypy.org/changeset/530358f34f23/ Log: Typo (thanks tshepang) diff --git a/performance.html b/performance.html --- a/performance.html +++ b/performance.html @@ -179,7 +179,7 @@

    Old- vs. new-style classes

    New-style classes allow faster attribute access and take up less core per instance than old-style classes. Much of this advantage may be -lostm, however, if attribute names are not constant. For example: x.a +lost, however, if attribute names are not constant. For example: x.a = y or even setattr(x, ‘a’, y) will be much faster than a dynamic version: setattr(x, ‘a’ + some_variable, y).

    Classes that inherit from both new- and old-style classes are diff --git a/source/performance.txt b/source/performance.txt --- a/source/performance.txt +++ b/source/performance.txt @@ -160,7 +160,7 @@ New-style classes allow faster attribute access and take up less core per instance than old-style classes. Much of this advantage may be -lostm, however, if attribute names are not constant. For example: x.a +lost, however, if attribute names are not constant. For example: x.a = y or even setattr(x, 'a', y) will be much faster than a dynamic version: setattr(x, 'a' + some_variable, y). From noreply at buildbot.pypy.org Sun Apr 7 13:43:01 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sun, 7 Apr 2013 13:43:01 +0200 (CEST) Subject: [pypy-commit] pypy default: Update: we have stackless.py Message-ID: <20130407114301.D4ACB1C3100@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63112:2d020e037ada Date: 2013-04-07 13:42 +0200 http://bitbucket.org/pypy/pypy/changeset/2d020e037ada/ Log: Update: we have stackless.py diff --git a/pypy/doc/stackless.rst b/pypy/doc/stackless.rst --- a/pypy/doc/stackless.rst +++ b/pypy/doc/stackless.rst @@ -17,8 +17,8 @@ Continulets can be directly used by application code, or it is possible to write (entirely at app-level) more user-friendly interfaces. -Currently PyPy implements greenlets_ on top of continulets. It would be -easy to implement tasklets and channels as well, emulating the model +Currently PyPy implements greenlets_ on top of continulets. It also +implements tasklets and channels, emulating the model of `Stackless Python`_. Continulets are extremely light-weight, which means that PyPy should be From noreply at buildbot.pypy.org Sun Apr 7 13:46:05 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sun, 7 Apr 2013 13:46:05 +0200 (CEST) Subject: [pypy-commit] pypy default: Note that compatibility is not 100%. Message-ID: <20130407114605.D3B2B1C3100@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63113:35e0cafe9bab Date: 2013-04-07 13:45 +0200 http://bitbucket.org/pypy/pypy/changeset/35e0cafe9bab/ Log: Note that compatibility is not 100%. diff --git a/pypy/doc/stackless.rst b/pypy/doc/stackless.rst --- a/pypy/doc/stackless.rst +++ b/pypy/doc/stackless.rst @@ -18,7 +18,7 @@ to write (entirely at app-level) more user-friendly interfaces. Currently PyPy implements greenlets_ on top of continulets. It also -implements tasklets and channels, emulating the model +implements (an approximation of) tasklets and channels, emulating the model of `Stackless Python`_. Continulets are extremely light-weight, which means that PyPy should be From noreply at buildbot.pypy.org Sun Apr 7 14:54:48 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sun, 7 Apr 2013 14:54:48 +0200 (CEST) Subject: [pypy-commit] pypy.org extradoc: Drop mention of 'translate.py'. Now building is always done by running Message-ID: <20130407125448.9450E1C0334@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: extradoc Changeset: r393:bc8c574377c8 Date: 2013-04-07 14:52 +0200 http://bitbucket.org/pypy/pypy.org/changeset/bc8c574377c8/ Log: Drop mention of 'translate.py'. Now building is always done by running 'rpython'. diff --git a/source/download.txt b/source/download.txt --- a/source/download.txt +++ b/source/download.txt @@ -154,21 +154,15 @@ 3. Enter the ``goal`` directory:: - cd pypy/pypy/translator/goal # release 2.0-beta-2 - cd pypy/pypy/goal # current trunk + cd pypy/pypy/goal -4. Run the ``translate.py`` script (called ``rpython.py`` in the current - trunk). Here are the common combinations +4. Run the ``rpython`` script. Here are the common combinations of options (works also with ``python`` instead of ``pypy``):: - pypy translate.py -Ojit # get the JIT version - pypy translate.py -O2 # get the no-jit version - pypy translate.py -O2 --sandbox # get the sandbox version - pypy translate.py -Ojit --backend=cli # only for branch/cli-jit - - Or with the current trunk:: - - ../../rpython/bin/rpython -Ojit # or -O2, etc. + pypy ../../rpython/bin/rpython -Ojit # get the JIT version + pypy ../../rpython/bin/rpython -O2 # get the no-jit version + pypy ../../rpython/bin/rpython -O2 --sandbox # get the sandbox version + pypy ../../rpython/bin/rpython -Ojit --backend=cli # only for branch/cli-jit 5. Enjoy Mandelbrot ``:-)`` It takes on the order of half an hour to finish the translation, and 2.x GB of RAM on a 32-bit system @@ -190,7 +184,7 @@ Linux 64-bit; probably not much more than 1.6 GB on 32-bit). It should be noted that it is less than with CPython. :: - PYPY_GC_MAX_DELTA=200MB pypy --jit loop_longevity=300 ./translate.py -Ojit + PYPY_GC_MAX_DELTA=200MB pypy --jit loop_longevity=300 ../../rpython/bin/rpython -Ojit * Because of ``asmgcroot``, compiling the generated C files containing the JIT is delicate. It requires using either MSVC or gcc with no particularly From noreply at buildbot.pypy.org Sun Apr 7 14:54:49 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sun, 7 Apr 2013 14:54:49 +0200 (CEST) Subject: [pypy-commit] pypy.org extradoc: Drop the "backend=cli" command-line here. Message-ID: <20130407125449.A39651C0334@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: extradoc Changeset: r394:17f759c5d309 Date: 2013-04-07 14:52 +0200 http://bitbucket.org/pypy/pypy.org/changeset/17f759c5d309/ Log: Drop the "backend=cli" command-line here. diff --git a/source/download.txt b/source/download.txt --- a/source/download.txt +++ b/source/download.txt @@ -159,10 +159,9 @@ 4. Run the ``rpython`` script. Here are the common combinations of options (works also with ``python`` instead of ``pypy``):: - pypy ../../rpython/bin/rpython -Ojit # get the JIT version - pypy ../../rpython/bin/rpython -O2 # get the no-jit version - pypy ../../rpython/bin/rpython -O2 --sandbox # get the sandbox version - pypy ../../rpython/bin/rpython -Ojit --backend=cli # only for branch/cli-jit + pypy ../../rpython/bin/rpython -Ojit # get the JIT version + pypy ../../rpython/bin/rpython -O2 # get the no-jit version + pypy ../../rpython/bin/rpython -O2 --sandbox # get the sandbox version 5. Enjoy Mandelbrot ``:-)`` It takes on the order of half an hour to finish the translation, and 2.x GB of RAM on a 32-bit system From noreply at buildbot.pypy.org Sun Apr 7 14:54:50 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sun, 7 Apr 2013 14:54:50 +0200 (CEST) Subject: [pypy-commit] pypy.org extradoc: regen Message-ID: <20130407125450.B4F941C0334@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: extradoc Changeset: r395:4673a6bd3cc6 Date: 2013-04-07 14:53 +0200 http://bitbucket.org/pypy/pypy.org/changeset/4673a6bd3cc6/ Log: regen diff --git a/download.html b/download.html --- a/download.html +++ b/download.html @@ -151,22 +151,15 @@

  • Enter the goal directory:

    -cd pypy/pypy/translator/goal      # release 2.0-beta-2
    -cd pypy/pypy/goal                 # current trunk
    +cd pypy/pypy/goal
     
  • -
  • Run the translate.py script (called rpython.py in the current -trunk). Here are the common combinations +

  • Run the rpython script. Here are the common combinations of options (works also with python instead of pypy):

    -pypy translate.py -Ojit                # get the JIT version
    -pypy translate.py -O2                  # get the no-jit version
    -pypy translate.py -O2 --sandbox        # get the sandbox version
    -pypy translate.py -Ojit --backend=cli  # only for branch/cli-jit
    -
    -

    Or with the current trunk:

    -
    -../../rpython/bin/rpython -Ojit        # or -O2, etc.
    +pypy ../../rpython/bin/rpython -Ojit           # get the JIT version
    +pypy ../../rpython/bin/rpython -O2             # get the no-jit version
    +pypy ../../rpython/bin/rpython -O2 --sandbox   # get the sandbox version
     
  • Enjoy Mandelbrot :-) It takes on the order of half an hour to @@ -190,7 +183,7 @@ Linux 64-bit; probably not much more than 1.6 GB on 32-bit). It should be noted that it is less than with CPython.

    -PYPY_GC_MAX_DELTA=200MB pypy --jit loop_longevity=300 ./translate.py -Ojit
    +PYPY_GC_MAX_DELTA=200MB pypy --jit loop_longevity=300 ../../rpython/bin/rpython -Ojit
     
  • Because of asmgcroot, compiling the generated C files containing the JIT From noreply at buildbot.pypy.org Sun Apr 7 15:07:51 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sun, 7 Apr 2013 15:07:51 +0200 (CEST) Subject: [pypy-commit] pypy.org extradoc: Fix the links for source. Fix the md5/sha1. As usual it's done by Message-ID: <20130407130751.B2BD11C0334@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: extradoc Changeset: r396:4d3e48fbf69c Date: 2013-04-07 15:07 +0200 http://bitbucket.org/pypy/pypy.org/changeset/4d3e48fbf69c/ Log: Fix the links for source. Fix the md5/sha1. As usual it's done by downloading the file and dumping the md5/sha1 that I got, which means it's bogus as a security measure, but people insist anyway. I'll try this time to leave out the .zip... diff --git a/source/download.txt b/source/download.txt --- a/source/download.txt +++ b/source/download.txt @@ -140,8 +140,8 @@ * `pypy-2.0b2-src.tar.bz2`__ (sources, Unix line endings) * `pypy-2.0b2-src.zip`__ (sources, Unix line endings too, sorry) - .. __: https://bitbucket.org/pypy/pypy/get/release-2.0-beta-2.tar.bz2 - .. __: https://bitbucket.org/pypy/pypy/get/release-2.0-beta-2.zip + .. __: https://bitbucket.org/pypy/pypy/get/release-2.0-beta2.tar.bz2 + .. __: https://bitbucket.org/pypy/pypy/get/release-2.0-beta2.zip Or you can checkout the current trunk using Mercurial_ (the trunk usually works and is of course more up-to-date):: @@ -226,8 +226,7 @@ e7655066baed3c7bbbca7df617817dd5 pypy-1.9-win32.zip 2c9f0054f3b93a6473f10be35277825a pypy-1.8-sandbox-linux64.tar.bz2 009c970b5fa75754ae4c32a5d108a8d4 pypy-1.8-sandbox-linux.tar.bz2 - 4a346df59983e4a5c50e8ee211f80619 release-2.0-beta-1.tar.bz2 (source) - 60270f1b919e75f818028da52ab8c3d3 release-2.0-beta-1.zip (source) + c6afb6dd3fcc57ba2c4144780a42412f release-2.0-beta2.tar.bz2 (source) 699fe12476a1783d6f91de59f48adc01c93c39df pypy-2.0-beta2-linux64-libc2.15.tar.bz2 591e661b091ed4849fdf5aab7e73393dea64016b pypy-2.0-beta2-linux.tar.bz2 @@ -239,5 +238,4 @@ 4f060f4fab0f07bbc7de0ac8f95275eb08d726a3 pypy-1.9-win32.zip 895aaf7bba5787dd30adda5cc0e0e7fc297c0ca7 pypy-1.8-sandbox-linux64.tar.bz2 be94460bed8b2682880495435c309b6611ae2c31 pypy-1.8-sandbox-linux.tar.bz2 - 281439ca2fb56edfe26fc65f99ab6eb238097425 release-2.0-beta-1.tar.bz2 (source) - a2fc9b8031b5817ccd4389d97e3d8c480b48eb78 release-2.0-beta-1.zip (source) + 66d77a7ef98b9bff33a6ac19834c3a598bb9fa97 release-2.0-beta2.tar.bz2 (source) From noreply at buildbot.pypy.org Sun Apr 7 15:07:52 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sun, 7 Apr 2013 15:07:52 +0200 (CEST) Subject: [pypy-commit] pypy.org extradoc: regen Message-ID: <20130407130752.BD9BC1C0334@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: extradoc Changeset: r397:895e14c1ad3a Date: 2013-04-07 15:07 +0200 http://bitbucket.org/pypy/pypy.org/changeset/895e14c1ad3a/ Log: regen diff --git a/download.html b/download.html --- a/download.html +++ b/download.html @@ -138,8 +138,8 @@

  • Get the source code. The following packages contain the source at the same revision as the above binaries:

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

    @@ -216,8 +216,7 @@ e7655066baed3c7bbbca7df617817dd5 pypy-1.9-win32.zip 2c9f0054f3b93a6473f10be35277825a pypy-1.8-sandbox-linux64.tar.bz2 009c970b5fa75754ae4c32a5d108a8d4 pypy-1.8-sandbox-linux.tar.bz2 -4a346df59983e4a5c50e8ee211f80619 release-2.0-beta-1.tar.bz2 (source) -60270f1b919e75f818028da52ab8c3d3 release-2.0-beta-1.zip (source) +c6afb6dd3fcc57ba2c4144780a42412f release-2.0-beta2.tar.bz2 (source) 699fe12476a1783d6f91de59f48adc01c93c39df pypy-2.0-beta2-linux64-libc2.15.tar.bz2 591e661b091ed4849fdf5aab7e73393dea64016b pypy-2.0-beta2-linux.tar.bz2 ec3d80d7806b0689d9da70ca27c741b1d9cea250 pypy-2.0-beta2-osx64.tar.bz2 @@ -228,8 +227,7 @@ 4f060f4fab0f07bbc7de0ac8f95275eb08d726a3 pypy-1.9-win32.zip 895aaf7bba5787dd30adda5cc0e0e7fc297c0ca7 pypy-1.8-sandbox-linux64.tar.bz2 be94460bed8b2682880495435c309b6611ae2c31 pypy-1.8-sandbox-linux.tar.bz2 -281439ca2fb56edfe26fc65f99ab6eb238097425 release-2.0-beta-1.tar.bz2 (source) -a2fc9b8031b5817ccd4389d97e3d8c480b48eb78 release-2.0-beta-1.zip (source) +66d77a7ef98b9bff33a6ac19834c3a598bb9fa97 release-2.0-beta2.tar.bz2 (source)
  • From noreply at buildbot.pypy.org Sun Apr 7 15:27:39 2013 From: noreply at buildbot.pypy.org (timo_jbo) Date: Sun, 7 Apr 2013 15:27:39 +0200 (CEST) Subject: [pypy-commit] pypy.org extradoc: features.txt: update text about pypy-net, add link to topazruby. Message-ID: <20130407132739.5766F1C0337@cobra.cs.uni-duesseldorf.de> Author: Timo Paulssen Branch: extradoc Changeset: r398:c233be4ff4bb Date: 2013-04-07 15:27 +0200 http://bitbucket.org/pypy/pypy.org/changeset/c233be4ff4bb/ Log: features.txt: update text about pypy-net, add link to topazruby. diff --git a/features.html b/features.html --- a/features.html +++ b/features.html @@ -96,19 +96,24 @@

    Other features

    PyPy has many secondary features and semi-independent projects. We will mention here:

    -
      -
    • the .NET backend: you get a version of pypy-net that runs -natively in the .NET/CLI VM. Of particular interest is the cli-jit -branch, in which you can make a version of pypy-net which also -contains a high-level JIT compiler (it compiles your Python programs -Just in Time into CLR bytecodes, which are in turn compiled natively -by the VM).
    • -
    • the Java backend: PyPy can run on the Java VM, but more care is +
        +
      • the .NET backend: There was a backend for building a native pypy +for the .NET/CLI VM. Of particular interest was the cli-jit +branch, in which you could make a version of pypy-net which also +contains a high-level JIT compiler (it compiled your Python programs +Just in Time into CLR bytecodes). The code of this backend is very +old by now and would require serious work to get back into a working +state. If you would like to tackle this project, please Contact us!

        +
      • +
      • the Java backend: PyPy can run on the Java VM, but more care is needed to finish this project. Writing a backend for our high-level -JIT compiler would be excellent. Contact us!

      • -
      • Other languages: we also implemented other languages that makes +JIT compiler would be excellent. Contact us!

        +
      • +
      • Other languages: we also implemented other languages that makes use of our RPython toolchain: Prolog (almost complete), as -well as Smalltalk, JavaScript, Io, Scheme and Gameboy.

      • +well as Smalltalk, JavaScript, Io, Scheme and Gameboy.

        +

        There is also a Ruby implementation called Topaz.

        +
      diff --git a/source/features.txt b/source/features.txt --- a/source/features.txt +++ b/source/features.txt @@ -85,12 +85,13 @@ PyPy has many secondary features and semi-independent projects. We will mention here: -* **the .NET backend:** you get a version of ``pypy-net`` that runs - natively in the .NET/CLI VM. Of particular interest is `the cli-jit - branch`_, in which you can make a version of ``pypy-net`` which also - contains a high-level JIT compiler (it compiles your Python programs - Just in Time into CLR bytecodes, which are in turn compiled natively - by the VM). +* **the .NET backend:** There was a backend for building a native pypy + for the .NET/CLI VM. Of particular interest was `the cli-jit + branch`_, in which you could make a version of ``pypy-net`` which also + contains a high-level JIT compiler (it compiled your Python programs + Just in Time into CLR bytecodes). The code of this backend is very + old by now and would require serious work to get back into a working + state. If you would like to tackle this project, please `Contact us`_! * **the Java backend:** PyPy can run on the Java VM, but more care is needed to finish this project. Writing a backend for our high-level @@ -100,6 +101,8 @@ use of our RPython toolchain: Prolog_ (almost complete), as well as Smalltalk_, JavaScript_, Io_, Scheme_ and Gameboy_. + There is also a Ruby implementation called Topaz_. + .. _`the cli-jit branch`: https://bitbucket.org/pypy/pypy/src/cli-jit .. _`contact us`: contact.html @@ -109,3 +112,4 @@ .. _Io: https://bitbucket.org/pypy/lang-io/ .. _Scheme: https://bitbucket.org/pypy/lang-scheme/ .. _Gameboy: https://bitbucket.org/pypy/lang-gameboy/ +.. _Topaz: http://topazruby.com/ From noreply at buildbot.pypy.org Sun Apr 7 15:54:57 2013 From: noreply at buildbot.pypy.org (bivab) Date: Sun, 7 Apr 2013 15:54:57 +0200 (CEST) Subject: [pypy-commit] buildbot default: Make this a master lock, because it is going to be shared across builders Message-ID: <20130407135457.7D5FC1C0DCB@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r771:98a8861f9ab1 Date: 2013-04-07 15:53 +0200 http://bitbucket.org/pypy/buildbot/changeset/98a8861f9ab1/ Log: Make this a master lock, because it is going to be shared across builders diff --git a/bot2/pypybuildbot/builds.py b/bot2/pypybuildbot/builds.py --- a/bot2/pypybuildbot/builds.py +++ b/bot2/pypybuildbot/builds.py @@ -23,7 +23,7 @@ #WinLockCPU = locks.MasterLock('win_cpu', maxCount=1) # The cross translation machine can accomodate 2 jobs at the same time -ARMCrossLock = locks.SlaveLock('arm_cpu', maxCount=2) +ARMCrossLock = locks.MasterLock('arm_cpu', maxCount=2) # while the boards can only run one job at the same time ARMBoardLock = locks.SlaveLock('arm_boards', maxCount=1) From noreply at buildbot.pypy.org Sun Apr 7 15:54:58 2013 From: noreply at buildbot.pypy.org (bivab) Date: Sun, 7 Apr 2013 15:54:58 +0200 (CEST) Subject: [pypy-commit] buildbot default: Move the ARM buildbot configuration to a custom file and add ARM Message-ID: <20130407135458.9B99E1C0DCB@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r772:136c91f68759 Date: 2013-04-07 15:54 +0200 http://bitbucket.org/pypy/buildbot/changeset/136c91f68759/ Log: Move the ARM buildbot configuration to a custom file and add ARM hardfloat/Raspbian builders diff --git a/bot2/pypybuildbot/arm_master.py b/bot2/pypybuildbot/arm_master.py new file mode 100644 --- /dev/null +++ b/bot2/pypybuildbot/arm_master.py @@ -0,0 +1,208 @@ + +import os +import getpass +from buildbot.scheduler import Nightly, Triggerable +from pypybuildbot.util import we_are_debugging, load + +pypybuilds = load('pypybuildbot.builds') +ARMCrossLock = pypybuilds.ARMCrossLock +ARMBoardLock = pypybuilds.ARMBoardLock + +# ARM own test factories +jit_translation_args = ['-Ojit'] +crosstranslationargs = ['--platform=arm', '--gcrootfinder=shadowstack'] +crosstranslationjitargs = ['--jit-backend=armv7'] +crosstranslationjitargs_raspbian = ['--jit-backend=armv6'] +# this one needs a larger timeout due to how it is run +pypyJitBackendOnlyOwnTestFactoryARM = pypybuilds.Own( + cherrypick=':'.join(["jit/backend/arm", + "jit/backend/llsupport", + "jit/backend/test", # kill this one in case it is too slow + ]), + timeout=6 * 3600) +pypyJitOnlyOwnTestFactoryARM = pypybuilds.Own(cherrypick="jit", timeout=2 * 3600) +pypyOwnTestFactoryARM = pypybuilds.Own(timeout=2 * 3600) + +pypyCrossTranslationFactoryARM = pypybuilds.NightlyBuild( + translationArgs=crosstranslationargs + ['-O2'], + platform='linux-armel', + interpreter='pypy', + prefix=['schroot', '-c', 'armel'], + trigger='APPLVLLINUXARM_scheduler') + +pypyJITCrossTranslationFactoryARM = pypybuilds.NightlyBuild( + translationArgs=(crosstranslationargs + + jit_translation_args + + crosstranslationjitargs), + platform='linux-armel', + interpreter='pypy', + prefix=['schroot', '-c', 'armel'], + trigger='JITLINUXARM_scheduler') + +pypyCrossTranslationFactoryRaspbianHF = pypybuilds.NightlyBuild( + translationArgs=crosstranslationargs + ['-O2'], + platform='linux-armhf-raspbian', + interpreter='pypy', + prefix=['schroot', '-c', 'raspbian'], + trigger='APPLVLLINUXARMHF_RASPBIAN_scheduler') + +pypyJITCrossTranslationFactoryRaspbianHF = pypybuilds.NightlyBuild( + translationArgs=(crosstranslationargs + + jit_translation_args + + crosstranslationjitargs_raspbian), + platform='linux-armhf-raspbian', + interpreter='pypy', + prefix=['schroot', '-c', 'raspbian'], + trigger='JITLINUXARMHF_RASPBIAN_scheduler') + +pypyARMJITTranslatedTestFactory = pypybuilds.TranslatedTests( + translationArgs=(crosstranslationargs + + jit_translation_args + + crosstranslationjitargs), + lib_python=True, + pypyjit=True, + app_tests=True, + platform='linux-armel', + ) +pypyARMTranslatedAppLevelTestFactory = pypybuilds.TranslatedTests( + translationArgs=crosstranslationargs + ['-O2'], + lib_python=True, + app_tests=True, + platform='linux-armel', +) + +pypyARMJITTranslatedTestFactory = pypybuilds.TranslatedTests( + translationArgs=(crosstranslationargs + + jit_translation_args + + crosstranslationjitargs), + lib_python=True, + pypyjit=True, + app_tests=True, + platform='linux-armhf-raspbian', + ) +pypyARMTranslatedAppLevelTestFactory = pypybuilds.TranslatedTests( + translationArgs=crosstranslationargs + ['-O2'], + lib_python=True, + app_tests=True, + platform='linux-armhf-raspbian', +) +# +APPLVLLINUXARM = "pypy-c-app-level-linux-armel" +APPLVLLINUXARMHF_RASPBIAN = "pypy-c-app-level-linux-armhf-raspbian" + +JITLINUXARM = "pypy-c-jit-linux-armel" +JITLINUXARMHF_RASPBIAN = "pypy-c-jit-linux-armhf-raspbian" + +JITBACKENDONLYLINUXARMEL = "jitbackendonly-own-linux-armel" +JITBACKENDONLYLINUXARMHF = "jitbackendonly-own-linux-armhf" + +# build only +BUILDLINUXARM = "build-pypy-c-linux-armel" +BUILDJITLINUXARM = "build-pypy-c-jit-linux-armel" +BUILDLINUXARMHF_RASPBIAN = "build-pypy-c-linux-armhf-raspbian" +BUILDJITLINUXARMHF_RASPBIAN = "build-pypy-c-jit-linux-armhf-raspbian" + + +schedulers = [ + Nightly("nighly-arm-0-00", [ + BUILDLINUXARM, # on hhu-cross-armel, uses 1 core + BUILDJITLINUXARM, # on hhu-cross-armel, uses 1 core + BUILDLINUXARMHF_RASPBIAN, # on hhu-cross-raspbianhf, uses 1 core + BUILDJITLINUXARMHF_RASPBIAN, # on hhu-cross-raspbianhf, uses 1 core + JITBACKENDONLYLINUXARMEL, # on hhu-imx.53 + JITBACKENDONLYLINUXARMHF, # on hhu-raspberry-pi + ], branch=None, hour=0, minute=0), + + Triggerable("APPLVLLINUXARM_scheduler", [ + APPLVLLINUXARM, # triggered by BUILDLINUXARM, on hhu-beagleboard + ]), + + Triggerable("JITLINUXARM_scheduler", [ + JITLINUXARM, # triggered by BUILDJITLINUXARM, on hhu-beagleboard + ]), + Triggerable("APPLVLLINUXARMHF_RASPBIAN_scheduler", [ + APPLVLLINUXARMHF_RASPBIAN, # triggered by BUILDLINUXARMHF_RASPBIAN, on hhu-raspberry-pi + ]), + + Triggerable("JITLINUXARMHF_RASPBIAN_scheduler", [ + JITLINUXARMHF_RASPBIAN, # triggered by BUILDJITLINUXARMHF_RASPBIAN, on hhu-raspberry-pi + ]), +] + +builders = [ + # ARM + # armel + {"name": JITBACKENDONLYLINUXARMEL, + "slavenames": ['hhu-i.mx53'], + "builddir": JITBACKENDONLYLINUXARMEL, + "factory": pypyJitBackendOnlyOwnTestFactoryARM, + "category": 'linux-armel', + "locks": [ARMBoardLock.access('counting')], + }, + # armhf + {"name": JITBACKENDONLYLINUXARMHF, + "slavenames": ['hhu-raspberry-pi'], + "builddir": JITBACKENDONLYLINUXARMHF, + "factory": pypyJitBackendOnlyOwnTestFactoryARM, + "category": 'linux-armhf', + "locks": [ARMBoardLock.access('counting')], + }, + # app level builders + {"name": APPLVLLINUXARM, + "slavenames": ["hhu-beagleboard"], + "builddir": APPLVLLINUXARM, + "factory": pypyARMTranslatedAppLevelTestFactory, + "category": "linux-armel", + "locks": [ARMBoardLock.access('counting')], + }, + {"name": JITLINUXARM, + "slavenames": ["hhu-beagleboard"], + 'builddir': JITLINUXARM, + 'factory': pypyARMJITTranslatedTestFactory, + 'category': 'linux-armel', + "locks": [ARMBoardLock.access('counting')], + }, + {"name": APPLVLLINUXARMHF_RASPBIAN, + "slavenames": ["hhu-raspberry-pi"], + "builddir": APPLVLLINUXARMHF_RASPBIAN, + "factory": pypyARMTranslatedAppLevelTestFactory, + "category": "linux-armhf", + "locks": [ARMBoardLock.access('counting')], + }, + {"name": JITLINUXARMHF_RASPBIAN, + "slavenames": ["hhu-raspberry-pi"], + 'builddir': JITLINUXARMHF_RASPBIAN, + 'factory': pypyARMJITTranslatedTestFactory, + 'category': 'linux-armhf', + "locks": [ARMBoardLock.access('counting')], + }, + # Translation Builders for ARM + {"name": BUILDLINUXARM, + "slavenames": ['hhu-cross-armel'], + "builddir": BUILDLINUXARM, + "factory": pypyCrossTranslationFactoryARM, + "category": 'linux-armel', + "locks": [ARMCrossLock.access('counting')], + }, + {"name": BUILDJITLINUXARM, + "slavenames": ['hhu-cross-armel'], + "builddir": BUILDJITLINUXARM, + "factory": pypyJITCrossTranslationFactoryARM, + "category": 'linux-armel', + "locks": [ARMCrossLock.access('counting')], + }, + {"name": BUILDLINUXARMHF_RASPBIAN, + "slavenames": ['hhu-cross-raspbianhf'], + "builddir": BUILDLINUXARMHF_RASPBIAN, + "factory": pypyCrossTranslationFactoryRaspbianHF , + "category": 'linux-armhf', + "locks": [ARMCrossLock.access('counting')], + }, + {"name": BUILDJITLINUXARMHF_RASPBIAN, + "slavenames": ['hhu-cross-raspbianhf'], + "builddir": BUILDJITLINUXARMHF_RASPBIAN, + "factory": pypyJITCrossTranslationFactoryRaspbianHF, + "category": 'linux-armhf', + "locks": [ARMCrossLock.access('counting')], + }, +] diff --git a/bot2/pypybuildbot/master.py b/bot2/pypybuildbot/master.py --- a/bot2/pypybuildbot/master.py +++ b/bot2/pypybuildbot/master.py @@ -47,10 +47,12 @@ pypybuilds = load('pypybuildbot.builds') + +# all ARM buildbot configuration si in arm_master.py +ARM = load('pypybuildbot.arm_master') + TannitCPU = pypybuilds.TannitCPU #WinLockCPU = pypybuilds.WinLockCPU -ARMCrossLock = pypybuilds.ARMCrossLock -ARMBoardLock = pypybuilds.ARMBoardLock pypyOwnTestFactory = pypybuilds.Own() pypyOwnTestFactoryWin = pypybuilds.Own(platform="win32") @@ -167,49 +169,6 @@ platform='linux64') -# ARM own test factories -crosstranslationargs = ['--platform=arm', '--gcrootfinder=shadowstack'] -crosstranslationjitargs = ['--jit-backend=armv7'] -# this one needs a larger timeout due to how it is run -pypyJitBackendOnlyOwnTestFactoryARM = pypybuilds.Own( - cherrypick=':'.join(["jit/backend/arm", - "jit/backend/llsupport", - "jit/backend/test", # kill this one in case it is too slow - ]), - timeout=6 * 3600) -pypyJitOnlyOwnTestFactoryARM = pypybuilds.Own(cherrypick="jit", timeout=2 * 3600) -pypyOwnTestFactoryARM = pypybuilds.Own(timeout=2 * 3600) -pypyCrossTranslationFactoryARM = pypybuilds.NightlyBuild( - translationArgs=crosstranslationargs + ['-O2'], - platform='linux-armel', - interpreter='pypy', - prefix=['schroot', '-c', 'armel'], - trigger='APPLVLLINUXARM_scheduler') - -pypyJITCrossTranslationFactoryARM = pypybuilds.NightlyBuild( - translationArgs=(crosstranslationargs - + jit_translation_args - + crosstranslationjitargs), - platform='linux-armel', - interpreter='pypy', - prefix=['schroot', '-c', 'armel'], - trigger='JITLINUXARM_scheduler') - -pypyARMJITTranslatedTestFactory = pypybuilds.TranslatedTests( - translationArgs=(crosstranslationargs - + jit_translation_args - + crosstranslationjitargs), - lib_python=True, - pypyjit=True, - app_tests=True, - platform='linux-armel', - ) -pypyARMTranslatedAppLevelTestFactory = pypybuilds.TranslatedTests( - translationArgs=crosstranslationargs+['-O2'], - lib_python=True, - app_tests=True, - platform='linux-armel', -) # LINUX32 = "own-linux-x86-32" @@ -221,7 +180,6 @@ WIN64 = "own-win-x86-64" APPLVLLINUX32 = "pypy-c-app-level-linux-x86-32" APPLVLLINUX64 = "pypy-c-app-level-linux-x86-64" -APPLVLLINUXARM = "pypy-c-app-level-linux-armel" APPLVLWIN32 = "pypy-c-app-level-win-x86-32" LIBPYTHON_LINUX32 = "pypy-c-lib-python-linux-x86-32" @@ -229,7 +187,6 @@ JITLINUX32 = "pypy-c-jit-linux-x86-32" JITLINUX64 = "pypy-c-jit-linux-x86-64" -JITLINUXARM = "pypy-c-jit-linux-armel" JITMACOSX64 = "pypy-c-jit-macosx-x86-64" JITWIN32 = "pypy-c-jit-win-x86-32" JITWIN64 = "pypy-c-jit-win-x86-64" @@ -237,17 +194,12 @@ JITFREEBSD964 = 'pypy-c-jit-freebsd-9-x86-64' JITINDIANA32 = "pypy-c-jit-indiana-x86-32" -JITBACKENDONLYLINUXARMEL = "jitbackendonly-own-linux-armel" -JITBACKENDONLYLINUXARMHF = "jitbackendonly-own-linux-armhf" JITONLYLINUXPPC64 = "jitonly-own-linux-ppc-64" JITBENCH = "jit-benchmark-linux-x86-32" JITBENCH64 = "jit-benchmark-linux-x86-64" JITBENCH64_2 = 'jit-benchmark-linux-x86-64-2' CPYTHON_64 = "cpython-2-benchmark-x86-64" -# build only -BUILDLINUXARM = "build-pypy-c-linux-armel" -BUILDJITLINUXARM = "build-pypy-c-jit-linux-armel" extra_opts= {'xerxes': {'keepalive_interval': 15}} @@ -292,22 +244,7 @@ Nightly("nighly-ppc", [ JITONLYLINUXPPC64, # on gcc1 ], branch='ppc-jit-backend', hour=1, minute=0), - - Nightly("nighly-arm-0-00", [ - BUILDLINUXARM, # on hhu-cross-armel, uses 1 core - BUILDJITLINUXARM, # on hhu-cross-armel, uses 1 core - JITBACKENDONLYLINUXARMEL, # on hhu-imx.53 - JITBACKENDONLYLINUXARMHF, # on hhu-raspberry-pi - ], branch=None, hour=0, minute=0), - - Triggerable("APPLVLLINUXARM_scheduler", [ - APPLVLLINUXARM, # triggered by BUILDLINUXARM, on hhu-beagleboard - ]), - - Triggerable("JITLINUXARM_scheduler", [ - JITLINUXARM, # triggered by BUILDJITLINUXARM, on hhu-beagleboard - ]), - ], + ] + ARM.schedulers, 'status': [status, ircbot], @@ -477,54 +414,7 @@ 'factory': pypyOwnTestFactoryIndiana, 'category': 'openindiana32', }, - # ARM - # armel - {"name": JITBACKENDONLYLINUXARMEL, - "slavenames": ['hhu-i.mx53'], - "builddir": JITBACKENDONLYLINUXARMEL, - "factory": pypyJitBackendOnlyOwnTestFactoryARM, - "category": 'linux-armel', - "locks": [ARMBoardLock.access('counting')], - }, - # armhf - {"name": JITBACKENDONLYLINUXARMHF, - "slavenames": ['hhu-raspberry-pi'], - "builddir": JITBACKENDONLYLINUXARMHF, - "factory": pypyJitBackendOnlyOwnTestFactoryARM, - "category": 'linux-armhf', - "locks": [ARMBoardLock.access('counting')], - }, - # app level builders - {"name": APPLVLLINUXARM, - "slavenames": ["hhu-beagleboard"], - "builddir": APPLVLLINUXARM, - "factory": pypyARMTranslatedAppLevelTestFactory, - "category": "linux-armel", - "locks": [ARMBoardLock.access('counting')], - }, - {"name": JITLINUXARM, - "slavenames": ["hhu-beagleboard"], - 'builddir': JITLINUXARM, - 'factory': pypyARMJITTranslatedTestFactory , - 'category': 'linux-armel', - "locks": [ARMBoardLock.access('counting')], - }, - # Translation Builders for ARM - {"name": BUILDLINUXARM, - "slavenames": ['hhu-cross-armel'], - "builddir": BUILDLINUXARM, - "factory": pypyCrossTranslationFactoryARM, - "category": 'linux-armel', - "locks": [ARMCrossLock.access('counting')], - }, - {"name": BUILDJITLINUXARM, - "slavenames": ['hhu-cross-armel'], - "builddir": BUILDJITLINUXARM, - "factory": pypyJITCrossTranslationFactoryARM, - "category": 'linux-armel', - "locks": [ARMCrossLock.access('counting')], - }, - ], + ] + ARM.builders, # http://readthedocs.org/docs/buildbot/en/latest/tour.html#debugging-with-manhole #'manhole': manhole.PasswordManhole("tcp:1234:interface=127.0.0.1", From noreply at buildbot.pypy.org Sun Apr 7 15:56:31 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sun, 7 Apr 2013 15:56:31 +0200 (CEST) Subject: [pypy-commit] pypy.org extradoc: Bah. Update Message-ID: <20130407135631.AAD531C0337@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: extradoc Changeset: r399:dac749cdd52e Date: 2013-04-07 15:56 +0200 http://bitbucket.org/pypy/pypy.org/changeset/dac749cdd52e/ Log: Bah. Update diff --git a/download.html b/download.html --- a/download.html +++ b/download.html @@ -157,9 +157,9 @@
    • Run the rpython script. Here are the common combinations of options (works also with python instead of pypy):

      -pypy ../../rpython/bin/rpython -Ojit           # get the JIT version
      -pypy ../../rpython/bin/rpython -O2             # get the no-jit version
      -pypy ../../rpython/bin/rpython -O2 --sandbox   # get the sandbox version
      +pypy ../../rpython/bin/rpython -Ojit targetpypystandalone           # get the JIT version
      +pypy ../../rpython/bin/rpython -O2 targetpypystandalone             # get the no-jit version
      +pypy ../../rpython/bin/rpython -O2 --sandbox targetpypystandalone   # get the sandbox version
       
    • Enjoy Mandelbrot :-) It takes on the order of half an hour to @@ -183,7 +183,7 @@ Linux 64-bit; probably not much more than 1.6 GB on 32-bit). It should be noted that it is less than with CPython.

      -PYPY_GC_MAX_DELTA=200MB pypy --jit loop_longevity=300 ../../rpython/bin/rpython -Ojit
      +PYPY_GC_MAX_DELTA=200MB pypy --jit loop_longevity=300 ../../rpython/bin/rpython -Ojit targetpypystandalone
       
    • Because of asmgcroot, compiling the generated C files containing the JIT diff --git a/source/download.txt b/source/download.txt --- a/source/download.txt +++ b/source/download.txt @@ -159,9 +159,9 @@ 4. Run the ``rpython`` script. Here are the common combinations of options (works also with ``python`` instead of ``pypy``):: - pypy ../../rpython/bin/rpython -Ojit # get the JIT version - pypy ../../rpython/bin/rpython -O2 # get the no-jit version - pypy ../../rpython/bin/rpython -O2 --sandbox # get the sandbox version + pypy ../../rpython/bin/rpython -Ojit targetpypystandalone # get the JIT version + pypy ../../rpython/bin/rpython -O2 targetpypystandalone # get the no-jit version + pypy ../../rpython/bin/rpython -O2 --sandbox targetpypystandalone # get the sandbox version 5. Enjoy Mandelbrot ``:-)`` It takes on the order of half an hour to finish the translation, and 2.x GB of RAM on a 32-bit system @@ -183,7 +183,7 @@ Linux 64-bit; probably not much more than 1.6 GB on 32-bit). It should be noted that it is less than with CPython. :: - PYPY_GC_MAX_DELTA=200MB pypy --jit loop_longevity=300 ../../rpython/bin/rpython -Ojit + PYPY_GC_MAX_DELTA=200MB pypy --jit loop_longevity=300 ../../rpython/bin/rpython -Ojit targetpypystandalone * Because of ``asmgcroot``, compiling the generated C files containing the JIT is delicate. It requires using either MSVC or gcc with no particularly From noreply at buildbot.pypy.org Sun Apr 7 15:59:07 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sun, 7 Apr 2013 15:59:07 +0200 (CEST) Subject: [pypy-commit] pypy default: Fix the default targetspec: the previous one didn't work Message-ID: <20130407135907.3582D1C0337@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63114:0126d6664978 Date: 2013-04-07 15:58 +0200 http://bitbucket.org/pypy/pypy/changeset/0126d6664978/ Log: Fix the default targetspec: the previous one didn't work diff --git a/rpython/translator/goal/translate.py b/rpython/translator/goal/translate.py --- a/rpython/translator/goal/translate.py +++ b/rpython/translator/goal/translate.py @@ -50,7 +50,7 @@ return result translate_optiondescr = OptionDescription("translate", "XXX", [ - StrOption("targetspec", "XXX", default='../../../pypy/goal/targetpypystandalone', + StrOption("targetspec", "XXX", default='targetpypystandalone', cmdline=None), ChoiceOption("opt", "optimization level", OPT_LEVELS, default=DEFAULT_OPT_LEVEL, From noreply at buildbot.pypy.org Sun Apr 7 16:57:08 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sun, 7 Apr 2013 16:57:08 +0200 (CEST) Subject: [pypy-commit] pypy stm-gc-2: Trying to apply a read-write lock to the issue of waiting for a global Message-ID: <20130407145708.25CC51C010B@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: stm-gc-2 Changeset: r63115:339cc84ccd49 Date: 2013-04-07 16:52 +0200 http://bitbucket.org/pypy/pypy/changeset/339cc84ccd49/ Log: Trying to apply a read-write lock to the issue of waiting for a global pause to do a major GC. Tests coming. diff --git a/rpython/translator/stm/src_stm/et.c b/rpython/translator/stm/src_stm/et.c --- a/rpython/translator/stm/src_stm/et.c +++ b/rpython/translator/stm/src_stm/et.c @@ -67,6 +67,9 @@ static volatile revision_t next_locked_value = LOCKED + 3; /* always odd */ static __thread struct tx_descriptor *thread_descriptor = NULL; +static pthread_rwlock_t rwlock_in_transaction = + PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP; + /************************************************************/ static void ValidateNow(struct tx_descriptor *); @@ -466,6 +469,7 @@ SpinLoop(0); // jump back to the setjmp_buf (this call does not return) d->active = 0; + pthread_rwlock_unlock(&rwlock_in_transaction); longjmp(*d->setjmp_buf, 1); } @@ -480,10 +484,11 @@ static void init_transaction(struct tx_descriptor *d) { + assert(d->active == 0); + pthread_rwlock_rdlock(&rwlock_in_transaction); if (clock_gettime(CLOCK_MONOTONIC, &d->start_real_time) < 0) { d->start_real_time.tv_nsec = -1; } - assert(d->active == 0); assert(d->list_of_read_objects.size == 0); assert(d->gcroots.size == 0); assert(!g2l_any_entry(&d->global_to_local)); @@ -677,6 +682,7 @@ gcptrlist_clear(&d->gcroots); d->num_commits++; d->active = 0; + pthread_rwlock_unlock(&rwlock_in_transaction); } /************************************************************/ From noreply at buildbot.pypy.org Sun Apr 7 16:57:09 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sun, 7 Apr 2013 16:57:09 +0200 (CEST) Subject: [pypy-commit] pypy stm-gc-2: Fix test_stmgcintf.py. Message-ID: <20130407145709.6CD751C010B@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: stm-gc-2 Changeset: r63116:d539fc09cdc6 Date: 2013-04-07 16:56 +0200 http://bitbucket.org/pypy/pypy/changeset/d539fc09cdc6/ Log: Fix test_stmgcintf.py. diff --git a/rpython/translator/stm/src_stm/et.c b/rpython/translator/stm/src_stm/et.c --- a/rpython/translator/stm/src_stm/et.c +++ b/rpython/translator/stm/src_stm/et.c @@ -5,6 +5,13 @@ * runs for long enough. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif +#ifndef _XOPEN_SOURCE +# define _XOPEN_SOURCE 500 +#endif + #include #include #include diff --git a/rpython/translator/stm/src_stm/rpyintf.c b/rpython/translator/stm/src_stm/rpyintf.c --- a/rpython/translator/stm/src_stm/rpyintf.c +++ b/rpython/translator/stm/src_stm/rpyintf.c @@ -105,7 +105,7 @@ assert(d->reads_size_limit_nonatomic == 0); #endif - return d->count_reads > d->reads_size_limit; + return d->count_reads >= d->reads_size_limit; } void stm_set_transaction_length(long length_max) diff --git a/rpython/translator/stm/test/test_stmgcintf.c b/rpython/translator/stm/test/test_stmgcintf.c --- a/rpython/translator/stm/test/test_stmgcintf.c +++ b/rpython/translator/stm/test/test_stmgcintf.c @@ -1,3 +1,6 @@ +#define _GNU_SOURCE +#define _XOPEN_SOURCE 500 + #include #define PYPY_LONG_BIT (sizeof(long) * 8) @@ -25,6 +28,10 @@ } S1; typedef char bool_t; +typedef char RPyString; + +#define _RPyString_AsString(x) x +#define RPyString_Size(x) strlen(x) #include "src_stm/et.h" diff --git a/rpython/translator/stm/test/test_stmgcintf.py b/rpython/translator/stm/test/test_stmgcintf.py --- a/rpython/translator/stm/test/test_stmgcintf.py +++ b/rpython/translator/stm/test/test_stmgcintf.py @@ -9,7 +9,7 @@ try: os.chdir(thisdir) exitcode = os.system( - "gcc -g -o '%s' -pthread -I.. test_stmgcintf.c" % ( + "gcc -lrt -g -o '%s' -pthread -I.. test_stmgcintf.c" % ( executable,)) assert exitcode == 0 finally: From noreply at buildbot.pypy.org Sun Apr 7 17:00:05 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sun, 7 Apr 2013 17:00:05 +0200 (CEST) Subject: [pypy-commit] pypy stm-gc-2: Better fix Message-ID: <20130407150005.A58481C010B@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: stm-gc-2 Changeset: r63117:4f86a6afbcdb Date: 2013-04-07 16:59 +0200 http://bitbucket.org/pypy/pypy/changeset/4f86a6afbcdb/ Log: Better fix diff --git a/rpython/translator/stm/src_stm/et.c b/rpython/translator/stm/src_stm/et.c --- a/rpython/translator/stm/src_stm/et.c +++ b/rpython/translator/stm/src_stm/et.c @@ -499,7 +499,7 @@ assert(d->list_of_read_objects.size == 0); assert(d->gcroots.size == 0); assert(!g2l_any_entry(&d->global_to_local)); - d->count_reads = 0; + d->count_reads = 1; fxcache_clear(&d->recent_reads_cache); gcptrlist_clear(&d->undolog); gcptrlist_clear(&d->abortinfo); diff --git a/rpython/translator/stm/src_stm/rpyintf.c b/rpython/translator/stm/src_stm/rpyintf.c --- a/rpython/translator/stm/src_stm/rpyintf.c +++ b/rpython/translator/stm/src_stm/rpyintf.c @@ -84,7 +84,8 @@ /* a single comparison to handle all cases: - if d->atomic, then we should return False. This is done by - forcing reads_size_limit to ULONG_MAX as soon as atomic > 0. + forcing reads_size_limit to ULONG_MAX as soon as atomic > 0, + and no possible value of 'count_reads' is greater than ULONG_MAX. - otherwise, if is_inevitable(), then we should return True. This is done by forcing both reads_size_limit and @@ -105,7 +106,7 @@ assert(d->reads_size_limit_nonatomic == 0); #endif - return d->count_reads >= d->reads_size_limit; + return d->count_reads > d->reads_size_limit; } void stm_set_transaction_length(long length_max) From noreply at buildbot.pypy.org Sun Apr 7 17:44:24 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sun, 7 Apr 2013 17:44:24 +0200 (CEST) Subject: [pypy-commit] pypy stm-gc-2: The minimal interface that should be enough to synchronize all threads Message-ID: <20130407154424.AC6071C0DCB@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: stm-gc-2 Changeset: r63118:ef7cc6c7f545 Date: 2013-04-07 17:44 +0200 http://bitbucket.org/pypy/pypy/changeset/ef7cc6c7f545/ Log: The minimal interface that should be enough to synchronize all threads at the start of a major GC diff --git a/rpython/translator/stm/src_stm/et.c b/rpython/translator/stm/src_stm/et.c --- a/rpython/translator/stm/src_stm/et.c +++ b/rpython/translator/stm/src_stm/et.c @@ -393,6 +393,8 @@ size_t size; struct timespec now; long long elapsed_time; + int err; + assert(d->active); assert(!is_inevitable(d)); assert(num < ABORT_REASONS); @@ -476,7 +478,8 @@ SpinLoop(0); // jump back to the setjmp_buf (this call does not return) d->active = 0; - pthread_rwlock_unlock(&rwlock_in_transaction); + err = pthread_rwlock_unlock(&rwlock_in_transaction); + assert(err == 0); longjmp(*d->setjmp_buf, 1); } @@ -491,8 +494,11 @@ static void init_transaction(struct tx_descriptor *d) { + int err; assert(d->active == 0); - pthread_rwlock_rdlock(&rwlock_in_transaction); + err = pthread_rwlock_rdlock(&rwlock_in_transaction); + assert(err == 0); + if (clock_gettime(CLOCK_MONOTONIC, &d->start_real_time) < 0) { d->start_real_time.tv_nsec = -1; } @@ -643,6 +649,7 @@ { revision_t cur_time; struct tx_descriptor *d = thread_descriptor; + int err; assert(d->active != 0); FindRootsForLocalCollect(d); @@ -689,7 +696,8 @@ gcptrlist_clear(&d->gcroots); d->num_commits++; d->active = 0; - pthread_rwlock_unlock(&rwlock_in_transaction); + err = pthread_rwlock_unlock(&rwlock_in_transaction); + assert(err == 0); } /************************************************************/ diff --git a/rpython/translator/stm/src_stm/rpyintf.c b/rpython/translator/stm/src_stm/rpyintf.c --- a/rpython/translator/stm/src_stm/rpyintf.c +++ b/rpython/translator/stm/src_stm/rpyintf.c @@ -63,6 +63,9 @@ } static unsigned long stm_regular_length_limit = ULONG_MAX; +static volatile int break_please = 0; + +static void reached_safe_point(void); void stm_add_atomic(long delta) { @@ -106,6 +109,9 @@ assert(d->reads_size_limit_nonatomic == 0); #endif + if (break_please) + reached_safe_point(); + return d->count_reads > d->reads_size_limit; } @@ -173,6 +179,9 @@ if (!d->atomic) BeginTransaction(&_jmpbuf); + if (break_please) + reached_safe_point(); + /* invoke the callback in the new transaction */ result = callback(arg, counter); @@ -192,6 +201,53 @@ PYPY_DEBUG_STOP("stm-perform-transaction"); } +static struct tx_descriptor *in_single_thread = NULL; /* for debugging */ + +void stm_start_single_thread(void) +{ + /* Called by the GC, just after a minor collection, when we need to do + a major collection. When it returns, it acquired the "write lock" + which prevents any other thread from running a transaction. */ + int err; + break_please = 1; + err = pthread_rwlock_unlock(&rwlock_in_transaction); + assert(err == 0); + err = pthread_rwlock_wrlock(&rwlock_in_transaction); + assert(err == 0); + break_please = 0; + + assert(in_single_thread == NULL); + in_single_thread = thread_descriptor; + assert(in_single_thread != NULL); +} + +void stm_stop_single_thread(void) +{ + int err; + + assert(in_single_thread == thread_descriptor); + in_single_thread = NULL; + + err = pthread_rwlock_unlock(&rwlock_in_transaction); + assert(err == 0); + err = pthread_rwlock_rdlock(&rwlock_in_transaction); + assert(err == 0); +} + +static void reached_safe_point(void) +{ + int err; + struct tx_descriptor *d = thread_descriptor; + assert(in_single_thread != d); + if (d->active) + { + err = pthread_rwlock_unlock(&rwlock_in_transaction); + assert(err == 0); + err = pthread_rwlock_rdlock(&rwlock_in_transaction); + assert(err == 0); + } +} + void stm_abort_and_retry(void) { AbortTransaction(4); /* manual abort */ diff --git a/rpython/translator/stm/test/test_stmgcintf.c b/rpython/translator/stm/test/test_stmgcintf.c --- a/rpython/translator/stm/test/test_stmgcintf.c +++ b/rpython/translator/stm/test/test_stmgcintf.c @@ -344,6 +344,22 @@ /************************************************************/ +void single_thread_1(void) +{ + stm_start_single_thread(); + stm_stop_single_thread(); + stm_start_single_thread(); + stm_stop_single_thread(); + /* check that the assert() included in these functions don't trigger */ +} + +void test_single_thread(void) +{ + run_in_transaction(single_thread_1, '.'); +} + +/************************************************************/ + #define XTEST(name) if (!strcmp(argv[1], #name)) { test_##name(); return 0; } @@ -361,6 +377,7 @@ XTEST(duplicator); XTEST(try_inevitable); XTEST(should_break_transaction); + XTEST(single_thread); printf("bad test name\n"); return 1; } From noreply at buildbot.pypy.org Sun Apr 7 20:45:15 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sun, 7 Apr 2013 20:45:15 +0200 (CEST) Subject: [pypy-commit] pypy stm-gc-2: Export this API through rstm.py. Message-ID: <20130407184515.20C231C0DCB@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: stm-gc-2 Changeset: r63119:b3939745e8f0 Date: 2013-04-07 20:25 +0200 http://bitbucket.org/pypy/pypy/changeset/b3939745e8f0/ Log: Export this API through rstm.py. diff --git a/rpython/rlib/rstm.py b/rpython/rlib/rstm.py --- a/rpython/rlib/rstm.py +++ b/rpython/rlib/rstm.py @@ -46,6 +46,12 @@ def abort_and_retry(): stmgcintf.StmOperations.abort_and_retry() +def start_single_thread(): + stmgcintf.StmOperations.start_single_thread() + +def stop_single_thread(): + stmgcintf.StmOperations.stop_single_thread() + def before_external_call(): if not is_atomic(): e = get_errno() diff --git a/rpython/translator/stm/stmgcintf.py b/rpython/translator/stm/stmgcintf.py --- a/rpython/translator/stm/stmgcintf.py +++ b/rpython/translator/stm/stmgcintf.py @@ -73,5 +73,8 @@ inspect_abort_info = smexternal('stm_inspect_abort_info', [], rffi.CCHARP) + start_single_thread = smexternal('stm_start_single_thread',[], lltype.Void) + stop_single_thread = smexternal('stm_stop_single_thread', [], lltype.Void) + # for testing abort_and_retry = smexternal('stm_abort_and_retry', [], lltype.Void) From noreply at buildbot.pypy.org Sun Apr 7 20:45:16 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sun, 7 Apr 2013 20:45:16 +0200 (CEST) Subject: [pypy-commit] pypy stm-gc-2: in-progress: fixing the tests Message-ID: <20130407184516.3CDED1C15A2@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: stm-gc-2 Changeset: r63120:e5770f052d9a Date: 2013-04-07 20:44 +0200 http://bitbucket.org/pypy/pypy/changeset/e5770f052d9a/ Log: in-progress: fixing the tests diff --git a/rpython/memory/gc/test/test_stmgc.py b/rpython/memory/gc/test/test_stmgc.py --- a/rpython/memory/gc/test/test_stmgc.py +++ b/rpython/memory/gc/test/test_stmgc.py @@ -57,11 +57,11 @@ if self.threadnum == 0: assert not hasattr(self, '_tls_dict') self._tls_dict = {0: tls} - self._tldicts = {0: {}} + self._tldicts = {0: []} self._transactional_copies = [] else: self._tls_dict[self.threadnum] = tls - self._tldicts[self.threadnum] = {} + self._tldicts[self.threadnum] = [] def get_tls(self): return self._tls_dict[self.threadnum] @@ -74,20 +74,27 @@ assert lltype.typeOf(obj) == llmemory.Address assert obj tldict = self._tldicts[self.threadnum] - return tldict.get(obj, llmemory.NULL) + for key, value in tldict: + if obj == key: + return value + else: + return llmemory.NULL def tldict_add(self, obj, localobj): assert lltype.typeOf(obj) == llmemory.Address assert lltype.typeOf(localobj) == llmemory.Address + assert obj + assert localobj tldict = self._tldicts[self.threadnum] - assert obj not in tldict - tldict[obj] = localobj + for key, _ in tldict: + assert obj != key + tldict.append((obj, localobj)) def tldict_enum(self): from rpython.memory.gc.stmtls import StmGCTLS callback = StmGCTLS._stm_enum_callback tls = self.get_tls() - for key, value in self._tldicts[self.threadnum].iteritems(): + for key, value in self._tldicts[self.threadnum]: assert (llmemory.cast_int_to_adr(self._gc.header(value).revision) == key) callback(tls, value) @@ -159,11 +166,9 @@ # ---------- # test helpers - def malloc(self, STRUCT, weakref=False, globl='auto'): + def malloc(self, STRUCT, weakref=False, globl=False): size = llarena.round_up_for_allocation(llmemory.sizeof(STRUCT)) tid = lltype.cast_primitive(llgroup.HALFWORD, 123 + weakref) - if globl == 'auto': - globl = (self.gc.stm_operations.threadnum == 0) if globl: totalsize = self.gc.gcheaderbuilder.size_gc_header + size adr1 = llarena.arena_malloc(llmemory.raw_malloc_usage(totalsize), @@ -179,6 +184,9 @@ contains_weakptr=weakref) realobj = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), gcref) return realobj + def settldict(self, globl, locl): + self.gc.stm_operations.tldict_add(llmemory.cast_ptr_to_adr(globl), + llmemory.cast_ptr_to_adr(locl)) def select_thread(self, threadnum): self.gc.stm_operations.threadnum = threadnum if threadnum not in self.gc.stm_operations._tls_dict: @@ -187,16 +195,16 @@ def gcsize(self, S): return (llmemory.raw_malloc_usage(llmemory.sizeof(self.gc.HDR)) + llmemory.raw_malloc_usage(llmemory.sizeof(S))) - def checkflags(self, obj, must_have_global, must_have_was_copied, - must_have_version='?'): + def checkflags(self, obj, globl='?', localcopy='?', version='?'): if lltype.typeOf(obj) != llmemory.Address: obj = llmemory.cast_ptr_to_adr(obj) hdr = self.gc.header(obj) - assert (hdr.tid & GCFLAG_GLOBAL != 0) == must_have_global - if must_have_was_copied != '?': - assert (hdr.tid & GCFLAG_LOCAL_COPY != 0) == must_have_was_copied - if must_have_version != '?': - assert hdr.version == must_have_version + if globl != '?': + assert (hdr.tid & GCFLAG_GLOBAL != 0) == globl + if localcopy != '?': + assert (hdr.tid & GCFLAG_LOCAL_COPY != 0) == localcopy + if version != '?': + assert hdr.version == version def header(self, P): if lltype.typeOf(P) != llmemory.Address: @@ -230,6 +238,7 @@ return G def stm_writebarrier(self, P): + P = llmemory.cast_ptr_to_adr(P) hdr = self.header(P) if hdr.tid & GCFLAG_NOT_WRITTEN == 0: # already a local, written-to object @@ -246,7 +255,7 @@ W = self.stm_localize(R) self.gc.header(W).tid &= ~GCFLAG_NOT_WRITTEN self.gc.header(R).tid |= GCFLAG_POSSIBLY_OUTDATED - return W + return W.ptr def stm_localize(self, R): L = self.gc.stm_operations.tldict_lookup(R) @@ -261,7 +270,7 @@ assert hdr.tid & GCFLAG_NOT_WRITTEN set_hdr_revision(hdr, R) # back-reference to the original self.gc.stm_operations.tldict_add(R, L) - self.gc.stm_operations._transactional_copies.append((R, L)) + self.gc.stm_operations._transactional_copies.append((R.ptr, L.ptr)) return L @@ -305,7 +314,7 @@ assert obj == t # self.select_thread(0) - s = self.malloc(S) + s = self.malloc(S, globl=True) # self.select_thread(1) assert self.header(s).tid & GCFLAG_GLOBAL != 0 @@ -313,37 +322,36 @@ self.header(s).tid |= GCFLAG_POSSIBLY_OUTDATED self.header(t).tid |= GCFLAG_LOCAL_COPY | GCFLAG_VISITED self.set_hdr_revision(self.header(t), s) - self.gc.stm_operations._tldicts[1][s_adr] = t_adr + self.settldict(s, t) obj = self.stm_writebarrier(s) # global copied object assert obj == t assert self.gc.stm_operations._transactional_copies == [] def test_write_barrier_new(self): self.select_thread(0) - s, s_adr = self.malloc(S) + s = self.malloc(S, globl=True) # global object, not copied so far s.a = 12 s.b = 34 # - self.select_thread(1) # global object, not copied so far - t_adr = self.stm_writebarrier(s_adr) - assert t_adr != s_adr - t = t_adr.ptr + self.select_thread(1) + t = self.stm_writebarrier(s) + assert t != s assert t.a == 12 assert t.b == 34 - assert self.gc.stm_operations._transactional_copies == [(s_adr, t_adr)] + assert self.gc.stm_operations._transactional_copies == [(s, t)] # - u_adr = self.stm_writebarrier(s_adr) # again - assert u_adr == t_adr + u = self.stm_writebarrier(s) # again + assert u == t # - u_adr = self.stm_writebarrier(u_adr) # local object - assert u_adr == t_adr + u = self.stm_writebarrier(u) # local object + assert u == t def test_write_barrier_main_thread(self): - t, t_adr = self.malloc(S, globl=False) - self.checkflags(t_adr, False, False) - obj = self.stm_writebarrier(t_adr) # main thread, but not global - assert obj == t_adr - self.checkflags(obj, False, False) + t = self.malloc(S, globl=False) + self.checkflags(t, globl=False, localcopy=False) + obj = self.stm_writebarrier(t) # main thread, but not global + assert obj == t + self.checkflags(obj, globl=False, localcopy=False) def test_random_gc_usage(self): import random From noreply at buildbot.pypy.org Sun Apr 7 21:15:48 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sun, 7 Apr 2013 21:15:48 +0200 (CEST) Subject: [pypy-commit] pypy stm-gc-2: in-progress Message-ID: <20130407191548.582601C0334@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: stm-gc-2 Changeset: r63121:5420a855df2c Date: 2013-04-07 21:10 +0200 http://bitbucket.org/pypy/pypy/changeset/5420a855df2c/ Log: in-progress diff --git a/rpython/memory/gc/test/test_stmgc.py b/rpython/memory/gc/test/test_stmgc.py --- a/rpython/memory/gc/test/test_stmgc.py +++ b/rpython/memory/gc/test/test_stmgc.py @@ -70,11 +70,13 @@ del self._tls_dict[self.threadnum] del self._tldicts[self.threadnum] + def get_tldict(self): + return self._tldicts[self.threadnum] + def tldict_lookup(self, obj): assert lltype.typeOf(obj) == llmemory.Address assert obj - tldict = self._tldicts[self.threadnum] - for key, value in tldict: + for key, value in self.get_tldict(): if obj == key: return value else: @@ -85,7 +87,7 @@ assert lltype.typeOf(localobj) == llmemory.Address assert obj assert localobj - tldict = self._tldicts[self.threadnum] + tldict = self.get_tldict() for key, _ in tldict: assert obj != key tldict.append((obj, localobj)) @@ -94,7 +96,7 @@ from rpython.memory.gc.stmtls import StmGCTLS callback = StmGCTLS._stm_enum_callback tls = self.get_tls() - for key, value in self._tldicts[self.threadnum]: + for key, value in self.get_tldict(): assert (llmemory.cast_int_to_adr(self._gc.header(value).revision) == key) callback(tls, value) @@ -217,6 +219,7 @@ set_hdr_revision(hdr, P) def stm_readbarrier(self, P): + P = llmemory.cast_ptr_to_adr(P) hdr = self.header(P) if hdr.tid & GCFLAG_GLOBAL == 0: # already a local object @@ -227,7 +230,7 @@ if hdr.tid & GCFLAG_POSSIBLY_OUTDATED == 0: assert not L elif L: - xxx + return L.ptr return R.ptr def stm_latest_global_rev(self, G): @@ -273,6 +276,26 @@ self.gc.stm_operations._transactional_copies.append((R.ptr, L.ptr)) return L + def do_local_collection(self): + self.gc.stop_transaction() + tldict = self.gc.stm_operations.get_tldict() + for obj, localobj in tldict: + hdr = self.gc.header(obj) + localhdr = self.gc.header(localobj) + assert localhdr.tid & GCFLAG_GLOBAL == 0 + assert localhdr.tid & GCFLAG_LOCAL_COPY + assert localhdr.tid & GCFLAG_POSSIBLY_OUTDATED == 0 + localhdr.tid |= GCFLAG_GLOBAL | GCFLAG_NOT_WRITTEN + localhdr.tid &= ~GCFLAG_LOCAL_COPY + assert localhdr.revision.adr == obj + localhdr.revision = r_uint(43) + assert hdr.tid & GCFLAG_GLOBAL + assert hdr.tid & GCFLAG_NOT_WRITTEN + assert hdr.tid & GCFLAG_POSSIBLY_OUTDATED + hdr.revision = llmemory.cast_adr_to_uint_symbolic(localobj) + del tldict[:] + self.gc.start_transaction() + class TestBasic(StmGCTests): @@ -393,7 +416,7 @@ shape.append(found[obj._obj]) return shape # - prebuilt = [self.malloc(SR, globl=True)[0] for i in range(15)] + prebuilt = [self.malloc(SR, globl=True) for i in range(15)] globals = set(obj._obj for obj in prebuilt) root_objects = prebuilt[:] all_objects = root_objects[:] @@ -401,7 +424,7 @@ # for iteration in range(3): # add 6 freshly malloced objects from the nursery - new_objects = [self.malloc(SR, globl=False)[0] for i in range(6)] + new_objects = [self.malloc(SR, globl=False) for i in range(6)] set_new_objects = set(obj._obj for obj in new_objects) all_objects = all_objects + new_objects set_all_objects = set(obj._obj for obj in all_objects) @@ -425,18 +448,16 @@ missing_objects.extend(all_objects) dstobj = random.choice(missing_objects) name = random.choice(('sr2', 'sr3')) - src_adr = llmemory.cast_ptr_to_adr(srcobj) - adr2 = self.stm_writebarrier(src_adr) - obj2 = llmemory.cast_adr_to_ptr(adr2, lltype.Ptr(SR)) + obj2 = self.stm_writebarrier(srcobj) setattr(obj2, name, dstobj) # # Record the shape of the graph of reachable objects shapes = [shape_of_reachable(obj) for obj in root_objects] # - # Do a minor collection + # Do a local end-of-transaction collection for p in fromstack: self.gc.root_walker.push(p) - self.gc.collect(0) + self.do_local_collection() # # Reload 'fromstack', which may have moved, and compare the shape # of the graph of reachable objects now @@ -488,7 +509,7 @@ from rpython.memory.gc.test import test_stmtls self.gc.root_walker = test_stmtls.FakeRootWalker() # - tr1, tr1_adr = self.malloc(SR, globl=False) # local + tr1 = self.malloc(SR, globl=False) # local self.checkflags(tr1_adr, False, False) # check that it is local self.gc.root_walker.push(tr1) self.gc.stop_transaction() @@ -500,8 +521,8 @@ from rpython.memory.gc.test import test_stmtls self.gc.root_walker = test_stmtls.FakeRootWalker() # - tr1, tr1_adr = self.malloc(SR, globl=False) # local - tr2, tr2_adr = self.malloc(SR, globl=False) # local + tr1 = self.malloc(SR, globl=False) # local + tr2 = self.malloc(SR, globl=False) # local self.checkflags(tr1_adr, False, False) # check that it is local self.checkflags(tr2_adr, False, False) # check that it is local tr1.sr2 = tr2 @@ -520,8 +541,8 @@ self.checkflags(sr2_adr, True, False) # sr2 is a global def test_collect_from_main_thread_was_global_objects(self): - tr1, tr1_adr = self.malloc(SR, globl=True) # a global prebuilt object - sr2, sr2_adr = self.malloc(SR, globl=False) # sr2 is a local + tr1 = self.malloc(SR, globl=True) # a global prebuilt object + sr2 = self.malloc(SR, globl=False) # sr2 is a local self.checkflags(sr2_adr, False, False) # check that sr2 is a local sr1_adr = self.gc.stm_writebarrier(tr1_adr) assert sr1_adr != tr1_adr # sr1 is the local copy @@ -538,16 +559,16 @@ def test_commit_transaction_empty(self): self.select_thread(1) - s, s_adr = self.malloc(S) - t, t_adr = self.malloc(S) + s = self.malloc(S) + t = self.malloc(S) self.gc.stop_transaction() # no roots self.gc.start_transaction() main_tls = self.gc.get_tls() assert main_tls.nursery_free == main_tls.nursery_start # empty def test_commit_tldict_entry_with_global_references(self): - t, t_adr = self.malloc(S) - tr, tr_adr = self.malloc(SR) + t = self.malloc(S) + tr = self.malloc(SR) tr.s1 = t self.select_thread(1) sr_adr = self.gc.stm_writebarrier(tr_adr) @@ -556,18 +577,18 @@ assert s_adr != t_adr def test_commit_local_obj_with_global_references(self): - t, t_adr = self.malloc(S) - tr, tr_adr = self.malloc(SR) + t = self.malloc(S) + tr = self.malloc(SR) tr.s1 = t self.select_thread(1) sr_adr = self.gc.stm_writebarrier(tr_adr) assert sr_adr != tr_adr sr = llmemory.cast_adr_to_ptr(sr_adr, lltype.Ptr(SR)) - sr2, sr2_adr = self.malloc(SR) + sr2 = self.malloc(SR) sr.sr2 = sr2 def test_commit_with_ref_to_local_copy(self): - tr, tr_adr = self.malloc(SR) + tr = self.malloc(SR) sr_adr = self.gc.stm_writebarrier(tr_adr) assert sr_adr != tr_adr sr = llmemory.cast_adr_to_ptr(sr_adr, lltype.Ptr(SR)) @@ -576,17 +597,17 @@ assert sr.sr2 == tr def test_do_get_size(self): - s1, s1_adr = self.malloc(S) + s1 = self.malloc(S) assert (repr(self.gc._stm_getsize(s1_adr)) == repr(fake_get_size(s1_adr))) def test_id_of_global(self): - s, s_adr = self.malloc(S) + s = self.malloc(S) i = self.gc.id(s) assert i == llmemory.cast_adr_to_int(s_adr) def test_id_of_globallocal(self): - s, s_adr = self.malloc(S) + s = self.malloc(S) t_adr = self.gc.stm_writebarrier(s_adr) # make a local copy assert t_adr != s_adr t = llmemory.cast_adr_to_ptr(t_adr, llmemory.GCREF) @@ -597,17 +618,17 @@ assert i == self.gc.id(s) def test_id_of_local_nonsurviving(self): - s, s_adr = self.malloc(S, globl=False) + s = self.malloc(S, globl=False) i = self.gc.id(s) assert i != llmemory.cast_adr_to_int(s_adr) assert i == self.gc.id(s) self.gc.stop_transaction() def test_id_of_local_surviving(self): - sr1, sr1_adr = self.malloc(SR, globl=True) + sr1 = self.malloc(SR, globl=True) assert sr1.s1 == lltype.nullptr(S) assert sr1.sr2 == lltype.nullptr(SR) - t2, t2_adr = self.malloc(S, globl=False) + t2 = self.malloc(S, globl=False) t2.a = 423 tr1_adr = self.gc.stm_writebarrier(sr1_adr) assert tr1_adr != sr1_adr @@ -624,14 +645,14 @@ assert self.gc.id(s2) == i def test_hash_of_global(self): - s, s_adr = self.malloc(S) + s = self.malloc(S) i = self.gc.identityhash(s) assert i == mangle_hash(llmemory.cast_adr_to_int(s_adr)) self.gc.collect(0) assert self.gc.identityhash(s) == i def test_hash_of_globallocal(self): - s, s_adr = self.malloc(S, globl=True) + s = self.malloc(S, globl=True) t_adr = self.stm_writebarrier(s_adr) # make a local copy t = llmemory.cast_adr_to_ptr(t_adr, llmemory.GCREF) i = self.gc.identityhash(t) @@ -641,7 +662,7 @@ assert i == self.gc.identityhash(s) def test_hash_of_local_nonsurviving(self): - s, s_adr = self.malloc(S, globl=False) + s = self.malloc(S, globl=False) i = self.gc.identityhash(s) # XXX fix me #assert i != mangle_hash(llmemory.cast_adr_to_int(s_adr)) @@ -649,8 +670,8 @@ self.gc.stop_transaction() def test_hash_of_local_surviving(self): - sr1, sr1_adr = self.malloc(SR, globl=True) - t2, t2_adr = self.malloc(S, globl=False) + sr1 = self.malloc(SR, globl=True) + t2 = self.malloc(S, globl=False) t2.a = 424 tr1_adr = self.stm_writebarrier(sr1_adr) assert tr1_adr != sr1_adr @@ -668,9 +689,9 @@ assert self.gc.identityhash(s2) == i def test_weakref_to_global(self): - swr1, swr1_adr = self.malloc(SWR, globl=True) - s2, s2_adr = self.malloc(S, globl=True) - wr1, wr1_adr = self.malloc(WR, globl=False, weakref=True) + swr1 = self.malloc(SWR, globl=True) + s2 = self.malloc(S, globl=True) + wr1 = self.malloc(WR, globl=False, weakref=True) wr1.wadr = s2_adr twr1_adr = self.gc.stm_writebarrier(swr1_adr) twr1 = llmemory.cast_adr_to_ptr(twr1_adr, lltype.Ptr(SWR)) @@ -681,9 +702,9 @@ assert wr2.wadr == s2_adr # survives def test_weakref_to_local_dying(self): - swr1, swr1_adr = self.malloc(SWR, globl=True) - t2, t2_adr = self.malloc(S, globl=False) - wr1, wr1_adr = self.malloc(WR, globl=False, weakref=True) + swr1 = self.malloc(SWR, globl=True) + t2 = self.malloc(S, globl=False) + wr1 = self.malloc(WR, globl=False, weakref=True) wr1.wadr = t2_adr twr1_adr = self.gc.stm_writebarrier(swr1_adr) twr1 = llmemory.cast_adr_to_ptr(twr1_adr, lltype.Ptr(SWR)) @@ -694,10 +715,10 @@ assert wr2.wadr == llmemory.NULL # dies def test_weakref_to_local_surviving(self): - sr1, sr1_adr = self.malloc(SR, globl=True) - swr1, swr1_adr = self.malloc(SWR, globl=True) - t2, t2_adr = self.malloc(S, globl=False) - wr1, wr1_adr = self.malloc(WR, globl=False, weakref=True) + sr1 = self.malloc(SR, globl=True) + swr1 = self.malloc(SWR, globl=True) + t2 = self.malloc(S, globl=False) + wr1 = self.malloc(WR, globl=False, weakref=True) wr1.wadr = t2_adr twr1_adr = self.gc.stm_writebarrier(swr1_adr) twr1 = llmemory.cast_adr_to_ptr(twr1_adr, lltype.Ptr(SWR)) @@ -718,8 +739,8 @@ from rpython.memory.gc.test import test_stmtls self.gc.root_walker = test_stmtls.FakeRootWalker() # - sr1, sr1_adr = self.malloc(SR, globl=False) - wr1, wr1_adr = self.malloc(WR, globl=False, weakref=True) + sr1 = self.malloc(SR, globl=False) + wr1 = self.malloc(WR, globl=False, weakref=True) wr1.wadr = sr1_adr # self.gc.root_walker.push(wr1) @@ -738,18 +759,18 @@ assert a == llmemory.NULL def test_normalize_global_already_global(self): - sr1, sr1_adr = self.malloc(SR) + sr1 = self.malloc(SR) a = self.gc.stm_normalize_global(sr1_adr) assert a == sr1_adr def test_normalize_global_purely_local(self): self.select_thread(1) - sr1, sr1_adr = self.malloc(SR) + sr1 = self.malloc(SR) a = self.gc.stm_normalize_global(sr1_adr) assert a == sr1_adr def test_normalize_global_local_copy(self): - sr1, sr1_adr = self.malloc(SR) + sr1 = self.malloc(SR) self.select_thread(1) tr1_adr = self.gc.stm_writebarrier(sr1_adr) a = self.gc.stm_normalize_global(sr1_adr) @@ -764,7 +785,7 @@ nongc = lltype.malloc(NONGC, immortal=True, flavor='raw') self.gc.root_walker.prebuilt_nongc = [(nongc, 's')] # - s, _ = self.malloc(S, globl=False) # a local object + s = self.malloc(S, globl=False) # a local object nongc.s = s self.gc.collect(0) # keeps LOCAL s = nongc.s # reload, it moved From noreply at buildbot.pypy.org Sun Apr 7 21:15:49 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sun, 7 Apr 2013 21:15:49 +0200 (CEST) Subject: [pypy-commit] pypy stm-gc-2: Skip all old failing tests Message-ID: <20130407191549.A48E51C0334@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: stm-gc-2 Changeset: r63122:65acd22b89cf Date: 2013-04-07 21:15 +0200 http://bitbucket.org/pypy/pypy/changeset/65acd22b89cf/ Log: Skip all old failing tests diff --git a/rpython/memory/gc/test/test_stmgc.py b/rpython/memory/gc/test/test_stmgc.py --- a/rpython/memory/gc/test/test_stmgc.py +++ b/rpython/memory/gc/test/test_stmgc.py @@ -377,6 +377,7 @@ self.checkflags(obj, globl=False, localcopy=False) def test_random_gc_usage(self): + py.test.skip("XXX") import random from rpython.memory.gc.test import test_stmtls self.gc.root_walker = test_stmtls.FakeRootWalker() @@ -481,6 +482,7 @@ print 'Iteration %d finished' % iteration def test_relocalize_objects_after_transaction_break(self): + py.test.skip("XXX") from rpython.memory.gc.test import test_stmtls self.gc.root_walker = test_stmtls.FakeRootWalker() # @@ -506,6 +508,7 @@ self.checkflags(tr3_adr, True, True) # tr3 has become global again def test_obj_with_invalid_offset_after_transaction_stop(self): + py.test.skip("XXX") from rpython.memory.gc.test import test_stmtls self.gc.root_walker = test_stmtls.FakeRootWalker() # @@ -518,6 +521,7 @@ py.test.raises(llarena.ArenaError, self.gc.root_walker.pop) def test_non_prebuilt_relocalize_after_transaction_break(self): + py.test.skip("XXX") from rpython.memory.gc.test import test_stmtls self.gc.root_walker = test_stmtls.FakeRootWalker() # @@ -541,6 +545,7 @@ self.checkflags(sr2_adr, True, False) # sr2 is a global def test_collect_from_main_thread_was_global_objects(self): + py.test.skip("XXX") tr1 = self.malloc(SR, globl=True) # a global prebuilt object sr2 = self.malloc(SR, globl=False) # sr2 is a local self.checkflags(sr2_adr, False, False) # check that sr2 is a local @@ -567,6 +572,7 @@ assert main_tls.nursery_free == main_tls.nursery_start # empty def test_commit_tldict_entry_with_global_references(self): + py.test.skip("XXX") t = self.malloc(S) tr = self.malloc(SR) tr.s1 = t @@ -577,6 +583,7 @@ assert s_adr != t_adr def test_commit_local_obj_with_global_references(self): + py.test.skip("XXX") t = self.malloc(S) tr = self.malloc(SR) tr.s1 = t @@ -588,6 +595,7 @@ sr.sr2 = sr2 def test_commit_with_ref_to_local_copy(self): + py.test.skip("XXX") tr = self.malloc(SR) sr_adr = self.gc.stm_writebarrier(tr_adr) assert sr_adr != tr_adr @@ -597,16 +605,19 @@ assert sr.sr2 == tr def test_do_get_size(self): + py.test.skip("XXX") s1 = self.malloc(S) assert (repr(self.gc._stm_getsize(s1_adr)) == repr(fake_get_size(s1_adr))) def test_id_of_global(self): + py.test.skip("XXX") s = self.malloc(S) i = self.gc.id(s) assert i == llmemory.cast_adr_to_int(s_adr) def test_id_of_globallocal(self): + py.test.skip("XXX") s = self.malloc(S) t_adr = self.gc.stm_writebarrier(s_adr) # make a local copy assert t_adr != s_adr @@ -618,6 +629,7 @@ assert i == self.gc.id(s) def test_id_of_local_nonsurviving(self): + py.test.skip("XXX") s = self.malloc(S, globl=False) i = self.gc.id(s) assert i != llmemory.cast_adr_to_int(s_adr) @@ -625,6 +637,7 @@ self.gc.stop_transaction() def test_id_of_local_surviving(self): + py.test.skip("XXX") sr1 = self.malloc(SR, globl=True) assert sr1.s1 == lltype.nullptr(S) assert sr1.sr2 == lltype.nullptr(SR) @@ -645,6 +658,7 @@ assert self.gc.id(s2) == i def test_hash_of_global(self): + py.test.skip("XXX") s = self.malloc(S) i = self.gc.identityhash(s) assert i == mangle_hash(llmemory.cast_adr_to_int(s_adr)) @@ -652,6 +666,7 @@ assert self.gc.identityhash(s) == i def test_hash_of_globallocal(self): + py.test.skip("XXX") s = self.malloc(S, globl=True) t_adr = self.stm_writebarrier(s_adr) # make a local copy t = llmemory.cast_adr_to_ptr(t_adr, llmemory.GCREF) @@ -662,6 +677,7 @@ assert i == self.gc.identityhash(s) def test_hash_of_local_nonsurviving(self): + py.test.skip("XXX") s = self.malloc(S, globl=False) i = self.gc.identityhash(s) # XXX fix me @@ -670,6 +686,7 @@ self.gc.stop_transaction() def test_hash_of_local_surviving(self): + py.test.skip("XXX") sr1 = self.malloc(SR, globl=True) t2 = self.malloc(S, globl=False) t2.a = 424 @@ -689,6 +706,7 @@ assert self.gc.identityhash(s2) == i def test_weakref_to_global(self): + py.test.skip("XXX") swr1 = self.malloc(SWR, globl=True) s2 = self.malloc(S, globl=True) wr1 = self.malloc(WR, globl=False, weakref=True) @@ -702,6 +720,7 @@ assert wr2.wadr == s2_adr # survives def test_weakref_to_local_dying(self): + py.test.skip("XXX") swr1 = self.malloc(SWR, globl=True) t2 = self.malloc(S, globl=False) wr1 = self.malloc(WR, globl=False, weakref=True) @@ -715,6 +734,7 @@ assert wr2.wadr == llmemory.NULL # dies def test_weakref_to_local_surviving(self): + py.test.skip("XXX") sr1 = self.malloc(SR, globl=True) swr1 = self.malloc(SWR, globl=True) t2 = self.malloc(S, globl=False) @@ -736,6 +756,7 @@ assert s2 == tr1.s1 # tr1 is a root, so not copied yet def test_weakref_to_local_in_main_thread(self): + py.test.skip("XXX") from rpython.memory.gc.test import test_stmtls self.gc.root_walker = test_stmtls.FakeRootWalker() # @@ -755,21 +776,25 @@ assert not wr1.wadr def test_normalize_global_null(self): + py.test.skip("XXX") a = self.gc.stm_normalize_global(llmemory.NULL) assert a == llmemory.NULL def test_normalize_global_already_global(self): + py.test.skip("XXX") sr1 = self.malloc(SR) a = self.gc.stm_normalize_global(sr1_adr) assert a == sr1_adr def test_normalize_global_purely_local(self): + py.test.skip("XXX") self.select_thread(1) sr1 = self.malloc(SR) a = self.gc.stm_normalize_global(sr1_adr) assert a == sr1_adr def test_normalize_global_local_copy(self): + py.test.skip("XXX") sr1 = self.malloc(SR) self.select_thread(1) tr1_adr = self.gc.stm_writebarrier(sr1_adr) From noreply at buildbot.pypy.org Mon Apr 8 00:06:36 2013 From: noreply at buildbot.pypy.org (matti) Date: Mon, 8 Apr 2013 00:06:36 +0200 (CEST) Subject: [pypy-commit] cffi load-from-exe-dir: patch to search exe dir for dll before searching path Message-ID: <20130407220636.E220C1C0334@cobra.cs.uni-duesseldorf.de> Author: matti Branch: load-from-exe-dir Changeset: r1243:933f1308f466 Date: 2013-04-08 01:06 +0300 http://bitbucket.org/cffi/cffi/changeset/933f1308f466/ Log: patch to search exe dir for dll before searching path diff --git a/cffi/api.py b/cffi/api.py --- a/cffi/api.py +++ b/cffi/api.py @@ -359,10 +359,23 @@ backendlib = backend.load_library(name, flags) except OSError: import ctypes.util - path = ctypes.util.find_library(name) - if path is None: - raise OSError("library not found: %r" % (name,)) - backendlib = backend.load_library(path, flags) + backendlib = None + if os.name == 'nt': + import sys + # Allow name in exe location, + # like in ctypes.util.find_library + directory = os.path.dirname(sys.executable) + if os.path.isfile(os.path.join(directory, name)): + backendlib = backend.load_library(name) + if not name.lower().endswith('.dll'): + tmpname = os.path.join(directory, name + '.dll') + if os.path.isfile(tmpname): + backendlib = backend.load_library(name) + if not backendlib: + path = ctypes.util.find_library(name) + if path is None: + raise OSError("library not found: %r" % (name,)) + backendlib = backend.load_library(path, flags) copied_enums = [] # def make_accessor(name): From noreply at buildbot.pypy.org Mon Apr 8 00:15:00 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Mon, 8 Apr 2013 00:15:00 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: removed the w_class field of w_objects with class reference. Only s_class remains, the interface remains the same Message-ID: <20130407221500.D2B851C0334@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r248:f0a08c690de4 Date: 2013-04-03 14:57 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/f0a08c690de4/ Log: removed the w_class field of w_objects with class reference. Only s_class remains, the interface remains the same diff --git a/spyvm/model.py b/spyvm/model.py --- a/spyvm/model.py +++ b/spyvm/model.py @@ -117,6 +117,7 @@ def __repr__(self): return self.as_repr_string() + @jit.elidable def as_repr_string(self): return "%r" % self @@ -139,6 +140,7 @@ def invariant(self): return isinstance(self.value, int) and self.value < 0x8000 + @jit.elidable def as_repr_string(self): return "W_SmallInteger(%d)" % self.value @@ -330,30 +332,29 @@ class W_AbstractObjectWithClassReference(W_AbstractObjectWithIdentityHash): """Objects with arbitrary class (ie not CompiledMethod, SmallInteger or Float).""" - _attrs_ = ['w_class', 's_class', 'space'] - s_class = None + _attrs_ = ['s_class', 'space'] def __init__(self, space, w_class): if w_class is not None: # it's None only for testing and space generation assert isinstance(w_class, W_PointersObject) - if w_class.has_shadow(): - self.s_class = w_class.as_class_get_shadow(w_class._shadow.space) - self.w_class = w_class + self.s_class = w_class.as_class_get_penumbra(space) + else: + self.s_class = None self.space = space def getclass(self, space): - assert self.w_class is not None - return self.w_class + return self.shadow_of_my_class(space).w_self() def __str__(self): if isinstance(self, W_PointersObject) and self.has_shadow(): return self._shadow.getname() else: name = None - if self.w_class.has_shadow(): - name = self.w_class._shadow.name + if self.has_class(): + name = self.s_class.name return "a %s" % (name or '?',) + @jit.elidable def as_repr_string(self): return self.as_embellished_string("W_O /w Class", "") @@ -365,20 +366,19 @@ additionalInformation) def invariant(self): + from spyvm import shadow return (W_AbstractObjectWithIdentityHash.invariant(self) and - isinstance(self.w_class, W_PointersObject)) + isinstance(self.s_class, shadow.ClassShadow)) def _become(self, w_other): - self.w_class, w_other.w_class = w_other.w_class, self.w_class self.s_class, w_other.s_class = w_other.s_class, self.s_class W_AbstractObjectWithIdentityHash._become(self, w_other) def has_class(self): - return self.w_class is not None + return self.s_class is not None def shadow_of_my_class(self, space): - if self.s_class is None: - self.s_class = self.w_class.as_class_get_shadow(space) + assert self.s_class is not None return self.s_class class W_PointersObject(W_AbstractObjectWithClassReference): @@ -398,8 +398,7 @@ def fillin(self, space, g_self): self._vars = g_self.get_pointers() - self.w_class = g_self.get_class() - self.s_class = None + self.s_class = g_self.get_class().as_class_get_penumbra(space) self.hash = g_self.get_hash() self.space = space @@ -481,7 +480,9 @@ # Should only be used during squeak-image loading. def as_class_get_penumbra(self, space): from spyvm.shadow import ClassShadow - self.store_shadow(ClassShadow(space, self)) + assert self._shadow is None or isinstance(self._shadow, ClassShadow) + if self._shadow is None: + self.store_shadow(ClassShadow(space, self)) return self._shadow def as_blockcontext_get_shadow(self, space): @@ -529,14 +530,15 @@ return True def clone(self, space): - w_result = W_PointersObject(self.space, self.w_class, len(self._vars)) + w_result = W_PointersObject(self.space, self.getclass(space), len(self._vars)) w_result._vars = [self.fetch(space, i) for i in range(len(self._vars))] return w_result + @jit.elidable def as_repr_string(self): return W_AbstractObjectWithClassReference.as_embellished_string(self, className='W_PointersObject', - additionalInformation='len(%d)' % self.size()) + additionalInformation='len=%d' % self.size()) class W_BytesObject(W_AbstractObjectWithClassReference): _attrs_ = ['bytes'] @@ -547,7 +549,7 @@ self.bytes = ['\x00'] * size def fillin(self, space, g_self): - self.w_class = g_self.get_class() + self.s_class = g_self.get_class().as_class_get_penumbra(space) self.bytes = g_self.get_bytes() self.hash = g_self.get_hash() self.space = space @@ -593,7 +595,7 @@ return self.bytes == other.bytes def clone(self, space): - w_result = W_BytesObject(self.space, self.w_class, len(self.bytes)) + w_result = W_BytesObject(self.space, self.getclass(space), len(self.bytes)) w_result.bytes = list(self.bytes) return w_result @@ -606,7 +608,7 @@ def fillin(self, space, g_self): self.words = g_self.get_ruints() - self.w_class = g_self.get_class() + self.s_class = g_self.get_class().as_class_get_penumbra(space) self.hash = g_self.get_hash() self.space = space @@ -632,7 +634,7 @@ isinstance(self.words, list)) def clone(self, space): - w_result = W_WordsObject(self.space, self.w_class, len(self.words)) + w_result = W_WordsObject(self.space, self.getclass(space), len(self.words)) w_result.words = list(self.words) return w_result @@ -677,7 +679,7 @@ return False def clone(self, space): - w_result = W_WordsObject(self.space, self.w_class, self._realsize) + w_result = W_WordsObject(self.space, self.getclass(space), self._realsize) n = 0 while n < self._realsize: w_result.words[n] = self.getword(n) diff --git a/spyvm/objspace.py b/spyvm/objspace.py --- a/spyvm/objspace.py +++ b/spyvm/objspace.py @@ -51,15 +51,15 @@ 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"] + s_Metaclass = self.classtable["w_Metaclass"].as_class_get_penumbra(self) # XXX proto_shadow = w_ProtoObjectClass._shadow proto_shadow.store_w_superclass(w_Class) # 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 + if w_cls_obj.s_class is None: + w_cls_obj.s_class = s_Metaclass def define_cls(cls_nm, supercls_nm, instvarsize=0, format=shadow.POINTERS, varsized=False): @@ -136,7 +136,7 @@ # package, and then patch up its fields here: w_nil = self.w_nil = model.w_nil w_nil.space = self - w_nil.w_class = self.classtable['w_UndefinedObject'] + w_nil.s_class = self.classtable['w_UndefinedObject'].as_class_get_penumbra(self) w_true = self.classtable['w_True'].as_class_get_shadow(self).new() self.w_true = w_true diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -752,7 +752,6 @@ if w_arg_class.instsize() != w_rcvr_class.instsize(): raise PrimitiveFailedError() - w_rcvr.w_class = w_arg.w_class w_rcvr.s_class = w_arg.s_class # ___________________________________________________________________________ diff --git a/spyvm/test/test_objectspace.py b/spyvm/test/test_objectspace.py --- a/spyvm/test/test_objectspace.py +++ b/spyvm/test/test_objectspace.py @@ -8,11 +8,11 @@ # Heuristic to detect if this is a metaclass. Don't use apart # from in this test file, because classtable['w_Metaclass'] is # bogus after loading an image. - return w_cls.w_class is space.classtable['w_Metaclass'] + return w_cls.s_class is space.classtable['w_Metaclass']._shadow def test_every_class_is_an_instance_of_a_metaclass(): for (nm, w_cls) in space.classtable.items(): - assert ismetaclass(w_cls) or ismetaclass(w_cls.w_class) + assert ismetaclass(w_cls) or ismetaclass(w_cls.s_class._w_self) def test_every_metaclass_inherits_from_class_and_behavior(): s_Class = space.classtable['w_Class'].as_class_get_shadow(space) @@ -25,7 +25,7 @@ def test_metaclass_of_metaclass_is_an_instance_of_metaclass(): w_Metaclass = space.classtable['w_Metaclass'] - assert w_Metaclass.w_class.w_class is w_Metaclass + assert w_Metaclass.getclass(space).getclass(space) is w_Metaclass def test_ruint(): from spyvm import model diff --git a/spyvm/test/test_primitives.py b/spyvm/test/test_primitives.py --- a/spyvm/test/test_primitives.py +++ b/spyvm/test/test_primitives.py @@ -19,7 +19,7 @@ s_self.reset_stack() s_self.push_all(stack) s_self.store_expected_argument_count(0) - self.w_class = space.w_MethodContext + self.s_class = space.w_MethodContext.as_class_get_shadow(space) def as_blockcontext_get_shadow(self): self._shadow = shadow.BlockContextShadow(space, self) diff --git a/spyvm/test/test_shadow.py b/spyvm/test/test_shadow.py --- a/spyvm/test/test_shadow.py +++ b/spyvm/test/test_shadow.py @@ -32,7 +32,7 @@ w_classofclass=None, methods={}): if w_classofclass is None: w_classofclass = build_smalltalk_class(None, 0x94, - w_superclass.w_class, + w_superclass.getclass(space), w_Metaclass) w_methoddict = build_methoddict(methods) size = constants.CLASS_NAME_INDEX + 1 diff --git a/targetimageloadingsmalltalk.py b/targetimageloadingsmalltalk.py --- a/targetimageloadingsmalltalk.py +++ b/targetimageloadingsmalltalk.py @@ -9,7 +9,7 @@ def _run_benchmark(interp, number, benchmark): - w_object = model.W_SmallInteger(number) + w_object = interp.space.wrap_int(number) t1 = time.time() try: w_result = interp.perform(w_object, benchmark) From noreply at buildbot.pypy.org Mon Apr 8 10:01:21 2013 From: noreply at buildbot.pypy.org (bivab) Date: Mon, 8 Apr 2013 10:01:21 +0200 (CEST) Subject: [pypy-commit] pypy default: enable armv6 and armv7 hardfloat versions as jit backend options for translation Message-ID: <20130408080121.937FA1C0723@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63123:a7b33dd521e1 Date: 2013-04-08 10:00 +0200 http://bitbucket.org/pypy/pypy/changeset/a7b33dd521e1/ Log: enable armv6 and armv7 hardfloat versions as jit backend options for translation diff --git a/rpython/config/translationoption.py b/rpython/config/translationoption.py --- a/rpython/config/translationoption.py +++ b/rpython/config/translationoption.py @@ -115,7 +115,7 @@ ("translation.gcrootfinder", DEFL_ROOTFINDER_WITHJIT), ("translation.list_comprehension_operations", True)]), ChoiceOption("jit_backend", "choose the backend for the JIT", - ["auto", "x86", "x86-without-sse2", 'armv7'], + ["auto", "x86", "x86-without-sse2", 'armv7', 'armv7hf', 'armv6hf'], default="auto", cmdline="--jit-backend"), ChoiceOption("jit_profiler", "integrate profiler support into the JIT", ["off", "oprofile"], From noreply at buildbot.pypy.org Mon Apr 8 10:01:51 2013 From: noreply at buildbot.pypy.org (bivab) Date: Mon, 8 Apr 2013 10:01:51 +0200 (CEST) Subject: [pypy-commit] buildbot default: update jit backend translation option for raspbian builds Message-ID: <20130408080151.811251C0723@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r773:96ace4f51f52 Date: 2013-04-08 10:01 +0200 http://bitbucket.org/pypy/buildbot/changeset/96ace4f51f52/ Log: update jit backend translation option for raspbian builds diff --git a/bot2/pypybuildbot/arm_master.py b/bot2/pypybuildbot/arm_master.py --- a/bot2/pypybuildbot/arm_master.py +++ b/bot2/pypybuildbot/arm_master.py @@ -1,6 +1,4 @@ -import os -import getpass from buildbot.scheduler import Nightly, Triggerable from pypybuildbot.util import we_are_debugging, load @@ -12,7 +10,7 @@ jit_translation_args = ['-Ojit'] crosstranslationargs = ['--platform=arm', '--gcrootfinder=shadowstack'] crosstranslationjitargs = ['--jit-backend=armv7'] -crosstranslationjitargs_raspbian = ['--jit-backend=armv6'] +crosstranslationjitargs_raspbian = ['--jit-backend=armv6hf'] # this one needs a larger timeout due to how it is run pypyJitBackendOnlyOwnTestFactoryARM = pypybuilds.Own( cherrypick=':'.join(["jit/backend/arm", From noreply at buildbot.pypy.org Mon Apr 8 10:55:50 2013 From: noreply at buildbot.pypy.org (arigo) Date: Mon, 8 Apr 2013 10:55:50 +0200 (CEST) Subject: [pypy-commit] pypy stm-gc-2: Don't call rgc.add_memory_pressure() from allocate_ll_lock(), Message-ID: <20130408085550.408941C15A2@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: stm-gc-2 Changeset: r63124:873d69a15bc6 Date: 2013-04-08 10:44 +0200 http://bitbucket.org/pypy/pypy/changeset/873d69a15bc6/ Log: Don't call rgc.add_memory_pressure() from allocate_ll_lock(), which I want to use from the GC itself. diff --git a/rpython/rlib/rthread.py b/rpython/rlib/rthread.py --- a/rpython/rlib/rthread.py +++ b/rpython/rlib/rthread.py @@ -90,6 +90,9 @@ _nowrapper=True) def allocate_lock(): + # Add some memory pressure for the size of the lock because it is an + # Opaque object + rgc.add_memory_pressure(TLOCKP_SIZE) return Lock(allocate_ll_lock()) @specialize.arg(0) @@ -184,9 +187,6 @@ if rffi.cast(lltype.Signed, res) <= 0: lltype.free(ll_lock, flavor='raw', track_allocation=False) raise error("out of resources") - # Add some memory pressure for the size of the lock because it is an - # Opaque object - rgc.add_memory_pressure(TLOCKP_SIZE) return ll_lock def free_ll_lock(ll_lock): From noreply at buildbot.pypy.org Mon Apr 8 10:55:51 2013 From: noreply at buildbot.pypy.org (arigo) Date: Mon, 8 Apr 2013 10:55:51 +0200 (CEST) Subject: [pypy-commit] pypy stm-gc-2: Maintain a doubly-linked chained list of stmtls objects. Message-ID: <20130408085551.89B7A1C15A7@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: stm-gc-2 Changeset: r63125:198336298673 Date: 2013-04-08 10:45 +0200 http://bitbucket.org/pypy/pypy/changeset/198336298673/ Log: Maintain a doubly-linked chained list of stmtls objects. diff --git a/rpython/memory/gc/stmgc.py b/rpython/memory/gc/stmgc.py --- a/rpython/memory/gc/stmgc.py +++ b/rpython/memory/gc/stmgc.py @@ -7,6 +7,7 @@ from rpython.rlib.rarithmetic import LONG_BIT, r_uint from rpython.rlib.debug import ll_assert, debug_start, debug_stop, fatalerror from rpython.rlib.debug import debug_print +from rpython.rlib import rthread WORD = LONG_BIT // 8 @@ -206,6 +207,9 @@ # self.sharedarea.setup() # + self.linked_list_stmtls = None + self.ll_global_lock = rthread.allocate_ll_lock() + # self.stm_operations.descriptor_init() self.stm_operations.begin_inevitable_transaction() self.setup_thread() @@ -217,6 +221,7 @@ "setup_thread: not in a transaction") from rpython.memory.gc.stmtls import StmGCTLS stmtls = StmGCTLS(self) + self.add_in_linked_list(stmtls) stmtls.start_transaction() def teardown_thread(self): @@ -229,9 +234,39 @@ stmtls = self.get_tls() stmtls.stop_transaction() self.stm_operations.commit_transaction() + self.remove_from_linked_list(stmtls) self.stm_operations.begin_inevitable_transaction() stmtls.delete() + def acquire_global_lock(self): + rthread.acquire_NOAUTO(self.ll_global_lock, True) + + def release_global_lock(self): + rthread.release_NOAUTO(self.ll_global_lock) + + def add_in_linked_list(self, stmtls): + self.acquire_global_lock() + stmtls.linked_list_prev = None + stmtls.linked_list_next = self.linked_list_stmtls + self.linked_list_stmtls = stmtls + self.release_global_lock() + + def remove_from_linked_list(self, stmtls): + self.acquire_global_lock() + c = 0 + stmprev = stmtls.linked_list_prev + stmnext = stmtls.linked_list_next + if stmnext: + stmnext.linked_list_prev = stmprev + if stmprev: + stmprev.linked_list_next = stmnext + c += 1 + if stmtls is self.linked_list_stmtls: + self.linked_list_stmtls = stmnext + c += 1 + ll_assert(c == 1, "remove_from_linked_list: bad linked list") + self.release_global_lock() + @always_inline def get_tls(self): from rpython.memory.gc.stmtls import StmGCTLS From noreply at buildbot.pypy.org Mon Apr 8 11:39:42 2013 From: noreply at buildbot.pypy.org (fijal) Date: Mon, 8 Apr 2013 11:39:42 +0200 (CEST) Subject: [pypy-commit] buildbot default: use pypy wherever possible Message-ID: <20130408093942.ED3A41C15A2@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r774:566e5e5d4bd9 Date: 2013-04-08 11:39 +0200 http://bitbucket.org/pypy/buildbot/changeset/566e5e5d4bd9/ Log: use pypy wherever possible diff --git a/bot2/pypybuildbot/master.py b/bot2/pypybuildbot/master.py --- a/bot2/pypybuildbot/master.py +++ b/bot2/pypybuildbot/master.py @@ -66,8 +66,7 @@ app_tests=True) pypyTranslatedAppLevelTestFactory64 = pypybuilds.Translated(lib_python=True, app_tests=True, - platform='linux64', - interpreter='python') + platform='linux64') # these are like the two above: the only difference is that they only run # lib-python tests,not -A tests @@ -97,7 +96,6 @@ translationArgs=jit_translation_args, targetArgs=[], lib_python=True, - interpreter='/usr/bin/python', pypyjit=True, app_tests=True, platform='linux64', @@ -129,7 +127,6 @@ lib_python=True, pypyjit=True, app_tests=True, - interpreter='python', ) pypyJITTranslatedTestFactoryWin = pypybuilds.Translated( From noreply at buildbot.pypy.org Mon Apr 8 11:45:27 2013 From: noreply at buildbot.pypy.org (fijal) Date: Mon, 8 Apr 2013 11:45:27 +0200 (CEST) Subject: [pypy-commit] pypy default: update links Message-ID: <20130408094527.653C61C15A7@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r63126:650bb10e2cfd Date: 2013-04-07 10:06 +0200 http://bitbucket.org/pypy/pypy/changeset/650bb10e2cfd/ Log: update links diff --git a/pypy/doc/release-2.0.0-beta2.rst b/pypy/doc/release-2.0.0-beta2.rst --- a/pypy/doc/release-2.0.0-beta2.rst +++ b/pypy/doc/release-2.0.0-beta2.rst @@ -82,3 +82,13 @@ * we now have special strategies for ``dict``/``set``/``list`` which contain unicode strings, which means that now such collections will be both faster and more compact. + +.. _`eventlet`: http://eventlet.net/ +.. _`gevent`: http://www.gevent.org/ +.. _`cffi`: http://cffi.readthedocs.org/en/release-0.6/ +.. _`JIT hooks`: http://doc.pypy.org/en/latest/jit-hooks.html +.. _`pypycore`: https://github.com/gevent-on-pypy/pypycore +.. _`pypy-hacks`: https://github.com/schmir/gevent/tree/pypy-hacks +.. _`_curses.py`: https://bitbucket.org/pypy/pypy/src/aefddd47f224e3c12e2ea74f5c796d76f4355bdb/lib_pypy/_curses.py?at=default +.. _`_sqlite3.py`: https://bitbucket.org/pypy/pypy/src/aefddd47f224e3c12e2ea74f5c796d76f4355bdb/lib_pypy/_sqlite3.py?at=default + From noreply at buildbot.pypy.org Mon Apr 8 11:45:28 2013 From: noreply at buildbot.pypy.org (fijal) Date: Mon, 8 Apr 2013 11:45:28 +0200 (CEST) Subject: [pypy-commit] pypy release-2.0-beta2: update links Message-ID: <20130408094528.A73791C15A7@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: release-2.0-beta2 Changeset: r63127:5ae220de793f Date: 2013-04-07 10:06 +0200 http://bitbucket.org/pypy/pypy/changeset/5ae220de793f/ Log: update links diff --git a/pypy/doc/release-2.0.0-beta2.rst b/pypy/doc/release-2.0.0-beta2.rst --- a/pypy/doc/release-2.0.0-beta2.rst +++ b/pypy/doc/release-2.0.0-beta2.rst @@ -82,3 +82,13 @@ * we now have special strategies for ``dict``/``set``/``list`` which contain unicode strings, which means that now such collections will be both faster and more compact. + +.. _`eventlet`: http://eventlet.net/ +.. _`gevent`: http://www.gevent.org/ +.. _`cffi`: http://cffi.readthedocs.org/en/release-0.6/ +.. _`JIT hooks`: http://doc.pypy.org/en/latest/jit-hooks.html +.. _`pypycore`: https://github.com/gevent-on-pypy/pypycore +.. _`pypy-hacks`: https://github.com/schmir/gevent/tree/pypy-hacks +.. _`_curses.py`: https://bitbucket.org/pypy/pypy/src/aefddd47f224e3c12e2ea74f5c796d76f4355bdb/lib_pypy/_curses.py?at=default +.. _`_sqlite3.py`: https://bitbucket.org/pypy/pypy/src/aefddd47f224e3c12e2ea74f5c796d76f4355bdb/lib_pypy/_sqlite3.py?at=default + From noreply at buildbot.pypy.org Mon Apr 8 11:45:29 2013 From: noreply at buildbot.pypy.org (fijal) Date: Mon, 8 Apr 2013 11:45:29 +0200 (CEST) Subject: [pypy-commit] pypy release-2.0-beta2: merge Message-ID: <20130408094529.EDB6E1C15A7@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: release-2.0-beta2 Changeset: r63128:79a42de0558e Date: 2013-04-08 11:42 +0200 http://bitbucket.org/pypy/pypy/changeset/79a42de0558e/ Log: merge diff --git a/pypy/doc/release-2.0.0-beta2.rst b/pypy/doc/release-2.0.0-beta2.rst --- a/pypy/doc/release-2.0.0-beta2.rst +++ b/pypy/doc/release-2.0.0-beta2.rst @@ -82,3 +82,13 @@ * we now have special strategies for ``dict``/``set``/``list`` which contain unicode strings, which means that now such collections will be both faster and more compact. + +.. _`eventlet`: http://eventlet.net/ +.. _`gevent`: http://www.gevent.org/ +.. _`cffi`: http://cffi.readthedocs.org/en/release-0.6/ +.. _`JIT hooks`: http://doc.pypy.org/en/latest/jit-hooks.html +.. _`pypycore`: https://github.com/gevent-on-pypy/pypycore +.. _`pypy-hacks`: https://github.com/schmir/gevent/tree/pypy-hacks +.. _`_curses.py`: https://bitbucket.org/pypy/pypy/src/aefddd47f224e3c12e2ea74f5c796d76f4355bdb/lib_pypy/_curses.py?at=default +.. _`_sqlite3.py`: https://bitbucket.org/pypy/pypy/src/aefddd47f224e3c12e2ea74f5c796d76f4355bdb/lib_pypy/_sqlite3.py?at=default + From noreply at buildbot.pypy.org Mon Apr 8 11:45:32 2013 From: noreply at buildbot.pypy.org (fijal) Date: Mon, 8 Apr 2013 11:45:32 +0200 (CEST) Subject: [pypy-commit] pypy default: merge Message-ID: <20130408094532.097541C15A7@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r63129:fb4daf6810f9 Date: 2013-04-08 11:44 +0200 http://bitbucket.org/pypy/pypy/changeset/fb4daf6810f9/ Log: merge diff --git a/.hgignore b/.hgignore --- a/.hgignore +++ b/.hgignore @@ -70,6 +70,7 @@ ^rpython/translator/cli/src/pypylib\.dll$ ^rpython/translator/cli/src/query\.exe$ ^rpython/translator/cli/src/main\.exe$ +^lib_pypy/__pycache__$ ^lib_pypy/ctypes_config_cache/_.+_cache\.py$ ^lib_pypy/ctypes_config_cache/_.+_.+_\.py$ ^rpython/translator/cli/query-descriptions$ diff --git a/lib-python/conftest.py b/lib-python/conftest.py --- a/lib-python/conftest.py +++ b/lib-python/conftest.py @@ -1,91 +1,89 @@ """ test configuration(s) for running CPython's regression -test suite on top of PyPy +test suite on top of PyPy """ import py import sys import pypy import re -from pypy.interpreter.gateway import ApplevelClass +from pypy.interpreter.gateway import ApplevelClass from pypy.interpreter.error import OperationError -from pypy.interpreter.module import Module as PyPyModule +from pypy.interpreter.module import Module as PyPyModule from pypy.interpreter.main import run_string, run_file -# the following adds command line options as a side effect! -from pypy.conftest import option as pypy_option +# the following adds command line options as a side effect! +from pypy.conftest import option as pypy_option -from pypy.tool.pytest import appsupport +from pypy.tool.pytest import appsupport from pypy.tool.pytest.confpath import pypydir, rpythondir, testdir, testresultdir from rpython.config.parse import parse_info pytest_plugins = "resultlog", rsyncdirs = ['.', '../pypy/'] -# -# Interfacing/Integrating with py.test's collection process +# +# Interfacing/Integrating with py.test's collection process # def pytest_addoption(parser): - group = parser.getgroup("complicance testing options") - group.addoption('-T', '--timeout', action="store", type="string", - default="1000", dest="timeout", - help="fail a test module after the given timeout. " - "specify in seconds or 'NUMmp' aka Mega-Pystones") - group.addoption('--pypy', action="store", type="string", - dest="pypy", help="use given pypy executable to run lib-python tests. " - "This will run the tests directly (i.e. not through py.py)") + group = parser.getgroup("complicance testing options") + group.addoption('-T', '--timeout', action="store", type="string", + default="1000", dest="timeout", + help="fail a test module after the given timeout. " + "specify in seconds or 'NUMmp' aka Mega-Pystones") + group.addoption('--pypy', action="store", type="string", dest="pypy", + help="use given pypy executable to run lib-python tests. " + "This will run the tests directly (i.e. not through py.py)") group.addoption('--filter', action="store", type="string", default=None, - dest="unittest_filter", help="Similar to -k, XXX") + dest="unittest_filter", help="Similar to -k, XXX") -def gettimeout(timeout): +def gettimeout(timeout): from rpython.translator.test import rpystone - if timeout.endswith('mp'): + if timeout.endswith('mp'): megapystone = float(timeout[:-2]) t, stone = pystone.Proc0(10000) - pystonetime = t/stone - seconds = megapystone * 1000000 * pystonetime - return seconds - return float(timeout) + pystonetime = t/stone + seconds = megapystone * 1000000 * pystonetime + return seconds + return float(timeout) # ________________________________________________________________________ # -# classification of all tests files (this is ongoing work) +# classification of all tests files (this is ongoing work) # -class RegrTest: - """ Regression Test Declaration.""" - def __init__(self, basename, core=False, - compiler=None, - usemodules = '', - skip=None): - self.basename = basename +class RegrTest: + """ Regression Test Declaration.""" + def __init__(self, basename, core=False, compiler=None, usemodules='', + skip=None): + self.basename = basename self._usemodules = usemodules.split() + ['signal', 'rctime', 'itertools', '_socket'] - self._compiler = compiler + self._compiler = compiler self.core = core self.skip = skip assert self.getfspath().check(), "%r not found!" % (basename,) def usemodules(self): - return self._usemodules #+ pypy_option.usemodules + return self._usemodules # + pypy_option.usemodules usemodules = property(usemodules) - def compiler(self): - return self._compiler #or pypy_option.compiler + def compiler(self): + return self._compiler # or pypy_option.compiler compiler = property(compiler) - def ismodified(self): + def ismodified(self): #XXX: ask hg return None - def getfspath(self): + def getfspath(self): return testdir.join(self.basename) - def run_file(self, space): + def run_file(self, space): fspath = self.getfspath() assert fspath.check() - modname = fspath.purebasename + modname = fspath.purebasename space.appexec([], '''(): from test import %(modname)s m = %(modname)s @@ -424,7 +422,7 @@ RegrTest('test_textwrap.py'), RegrTest('test_thread.py', usemodules="thread", core=True), RegrTest('test_threaded_import.py', usemodules="thread", core=True), - RegrTest('test_threadedtempfile.py', + RegrTest('test_threadedtempfile.py', usemodules="thread", core=False), RegrTest('test_threading.py', usemodules="thread", core=True), RegrTest('test_threading_local.py', usemodules="thread", core=True), @@ -504,7 +502,7 @@ def pytest_configure(config): config._basename2spec = cache = {} - for x in testmap: + for x in testmap: cache[x.basename] = x def pytest_collect_file(path, parent, __multicall__): @@ -520,33 +518,33 @@ return RunFileExternal(path.basename, parent=parent, regrtest=regrtest) class RunFileExternal(py.test.collect.File): - def __init__(self, name, parent, regrtest): - super(RunFileExternal, self).__init__(name, parent) - self.regrtest = regrtest + def __init__(self, name, parent, regrtest): + super(RunFileExternal, self).__init__(name, parent) + self.regrtest = regrtest self.fspath = regrtest.getfspath() - def collect(self): - if self.regrtest.ismodified(): + def collect(self): + if self.regrtest.ismodified(): name = 'modified' else: name = 'unmodified' - return [ReallyRunFileExternal(name, parent=self)] + return [ReallyRunFileExternal(name, parent=self)] # -# testmethod: +# testmethod: # invoking in a separate process: py.py TESTFILE # import os import time import getpass -class ReallyRunFileExternal(py.test.collect.Item): +class ReallyRunFileExternal(py.test.collect.Item): class ExternalFailure(Exception): """Failure in running subprocess""" - def getinvocation(self, regrtest): - fspath = regrtest.getfspath() - python = sys.executable + def getinvocation(self, regrtest): + fspath = regrtest.getfspath() + python = sys.executable pypy_script = pypydir.join('bin', 'pyinteractive.py') alarm_script = pypydir.join('tool', 'alarm.py') if sys.platform == 'win32': @@ -555,9 +553,9 @@ watchdog_name = 'watchdog.py' watchdog_script = rpythondir.join('tool', watchdog_name) - regr_script = pypydir.join('tool', 'pytest', + regr_script = pypydir.join('tool', 'pytest', 'run-script', 'regrverbose.py') - + regrrun = str(regr_script) option = self.config.option TIMEOUT = gettimeout(option.timeout.lower()) @@ -566,8 +564,7 @@ if not execpath.check(): execpath = py.path.local.sysfind(option.pypy) if not execpath: - raise LookupError("could not find executable %r" % - (option.pypy,)) + raise LookupError("could not find executable %r" % option.pypy) # check modules info = py.process.cmdexec("%s --info" % execpath) @@ -576,34 +573,29 @@ if info.get('objspace.usemodules.%s' % mod) is not True: py.test.skip("%s module not included in %s" % (mod, execpath)) - - cmd = "%s %s %s" %( - execpath, - regrrun, fspath.purebasename) + cmd = "%s %s %s" % (execpath, regrrun, fspath.purebasename) # add watchdog for timing out - cmd = "%s %s %s %s" %( - python, watchdog_script, TIMEOUT, - cmd) + cmd = "%s %s %s %s" % (python, watchdog_script, TIMEOUT, cmd) else: pypy_options = [] pypy_options.extend( ['--withmod-%s' % mod for mod in regrtest.usemodules]) - sopt = " ".join(pypy_options) - cmd = "%s %s %d %s -S %s %s %s -v" %( - python, alarm_script, TIMEOUT, - pypy_script, sopt, + sopt = " ".join(pypy_options) + cmd = "%s %s %d %s -S %s %s %s -v" % ( + python, alarm_script, TIMEOUT, + pypy_script, sopt, regrrun, fspath.purebasename) - return cmd + return cmd - def runtest(self): - """ invoke a subprocess running the test file via PyPy. - record its output into the 'result/user at host' subdirectory. - (we might want to create subdirectories for - each user, because we will probably all produce + def runtest(self): + """ invoke a subprocess running the test file via PyPy. + record its output into the 'result/user at host' subdirectory. + (we might want to create subdirectories for + each user, because we will probably all produce such result runs and they will not be the same - i am afraid. - """ + i am afraid. + """ regrtest = self.parent.regrtest if regrtest.skip: if regrtest.skip is True: @@ -611,8 +603,8 @@ else: msg = regrtest.skip py.test.skip(msg) - (skipped, exit_status, test_stdout, - test_stderr) = self.getresult(regrtest) + (skipped, exit_status, test_stdout, test_stderr) = \ + self.getresult(regrtest) if skipped: py.test.skip(test_stderr.splitlines()[-1]) if exit_status: @@ -624,13 +616,13 @@ out, err = excinfo.value.args return out + err - def getstatusouterr(self, cmd): + def getstatusouterr(self, cmd): tempdir = py.test.ensuretemp(self.fspath.basename) stdout = tempdir.join(self.fspath.basename) + '.out' stderr = tempdir.join(self.fspath.basename) + '.err' if sys.platform == 'win32': - status = os.system("%s >%s 2>%s" %(cmd, stdout, stderr)) - if status>=0: + status = os.system("%s >%s 2>%s" % (cmd, stdout, stderr)) + if status >= 0: status = status else: status = 'abnormal termination 0x%x' % status @@ -644,22 +636,22 @@ stdout.write('') stderr.write('') else: - status = os.system("%s >>%s 2>>%s" %(cmd, stdout, stderr)) + status = os.system("%s >>%s 2>>%s" % (cmd, stdout, stderr)) if os.WIFEXITED(status): status = os.WEXITSTATUS(status) else: status = 'abnormal termination 0x%x' % status return status, stdout.read(mode='rU'), stderr.read(mode='rU') - def getresult(self, regrtest): + def getresult(self, regrtest): cmd = self.getinvocation(regrtest) tempdir = py.test.ensuretemp(self.fspath.basename) oldcwd = tempdir.chdir() exit_status, test_stdout, test_stderr = self.getstatusouterr(cmd) oldcwd.chdir() skipped = False - timedout = test_stderr.rfind(26*"=" + "timedout" + 26*"=") != -1 - if not timedout: + timedout = test_stderr.rfind(26*"=" + "timedout" + 26*"=") != -1 + if not timedout: timedout = test_stderr.rfind("KeyboardInterrupt") != -1 if test_stderr.rfind(26*"=" + "skipped" + 26*"=") != -1: skipped = True @@ -669,12 +661,12 @@ # test in test_zipimport_support.py if re.search(r'\bFAIL\b', test_stdout) or re.search('[^:]ERROR', test_stderr): outcome = 'FAIL' - exit_status = 2 - elif timedout: - outcome = "T/O" - else: + exit_status = 2 + elif timedout: + outcome = "T/O" + else: outcome = "ERR" - + return skipped, exit_status, test_stdout, test_stderr def _keywords(self): @@ -683,4 +675,3 @@ if regrtest.core: lst.append('core') return lst - diff --git a/lib_pypy/_collections.py b/lib_pypy/_collections.py --- a/lib_pypy/_collections.py +++ b/lib_pypy/_collections.py @@ -8,7 +8,6 @@ # Note that PyPy also contains a built-in module '_collections' which will hide # this one if compiled in. -import operator try: from threading import _get_ident as _thread_ident except ImportError: diff --git a/lib_pypy/_ctypes/function.py b/lib_pypy/_ctypes/function.py --- a/lib_pypy/_ctypes/function.py +++ b/lib_pypy/_ctypes/function.py @@ -8,7 +8,6 @@ import _ffi import sys import traceback -import warnings try: from __pypy__ import builtinify except ImportError: builtinify = lambda f: f @@ -315,8 +314,12 @@ return if argtypes is None: - warnings.warn('C function without declared arguments called', - RuntimeWarning, stacklevel=2) + # XXX this warning was originally meaning "it's going to be + # really slow". Now we don't worry that much about slowness + # of ctypes, and it's strange to get warnings for perfectly- + # legal code. + #warnings.warn('C function without declared arguments called', + # RuntimeWarning, stacklevel=2) argtypes = [] if self._com_index: @@ -342,6 +345,7 @@ if not outargs: return result + from ctypes import c_void_p simple_cdata = type(c_void_p()).__bases__[0] outargs = [x.value if type(x).__bases__[0] is simple_cdata else x for x in outargs] diff --git a/lib_pypy/_curses.py b/lib_pypy/_curses.py --- a/lib_pypy/_curses.py +++ b/lib_pypy/_curses.py @@ -359,9 +359,12 @@ if not lib._m_NetBSD: for key in range(lib.KEY_MIN, lib.KEY_MAX): key_n = lib.keyname(key) - if key_n == ffi.NULL or ffi.string(key_n) == "UNKNOWN KEY": + if key_n == ffi.NULL: continue - key_n = ffi.string(key_n).replace('(', '').replace(')', '') + key_n = ffi.string(key_n) + if key_n == b"UNKNOWN KEY": + continue + key_n = key_n.decode().replace('(', '').replace(')', '') globals()[key_n] = key _setup() diff --git a/lib_pypy/_pypy_interact.py b/lib_pypy/_pypy_interact.py --- a/lib_pypy/_pypy_interact.py +++ b/lib_pypy/_pypy_interact.py @@ -74,7 +74,6 @@ # ____________________________________________________________ if __name__ == '__main__': # for testing - import os if os.getenv('PYTHONSTARTUP'): execfile(os.getenv('PYTHONSTARTUP')) interactive_console() diff --git a/lib_pypy/_sha512.py b/lib_pypy/_sha512.py --- a/lib_pypy/_sha512.py +++ b/lib_pypy/_sha512.py @@ -30,23 +30,23 @@ def sha_transform(sha_info): W = [] - + d = sha_info['data'] for i in xrange(0,16): W.append( (d[8*i]<<56) + (d[8*i+1]<<48) + (d[8*i+2]<<40) + (d[8*i+3]<<32) + (d[8*i+4]<<24) + (d[8*i+5]<<16) + (d[8*i+6]<<8) + d[8*i+7]) - + for i in xrange(16,80): W.append( (Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]) & 0xffffffffffffffff ) - + ss = sha_info['digest'][:] - + def RND(a,b,c,d,e,f,g,h,i,ki): t0 = (h + Sigma1(e) + Ch(e, f, g) + ki + W[i]) & 0xffffffffffffffff t1 = (Sigma0(a) + Maj(a, b, c)) & 0xffffffffffffffff d = (d + t0) & 0xffffffffffffffff h = (t0 + t1) & 0xffffffffffffffff return d & 0xffffffffffffffff, h & 0xffffffffffffffff - + ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],0,0x428a2f98d728ae22) ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],1,0x7137449123ef65cd) ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],2,0xb5c0fbcfec4d3b2f) @@ -127,8 +127,7 @@ ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],77,0x597f299cfc657e2a) ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],78,0x5fcb6fab3ad6faec) ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],79,0x6c44198c4a475817) - - + dig = [] for i, x in enumerate(sha_info['digest']): dig.append( (x + ss[i]) & 0xffffffffffffffff ) @@ -167,36 +166,35 @@ if clo < sha_info['count_lo']: sha_info['count_hi'] += 1 sha_info['count_lo'] = clo - + sha_info['count_hi'] += (count >> 29) - + if sha_info['local']: i = SHA_BLOCKSIZE - sha_info['local'] if i > count: i = count - + # copy buffer for x in enumerate(buffer[buffer_idx:buffer_idx+i]): sha_info['data'][sha_info['local']+x[0]] = struct.unpack('B', x[1])[0] - + count -= i buffer_idx += i - + sha_info['local'] += i if sha_info['local'] == SHA_BLOCKSIZE: sha_transform(sha_info) sha_info['local'] = 0 else: return - + while count >= SHA_BLOCKSIZE: # copy buffer sha_info['data'] = [struct.unpack('B',c)[0] for c in buffer[buffer_idx:buffer_idx + SHA_BLOCKSIZE]] count -= SHA_BLOCKSIZE buffer_idx += SHA_BLOCKSIZE sha_transform(sha_info) - - + # copy buffer pos = sha_info['local'] sha_info['data'][pos:pos+count] = [struct.unpack('B',c)[0] for c in buffer[buffer_idx:buffer_idx + count]] @@ -216,7 +214,7 @@ sha_info['data'] = [0] * SHA_BLOCKSIZE else: sha_info['data'] = sha_info['data'][:count] + ([0] * (SHA_BLOCKSIZE - count)) - + sha_info['data'][112] = 0; sha_info['data'][113] = 0; sha_info['data'][114] = 0; @@ -225,7 +223,7 @@ sha_info['data'][117] = 0; sha_info['data'][118] = 0; sha_info['data'][119] = 0; - + sha_info['data'][120] = (hi_bit_count >> 24) & 0xff sha_info['data'][121] = (hi_bit_count >> 16) & 0xff sha_info['data'][122] = (hi_bit_count >> 8) & 0xff @@ -234,9 +232,9 @@ sha_info['data'][125] = (lo_bit_count >> 16) & 0xff sha_info['data'][126] = (lo_bit_count >> 8) & 0xff sha_info['data'][127] = (lo_bit_count >> 0) & 0xff - + sha_transform(sha_info) - + dig = [] for i in sha_info['digest']: dig.extend([ ((i>>56) & 0xff), ((i>>48) & 0xff), ((i>>40) & 0xff), ((i>>32) & 0xff), ((i>>24) & 0xff), ((i>>16) & 0xff), ((i>>8) & 0xff), (i & 0xff) ]) @@ -250,13 +248,13 @@ self._sha = sha_init() if s: sha_update(self._sha, getbuf(s)) - + def update(self, s): sha_update(self._sha, getbuf(s)) - + def digest(self): return sha_final(self._sha.copy())[:self._sha['digestsize']] - + def hexdigest(self): return ''.join(['%.2x' % ord(i) for i in self.digest()]) @@ -279,12 +277,14 @@ return new def test(): + import _sha512 + a_str = "just a test string" - + assert _sha512.sha512().hexdigest() == sha512().hexdigest() assert _sha512.sha512(a_str).hexdigest() == sha512(a_str).hexdigest() assert _sha512.sha512(a_str*7).hexdigest() == sha512(a_str*7).hexdigest() - + s = sha512(a_str) s.update(a_str) assert _sha512.sha512(a_str+a_str).hexdigest() == s.hexdigest() diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -29,7 +29,6 @@ import string import sys import weakref -import array from threading import _get_ident as _thread_get_ident try: from __pypy__ import newlist_hint @@ -219,7 +218,7 @@ const char **pzTail /* OUT: Pointer to unused portion of zSql */ ); -void sqlite3_result_blob(sqlite3_context*, const char*, int, void(*)(void*)); +void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); void sqlite3_result_double(sqlite3_context*, double); void sqlite3_result_error(sqlite3_context*, const char*, int); void sqlite3_result_error16(sqlite3_context*, const void*, int); @@ -853,7 +852,7 @@ self._reset = False self.__locked = False self.__closed = False - self.__description = None + self.__lastrowid = None self.__rowcount = -1 con._check_thread() @@ -959,11 +958,7 @@ elif typ == _lib.SQLITE_BLOB: blob = _lib.sqlite3_column_blob(self.__statement._statement, i) blob_len = _lib.sqlite3_column_bytes(self.__statement._statement, i) - # make a copy of the data into an array, in order to get - # a read-write buffer in the end, and one that own the - # memory for a more predictable length of time than 'blob' - copy = array.array("c", _ffi.buffer(blob, blob_len)) - val = _BLOB_TYPE(copy) + val = _BLOB_TYPE(_ffi.buffer(blob, blob_len)[:]) row.append(val) return tuple(row) @@ -977,20 +972,24 @@ try: if not isinstance(sql, basestring): raise ValueError("operation parameter must be str or unicode") - self.__description = None + try: + del self.__description + except AttributeError: + pass self.__rowcount = -1 self.__statement = self.__connection._statement_cache.get(sql) if self.__connection._isolation_level is not None: - if self.__statement._kind == Statement._DDL: + if self.__statement._type in ("UPDATE", "DELETE", "INSERT", "REPLACE"): + if not self.__connection._in_transaction: + self.__connection._begin() + elif self.__statement._type == "OTHER": if self.__connection._in_transaction: self.__connection.commit() - elif self.__statement._kind == Statement._DML: - if not self.__connection._in_transaction: - self.__connection._begin() - - if multiple and self.__statement._kind != Statement._DML: - raise ProgrammingError("executemany is only for DML statements") + elif self.__statement._type == "SELECT": + if multiple: + raise ProgrammingError("You cannot execute SELECT " + "statements in executemany().") for params in many_params: self.__statement._set_params(params) @@ -1001,17 +1000,26 @@ self.__statement._reset() raise self.__connection._get_exception(ret) - if self.__statement._kind == Statement._DML: + if ret == _lib.SQLITE_ROW: + if multiple: + raise ProgrammingError("executemany() can only execute DML statements.") + self.__build_row_cast_map() + self.__next_row = self.__fetch_one_row() + elif ret == _lib.SQLITE_DONE and not multiple: self.__statement._reset() - if ret == _lib.SQLITE_ROW: - self.__build_row_cast_map() - self.__next_row = self.__fetch_one_row() - - if self.__statement._kind == Statement._DML: + if self.__statement._type in ("UPDATE", "DELETE", "INSERT", "REPLACE"): if self.__rowcount == -1: self.__rowcount = 0 self.__rowcount += _lib.sqlite3_changes(self.__connection._db) + + if not multiple and self.__statement._type == "INSERT": + self.__lastrowid = _lib.sqlite3_last_insert_rowid(self.__connection._db) + else: + self.__lastrowid = None + + if multiple: + self.__statement._reset() finally: self.__connection._in_transaction = \ not _lib.sqlite3_get_autocommit(self.__connection._db) @@ -1123,13 +1131,15 @@ rowcount = property(__get_rowcount) def __get_description(self): - if self.__description is None: + try: + return self.__description + except AttributeError: self.__description = self.__statement._get_description() - return self.__description + return self.__description description = property(__get_description) def __get_lastrowid(self): - return _lib.sqlite3_last_insert_rowid(self.__connection._db) + return self.__lastrowid lastrowid = property(__get_lastrowid) def setinputsizes(self, *args): @@ -1140,8 +1150,6 @@ class Statement(object): - _DML, _DQL, _DDL = range(3) - _statement = None def __init__(self, connection, sql): @@ -1152,13 +1160,14 @@ if not isinstance(sql, basestring): raise Warning("SQL is of wrong type. Must be string or unicode.") - first_word = self._statement_kind = sql.lstrip().split(" ")[0].upper() - if first_word in ("INSERT", "UPDATE", "DELETE", "REPLACE"): - self._kind = Statement._DML - elif first_word in ("SELECT", "PRAGMA"): - self._kind = Statement._DQL + + first_word = sql.lstrip().split(" ")[0].upper() + if first_word == "": + self._type = "INVALID" + elif first_word in ("SELECT", "INSERT", "UPDATE", "DELETE", "REPLACE"): + self._type = first_word else: - self._kind = Statement._DDL + self._type = "OTHER" if isinstance(sql, unicode): sql = sql.encode('utf-8') @@ -1171,11 +1180,12 @@ if ret == _lib.SQLITE_OK and not self._statement: # an empty statement, work around that, as it's the least trouble + self._type = "SELECT" c_sql = _ffi.new("char[]", b"select 42") ret = _lib.sqlite3_prepare_v2(self.__con._db, c_sql, -1, statement_star, next_char) self._statement = statement_star[0] - self._kind = Statement._DQL + if ret != _lib.SQLITE_OK: raise self.__con._get_exception(ret) @@ -1286,7 +1296,7 @@ raise ValueError("parameters are of unsupported type") def _get_description(self): - if self._kind == Statement._DML: + if self._type in ("INSERT", "UPDATE", "DELETE", "REPLACE"): return None desc = [] for i in xrange(_lib.sqlite3_column_count(self._statement)): @@ -1391,7 +1401,7 @@ elif typ == _lib.SQLITE_BLOB: blob = _lib.sqlite3_value_blob(params[i]) blob_len = _lib.sqlite3_value_bytes(params[i]) - val = _BLOB_TYPE(_ffi.buffer(blob, blob_len)) + val = _BLOB_TYPE(_ffi.buffer(blob, blob_len)[:]) else: raise NotImplementedError _params.append(val) diff --git a/lib_pypy/dbm.py b/lib_pypy/dbm.py --- a/lib_pypy/dbm.py +++ b/lib_pypy/dbm.py @@ -168,7 +168,7 @@ 'c': os.O_RDWR | os.O_CREAT, 'n': os.O_RDWR | os.O_CREAT | os.O_TRUNC, }[flag] - except KeyError, e: + except KeyError: raise error("arg 2 to open should be 'r', 'w', 'c', or 'n'") a_db = getattr(lib, funcs['open'])(filename, openflag, mode) diff --git a/lib_pypy/greenlet.py b/lib_pypy/greenlet.py --- a/lib_pypy/greenlet.py +++ b/lib_pypy/greenlet.py @@ -1,4 +1,4 @@ -import _continuation, sys +import _continuation __version__ = "0.4.0" diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -115,9 +115,9 @@ .. branch: remove-list-smm .. branch: bridge-logging .. branch: curses_cffi - cffi implementation of _curses .. branch: sqlite-cffi +cffi implementation of sqlite3 -cffi implementation of sqlite3 +.. branch: release-2.0-beta2 diff --git a/pypy/interpreter/astcompiler/misc.py b/pypy/interpreter/astcompiler/misc.py --- a/pypy/interpreter/astcompiler/misc.py +++ b/pypy/interpreter/astcompiler/misc.py @@ -1,5 +1,4 @@ from pypy.interpreter import gateway -from pypy.interpreter.astcompiler import ast from rpython.rlib.objectmodel import we_are_translated from rpython.rlib.unroll import unrolling_iterable @@ -28,6 +27,7 @@ def parse_future(tree, feature_flags): + from pypy.interpreter.astcompiler import ast future_lineno = 0 future_column = 0 flags = 0 @@ -91,13 +91,9 @@ return lookup -MANGLE_LEN = 256 # magic constant from compile.c - def mangle(name, klass): if not name.startswith('__'): return name - if len(name) + 2 >= MANGLE_LEN: - return name # Don't mangle __id__ or names with dots. The only time a name with a dot # can occur is when we are compiling an import statement that has a package # name. @@ -109,14 +105,4 @@ i = i + 1 except IndexError: return name - klass = klass[i:] - - tlen = len(klass) + len(name) - if tlen > MANGLE_LEN: - end = len(klass) + MANGLE_LEN-tlen - if end < 0: - klass = '' # slices of negative length are invalid in RPython - else: - klass = klass[:end] - - return "_%s%s" % (klass, name) + return "_%s%s" % (klass[i:], name) diff --git a/pypy/interpreter/astcompiler/test/test_misc.py b/pypy/interpreter/astcompiler/test/test_misc.py new file mode 100644 --- /dev/null +++ b/pypy/interpreter/astcompiler/test/test_misc.py @@ -0,0 +1,14 @@ +from pypy.interpreter.astcompiler.misc import mangle + +def test_mangle(): + assert mangle("foo", "Bar") == "foo" + assert mangle("__foo__", "Bar") == "__foo__" + assert mangle("foo.baz", "Bar") == "foo.baz" + assert mangle("__", "Bar") == "__" + assert mangle("___", "Bar") == "___" + assert mangle("____", "Bar") == "____" + assert mangle("__foo", "Bar") == "_Bar__foo" + assert mangle("__foo", "_Bar") == "_Bar__foo" + assert mangle("__foo", "__Bar") == "_Bar__foo" + assert mangle("__foo", "___") == "__foo" + assert mangle("___foo", "__Bar") == "_Bar___foo" diff --git a/pypy/module/_socket/test/test_sock_app.py b/pypy/module/_socket/test/test_sock_app.py --- a/pypy/module/_socket/test/test_sock_app.py +++ b/pypy/module/_socket/test/test_sock_app.py @@ -233,7 +233,7 @@ def test_unknown_addr_as_object(): from pypy.module._socket.interp_socket import addr_as_object - c_addr = lltype.malloc(rsocket._c.sockaddr, flavor='raw') + c_addr = lltype.malloc(rsocket._c.sockaddr, flavor='raw', track_allocation=False) c_addr.c_sa_data[0] = 'c' rffi.setintfield(c_addr, 'c_sa_family', 15) # XXX what size to pass here? for the purpose of this test it has diff --git a/pypy/module/cpyext/include/patchlevel.h b/pypy/module/cpyext/include/patchlevel.h --- a/pypy/module/cpyext/include/patchlevel.h +++ b/pypy/module/cpyext/include/patchlevel.h @@ -29,7 +29,7 @@ #define PY_VERSION "2.7.3" /* PyPy version as a string */ -#define PYPY_VERSION "2.0.0-beta1" +#define PYPY_VERSION "2.0.0-beta2" /* Subversion Revision number of this file (not of the repository). * Empty since Mercurial migration. */ diff --git a/pypy/module/sys/version.py b/pypy/module/sys/version.py --- a/pypy/module/sys/version.py +++ b/pypy/module/sys/version.py @@ -11,7 +11,7 @@ #XXX # sync CPYTHON_VERSION with patchlevel.h, package.py CPYTHON_API_VERSION = 1013 #XXX # sync with include/modsupport.h -PYPY_VERSION = (2, 0, 0, "beta", 1) #XXX # sync patchlevel.h +PYPY_VERSION = (2, 0, 0, "beta", 2) #XXX # sync patchlevel.h if platform.name == 'msvc': COMPILER_INFO = 'MSC v.%d 32 bit' % (platform.version * 10 + 600) diff --git a/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py b/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py --- a/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py +++ b/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py @@ -510,6 +510,7 @@ assert seen == ["yadda"] def test_warnings(self): + py.test.skip("warnings are disabled") import warnings warnings.simplefilter("always") with warnings.catch_warnings(record=True) as w: diff --git a/pypy/module/test_lib_pypy/test_sqlite3.py b/pypy/module/test_lib_pypy/test_sqlite3.py --- a/pypy/module/test_lib_pypy/test_sqlite3.py +++ b/pypy/module/test_lib_pypy/test_sqlite3.py @@ -1,16 +1,25 @@ """Tests for _sqlite3.py""" -import sys +import pytest, sys + if sys.version_info < (2, 7): - skip("lib_pypy._sqlite3 doesn't work with python < 2.7") + pytest.skip("_sqlite3 requires Python 2.7") +try: + import _cffi_backend +except ImportError: + # On CPython, "pip install cffi". On old PyPy's, no chance + pytest.skip("_sqlite3 requires _cffi_backend to be installed") -import pytest from lib_pypy import _sqlite3 -def test_list_ddl(): +def pytest_funcarg__con(request): + con = _sqlite3.connect(':memory:') + request.addfinalizer(lambda: con.close()) + return con + +def test_list_ddl(con): """From issue996. Mostly just looking for lack of exceptions.""" - connection = _sqlite3.connect(':memory:') - cursor = connection.cursor() + cursor = con.cursor() cursor.execute('CREATE TABLE foo (bar INTEGER)') result = list(cursor) assert result == [] @@ -21,8 +30,7 @@ result = list(cursor) assert result == [(42,)] -def test_total_changes_after_close(): - con = _sqlite3.connect(':memory:') +def test_total_changes_after_close(con): con.close() pytest.raises(_sqlite3.ProgrammingError, "con.total_changes") @@ -35,25 +43,22 @@ e = pytest.raises(_sqlite3.ProgrammingError, "con.cursor()") assert '__init__' in e.value.message -def test_cursor_check_init(): +def test_cursor_check_init(con): class Cursor(_sqlite3.Cursor): def __init__(self, name): pass - con = _sqlite3.connect(":memory:") cur = Cursor(con) e = pytest.raises(_sqlite3.ProgrammingError, "cur.execute('select 1')") assert '__init__' in e.value.message -def test_connection_after_close(): - con = _sqlite3.connect(':memory:') +def test_connection_after_close(con): pytest.raises(TypeError, "con()") con.close() # raises ProgrammingError because should check closed before check args pytest.raises(_sqlite3.ProgrammingError, "con()") -def test_cursor_iter(): - con = _sqlite3.connect(':memory:') +def test_cursor_iter(con): cur = con.cursor() with pytest.raises(StopIteration): next(cur) @@ -85,8 +90,7 @@ with pytest.raises(StopIteration): next(cur) -def test_cursor_after_close(): - con = _sqlite3.connect(':memory:') +def test_cursor_after_close(con): cur = con.execute('select 1') cur.close() con.close() @@ -131,11 +135,10 @@ finally: resource.setrlimit(resource.RLIMIT_NOFILE, limit) -def test_on_conflict_rollback_executemany(): +def test_on_conflict_rollback_executemany(con): major, minor, micro = _sqlite3.sqlite_version.split('.') if (int(major), int(minor), int(micro)) < (3, 2, 2): pytest.skip("requires sqlite3 version >= 3.2.2") - con = _sqlite3.connect(":memory:") con.execute("create table foo(x, unique(x) on conflict rollback)") con.execute("insert into foo(x) values (1)") try: @@ -147,10 +150,8 @@ con.commit() except _sqlite3.OperationalError: pytest.fail("_sqlite3 knew nothing about the implicit ROLLBACK") - con.close() -def test_statement_arg_checking(): - con = _sqlite3.connect(':memory:') +def test_statement_arg_checking(con): with pytest.raises(_sqlite3.Warning) as e: con(123) assert str(e.value) == 'SQL is of wrong type. Must be string or unicode.' @@ -164,8 +165,7 @@ con.executescript(123) assert str(e.value) == 'script argument must be unicode or string.' -def test_statement_param_checking(): - con = _sqlite3.connect(':memory:') +def test_statement_param_checking(con): con.execute('create table foo(x)') con.execute('insert into foo(x) values (?)', [2]) con.execute('insert into foo(x) values (?)', (2,)) @@ -183,10 +183,8 @@ with pytest.raises(ValueError) as e: con.execute('insert into foo(x) values (?)', 2) assert str(e.value) == 'parameters are of unsupported type' - con.close() -def test_explicit_begin(): - con = _sqlite3.connect(':memory:') +def test_explicit_begin(con): con.execute('BEGIN') con.execute('BEGIN ') con.execute('BEGIN') @@ -194,25 +192,33 @@ con.execute('BEGIN') con.commit() -def test_row_factory_use(): - con = _sqlite3.connect(':memory:') +def test_row_factory_use(con): con.row_factory = 42 con.execute('select 1') -def test_returning_blob_must_own_memory(): +def test_returning_blob_must_own_memory(con): import gc - con = _sqlite3.connect(":memory:") con.create_function("returnblob", 0, lambda: buffer("blob")) - cur = con.cursor() - cur.execute("select returnblob()") + cur = con.execute("select returnblob()") val = cur.fetchone()[0] for i in range(5): gc.collect() got = (val[0], val[1], val[2], val[3]) assert got == ('b', 'l', 'o', 'b') + # in theory 'val' should be a read-write buffer + # but it's not right now + pytest.skip("in theory 'val' should be a read-write buffer") + val[1] = 'X' + got = (val[0], val[1], val[2], val[3]) + assert got == ('b', 'X', 'o', 'b') -def test_description_after_fetchall(): - con = _sqlite3.connect(":memory:") +def test_description_after_fetchall(con): cur = con.cursor() cur.execute("select 42").fetchall() assert cur.description is not None + +def test_executemany_lastrowid(con): + cur = con.cursor() + cur.execute("create table test(a)") + cur.executemany("insert into test values (?)", [[1], [2], [3]]) + assert cur.lastrowid is None diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py --- a/pypy/objspace/std/typeobject.py +++ b/pypy/objspace/std/typeobject.py @@ -4,6 +4,7 @@ from pypy.interpreter.function import Function, StaticMethod from pypy.interpreter.typedef import weakref_descr, GetSetProperty,\ descr_get_dict +from pypy.interpreter.astcompiler.misc import mangle from pypy.objspace.std.model import W_Object from pypy.objspace.std.register_all import register_all from pypy.objspace.std.stdtypedef import std_dict_descr, issubtypedef, Member @@ -26,34 +27,6 @@ return w_value.w_value return w_value -# from compiler/misc.py - -MANGLE_LEN = 256 # magic constant from compile.c - -def _mangle(name, klass): - if not name.startswith('__'): - return name - if len(name) + 2 >= MANGLE_LEN: - return name - if name.endswith('__'): - return name - try: - i = 0 - while klass[i] == '_': - i = i + 1 - except IndexError: - return name - klass = klass[i:] - - tlen = len(klass) + len(name) - if tlen > MANGLE_LEN: - end = len(klass) + MANGLE_LEN-tlen - if end < 0: - klass = '' # annotator hint - else: - klass = klass[:end] - - return "_%s%s" % (klass, name) class VersionTag(object): pass @@ -987,7 +960,7 @@ raise OperationError(space.w_TypeError, space.wrap('__slots__ must be identifiers')) # create member - slot_name = _mangle(slot_name, w_self.name) + slot_name = mangle(slot_name, w_self.name) if slot_name not in w_self.dict_w: # Force interning of slot names. slot_name = space.str_w(space.new_interned_str(slot_name)) diff --git a/pypy/tool/release/package.py b/pypy/tool/release/package.py --- a/pypy/tool/release/package.py +++ b/pypy/tool/release/package.py @@ -67,7 +67,8 @@ 'Bogus path: %r does not exist (see docstring for more info)' % (os.path.dirname(str(pypy_c)),)) subprocess.check_call([str(pypy_c), '-c', 'import _sqlite3']) - subprocess.check_call([str(pypy_c), '-c', 'import _curses']) + if not sys.platform == 'win32': + subprocess.check_call([str(pypy_c), '-c', 'import _curses']) if sys.platform == 'win32' and not rename_pypy_c.lower().endswith('.exe'): rename_pypy_c += '.exe' binaries = [(pypy_c, rename_pypy_c)] diff --git a/pypy/tool/release/test/test_package.py b/pypy/tool/release/test/test_package.py --- a/pypy/tool/release/test/test_package.py +++ b/pypy/tool/release/test/test_package.py @@ -17,7 +17,7 @@ exe_name_in_archive = 'bin/pypy' pypy_c = py.path.local(pypydir).join('goal', basename) if not pypy_c.check(): - os.system("echo faked_pypy_c> %s" % (pypy_c,)) + pypy_c.write("#!/bin/sh") pypy_c.chmod(0755) fake_pypy_c = True else: diff --git a/pypy/tool/test/test_tab.py b/pypy/tool/test/test_tab.py --- a/pypy/tool/test/test_tab.py +++ b/pypy/tool/test/test_tab.py @@ -5,7 +5,7 @@ import os from pypy.conftest import pypydir -ROOT = pypydir +ROOT = os.path.abspath(os.path.join(pypydir, '..')) EXCLUDE = {} diff --git a/rpython/flowspace/framestate.py b/rpython/flowspace/framestate.py --- a/rpython/flowspace/framestate.py +++ b/rpython/flowspace/framestate.py @@ -2,7 +2,7 @@ from rpython.rlib.unroll import SpecTag -class FrameState: +class FrameState(object): def __init__(self, mergeable, blocklist, next_instr): self.mergeable = mergeable self.blocklist = blocklist @@ -63,6 +63,7 @@ class UnionError(Exception): "The two states should be merged." + def union(w1, w2): "Union of two variables or constants." if w1 is None or w2 is None: @@ -117,7 +118,7 @@ key = unroller.__class__, len(vars) try: tag = PICKLE_TAGS[key] - except: + except KeyError: tag = PICKLE_TAGS[key] = Constant(PickleTag()) UNPICKLE_TAGS[tag] = key lst[i:i + 1] = [tag] + vars diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -305,7 +305,7 @@ self._restore_exception(mc, exc0, exc1) mc.VPOP([vfpr.value for vfpr in r.caller_vfp_resp]) assert exc0 is not None - assert exc1 is not None + assert exc1 is not None mc.POP([gpr.value for gpr in r.caller_resp] + [exc0.value, exc1.value]) # @@ -526,9 +526,7 @@ self.gen_shadowstack_header(gcrootmap) def gen_shadowstack_header(self, gcrootmap): - # we need to put two words into the shadowstack: the MARKER_FRAME - # and the address of the frame (fp, actually) - # lr = rst addr + # lr = shadow stack top addr # ip = *lr rst = gcrootmap.get_root_stack_top_addr() self.mc.gen_load_int(r.lr.value, rst) @@ -1062,8 +1060,7 @@ self.mc.PUSH([helper.value], cond=cond) self.load_reg(self.mc, loc, r.fp, offset, cond=cond, helper=helper) if save_helper: - self.mc.POP([helper.value], cond=cond) - + self.mc.POP([helper.value], cond=cond) def _mov_imm_float_to_loc(self, prev_loc, loc, cond=c.AL): if loc.is_vfp_reg(): diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -628,12 +628,14 @@ bool(self._regalloc.vfprm.reg_bindings)) assert self.wb_slowpath[helper_num] != 0 # - if not is_frame and loc_base is not r.r0: + if loc_base is not r.r0: # push two registers to keep stack aligned mc.PUSH([r.r0.value, loc_base.value]) - remap_frame_layout(self, [loc_base], [r.r0], r.ip) + mc.MOV_rr(r.r0.value, loc_base.value) + if is_frame: + assert loc_base is r.fp mc.BL(self.wb_slowpath[helper_num]) - if not is_frame and loc_base is not r.r0: + if loc_base is not r.r0: mc.POP([r.r0.value, loc_base.value]) if card_marking: diff --git a/rpython/jit/backend/arm/runner.py b/rpython/jit/backend/arm/runner.py --- a/rpython/jit/backend/arm/runner.py +++ b/rpython/jit/backend/arm/runner.py @@ -120,7 +120,7 @@ """ARM v7 uses hardfp ABI, requires vfp""" hf_abi = True backend_name = "armv7hf" - supports_floats = False + supports_floats = True supports_singlefloats = False @@ -129,5 +129,5 @@ hf_abi = True arch_version = 6 backend_name = "armv6hf" - supports_floats = False + supports_floats = True supports_singlefloats = False diff --git a/rpython/jit/backend/arm/test/test_calling_convention.py b/rpython/jit/backend/arm/test/test_calling_convention.py --- a/rpython/jit/backend/arm/test/test_calling_convention.py +++ b/rpython/jit/backend/arm/test/test_calling_convention.py @@ -72,7 +72,7 @@ callargs = [] def func(f0, f1, f2, f3, f4, f5, f6, i0, f7, i1, f8, f9): callargs.append(zip(range(12), - [f0, f1, f2, f3, f4, f5, f6, i0, f7, i1, f8, f9])) + [f0, f1, f2, f3, f4, f5, f6, i0, f7, i1, f8, f9])) return f0 + f1 + f2 + f3 + f4 + f5 + f6 + float(i0 + i1) + f7 + f8 + f9 F = lltype.Float I = lltype.Signed @@ -103,7 +103,7 @@ callargs = [] def func(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9): callargs.append(zip(range(10), - [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9])) + [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9])) return f0 + f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8 + f9 F = lltype.Float FUNC = self.FuncType([F] * 10, F) @@ -125,7 +125,7 @@ callargs = [] def func(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9): callargs.append(zip(range(10), - [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9])) + [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9])) return f0 + f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8 + f9 I = lltype.Signed diff --git a/rpython/jit/backend/arm/test/test_runner.py b/rpython/jit/backend/arm/test/test_runner.py --- a/rpython/jit/backend/arm/test/test_runner.py +++ b/rpython/jit/backend/arm/test/test_runner.py @@ -34,11 +34,11 @@ else: bridge_loop_instructions = ['ldr', 'mov', 'nop', 'nop', 'nop', 'cmp', 'bge', 'push', 'ldr', 'mov', - '', # inline constant + '*', # inline constant 'push', 'ldr', 'mov', - 'ldrsblt', #inline constant (decodes as instruction) + '*', # inline constant 'blx', 'ldr', 'mov', - '', # inline constant + '*', # inline constant 'bx'] def get_cpu(self): diff --git a/rpython/jit/backend/llsupport/test/test_gc_integration.py b/rpython/jit/backend/llsupport/test/test_gc_integration.py --- a/rpython/jit/backend/llsupport/test/test_gc_integration.py +++ b/rpython/jit/backend/llsupport/test/test_gc_integration.py @@ -256,7 +256,9 @@ if self.cpu.IS_64_BIT: assert frame.jf_gcmap[idx] == (1<<29) | (1 << 30) else: - assert frame.jf_gcmap[idx] == (1<<24) | (1 << 23) + assert frame.jf_gcmap[idx] + exp_idx = self.cpu.JITFRAME_FIXED_SIZE - 32 * idx + 1 # +1 from i0 + assert frame.jf_gcmap[idx] == (1 << (exp_idx + 1)) | (1 << exp_idx) self.cpu = self.getcpu(check) ops = ''' @@ -680,7 +682,7 @@ def f(frame, x): # all the gc pointers are alive p1 -> p7 (but not p0) - assert bin(frame.jf_gcmap[0]).count('1') == 7 + assert getmap(frame).count('1') == 7 # assert x == 1 return 2 @@ -713,7 +715,7 @@ def f(frame, arg, x): assert not arg assert frame.jf_gcmap[0] & 31 == 0 - assert bin(frame.jf_gcmap[0]).count('1') == 3 # p1, p2, p3, but + assert getmap(frame).count('1') == 3 # p1, p2, p3, but # not in registers frame.jf_descr = frame.jf_force_descr # make guard_not_forced fail assert x == 1 @@ -749,7 +751,8 @@ cpu.compile_loop(loop.inputargs, loop.operations, token) frame = lltype.cast_opaque_ptr(JITFRAMEPTR, cpu.execute_token(token, 1, a)) - assert bin(frame.jf_gcmap[0]).count('1') == 4 + + assert getmap(frame).count('1') == 4 def test_call_gcmap_no_guard(self): cpu = self.cpu @@ -757,7 +760,7 @@ def f(frame, arg, x): assert not arg assert frame.jf_gcmap[0] & 31 == 0 - assert bin(frame.jf_gcmap[0]).count('1') == 3 # p1, p2, p3 + assert getmap(frame).count('1') == 3 # p1, p2, p3 frame.jf_descr = frame.jf_force_descr # make guard_not_forced fail assert x == 1 return lltype.nullptr(llmemory.GCREF.TO) @@ -792,4 +795,5 @@ cpu.compile_loop(loop.inputargs, loop.operations, token) frame = lltype.cast_opaque_ptr(JITFRAMEPTR, cpu.execute_token(token, 1, a)) - assert bin(frame.jf_gcmap[0]).count('1') == 4 + assert getmap(frame).count('1') == 4 + diff --git a/rpython/jit/backend/test/calling_convention_test.py b/rpython/jit/backend/test/calling_convention_test.py --- a/rpython/jit/backend/test/calling_convention_test.py +++ b/rpython/jit/backend/test/calling_convention_test.py @@ -384,7 +384,7 @@ def test_call_aligned_explicit_check(self): if (not platform.machine().startswith('arm') and - sys.maxint == 2 ** 31 - 1): # XXX is still necessary on x86? + sys.maxint == 2 ** 31 - 1): # XXX is still necessary on x86? py.test.skip("libffi on 32bit is broken") cpu = self.cpu if not cpu.supports_floats: diff --git a/rpython/jit/backend/test/runner_test.py b/rpython/jit/backend/test/runner_test.py --- a/rpython/jit/backend/test/runner_test.py +++ b/rpython/jit/backend/test/runner_test.py @@ -3475,6 +3475,8 @@ def checkops(mc, ops): assert len(mc) == len(ops) for i in range(len(mc)): + if ops[i] == '*': + continue # ingore ops marked as '*', i.e. inline constants assert mc[i].split("\t")[2].startswith(ops[i]) data = ctypes.string_at(info.asmaddr, info.asmlen) diff --git a/rpython/jit/backend/x86/runner.py b/rpython/jit/backend/x86/runner.py --- a/rpython/jit/backend/x86/runner.py +++ b/rpython/jit/backend/x86/runner.py @@ -58,10 +58,10 @@ self.assembler = Assembler386(self, self.translate_support_code) def build_regalloc(self): - ''' for tests''' - from rpython.jit.backend.x86.regalloc import RegAlloc - assert self.assembler is not None - return RegAlloc(self.assembler, False) + ''' for tests''' + from rpython.jit.backend.x86.regalloc import RegAlloc + assert self.assembler is not None + return RegAlloc(self.assembler, False) def setup_once(self): self.profile_agent.startup() diff --git a/rpython/jit/metainterp/optimizeopt/rewrite.py b/rpython/jit/metainterp/optimizeopt/rewrite.py --- a/rpython/jit/metainterp/optimizeopt/rewrite.py +++ b/rpython/jit/metainterp/optimizeopt/rewrite.py @@ -456,7 +456,7 @@ [op.getarg(1), ConstInt(index + source_start)], resbox, descr=arraydescr) - self.optimizer.propagate_forward(newop) + self.optimizer.send_extra_operation(newop) val = self.getvalue(resbox) if dest_value.is_virtual(): dest_value.setitem(index + dest_start, val) diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py --- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py @@ -4282,9 +4282,9 @@ self.optimize_loop(ops, expected) def test_add_sub_ovf_second_operation_regular(self): - py.test.skip("Smalltalk would like this to pass") - # This situation occurs in Smalltalk because it uses 1-based indexing. - # The below code is equivalent to a loop over an array. + py.test.skip("Smalltalk would like this to pass") + # This situation occurs in Smalltalk because it uses 1-based indexing. + # The below code is equivalent to a loop over an array. ops = """ [i1] i2 = int_sub(i1, 1) @@ -7609,6 +7609,25 @@ """ self.optimize_loop(ops, ops) + def test_setarrayitem_followed_by_arraycopy_2(self): + ops = """ + [i1, i2] + p1 = new_array(i1, descr=arraydescr) + setarrayitem_gc(p1, 0, i2, descr=arraydescr) + p3 = new_array(5, descr=arraydescr) + call(0, p1, p3, 0, 1, 1, descr=arraycopydescr) + i4 = getarrayitem_gc(p3, 1, descr=arraydescr) + jump(i1, i4) + """ + expected = """ + [i1, i2] + # operations are not all removed because this new_array() is var-sized + p1 = new_array(i1, descr=arraydescr) + setarrayitem_gc(p1, 0, i2, descr=arraydescr) + jump(i1, i2) + """ + self.optimize_loop(ops, expected) + def test_heap_cache_virtuals_forced_by_delayed_setfield(self): py.test.skip('not yet supoprted') ops = """ diff --git a/rpython/jit/tl/tla/tla_assembler.py b/rpython/jit/tl/tla/tla_assembler.py --- a/rpython/jit/tl/tla/tla_assembler.py +++ b/rpython/jit/tl/tla/tla_assembler.py @@ -2,8 +2,8 @@ import sys import py +from rpython.jit.tl.tla.test_tla import assemble py.path.local(__file__) -from rpython.jit.tl.tla.test_tla import assemble def usage(): print >> sys.stderr, 'Usage: tla_assembler.py filename.tla.py' diff --git a/rpython/rtyper/lltypesystem/lltype.py b/rpython/rtyper/lltypesystem/lltype.py --- a/rpython/rtyper/lltypesystem/lltype.py +++ b/rpython/rtyper/lltypesystem/lltype.py @@ -503,7 +503,7 @@ return obj def __init__(self, OF, length, **kwds): - if hasattr(self, '_name'): + if '_name' in self.__dict__: assert self.OF == OF assert self.length == length return diff --git a/rpython/translator/platform/arm.py b/rpython/translator/platform/arm.py --- a/rpython/translator/platform/arm.py +++ b/rpython/translator/platform/arm.py @@ -47,11 +47,12 @@ return ExecutionResult(returncode, stdout, stderr) def include_dirs_for_libffi(self): - return [SB2 + '/usr/include/arm-linux-gnueabi/'] + return [SB2 + '/usr/include/arm-linux-gnueabi/', + SB2 + '/usr/include/arm-linux-gnueabihf/'] def library_dirs_for_libffi(self): - # on the other hand, library lands in usual place... - return [] + return [SB2 + '/usr/lib/arm-linux-gnueabi/', + SB2 + '/usr/lib/arm-linux-gnueabihf/'] def execute_makefile(self, path_to_makefile, extra_opts=[]): if isinstance(path_to_makefile, GnuMakefile): From noreply at buildbot.pypy.org Mon Apr 8 11:45:33 2013 From: noreply at buildbot.pypy.org (fijal) Date: Mon, 8 Apr 2013 11:45:33 +0200 (CEST) Subject: [pypy-commit] pypy default: merge Message-ID: <20130408094533.42CC41C15A7@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r63130:9cbd1b5985f9 Date: 2013-04-08 11:45 +0200 http://bitbucket.org/pypy/pypy/changeset/9cbd1b5985f9/ Log: merge diff --git a/pypy/doc/stackless.rst b/pypy/doc/stackless.rst --- a/pypy/doc/stackless.rst +++ b/pypy/doc/stackless.rst @@ -17,8 +17,8 @@ Continulets can be directly used by application code, or it is possible to write (entirely at app-level) more user-friendly interfaces. -Currently PyPy implements greenlets_ on top of continulets. It would be -easy to implement tasklets and channels as well, emulating the model +Currently PyPy implements greenlets_ on top of continulets. It also +implements (an approximation of) tasklets and channels, emulating the model of `Stackless Python`_. Continulets are extremely light-weight, which means that PyPy should be diff --git a/rpython/config/translationoption.py b/rpython/config/translationoption.py --- a/rpython/config/translationoption.py +++ b/rpython/config/translationoption.py @@ -115,7 +115,7 @@ ("translation.gcrootfinder", DEFL_ROOTFINDER_WITHJIT), ("translation.list_comprehension_operations", True)]), ChoiceOption("jit_backend", "choose the backend for the JIT", - ["auto", "x86", "x86-without-sse2", 'armv7'], + ["auto", "x86", "x86-without-sse2", 'armv7', 'armv7hf', 'armv6hf'], default="auto", cmdline="--jit-backend"), ChoiceOption("jit_profiler", "integrate profiler support into the JIT", ["off", "oprofile"], diff --git a/rpython/translator/goal/translate.py b/rpython/translator/goal/translate.py --- a/rpython/translator/goal/translate.py +++ b/rpython/translator/goal/translate.py @@ -50,7 +50,7 @@ return result translate_optiondescr = OptionDescription("translate", "XXX", [ - StrOption("targetspec", "XXX", default='../../../pypy/goal/targetpypystandalone', + StrOption("targetspec", "XXX", default='targetpypystandalone', cmdline=None), ChoiceOption("opt", "optimization level", OPT_LEVELS, default=DEFAULT_OPT_LEVEL, From noreply at buildbot.pypy.org Mon Apr 8 11:45:53 2013 From: noreply at buildbot.pypy.org (arigo) Date: Mon, 8 Apr 2013 11:45:53 +0200 (CEST) Subject: [pypy-commit] pypy default: Support for 'rep ret' Message-ID: <20130408094553.9C0DB1C15A7@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63131:33015def606f Date: 2013-04-08 11:45 +0200 http://bitbucket.org/pypy/pypy/changeset/33015def606f/ Log: Support for 'rep ret' diff --git a/rpython/translator/c/gcc/test/elf64/track_basic_argument_registers.s b/rpython/translator/c/gcc/test/elf64/track_basic_argument_registers.s --- a/rpython/translator/c/gcc/test/elf64/track_basic_argument_registers.s +++ b/rpython/translator/c/gcc/test/elf64/track_basic_argument_registers.s @@ -25,7 +25,8 @@ /* GCROOT -48(%rbp) */ movq -24(%rbp), %rax leave - ret + ; try out a "rep ret" instead of just a "ret", for bad reasons + rep ret .cfi_endproc .LFE0: .size foobar, .-foobar diff --git a/rpython/translator/c/gcc/trackgcroot.py b/rpython/translator/c/gcc/trackgcroot.py --- a/rpython/translator/c/gcc/trackgcroot.py +++ b/rpython/translator/c/gcc/trackgcroot.py @@ -664,6 +664,12 @@ def visit_ret(self, line): return InsnRet(self.CALLEE_SAVE_REGISTERS) + def visit_rep(self, line): + # 'rep ret': bad reasons for this bogus 'rep' here + if line.split()[:2] == ['rep', 'ret']: + return self.visit_ret(line) + return [] + def visit_jmp(self, line): tablelabels = [] match = self.r_jmp_switch.match(line) From noreply at buildbot.pypy.org Mon Apr 8 11:52:02 2013 From: noreply at buildbot.pypy.org (fijal) Date: Mon, 8 Apr 2013 11:52:02 +0200 (CEST) Subject: [pypy-commit] buildbot default: kill benchmarks on speed Message-ID: <20130408095202.E1DB31C15A2@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r775:358f8194ba69 Date: 2013-04-08 11:51 +0200 http://bitbucket.org/pypy/buildbot/changeset/358f8194ba69/ Log: kill benchmarks on speed diff --git a/bot2/pypybuildbot/master.py b/bot2/pypybuildbot/master.py --- a/bot2/pypybuildbot/master.py +++ b/bot2/pypybuildbot/master.py @@ -158,13 +158,6 @@ pypyJITBenchmarkFactory_tannit = pypybuilds.JITBenchmark() pypyJITBenchmarkFactory64_tannit = pypybuilds.JITBenchmark(platform='linux64', postfix='-64') -pypyJITBenchmarkFactory64_speed = pypybuilds.JITBenchmark(platform='linux64', - postfix='-64', - host='speed_python') - -cPython27BenchmarkFactory64 = pypybuilds.CPythonBenchmark('2.7', - platform='linux64') - # @@ -323,20 +316,6 @@ "category": "benchmark-run", # the locks are acquired with fine grain inside the build }, - {"name": JITBENCH64_2, - "slavenames": ["speed-python-64"], - "builddir": JITBENCH64_2, - "factory": pypyJITBenchmarkFactory64_speed, - "category": "benchmark-run", - # the locks are acquired with fine grain inside the build - }, - {"name": CPYTHON_64, - "slavenames": ["speed-python-64"], - "builddir": CPYTHON_64, - "factory": cPython27BenchmarkFactory64, - "category": "benchmark-run", - # the locks are acquired with fine grain inside the build - }, {"name": MACOSX32, "slavenames": ["minime"], "builddir": MACOSX32, From noreply at buildbot.pypy.org Mon Apr 8 13:05:04 2013 From: noreply at buildbot.pypy.org (arigo) Date: Mon, 8 Apr 2013 13:05:04 +0200 (CEST) Subject: [pypy-commit] pypy default: Fix _curses to not use unicode names when creating attributes. Message-ID: <20130408110504.048151C010B@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63132:95c7ec00101c Date: 2013-04-08 11:06 +0000 http://bitbucket.org/pypy/pypy/changeset/95c7ec00101c/ Log: Fix _curses to not use unicode names when creating attributes. Fix translation to work anyway in this case (because pypy 2.0-beta2 has such attributes). diff --git a/lib_pypy/_curses.py b/lib_pypy/_curses.py --- a/lib_pypy/_curses.py +++ b/lib_pypy/_curses.py @@ -364,7 +364,9 @@ key_n = ffi.string(key_n) if key_n == b"UNKNOWN KEY": continue - key_n = key_n.decode().replace('(', '').replace(')', '') + if not isinstance(key_n, str): # python 3 + key_n = key_n.decode() + key_n = key_n.replace('(', '').replace(')', '') globals()[key_n] = key _setup() diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py --- a/pypy/interpreter/baseobjspace.py +++ b/pypy/interpreter/baseobjspace.py @@ -709,6 +709,7 @@ def new_interned_w_str(self, w_s): s = self.str_w(w_s) + assert isinstance(s, str) try: return self.interned_strings[s] except KeyError: @@ -717,6 +718,7 @@ return w_s def new_interned_str(self, s): + assert isinstance(s, str) try: return self.interned_strings[s] except KeyError: diff --git a/pypy/module/_minimal_curses/__init__.py b/pypy/module/_minimal_curses/__init__.py --- a/pypy/module/_minimal_curses/__init__.py +++ b/pypy/module/_minimal_curses/__init__.py @@ -27,6 +27,7 @@ } for i in dir(_curses): + i = str(i) # workaround for pypy 2.0-beta2 val = getattr(_curses, i) if i.isupper() and type(val) is int: Module.interpleveldefs[i] = "space.wrap(%s)" % val From noreply at buildbot.pypy.org Mon Apr 8 13:05:05 2013 From: noreply at buildbot.pypy.org (arigo) Date: Mon, 8 Apr 2013 13:05:05 +0200 (CEST) Subject: [pypy-commit] pypy default: merge heads Message-ID: <20130408110505.3CD571C010B@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63133:8ca71dff5420 Date: 2013-04-08 11:07 +0000 http://bitbucket.org/pypy/pypy/changeset/8ca71dff5420/ Log: merge heads diff --git a/pypy/doc/release-2.0.0-beta2.rst b/pypy/doc/release-2.0.0-beta2.rst --- a/pypy/doc/release-2.0.0-beta2.rst +++ b/pypy/doc/release-2.0.0-beta2.rst @@ -82,3 +82,13 @@ * we now have special strategies for ``dict``/``set``/``list`` which contain unicode strings, which means that now such collections will be both faster and more compact. + +.. _`eventlet`: http://eventlet.net/ +.. _`gevent`: http://www.gevent.org/ +.. _`cffi`: http://cffi.readthedocs.org/en/release-0.6/ +.. _`JIT hooks`: http://doc.pypy.org/en/latest/jit-hooks.html +.. _`pypycore`: https://github.com/gevent-on-pypy/pypycore +.. _`pypy-hacks`: https://github.com/schmir/gevent/tree/pypy-hacks +.. _`_curses.py`: https://bitbucket.org/pypy/pypy/src/aefddd47f224e3c12e2ea74f5c796d76f4355bdb/lib_pypy/_curses.py?at=default +.. _`_sqlite3.py`: https://bitbucket.org/pypy/pypy/src/aefddd47f224e3c12e2ea74f5c796d76f4355bdb/lib_pypy/_sqlite3.py?at=default + diff --git a/rpython/config/translationoption.py b/rpython/config/translationoption.py --- a/rpython/config/translationoption.py +++ b/rpython/config/translationoption.py @@ -115,7 +115,7 @@ ("translation.gcrootfinder", DEFL_ROOTFINDER_WITHJIT), ("translation.list_comprehension_operations", True)]), ChoiceOption("jit_backend", "choose the backend for the JIT", - ["auto", "x86", "x86-without-sse2", 'armv7'], + ["auto", "x86", "x86-without-sse2", 'armv7', 'armv7hf', 'armv6hf'], default="auto", cmdline="--jit-backend"), ChoiceOption("jit_profiler", "integrate profiler support into the JIT", ["off", "oprofile"], diff --git a/rpython/translator/c/gcc/test/elf64/track_basic_argument_registers.s b/rpython/translator/c/gcc/test/elf64/track_basic_argument_registers.s --- a/rpython/translator/c/gcc/test/elf64/track_basic_argument_registers.s +++ b/rpython/translator/c/gcc/test/elf64/track_basic_argument_registers.s @@ -25,7 +25,8 @@ /* GCROOT -48(%rbp) */ movq -24(%rbp), %rax leave - ret + ; try out a "rep ret" instead of just a "ret", for bad reasons + rep ret .cfi_endproc .LFE0: .size foobar, .-foobar diff --git a/rpython/translator/c/gcc/trackgcroot.py b/rpython/translator/c/gcc/trackgcroot.py --- a/rpython/translator/c/gcc/trackgcroot.py +++ b/rpython/translator/c/gcc/trackgcroot.py @@ -664,6 +664,12 @@ def visit_ret(self, line): return InsnRet(self.CALLEE_SAVE_REGISTERS) + def visit_rep(self, line): + # 'rep ret': bad reasons for this bogus 'rep' here + if line.split()[:2] == ['rep', 'ret']: + return self.visit_ret(line) + return [] + def visit_jmp(self, line): tablelabels = [] match = self.r_jmp_switch.match(line) From noreply at buildbot.pypy.org Mon Apr 8 15:02:02 2013 From: noreply at buildbot.pypy.org (arigo) Date: Mon, 8 Apr 2013 15:02:02 +0200 (CEST) Subject: [pypy-commit] pypy default: Bah, that was not RPython Message-ID: <20130408130202.864E51C0723@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63134:f65f68c72721 Date: 2013-04-08 13:04 +0000 http://bitbucket.org/pypy/pypy/changeset/f65f68c72721/ Log: Bah, that was not RPython diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py --- a/pypy/interpreter/baseobjspace.py +++ b/pypy/interpreter/baseobjspace.py @@ -709,7 +709,7 @@ def new_interned_w_str(self, w_s): s = self.str_w(w_s) - assert isinstance(s, str) + assert type(s) is str try: return self.interned_strings[s] except KeyError: @@ -718,7 +718,7 @@ return w_s def new_interned_str(self, s): - assert isinstance(s, str) + assert type(s) is str try: return self.interned_strings[s] except KeyError: From noreply at buildbot.pypy.org Mon Apr 8 15:27:13 2013 From: noreply at buildbot.pypy.org (antocuni) Date: Mon, 8 Apr 2013 15:27:13 +0200 (CEST) Subject: [pypy-commit] pypy release-2.0-beta2: Added tag pypy-2.0-beta2 for changeset 79a42de0558e Message-ID: <20130408132713.922A21C019F@cobra.cs.uni-duesseldorf.de> Author: Antonio Cuni Branch: release-2.0-beta2 Changeset: r63135:4b60269153b5 Date: 2013-04-08 14:26 +0100 http://bitbucket.org/pypy/pypy/changeset/4b60269153b5/ Log: Added tag pypy-2.0-beta2 for changeset 79a42de0558e diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -3,3 +3,4 @@ d8ac7d23d3ec5f9a0fa1264972f74a010dbfd07f release-1.6 ff4af8f318821f7f5ca998613a60fca09aa137da release-1.7 07e08e9c885ca67d89bcc304e45a32346daea2fa release-2.0-beta-1 +79a42de0558e05a94a57816e2c13919ff24da71d pypy-2.0-beta2 From noreply at buildbot.pypy.org Mon Apr 8 15:27:53 2013 From: noreply at buildbot.pypy.org (arigo) Date: Mon, 8 Apr 2013 15:27:53 +0200 (CEST) Subject: [pypy-commit] pypy default: Grrrrrrr. Message-ID: <20130408132753.1D57D1C019F@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63136:143f3089b372 Date: 2013-04-08 13:29 +0000 http://bitbucket.org/pypy/pypy/changeset/143f3089b372/ Log: Grrrrrrr. diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py --- a/pypy/interpreter/baseobjspace.py +++ b/pypy/interpreter/baseobjspace.py @@ -709,7 +709,8 @@ def new_interned_w_str(self, w_s): s = self.str_w(w_s) - assert type(s) is str + if not we_are_translated(): + assert type(s) is str try: return self.interned_strings[s] except KeyError: @@ -718,7 +719,8 @@ return w_s def new_interned_str(self, s): - assert type(s) is str + if not we_are_translated(): + assert type(s) is str try: return self.interned_strings[s] except KeyError: From noreply at buildbot.pypy.org Mon Apr 8 15:47:00 2013 From: noreply at buildbot.pypy.org (bivab) Date: Mon, 8 Apr 2013 15:47:00 +0200 (CEST) Subject: [pypy-commit] pypy default: Disable using a free register as temp register when moving values around, this currently has unintended side-effects in code that emits a jump to a label Message-ID: <20130408134700.1E5961C010B@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63137:5ec20083ccc5 Date: 2013-04-08 15:45 +0200 http://bitbucket.org/pypy/pypy/changeset/5ec20083ccc5/ Log: Disable using a free register as temp register when moving values around, this currently has unintended side-effects in code that emits a jump to a label diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -1035,7 +1035,8 @@ assert 0, 'unsupported case' def _mov_stack_to_loc(self, prev_loc, loc, cond=c.AL): - helper = self._regalloc.get_free_reg() + # disabled for now, has side effects in combination with remap_frame_layout when called from a jump + helper = None # self._regalloc.get_free_reg() if loc.is_reg(): assert prev_loc.type != FLOAT, 'trying to load from an \ incompatible location into a core register' From noreply at buildbot.pypy.org Mon Apr 8 15:47:01 2013 From: noreply at buildbot.pypy.org (bivab) Date: Mon, 8 Apr 2013 15:47:01 +0200 (CEST) Subject: [pypy-commit] pypy default: merge heads Message-ID: <20130408134701.5947A1C010B@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63138:417165a0cad6 Date: 2013-04-08 15:46 +0200 http://bitbucket.org/pypy/pypy/changeset/417165a0cad6/ Log: merge heads diff --git a/lib_pypy/_curses.py b/lib_pypy/_curses.py --- a/lib_pypy/_curses.py +++ b/lib_pypy/_curses.py @@ -364,7 +364,9 @@ key_n = ffi.string(key_n) if key_n == b"UNKNOWN KEY": continue - key_n = key_n.decode().replace('(', '').replace(')', '') + if not isinstance(key_n, str): # python 3 + key_n = key_n.decode() + key_n = key_n.replace('(', '').replace(')', '') globals()[key_n] = key _setup() diff --git a/pypy/doc/release-2.0.0-beta2.rst b/pypy/doc/release-2.0.0-beta2.rst --- a/pypy/doc/release-2.0.0-beta2.rst +++ b/pypy/doc/release-2.0.0-beta2.rst @@ -82,3 +82,13 @@ * we now have special strategies for ``dict``/``set``/``list`` which contain unicode strings, which means that now such collections will be both faster and more compact. + +.. _`eventlet`: http://eventlet.net/ +.. _`gevent`: http://www.gevent.org/ +.. _`cffi`: http://cffi.readthedocs.org/en/release-0.6/ +.. _`JIT hooks`: http://doc.pypy.org/en/latest/jit-hooks.html +.. _`pypycore`: https://github.com/gevent-on-pypy/pypycore +.. _`pypy-hacks`: https://github.com/schmir/gevent/tree/pypy-hacks +.. _`_curses.py`: https://bitbucket.org/pypy/pypy/src/aefddd47f224e3c12e2ea74f5c796d76f4355bdb/lib_pypy/_curses.py?at=default +.. _`_sqlite3.py`: https://bitbucket.org/pypy/pypy/src/aefddd47f224e3c12e2ea74f5c796d76f4355bdb/lib_pypy/_sqlite3.py?at=default + diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py --- a/pypy/interpreter/baseobjspace.py +++ b/pypy/interpreter/baseobjspace.py @@ -709,6 +709,8 @@ def new_interned_w_str(self, w_s): s = self.str_w(w_s) + if not we_are_translated(): + assert type(s) is str try: return self.interned_strings[s] except KeyError: @@ -717,6 +719,8 @@ return w_s def new_interned_str(self, s): + if not we_are_translated(): + assert type(s) is str try: return self.interned_strings[s] except KeyError: diff --git a/pypy/module/_minimal_curses/__init__.py b/pypy/module/_minimal_curses/__init__.py --- a/pypy/module/_minimal_curses/__init__.py +++ b/pypy/module/_minimal_curses/__init__.py @@ -27,6 +27,7 @@ } for i in dir(_curses): + i = str(i) # workaround for pypy 2.0-beta2 val = getattr(_curses, i) if i.isupper() and type(val) is int: Module.interpleveldefs[i] = "space.wrap(%s)" % val diff --git a/rpython/translator/c/gcc/test/elf64/track_basic_argument_registers.s b/rpython/translator/c/gcc/test/elf64/track_basic_argument_registers.s --- a/rpython/translator/c/gcc/test/elf64/track_basic_argument_registers.s +++ b/rpython/translator/c/gcc/test/elf64/track_basic_argument_registers.s @@ -25,7 +25,8 @@ /* GCROOT -48(%rbp) */ movq -24(%rbp), %rax leave - ret + ; try out a "rep ret" instead of just a "ret", for bad reasons + rep ret .cfi_endproc .LFE0: .size foobar, .-foobar diff --git a/rpython/translator/c/gcc/trackgcroot.py b/rpython/translator/c/gcc/trackgcroot.py --- a/rpython/translator/c/gcc/trackgcroot.py +++ b/rpython/translator/c/gcc/trackgcroot.py @@ -664,6 +664,12 @@ def visit_ret(self, line): return InsnRet(self.CALLEE_SAVE_REGISTERS) + def visit_rep(self, line): + # 'rep ret': bad reasons for this bogus 'rep' here + if line.split()[:2] == ['rep', 'ret']: + return self.visit_ret(line) + return [] + def visit_jmp(self, line): tablelabels = [] match = self.r_jmp_switch.match(line) From noreply at buildbot.pypy.org Mon Apr 8 17:07:12 2013 From: noreply at buildbot.pypy.org (antocuni) Date: Mon, 8 Apr 2013 17:07:12 +0200 (CEST) Subject: [pypy-commit] pypy default: download the nightly of the current branch Message-ID: <20130408150712.02DCD1C010B@cobra.cs.uni-duesseldorf.de> Author: Antonio Cuni Branch: Changeset: r63139:1f99f6cb2850 Date: 2013-04-08 16:03 +0100 http://bitbucket.org/pypy/pypy/changeset/1f99f6cb2850/ Log: download the nightly of the current branch diff --git a/pypy/goal/getnightly.py b/pypy/goal/getnightly.py --- a/pypy/goal/getnightly.py +++ b/pypy/goal/getnightly.py @@ -13,8 +13,13 @@ if sys.maxint == 2**63 - 1: arch += '64' +hg = py.path.local.sysfind('hg') +branch = hg.sysexec('branch').strip() +if branch == 'default': + branch = 'trunk' + filename = 'pypy-c-jit-latest-%s.tar.bz2' % arch -url = 'http://buildbot.pypy.org/nightly/trunk/%s' % filename +url = 'http://buildbot.pypy.org/nightly/%s/%s' % (branch, filename) tmp = py.path.local.mkdtemp() mydir = tmp.chdir() print 'Downloading pypy to', tmp From noreply at buildbot.pypy.org Mon Apr 8 17:09:10 2013 From: noreply at buildbot.pypy.org (arigo) Date: Mon, 8 Apr 2013 17:09:10 +0200 (CEST) Subject: [pypy-commit] pypy stm-gc-2: (untested) add a way to walk all roots, for major collections Message-ID: <20130408150910.A7A6A1C010B@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: stm-gc-2 Changeset: r63142:b88de4215050 Date: 2013-04-08 14:28 +0200 http://bitbucket.org/pypy/pypy/changeset/b88de4215050/ Log: (untested) add a way to walk all roots, for major collections diff --git a/rpython/memory/gc/stmtls.py b/rpython/memory/gc/stmtls.py --- a/rpython/memory/gc/stmtls.py +++ b/rpython/memory/gc/stmtls.py @@ -36,6 +36,11 @@ self.null_address_dict = self.gc.null_address_dict self.AddressStack = self.gc.AddressStack self.AddressDict = self.gc.AddressDict + if we_are_translated(): + self.adr_of_stack_base = llop.gc_adr_of_root_stack_base( + llmemory.Address) + self.adr_of_stack_top = llop.gc_adr_of_root_stack_top( + llmemory.Address) # # --- current position, or NULL when mallocs are forbidden self.nursery_free = NULL diff --git a/rpython/memory/gctransform/stmframework.py b/rpython/memory/gctransform/stmframework.py --- a/rpython/memory/gctransform/stmframework.py +++ b/rpython/memory/gctransform/stmframework.py @@ -119,6 +119,7 @@ if addr.signed[0] == END_MARKER: break callback(arg, addr) + return addr self.rootstackhook = walk_stack_root rsd = gctransformer.root_stack_depth @@ -188,3 +189,19 @@ if gc.points_to_valid_gc_object(result): collect_nongc_root(arg, result) addr += sizeofaddr + + @specialize.argtype(2) + def walk_all_stack_roots(self, collect_stack_root, arg): + # assume that we have the ll_global_lock here + stmtls = self.gc.linked_list_stmtls + while stmtls is not None: + # for every stmtls: + root_stack_base = stmtls.adr_of_stack_base.address[0] + root_stack_top = stmtls.adr_of_stack_top.address[0] + # we walk all segments of the shadow stack, each of them + # with an END_MARKER at the bottom, until we reach the + # marker that is at root_stack_base. + while root_stack_top != root_stack_base: + root_stack_top = self.rootstackhook(collect_stack_root, arg, + root_stack_top) + stmtls = stmtls.linked_list_next From noreply at buildbot.pypy.org Mon Apr 8 17:09:11 2013 From: noreply at buildbot.pypy.org (arigo) Date: Mon, 8 Apr 2013 17:09:11 +0200 (CEST) Subject: [pypy-commit] pypy default: Fix for lldebug translations. The value "1 << 32" or "1 << 64" is Message-ID: <20130408150911.CEFBA1C010B@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63143:10b99353a53c Date: 2013-04-08 17:08 +0200 http://bitbucket.org/pypy/pypy/changeset/10b99353a53c/ Log: Fix for lldebug translations. The value "1 << 32" or "1 << 64" is computed, triggering an assert, but never used. diff --git a/pypy/module/_cffi_backend/ctypeprim.py b/pypy/module/_cffi_backend/ctypeprim.py --- a/pypy/module/_cffi_backend/ctypeprim.py +++ b/pypy/module/_cffi_backend/ctypeprim.py @@ -162,7 +162,7 @@ def __init__(self, *args): W_CTypePrimitive.__init__(self, *args) self.value_fits_long = self.size <= rffi.sizeof(lltype.Signed) - if self.size < rffi.sizeof(lltype.SignedLongLong): + if self.size < rffi.sizeof(lltype.Signed): assert self.value_fits_long sh = self.size * 8 self.vmin = r_uint(-1) << (sh - 1) From noreply at buildbot.pypy.org Mon Apr 8 17:41:52 2013 From: noreply at buildbot.pypy.org (antocuni) Date: Mon, 8 Apr 2013 17:41:52 +0200 (CEST) Subject: [pypy-commit] pypy refactor-call_release_gil: hg merge default Message-ID: <20130408154152.2AFA81C30F2@cobra.cs.uni-duesseldorf.de> Author: Antonio Cuni Branch: refactor-call_release_gil Changeset: r63144:c25a11a6ad46 Date: 2013-04-08 16:41 +0100 http://bitbucket.org/pypy/pypy/changeset/c25a11a6ad46/ Log: hg merge default diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py --- a/pypy/interpreter/baseobjspace.py +++ b/pypy/interpreter/baseobjspace.py @@ -709,7 +709,8 @@ def new_interned_w_str(self, w_s): s = self.str_w(w_s) - assert type(s) is str + if not we_are_translated(): + assert type(s) is str try: return self.interned_strings[s] except KeyError: @@ -718,7 +719,8 @@ return w_s def new_interned_str(self, s): - assert type(s) is str + if not we_are_translated(): + assert type(s) is str try: return self.interned_strings[s] except KeyError: diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -1035,7 +1035,8 @@ assert 0, 'unsupported case' def _mov_stack_to_loc(self, prev_loc, loc, cond=c.AL): - helper = self._regalloc.get_free_reg() + # disabled for now, has side effects in combination with remap_frame_layout when called from a jump + helper = None # self._regalloc.get_free_reg() if loc.is_reg(): assert prev_loc.type != FLOAT, 'trying to load from an \ incompatible location into a core register' From noreply at buildbot.pypy.org Mon Apr 8 18:47:52 2013 From: noreply at buildbot.pypy.org (mattip) Date: Mon, 8 Apr 2013 18:47:52 +0200 (CEST) Subject: [pypy-commit] pypy default: on windows, search for sqlite3.dll first next to the exe, then on the path, fixes packaged pypy 'import sqlite3' Message-ID: <20130408164752.1CDF11C010B@cobra.cs.uni-duesseldorf.de> Author: mattip Branch: Changeset: r63145:341a34c7d62f Date: 2013-04-08 19:44 +0300 http://bitbucket.org/pypy/pypy/changeset/341a34c7d62f/ Log: on windows, search for sqlite3.dll first next to the exe, then on the path, fixes packaged pypy 'import sqlite3' diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -256,7 +256,12 @@ typedef ... sqlite3; int sqlite3_enable_load_extension(sqlite3 *db, int onoff); """) - unverified_lib = unverified_ffi.dlopen('sqlite3') + libname = 'sqlite3' + if sys.platform == 'win32': + _libname = os.path.join(os.path.dirname(sys.executable), libname) + if os.path.exists(_libname + '.dll'): + libname = _libname + unverified_lib = unverified_ffi.dlopen(libname) return hasattr(unverified_lib, 'sqlite3_enable_load_extension') if _has_load_extension(): From noreply at buildbot.pypy.org Mon Apr 8 18:49:06 2013 From: noreply at buildbot.pypy.org (arigo) Date: Mon, 8 Apr 2013 18:49:06 +0200 (CEST) Subject: [pypy-commit] pypy default: Test and fix for debug_fatalerror in the blackhole interp. Message-ID: <20130408164906.D7B591C010B@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63146:aaf788a134be Date: 2013-04-08 18:31 +0200 http://bitbucket.org/pypy/pypy/changeset/aaf788a134be/ Log: Test and fix for debug_fatalerror in the blackhole interp. diff --git a/rpython/jit/metainterp/blackhole.py b/rpython/jit/metainterp/blackhole.py --- a/rpython/jit/metainterp/blackhole.py +++ b/rpython/jit/metainterp/blackhole.py @@ -857,6 +857,8 @@ @arguments("r") def bhimpl_debug_fatalerror(msg): + from rpython.rtyper.lltypesystem import rstr + msg = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), msg) llop.debug_fatalerror(lltype.Void, msg) @arguments("r", "i", "i", "i", "i") diff --git a/rpython/jit/metainterp/test/test_blackhole.py b/rpython/jit/metainterp/test/test_blackhole.py --- a/rpython/jit/metainterp/test/test_blackhole.py +++ b/rpython/jit/metainterp/test/test_blackhole.py @@ -228,5 +228,15 @@ assert BlackholeInterpreter.bhimpl_int_lshift.im_func(100, 3) == 100<<3 assert BlackholeInterpreter.bhimpl_int_rshift.im_func(100, 3) == 100>>3 - assert BlackholeInterpreter.bhimpl_uint_rshift.im_func(100, 3) == 100>>3 - + assert BlackholeInterpreter.bhimpl_uint_rshift.im_func(100, 3) == 100>>3 + +def test_debug_fatalerror(): + from rpython.rtyper.lltypesystem import lltype, llmemory, rstr + from rpython.rtyper.llinterp import LLFatalError + msg = rstr.mallocstr(1) + msg.chars[0] = "!" + msg = lltype.cast_opaque_ptr(llmemory.GCREF, msg) + e = py.test.raises(LLFatalError, + BlackholeInterpreter.bhimpl_debug_fatalerror.im_func, + msg) + assert str(e.value) == '!' diff --git a/rpython/rtyper/lltypesystem/lloperation.py b/rpython/rtyper/lltypesystem/lloperation.py --- a/rpython/rtyper/lltypesystem/lloperation.py +++ b/rpython/rtyper/lltypesystem/lloperation.py @@ -555,7 +555,7 @@ 'debug_offset': LLOp(canrun=True), 'debug_flush': LLOp(canrun=True), 'debug_assert': LLOp(tryfold=True), - 'debug_fatalerror': LLOp(), + 'debug_fatalerror': LLOp(canrun=True), 'debug_llinterpcall': LLOp(canraise=(Exception,)), # Python func call 'res=arg[0](*arg[1:])' # in backends, abort() or whatever is fine diff --git a/rpython/rtyper/lltypesystem/opimpl.py b/rpython/rtyper/lltypesystem/opimpl.py --- a/rpython/rtyper/lltypesystem/opimpl.py +++ b/rpython/rtyper/lltypesystem/opimpl.py @@ -654,6 +654,13 @@ from rpython.rlib.rtimer import read_timestamp return read_timestamp() +def op_debug_fatalerror(ll_msg): + from rpython.rtyper.lltypesystem import lltype, rstr + from rpython.rtyper.llinterp import LLFatalError + assert lltype.typeOf(ll_msg) == lltype.Ptr(rstr.STR) + msg = ''.join(ll_msg.chars) + raise LLFatalError(msg) + # ____________________________________________________________ def get_op_impl(opname): From noreply at buildbot.pypy.org Mon Apr 8 18:49:08 2013 From: noreply at buildbot.pypy.org (arigo) Date: Mon, 8 Apr 2013 18:49:08 +0200 (CEST) Subject: [pypy-commit] pypy stm-gc-2: in-progress: carefully copy parts of minimarkpage.py Message-ID: <20130408164908.28AE41C010B@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: stm-gc-2 Changeset: r63147:21d5dccf753c Date: 2013-04-08 18:35 +0200 http://bitbucket.org/pypy/pypy/changeset/21d5dccf753c/ Log: in-progress: carefully copy parts of minimarkpage.py diff --git a/rpython/memory/gc/stmshared.py b/rpython/memory/gc/stmshared.py --- a/rpython/memory/gc/stmshared.py +++ b/rpython/memory/gc/stmshared.py @@ -1,17 +1,87 @@ -from rpython.rtyper.lltypesystem import lltype, llmemory, llarena +from rpython.rtyper.lltypesystem import lltype, llmemory, llarena, rffi +from rpython.rlib.rarithmetic import LONG_BIT from rpython.rlib.objectmodel import free_non_gc_object +from rpython.rlib.debug import fatalerror +from rpython.rlib import rthread +WORD = LONG_BIT // 8 NULL = llmemory.NULL +WORD_POWER_2 = {32: 2, 64: 3}[LONG_BIT] +assert 1 << WORD_POWER_2 == WORD + +# Linux's glibc is good at 'malloc(1023*WORD)': the blocks ("pages") it +# returns are exactly 1024 words apart, reserving only one extra word +# for its internal data +TRANSLATED_PAGE_SIZE = 1023 * WORD + +# This is the largest size that StmGCSharedArea will map to its internal +# "pages" structures. +TRANSLATED_SMALL_REQUEST_THRESHOLD = 35 * WORD + +# ------------------------------------------------------------ +# The basic idea here is that each page will contain objects that are +# each of the same size. Moreover each page belongs to one thread only: +# only this thread can use it to satisfy more allocations --- with however +# one exception: pages with low usage after a major collection are moved +# to a global list where any thread can pick them up. + +PAGE_PTR = lltype.Ptr(lltype.ForwardReference()) +PAGE_HEADER = lltype.Struct('PageHeader', + # -- The following pointer makes a chained list of pages. For non-full + # pages, it is a chained list of pages having the same size class, + # rooted in 'page_for_size[size_class]'. For full pages, it is a + # different chained list rooted in 'full_page_for_size[size_class]'. + ('nextpage', PAGE_PTR), + # -- The number of free blocks. The numbers of uninitialized and + # allocated blocks can be deduced from the context if needed. + ('nfree', lltype.Signed), + # -- The chained list of free blocks. It ends as a pointer to the + # first uninitialized block (pointing to data that is uninitialized, + # or to the end of the page). + ('freeblock', llmemory.Address), + # -- The structure above is 3 words, which is a good value: + # '(1023-3) % N' is zero or very small for various small N's, + # i.e. there is not much wasted space. + ) +PAGE_PTR.TO.become(PAGE_HEADER) +PAGE_NULL = lltype.nullptr(PAGE_HEADER) + +# ------------------------------------------------------------ class StmGCSharedArea(object): _alloc_flavor_ = 'raw' - def __init__(self, gc): + def __init__(self, gc, page_size, small_request_threshold): self.gc = gc + self.page_size = page_size + self.small_request_threshold = small_request_threshold + # + # This array contains 'length' chained lists of pages. + # For each size N between WORD and 'small_request_threshold' + # (included), the corresponding chained list contains pages + # which store objects of size N. This is only used for pages + # with low usage after a major collection; as soon as a page + # is used, or if its usage says high after a major collection, + # it belongs to the lists of StmGCThreadLocalAllocator. + length = small_request_threshold / WORD + 1 + self.low_usage_page = lltype.malloc(rffi.CArray(PAGE_PTR), length, + flavor='raw', zero=True, + immortal=True) + self.nblocks_for_size = lltype.malloc(rffi.CArray(lltype.Signed), + length, flavor='raw', + immortal=True) + self.hdrsize = llmemory.raw_malloc_usage(llmemory.sizeof(PAGE_HEADER)) + self.nblocks_for_size[0] = 0 # unused + for i in range(1, length): + self.nblocks_for_size[i] = (page_size - self.hdrsize) // (WORD * i) + assert self.nblocks_for_size[length-1] >= 1 def setup(self): - pass + self.ll_low_usage_lock = rthread.allocate_ll_lock() + + +# ------------------------------------------------------------ class StmGCThreadLocalAllocator(object): @@ -25,11 +95,101 @@ self.gc = sharedarea.gc self.sharedarea = sharedarea self.chained_list = NULL + # + # These two arrays contain each 'length' chained lists of pages. + # For each size N between WORD and 'small_request_threshold' + # (included), the corresponding chained list contains pages + # which store objects of size N. The 'page_for_size' lists are + # for pages which still have room for at least one more object, + # and the 'full_page_for_size' lists are for full pages. + length = sharedarea.small_request_threshold / WORD + 1 + self.page_for_size = lltype.malloc(rffi.CArray(PAGE_PTR), length, + flavor='raw', zero=True, + immortal=True) + self.full_page_for_size = lltype.malloc(rffi.CArray(PAGE_PTR), length, + flavor='raw', zero=True, + immortal=True) + + def _malloc_size_class(self, size_class): + """Malloc one object of the given size_class (== number of WORDs).""" + ll_assert(size_class > 0, "malloc_size_class: null or neg size_class") + ll_assert(size_class <= self.sharedarea.small_request_threshold, + "malloc_size_class: too big") + # + # Get the page to use + page = self.page_for_size[size_class] + if page == PAGE_NULL: + page = self._allocate_new_page(size_class) + # + # The result is simply 'page.freeblock' + result = page.freeblock + if page.nfree > 0: + # + # The 'result' was part of the chained list; read the next. + page.nfree -= 1 + freeblock = result.address[0] + llarena.arena_reset(result, + llmemory.sizeof(llmemory.Address), + 0) + # + else: + # The 'result' is part of the uninitialized blocks. + freeblock = result + nsize + # + page.freeblock = freeblock + # + pageaddr = llarena.getfakearenaaddress(llmemory.cast_ptr_to_adr(page)) + if freeblock - pageaddr > self.page_size - nsize: + # This was the last free block, so unlink the page from the + # chained list and put it in the 'full_page_for_size' list. + self.page_for_size[size_class] = page.nextpage + page.nextpage = self.full_page_for_size[size_class] + self.full_page_for_size[size_class] = page + # + return result + + + def _allocate_new_page(self, size_class): + """Allocate and return a new page for the given size_class.""" + # + # If 'low_usage_page' has pages ready, return one of them. + # Check both before acquiring the lock (NULL is the common case + # and getting it occasionally wrong is not a problem), and after. + result = NULL + sharedarea = self.sharedarea + if sharedarea.low_usage_page[size_class] != PAGE_NULL: + XXX # self.ll_low_usage_lock... + # + # If unsuccessful, just raw-malloc a new page. + if not result: + result = llarena.arena_malloc(sharedarea.page_size, 0) + if not result: + fatalerror("FIXME: Out of memory! (should raise MemoryError)") + return PAGE_NULL + llarena.arena_reserve(result, llmemory.sizeof(PAGE_HEADER)) + # + # Initialize the fields of the resulting page + page = llmemory.cast_adr_to_ptr(result, PAGE_PTR) + page.nfree = 0 + page.freeblock = result + sharedarea.hdrsize + page.nextpage = PAGE_NULL + ll_assert(self.page_for_size[size_class] == PAGE_NULL, + "allocate_new_page() called but a page is already waiting") + self.page_for_size[size_class] = page + return page + def malloc_object(self, totalsize): """Malloc. You should also call add_regular() later, or keep it in some other data structure. Note that it is not zero-filled.""" - return llarena.arena_malloc(llmemory.raw_malloc_usage(totalsize), 0) + nsize = llmemory.raw_malloc_usage(totalsize) + if nsize <= self.sharedarea.small_request_threshold: + result = self._malloc_size_class(nsize >> WORD_POWER_2) + llarena.arena_reserve(result, _dummy_size(totalsize)) + return result + else: + XXX + #llarena.arena_malloc(llmemory.raw_malloc_usage(totalsize), 0) def add_regular(self, obj): """After malloc_object(), register the object in the internal chained @@ -55,3 +215,13 @@ def delete(self): free_non_gc_object(self) + + +# ____________________________________________________________ + +def _dummy_size(size): + if we_are_translated(): + return size + if isinstance(size, int): + size = llmemory.sizeof(lltype.Char) * size + return size From noreply at buildbot.pypy.org Mon Apr 8 18:49:09 2013 From: noreply at buildbot.pypy.org (arigo) Date: Mon, 8 Apr 2013 18:49:09 +0200 (CEST) Subject: [pypy-commit] pypy default: merge heads Message-ID: <20130408164909.631431C010B@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63148:a220976210af Date: 2013-04-08 18:48 +0200 http://bitbucket.org/pypy/pypy/changeset/a220976210af/ Log: merge heads diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -256,7 +256,12 @@ typedef ... sqlite3; int sqlite3_enable_load_extension(sqlite3 *db, int onoff); """) - unverified_lib = unverified_ffi.dlopen('sqlite3') + libname = 'sqlite3' + if sys.platform == 'win32': + _libname = os.path.join(os.path.dirname(sys.executable), libname) + if os.path.exists(_libname + '.dll'): + libname = _libname + unverified_lib = unverified_ffi.dlopen(libname) return hasattr(unverified_lib, 'sqlite3_enable_load_extension') if _has_load_extension(): From noreply at buildbot.pypy.org Mon Apr 8 19:29:48 2013 From: noreply at buildbot.pypy.org (antocuni) Date: Mon, 8 Apr 2013 19:29:48 +0200 (CEST) Subject: [pypy-commit] pypy refactor-call_release_gil: (antocuni, arigato) backout the backout of the merge of refactor-call_release_gil: Message-ID: <20130408172948.3CE3B1C301F@cobra.cs.uni-duesseldorf.de> Author: Antonio Cuni Branch: refactor-call_release_gil Changeset: r63149:3b9a5ed9579d Date: 2013-04-08 18:29 +0100 http://bitbucket.org/pypy/pypy/changeset/3b9a5ed9579d/ Log: (antocuni, arigato) backout the backout of the merge of refactor- call_release_gil: hg backout 3ef424d4281f --parent bbcac902d4247dc6f71ef393908405d477015630 note that by doing this we are loosing the history in "hg blame", because all the lines now belongs to this changeset. To see the real history, you can "hg blame" at revision 71e2d672347d diff --git a/pypy/module/pypyjit/test_pypy_c/test__ffi.py b/pypy/module/pypyjit/test_pypy_c/test__ffi.py --- a/pypy/module/pypyjit/test_pypy_c/test__ffi.py +++ b/pypy/module/pypyjit/test_pypy_c/test__ffi.py @@ -110,7 +110,6 @@ loops = log.loops_by_id('sleep') assert len(loops) == 1 # make sure that we actually JITted the loop - def test_ctypes_call(self): from rpython.rlib.test.test_clibffi import get_libm_name def main(libm_name): @@ -209,3 +208,65 @@ # so far just check that call_release_gil() is produced. # later, also check that the arguments to call_release_gil() # are constants, and that the numerous raw_mallocs are removed + + def test_cffi_call_guard_not_forced_fails(self): + # this is the test_pypy_c equivalent of + # rpython/jit/metainterp/test/test_fficall::test_guard_not_forced_fails + # + # it requires cffi to be installed for pypy in order to run + def main(): + import sys + try: + import cffi + except ImportError: + sys.stderr.write('SKIP: cannot import cffi\n') + return 0 + + ffi = cffi.FFI() + + ffi.cdef(""" + typedef void (*functype)(int); + int foo(int n, functype func); + """) + + lib = ffi.verify(""" + #include + typedef void (*functype)(int); + + int foo(int n, functype func) { + if (n >= 2000) { + func(n); + } + return n*2; + } + """) + + @ffi.callback("functype") + def mycallback(n): + if n < 5000: + return + # make sure that guard_not_forced fails + d = {} + f = sys._getframe() + while f: + d.update(f.f_locals) + f = f.f_back + + n = 0 + while n < 10000: + res = lib.foo(n, mycallback) # ID: cfficall + # this is the real point of the test: before the + # refactor-call_release_gil branch, the assert failed when + # res == 5000 + assert res == n*2 + n += 1 + return n + + log = self.run(main, [], import_site=True) + assert log.result == 10000 + loop, = log.loops_by_id('cfficall') + assert loop.match_by_id('cfficall', """ + ... + f1 = call_release_gil(..., descr=) + ... + """) diff --git a/rpython/jit/backend/llgraph/runner.py b/rpython/jit/backend/llgraph/runner.py --- a/rpython/jit/backend/llgraph/runner.py +++ b/rpython/jit/backend/llgraph/runner.py @@ -840,10 +840,22 @@ # manipulation here (as a hack, instead of really doing # the aroundstate manipulation ourselves) return self.execute_call_may_force(descr, func, *args) + guard_op = self.lltrace.operations[self.current_index + 1] + assert guard_op.getopnum() == rop.GUARD_NOT_FORCED + self.force_guard_op = guard_op call_args = support.cast_call_args_in_order(descr.ARGS, args) - FUNC = lltype.FuncType(descr.ARGS, descr.RESULT) - func_to_call = rffi.cast(lltype.Ptr(FUNC), func) - result = func_to_call(*call_args) + # + func_adr = llmemory.cast_int_to_adr(func) + if hasattr(func_adr.ptr._obj, '_callable'): + # this is needed e.g. by test_fficall.test_guard_not_forced_fails, + # because to actually force the virtualref we need to llinterp the + # graph, not to directly execute the python function + result = self.cpu.maybe_on_top_of_llinterp(func, call_args, descr.RESULT) + else: + FUNC = lltype.FuncType(descr.ARGS, descr.RESULT) + func_to_call = rffi.cast(lltype.Ptr(FUNC), func) + result = func_to_call(*call_args) + del self.force_guard_op return support.cast_result(descr.RESULT, result) def execute_call_assembler(self, descr, *args): diff --git a/rpython/jit/backend/model.py b/rpython/jit/backend/model.py --- a/rpython/jit/backend/model.py +++ b/rpython/jit/backend/model.py @@ -1,6 +1,6 @@ import weakref from rpython.rlib.debug import debug_start, debug_print, debug_stop -from rpython.rtyper.lltypesystem import lltype +from rpython.rtyper.lltypesystem import lltype, llmemory class CPUTotalTracker(object): total_compiled_loops = 0 @@ -194,6 +194,11 @@ def typedescrof(self, TYPE): raise NotImplementedError + @staticmethod + def cast_int_to_ptr(x, TYPE): + x = llmemory.cast_int_to_adr(x) + return llmemory.cast_adr_to_ptr(x, TYPE) + # ---------- the backend-dependent operations ---------- # lltype specific operations diff --git a/rpython/jit/backend/x86/test/test_fficall.py b/rpython/jit/backend/x86/test/test_fficall.py --- a/rpython/jit/backend/x86/test/test_fficall.py +++ b/rpython/jit/backend/x86/test/test_fficall.py @@ -5,4 +5,19 @@ class TestFfiCall(Jit386Mixin, test_fficall.FfiCallTests): # for the individual tests see # ====> ../../../metainterp/test/test_fficall.py - pass + + def _add_libffi_types_to_ll2types_maybe(self): + # this is needed by test_guard_not_forced_fails, because it produces a + # loop which reads the value of types.* in a variable, then a guard + # fail and we switch to blackhole: the problem is that at this point + # the blackhole interp has a real integer, but it needs to convert it + # back to a lltype pointer (which is handled by ll2ctypes, deeply in + # the logic). The workaround is to teach ll2ctypes in advance which + # are the addresses of the various types.* structures. + # Try to comment this code out and run the test to see how it fails :) + from rpython.rtyper.lltypesystem import rffi, lltype, ll2ctypes + from rpython.rlib.jit_libffi import types + for key, value in types.__dict__.iteritems(): + if isinstance(value, lltype._ptr): + addr = rffi.cast(lltype.Signed, value) + ll2ctypes._int2obj[addr] = value diff --git a/rpython/jit/codewriter/jtransform.py b/rpython/jit/codewriter/jtransform.py --- a/rpython/jit/codewriter/jtransform.py +++ b/rpython/jit/codewriter/jtransform.py @@ -1747,6 +1747,11 @@ assert False, 'unsupported oopspec: %s' % oopspec_name return self._handle_oopspec_call(op, args, oopspecindex, extraeffect) + def rewrite_op_jit_ffi_save_result(self, op): + kind = op.args[0].value + assert kind in ('int', 'float') + return SpaceOperation('libffi_save_result_%s' % kind, op.args[1:], None) + def rewrite_op_jit_force_virtual(self, op): return self._do_builtin_call(op) diff --git a/rpython/jit/metainterp/blackhole.py b/rpython/jit/metainterp/blackhole.py --- a/rpython/jit/metainterp/blackhole.py +++ b/rpython/jit/metainterp/blackhole.py @@ -8,8 +8,9 @@ from rpython.rlib.rarithmetic import intmask, LONG_BIT, r_uint, ovfcheck from rpython.rlib.rtimer import read_timestamp from rpython.rlib.unroll import unrolling_iterable -from rpython.rtyper.lltypesystem import lltype, llmemory, rclass +from rpython.rtyper.lltypesystem import lltype, llmemory, rclass, rffi from rpython.rtyper.lltypesystem.lloperation import llop +from rpython.rlib.jit_libffi import CIF_DESCRIPTION_P def arguments(*argtypes, **kwds): @@ -1348,6 +1349,25 @@ def bhimpl_ll_read_timestamp(): return read_timestamp() + @arguments("cpu", "i", "i", "i") + def bhimpl_libffi_save_result_int(self, cif_description, exchange_buffer, result): + ARRAY = lltype.Ptr(rffi.CArray(lltype.Signed)) + cif_description = self.cast_int_to_ptr(cif_description, CIF_DESCRIPTION_P) + exchange_buffer = self.cast_int_to_ptr(exchange_buffer, rffi.CCHARP) + # + data_out = rffi.ptradd(exchange_buffer, cif_description.exchange_result) + rffi.cast(ARRAY, data_out)[0] = result + + @arguments("cpu", "i", "i", "f") + def bhimpl_libffi_save_result_float(self, cif_description, exchange_buffer, result): + ARRAY = lltype.Ptr(rffi.CArray(lltype.Float)) + cif_description = self.cast_int_to_ptr(cif_description, CIF_DESCRIPTION_P) + exchange_buffer = self.cast_int_to_ptr(exchange_buffer, rffi.CCHARP) + # + data_out = rffi.ptradd(exchange_buffer, cif_description.exchange_result) + rffi.cast(ARRAY, data_out)[0] = result + + # ---------- # helpers to resume running in blackhole mode when a guard failed diff --git a/rpython/jit/metainterp/history.py b/rpython/jit/metainterp/history.py --- a/rpython/jit/metainterp/history.py +++ b/rpython/jit/metainterp/history.py @@ -775,8 +775,8 @@ def show(self, errmsg=None): "NOT_RPYTHON" - from rpython.jit.metainterp.graphpage import display_loops - display_loops([self], errmsg) + from rpython.jit.metainterp.graphpage import display_procedures + display_procedures([self], errmsg) def check_consistency(self): # for testing "NOT_RPYTHON" diff --git a/rpython/jit/metainterp/pyjitpl.py b/rpython/jit/metainterp/pyjitpl.py --- a/rpython/jit/metainterp/pyjitpl.py +++ b/rpython/jit/metainterp/pyjitpl.py @@ -1185,6 +1185,30 @@ def opimpl_ll_read_timestamp(self): return self.metainterp.execute_and_record(rop.READ_TIMESTAMP, None) + @arguments("box", "box", "box") + def opimpl_libffi_save_result_int(self, box_cif_description, box_exchange_buffer, + box_result): + from rpython.rtyper.lltypesystem import llmemory + from rpython.rlib.jit_libffi import CIF_DESCRIPTION_P + from rpython.jit.backend.llsupport.ffisupport import get_arg_descr + + cif_description = box_cif_description.getint() + cif_description = llmemory.cast_int_to_adr(cif_description) + cif_description = llmemory.cast_adr_to_ptr(cif_description, + CIF_DESCRIPTION_P) + + kind, descr, itemsize = get_arg_descr(self.metainterp.cpu, cif_description.rtype) + + if kind != 'v': + ofs = cif_description.exchange_result + assert ofs % itemsize == 0 # alignment check (result) + self.metainterp.history.record(rop.SETARRAYITEM_RAW, + [box_exchange_buffer, + ConstInt(ofs // itemsize), box_result], + None, descr) + + opimpl_libffi_save_result_float = opimpl_libffi_save_result_int + # ------------------------------ def setup_call(self, argboxes): @@ -2589,27 +2613,15 @@ box_arg, descr) arg_boxes.append(box_arg) # - kind, descr, itemsize = get_arg_descr(self.cpu, cif_description.rtype) - if kind == 'i': - box_result = history.BoxInt() - elif kind == 'f': - box_result = history.BoxFloat() - else: - assert kind == 'v' - box_result = None + box_result = op.result self.history.record(rop.CALL_RELEASE_GIL, [op.getarg(2)] + arg_boxes, box_result, calldescr) # self.history.operations.extend(extra_guards) # - if box_result is not None: - ofs = cif_description.exchange_result - assert ofs % itemsize == 0 # alignment check (result) - self.history.record(rop.SETARRAYITEM_RAW, - [box_exchange_buffer, - ConstInt(ofs // itemsize), box_result], - None, descr) + # note that the result is written back to the exchange_buffer by the + # special op libffi_save_result_{int,float} def direct_call_release_gil(self): op = self.history.operations.pop() diff --git a/rpython/jit/metainterp/test/test_fficall.py b/rpython/jit/metainterp/test/test_fficall.py --- a/rpython/jit/metainterp/test/test_fficall.py +++ b/rpython/jit/metainterp/test/test_fficall.py @@ -1,14 +1,16 @@ - import py +from _pytest.monkeypatch import monkeypatch import ctypes, math from rpython.rtyper.lltypesystem import lltype, rffi +from rpython.rtyper.annlowlevel import llhelper from rpython.jit.metainterp.test.support import LLJitMixin from rpython.rlib import jit -from rpython.rlib.jit_libffi import types, CIF_DESCRIPTION, FFI_TYPE_PP +from rpython.rlib import jit_libffi +from rpython.rlib.jit_libffi import (types, CIF_DESCRIPTION, FFI_TYPE_PP, + jit_ffi_call, jit_ffi_save_result) from rpython.rlib.unroll import unrolling_iterable from rpython.rlib.rarithmetic import intmask - def get_description(atypes, rtype): p = lltype.malloc(CIF_DESCRIPTION, len(atypes), flavor='raw', immortal=True) @@ -21,6 +23,22 @@ p.atypes[i] = atypes[i] return p +class FakeFFI(object): + """ + Context manager to monkey patch jit_libffi with our custom "libffi-like" + function + """ + + def __init__(self, fake_call_impl_any): + self.fake_call_impl_any = fake_call_impl_any + self.monkey = monkeypatch() + + def __enter__(self, *args): + self.monkey.setattr(jit_libffi, 'jit_ffi_call_impl_any', self.fake_call_impl_any) + + def __exit__(self, *args): + self.monkey.undo() + class FfiCallTests(object): @@ -41,8 +59,7 @@ unroll_avalues = unrolling_iterable(avalues) - @jit.oopspec("libffi_call(cif_description,func_addr,exchange_buffer)") - def fake_call(cif_description, func_addr, exchange_buffer): + def fake_call_impl_any(cif_description, func_addr, exchange_buffer): ofs = 16 for avalue in unroll_avalues: TYPE = rffi.CArray(lltype.typeOf(avalue)) @@ -67,7 +84,7 @@ rffi.cast(lltype.Ptr(TYPE), data)[0] = avalue ofs += 16 - fake_call(cif_description, func_addr, exbuf) + jit_ffi_call(cif_description, func_addr, exbuf) if rvalue is None: res = 654321 @@ -78,14 +95,15 @@ lltype.free(exbuf, flavor='raw') return res - res = f() - assert res == rvalue or (res, rvalue) == (654321, None) - res = self.interp_operations(f, []) - assert res == rvalue or (res, rvalue) == (654321, None) - self.check_operations_history(call_may_force=0, - call_release_gil=1) + with FakeFFI(fake_call_impl_any): + res = f() + assert res == rvalue or (res, rvalue) == (654321, None) + res = self.interp_operations(f, []) + assert res == rvalue or (res, rvalue) == (654321, None) + self.check_operations_history(call_may_force=0, + call_release_gil=1) - def test_simple_call(self): + def test_simple_call_int(self): self._run([types.signed] * 2, types.signed, [456, 789], -42) def test_many_arguments(self): @@ -104,6 +122,91 @@ self._run([types.signed], types.sint8, [456], rffi.cast(rffi.SIGNEDCHAR, -42)) + def _add_libffi_types_to_ll2types_maybe(self): + # not necessary on the llgraph backend, but needed for x86. + # see rpython/jit/backend/x86/test/test_fficall.py + pass + + def test_guard_not_forced_fails(self): + self._add_libffi_types_to_ll2types_maybe() + FUNC = lltype.FuncType([lltype.Signed], lltype.Signed) + + cif_description = get_description([types.slong], types.slong) + cif_description.exchange_args[0] = 16 + cif_description.exchange_result = 32 + + ARRAY = lltype.Ptr(rffi.CArray(lltype.Signed)) + + @jit.dont_look_inside + def fn(n): + if n >= 50: + exctx.m = exctx.topframeref().n # forces the frame + return n*2 + + # this function simulates what a real libffi_call does: reading from + # the buffer, calling a function (which can potentially call callbacks + # and force frames) and write back to the buffer + def fake_call_impl_any(cif_description, func_addr, exchange_buffer): + # read the args from the buffer + data_in = rffi.ptradd(exchange_buffer, 16) + n = rffi.cast(ARRAY, data_in)[0] + # + # logic of the function + func_ptr = rffi.cast(lltype.Ptr(FUNC), func_addr) + n = func_ptr(n) + # + # write the result to the buffer + data_out = rffi.ptradd(exchange_buffer, 32) + rffi.cast(ARRAY, data_out)[0] = n + + def do_call(n): + func_ptr = llhelper(lltype.Ptr(FUNC), fn) + exbuf = lltype.malloc(rffi.CCHARP.TO, 48, flavor='raw', zero=True) + data_in = rffi.ptradd(exbuf, 16) + rffi.cast(ARRAY, data_in)[0] = n + jit_ffi_call(cif_description, func_ptr, exbuf) + data_out = rffi.ptradd(exbuf, 32) + res = rffi.cast(ARRAY, data_out)[0] + lltype.free(exbuf, flavor='raw') + return res + + # + # + class XY: + pass + class ExCtx: + pass + exctx = ExCtx() + myjitdriver = jit.JitDriver(greens = [], reds = ['n']) + def f(): + n = 0 + while n < 100: + myjitdriver.jit_merge_point(n=n) + xy = XY() + xy.n = n + exctx.topframeref = vref = jit.virtual_ref(xy) + res = do_call(n) # this is equivalent of a cffi call which + # sometimes forces a frame + + # when n==50, fn() will force the frame, so guard_not_forced + # fails and we enter blackholing: this test makes sure that + # the result of call_release_gil is kept alive before the + # libffi_save_result, and that the corresponding box is passed + # in the fail_args. Before the fix, the result of + # call_release_gil was simply lost and when guard_not_forced + # failed, and the value of "res" was unpredictable. + # See commit b84ff38f34bd and subsequents. + assert res == n*2 + jit.virtual_ref_finish(vref, xy) + exctx.topframeref = jit.vref_None + n += 1 + return n + + with FakeFFI(fake_call_impl_any): + assert f() == 100 + res = self.meta_interp(f, []) + assert res == 100 + class TestFfiCall(FfiCallTests, LLJitMixin): def test_jit_ffi_vref(self): diff --git a/rpython/rlib/jit_libffi.py b/rpython/rlib/jit_libffi.py --- a/rpython/rlib/jit_libffi.py +++ b/rpython/rlib/jit_libffi.py @@ -1,6 +1,8 @@ from rpython.rtyper.lltypesystem import lltype, rffi +from rpython.rtyper.extregistry import ExtRegistryEntry from rpython.rlib import clibffi, jit +from rpython.rlib.nonconst import NonConstant FFI_CIF = clibffi.FFI_CIFP.TO @@ -65,11 +67,79 @@ return rffi.cast(lltype.Signed, res) - at jit.oopspec("libffi_call(cif_description, func_addr, exchange_buffer)") +# ============================= +# jit_ffi_call and its helpers +# ============================= + +## Problem: jit_ffi_call is turned into call_release_gil by pyjitpl. Before +## the refactor-call_release_gil branch, the resulting code looked like this: +## +## buffer = ... +## i0 = call_release_gil(...) +## guard_not_forced() +## setarray_item_raw(buffer, ..., i0) +## +## The problem is that the result box i0 was generated freshly inside pyjitpl, +## and the codewriter did not know about its liveness: the result was that i0 +## was not in the fail_args of guard_not_forced. See +## test_fficall::test_guard_not_forced_fails for a more detalied explanation +## of the problem. +## +## The solution is to create a new separate operation libffi_save_result whose +## job is to write the result in the exchange_buffer: during normal execution +## this is a no-op because the buffer is already filled by libffi, but during +## jitting the behavior is to actually write into the buffer. +## +## The result is that now the jitcode looks like this: +## +## %i0 = libffi_call_int(...) +## -live- +## libffi_save_result_int(..., %i0) +## +## the "-live-" is the key, because it make sure that the value is not lost if +## guard_not_forced fails. + + def jit_ffi_call(cif_description, func_addr, exchange_buffer): """Wrapper around ffi_call(). Must receive a CIF_DESCRIPTION_P that describes the layout of the 'exchange_buffer'. """ + if cif_description.rtype == types.void: + jit_ffi_call_impl_void(cif_description, func_addr, exchange_buffer) + elif cif_description.rtype == types.double: + result = jit_ffi_call_impl_float(cif_description, func_addr, exchange_buffer) + jit_ffi_save_result('float', cif_description, exchange_buffer, result) + else: + result = jit_ffi_call_impl_int(cif_description, func_addr, exchange_buffer) + jit_ffi_save_result('int', cif_description, exchange_buffer, result) + + +# we must return a NonConstant else we get the constant -1 as the result of +# the flowgraph, and the codewriter does not produce a box for the +# result. Note that when not-jitted, the result is unused, but when jitted the +# box of the result contains the actual value returned by the C function. + + at jit.oopspec("libffi_call(cif_description,func_addr,exchange_buffer)") +def jit_ffi_call_impl_int(cif_description, func_addr, exchange_buffer): + jit_ffi_call_impl_any(cif_description, func_addr, exchange_buffer) + return NonConstant(-1) + + at jit.oopspec("libffi_call(cif_description,func_addr,exchange_buffer)") +def jit_ffi_call_impl_float(cif_description, func_addr, exchange_buffer): + jit_ffi_call_impl_any(cif_description, func_addr, exchange_buffer) + return NonConstant(-1.0) + + at jit.oopspec("libffi_call(cif_description,func_addr,exchange_buffer)") +def jit_ffi_call_impl_void(cif_description, func_addr, exchange_buffer): + jit_ffi_call_impl_any(cif_description, func_addr, exchange_buffer) + return None + +def jit_ffi_call_impl_any(cif_description, func_addr, exchange_buffer): + """ + This is the function which actually calls libffi. All the rest if just + infrastructure to convince the JIT to pass a typed result box to + jit_ffi_save_result + """ buffer_array = rffi.cast(rffi.VOIDPP, exchange_buffer) for i in range(cif_description.nargs): data = rffi.ptradd(exchange_buffer, cif_description.exchange_args[i]) @@ -79,6 +149,31 @@ clibffi.c_ffi_call(cif_description.cif, func_addr, rffi.cast(rffi.VOIDP, resultdata), buffer_array) + return -1 + + + +def jit_ffi_save_result(kind, cif_description, exchange_buffer, result): + """ + This is a no-op during normal execution, but actually fills the buffer + when jitted + """ + pass + +class Entry(ExtRegistryEntry): + _about_ = jit_ffi_save_result + + def compute_result_annotation(self, kind_s, *args_s): + from rpython.annotator import model as annmodel + assert isinstance(kind_s, annmodel.SomeString) + assert kind_s.const in ('int', 'float') + + def specialize_call(self, hop): + hop.exception_cannot_occur() + vlist = hop.inputargs(lltype.Void, *hop.args_r[1:]) + return hop.genop('jit_ffi_save_result', vlist, + resulttype=lltype.Void) + # ____________________________________________________________ diff --git a/rpython/rtyper/lltypesystem/lloperation.py b/rpython/rtyper/lltypesystem/lloperation.py --- a/rpython/rtyper/lltypesystem/lloperation.py +++ b/rpython/rtyper/lltypesystem/lloperation.py @@ -456,6 +456,7 @@ 'jit_is_virtual': LLOp(canrun=True), 'jit_force_quasi_immutable': LLOp(canrun=True), 'jit_record_known_class' : LLOp(canrun=True), + 'jit_ffi_save_result': LLOp(canrun=True), 'get_exception_addr': LLOp(), 'get_exc_value_addr': LLOp(), 'do_malloc_fixedsize_clear':LLOp(canmallocgc=True), diff --git a/rpython/rtyper/lltypesystem/opimpl.py b/rpython/rtyper/lltypesystem/opimpl.py --- a/rpython/rtyper/lltypesystem/opimpl.py +++ b/rpython/rtyper/lltypesystem/opimpl.py @@ -597,6 +597,9 @@ def op_jit_record_known_class(x, y): pass +def op_jit_ffi_save_result(*args): + pass + def op_get_group_member(TYPE, grpptr, memberoffset): from rpython.rtyper.lltypesystem import llgroup assert isinstance(memberoffset, llgroup.GroupMemberOffset) diff --git a/rpython/translator/c/funcgen.py b/rpython/translator/c/funcgen.py --- a/rpython/translator/c/funcgen.py +++ b/rpython/translator/c/funcgen.py @@ -843,6 +843,9 @@ def OP_JIT_FORCE_QUASI_IMMUTABLE(self, op): return '/* JIT_FORCE_QUASI_IMMUTABLE %s */' % op + def OP_JIT_FFI_SAVE_RESULT(self, op): + return '/* JIT_FFI_SAVE_RESULT %s */' % op + def OP_GET_GROUP_MEMBER(self, op): typename = self.db.gettype(op.result.concretetype) return '%s = (%s)_OP_GET_GROUP_MEMBER(%s, %s);' % ( diff --git a/rpython/translator/cli/opcodes.py b/rpython/translator/cli/opcodes.py --- a/rpython/translator/cli/opcodes.py +++ b/rpython/translator/cli/opcodes.py @@ -99,6 +99,7 @@ 'jit_force_virtual': DoNothing, 'jit_force_quasi_immutable':Ignore, 'jit_is_virtual': [PushPrimitive(ootype.Bool, False)], + 'jit_ffi_save_result': Ignore, } # __________ numeric operations __________ diff --git a/rpython/translator/jvm/opcodes.py b/rpython/translator/jvm/opcodes.py --- a/rpython/translator/jvm/opcodes.py +++ b/rpython/translator/jvm/opcodes.py @@ -102,6 +102,7 @@ 'jit_force_virtual': DoNothing, 'jit_force_quasi_immutable': Ignore, 'jit_is_virtual': PushPrimitive(ootype.Bool, False), + 'jit_ffi_save_result': Ignore, 'debug_assert': [], # TODO: implement? 'debug_start_traceback': Ignore, From noreply at buildbot.pypy.org Mon Apr 8 19:32:31 2013 From: noreply at buildbot.pypy.org (arigo) Date: Mon, 8 Apr 2013 19:32:31 +0200 (CEST) Subject: [pypy-commit] pypy stm-gc-2: Add a test. Various fixes, of course. Message-ID: <20130408173231.A42641C15A2@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: stm-gc-2 Changeset: r63150:a775bcc0f708 Date: 2013-04-08 19:32 +0200 http://bitbucket.org/pypy/pypy/changeset/a775bcc0f708/ Log: Add a test. Various fixes, of course. diff --git a/rpython/memory/gc/stmshared.py b/rpython/memory/gc/stmshared.py --- a/rpython/memory/gc/stmshared.py +++ b/rpython/memory/gc/stmshared.py @@ -1,7 +1,7 @@ from rpython.rtyper.lltypesystem import lltype, llmemory, llarena, rffi from rpython.rlib.rarithmetic import LONG_BIT -from rpython.rlib.objectmodel import free_non_gc_object -from rpython.rlib.debug import fatalerror +from rpython.rlib.objectmodel import free_non_gc_object, we_are_translated +from rpython.rlib.debug import ll_assert, fatalerror from rpython.rlib import rthread WORD = LONG_BIT // 8 @@ -109,6 +109,9 @@ self.full_page_for_size = lltype.malloc(rffi.CArray(PAGE_PTR), length, flavor='raw', zero=True, immortal=True) + # + if not we_are_translated(): + self._seen_pages = set() def _malloc_size_class(self, size_class): """Malloc one object of the given size_class (== number of WORDs).""" @@ -123,6 +126,7 @@ # # The result is simply 'page.freeblock' result = page.freeblock + nsize = size_class << WORD_POWER_2 if page.nfree > 0: # # The 'result' was part of the chained list; read the next. @@ -139,7 +143,7 @@ page.freeblock = freeblock # pageaddr = llarena.getfakearenaaddress(llmemory.cast_ptr_to_adr(page)) - if freeblock - pageaddr > self.page_size - nsize: + if freeblock - pageaddr > self.sharedarea.page_size - nsize: # This was the last free block, so unlink the page from the # chained list and put it in the 'full_page_for_size' list. self.page_for_size[size_class] = page.nextpage @@ -166,6 +170,8 @@ if not result: fatalerror("FIXME: Out of memory! (should raise MemoryError)") return PAGE_NULL + if not we_are_translated(): + self._seen_pages.add(result) llarena.arena_reserve(result, llmemory.sizeof(PAGE_HEADER)) # # Initialize the fields of the resulting page @@ -184,7 +190,8 @@ some other data structure. Note that it is not zero-filled.""" nsize = llmemory.raw_malloc_usage(totalsize) if nsize <= self.sharedarea.small_request_threshold: - result = self._malloc_size_class(nsize >> WORD_POWER_2) + size_class = (nsize + WORD_POWER_2 - 1) >> WORD_POWER_2 + result = self._malloc_size_class(size_class) llarena.arena_reserve(result, _dummy_size(totalsize)) return result else: diff --git a/rpython/memory/gc/test/test_stmshared.py b/rpython/memory/gc/test/test_stmshared.py new file mode 100644 --- /dev/null +++ b/rpython/memory/gc/test/test_stmshared.py @@ -0,0 +1,21 @@ +from rpython.memory.gc.stmshared import WORD +from rpython.memory.gc.stmshared import StmGCSharedArea +from rpython.memory.gc.stmshared import StmGCThreadLocalAllocator + + +def test_simple(): + shared = StmGCSharedArea("gc", 10*WORD, 2*WORD) + shared.setup() + thl1 = StmGCThreadLocalAllocator(shared) + thl1.malloc_object(2*WORD-1) + assert len(thl1._seen_pages) == 1 + thl1.malloc_object(2*WORD) + assert len(thl1._seen_pages) == 1 + thl1.malloc_object(1*WORD) + assert len(thl1._seen_pages) == 2 + thl1.malloc_object(2*WORD) + assert len(thl1._seen_pages) == 2 + thl1.malloc_object(2*WORD) + assert len(thl1._seen_pages) == 3 + thl1.malloc_object(2*WORD) + assert len(thl1._seen_pages) == 3 From noreply at buildbot.pypy.org Mon Apr 8 19:52:11 2013 From: noreply at buildbot.pypy.org (ltratt) Date: Mon, 8 Apr 2013 19:52:11 +0200 (CEST) Subject: [pypy-commit] pypy default: Fix typing issue. Message-ID: <20130408175211.490771C15A2@cobra.cs.uni-duesseldorf.de> Author: Laurence Tratt Branch: Changeset: r63151:9ed36ac750d8 Date: 2013-04-08 18:50 +0100 http://bitbucket.org/pypy/pypy/changeset/9ed36ac750d8/ Log: Fix typing issue. This prevented PyPy from building on OpenBSD (and maybe other platforms). Fix suggested by mattip, based on precedent in ll_os_stat.py. diff --git a/pypy/module/__pypy__/interp_time.py b/pypy/module/__pypy__/interp_time.py --- a/pypy/module/__pypy__/interp_time.py +++ b/pypy/module/__pypy__/interp_time.py @@ -61,7 +61,7 @@ ret = c_clock_gettime(clk_id, tp) if ret != 0: raise exception_from_errno(space, space.w_IOError) - return space.wrap(tp.c_tv_sec + tp.c_tv_nsec * 1e-9) + return space.wrap(int(tp.c_tv_sec) + 1e-9 * int(tp.c_tv_nsec)) @unwrap_spec(clk_id="c_int") def clock_getres(space, clk_id): @@ -69,4 +69,4 @@ ret = c_clock_getres(clk_id, tp) if ret != 0: raise exception_from_errno(space, space.w_IOError) - return space.wrap(tp.c_tv_sec + tp.c_tv_nsec * 1e-9) + return space.wrap(int(tp.c_tv_sec) + 1e-9 * int(tp.c_tv_nsec)) From noreply at buildbot.pypy.org Mon Apr 8 20:35:05 2013 From: noreply at buildbot.pypy.org (mattip) Date: Mon, 8 Apr 2013 20:35:05 +0200 (CEST) Subject: [pypy-commit] pypy default: a failing test for issue 1438 Message-ID: <20130408183505.B36811C019F@cobra.cs.uni-duesseldorf.de> Author: mattip Branch: Changeset: r63152:ecf9e3e0f3b1 Date: 2013-04-08 20:07 +0300 http://bitbucket.org/pypy/pypy/changeset/ecf9e3e0f3b1/ Log: a failing test for issue 1438 diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py --- a/pypy/module/micronumpy/test/test_numarray.py +++ b/pypy/module/micronumpy/test/test_numarray.py @@ -422,6 +422,12 @@ assert a[4] == 5.0 raises(IndexError, "a[5] = 0.0") raises(IndexError, "a[-6] = 3.0") + a = array(range(5), dtype=float) + a[0] = 0.005 + assert a[0] == 0.005 + a[1] = array(-0.005) + assert a[1] == -0.005 + def test_setitem_tuple(self): from numpypy import array From noreply at buildbot.pypy.org Mon Apr 8 20:35:07 2013 From: noreply at buildbot.pypy.org (mattip) Date: Mon, 8 Apr 2013 20:35:07 +0200 (CEST) Subject: [pypy-commit] pypy default: add more tests, fix by adding __float__ (ronan, mattip) Message-ID: <20130408183507.202D41C019F@cobra.cs.uni-duesseldorf.de> Author: mattip Branch: Changeset: r63153:84ff2854255f Date: 2013-04-08 21:21 +0300 http://bitbucket.org/pypy/pypy/changeset/84ff2854255f/ Log: add more tests, fix by adding __float__ (ronan, mattip) diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py --- a/pypy/module/micronumpy/interp_numarray.py +++ b/pypy/module/micronumpy/interp_numarray.py @@ -772,6 +772,16 @@ return space.int(self.descr_getitem(space, space.wrap(0))) raise OperationError(space.w_TypeError, space.wrap("only length-1 arrays can be converted to Python scalars")) + def descr_float(self, space): + shape = self.get_shape() + if len(shape) == 0: + assert isinstance(self.implementation, scalar.Scalar) + return space.float(space.wrap(self.implementation.get_scalar_value())) + if shape == [1]: + return space.float(self.descr_getitem(space, space.wrap(0))) + raise OperationError(space.w_TypeError, space.wrap("only length-1 arrays can be converted to Python scalars")) + + @unwrap_spec(offset=int) def descr_new_array(space, w_subtype, w_shape, w_dtype=None, w_buffer=None, @@ -813,6 +823,7 @@ __repr__ = interp2app(W_NDimArray.descr_repr), __str__ = interp2app(W_NDimArray.descr_str), __int__ = interp2app(W_NDimArray.descr_int), + __float__ = interp2app(W_NDimArray.descr_float), __pos__ = interp2app(W_NDimArray.descr_pos), __neg__ = interp2app(W_NDimArray.descr_neg), diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py --- a/pypy/module/micronumpy/test/test_numarray.py +++ b/pypy/module/micronumpy/test/test_numarray.py @@ -422,11 +422,17 @@ assert a[4] == 5.0 raises(IndexError, "a[5] = 0.0") raises(IndexError, "a[-6] = 3.0") + a[1] = array(100) + a[2] = array([100]) + assert a[1] == 100 + assert a[2] == 100 a = array(range(5), dtype=float) a[0] = 0.005 assert a[0] == 0.005 a[1] = array(-0.005) + a[2] = array([-0.005]) assert a[1] == -0.005 + assert a[2] == -0.005 def test_setitem_tuple(self): From noreply at buildbot.pypy.org Mon Apr 8 20:35:08 2013 From: noreply at buildbot.pypy.org (mattip) Date: Mon, 8 Apr 2013 20:35:08 +0200 (CEST) Subject: [pypy-commit] pypy default: merge heads Message-ID: <20130408183508.49ACC1C019F@cobra.cs.uni-duesseldorf.de> Author: mattip Branch: Changeset: r63154:1c7e961aa0ab Date: 2013-04-08 21:22 +0300 http://bitbucket.org/pypy/pypy/changeset/1c7e961aa0ab/ Log: merge heads diff --git a/pypy/module/__pypy__/interp_time.py b/pypy/module/__pypy__/interp_time.py --- a/pypy/module/__pypy__/interp_time.py +++ b/pypy/module/__pypy__/interp_time.py @@ -61,7 +61,7 @@ ret = c_clock_gettime(clk_id, tp) if ret != 0: raise exception_from_errno(space, space.w_IOError) - return space.wrap(tp.c_tv_sec + tp.c_tv_nsec * 1e-9) + return space.wrap(int(tp.c_tv_sec) + 1e-9 * int(tp.c_tv_nsec)) @unwrap_spec(clk_id="c_int") def clock_getres(space, clk_id): @@ -69,4 +69,4 @@ ret = c_clock_getres(clk_id, tp) if ret != 0: raise exception_from_errno(space, space.w_IOError) - return space.wrap(tp.c_tv_sec + tp.c_tv_nsec * 1e-9) + return space.wrap(int(tp.c_tv_sec) + 1e-9 * int(tp.c_tv_nsec)) diff --git a/rpython/jit/metainterp/blackhole.py b/rpython/jit/metainterp/blackhole.py --- a/rpython/jit/metainterp/blackhole.py +++ b/rpython/jit/metainterp/blackhole.py @@ -857,6 +857,8 @@ @arguments("r") def bhimpl_debug_fatalerror(msg): + from rpython.rtyper.lltypesystem import rstr + msg = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), msg) llop.debug_fatalerror(lltype.Void, msg) @arguments("r", "i", "i", "i", "i") diff --git a/rpython/jit/metainterp/test/test_blackhole.py b/rpython/jit/metainterp/test/test_blackhole.py --- a/rpython/jit/metainterp/test/test_blackhole.py +++ b/rpython/jit/metainterp/test/test_blackhole.py @@ -228,5 +228,15 @@ assert BlackholeInterpreter.bhimpl_int_lshift.im_func(100, 3) == 100<<3 assert BlackholeInterpreter.bhimpl_int_rshift.im_func(100, 3) == 100>>3 - assert BlackholeInterpreter.bhimpl_uint_rshift.im_func(100, 3) == 100>>3 - + assert BlackholeInterpreter.bhimpl_uint_rshift.im_func(100, 3) == 100>>3 + +def test_debug_fatalerror(): + from rpython.rtyper.lltypesystem import lltype, llmemory, rstr + from rpython.rtyper.llinterp import LLFatalError + msg = rstr.mallocstr(1) + msg.chars[0] = "!" + msg = lltype.cast_opaque_ptr(llmemory.GCREF, msg) + e = py.test.raises(LLFatalError, + BlackholeInterpreter.bhimpl_debug_fatalerror.im_func, + msg) + assert str(e.value) == '!' diff --git a/rpython/rtyper/lltypesystem/lloperation.py b/rpython/rtyper/lltypesystem/lloperation.py --- a/rpython/rtyper/lltypesystem/lloperation.py +++ b/rpython/rtyper/lltypesystem/lloperation.py @@ -555,7 +555,7 @@ 'debug_offset': LLOp(canrun=True), 'debug_flush': LLOp(canrun=True), 'debug_assert': LLOp(tryfold=True), - 'debug_fatalerror': LLOp(), + 'debug_fatalerror': LLOp(canrun=True), 'debug_llinterpcall': LLOp(canraise=(Exception,)), # Python func call 'res=arg[0](*arg[1:])' # in backends, abort() or whatever is fine diff --git a/rpython/rtyper/lltypesystem/opimpl.py b/rpython/rtyper/lltypesystem/opimpl.py --- a/rpython/rtyper/lltypesystem/opimpl.py +++ b/rpython/rtyper/lltypesystem/opimpl.py @@ -654,6 +654,13 @@ from rpython.rlib.rtimer import read_timestamp return read_timestamp() +def op_debug_fatalerror(ll_msg): + from rpython.rtyper.lltypesystem import lltype, rstr + from rpython.rtyper.llinterp import LLFatalError + assert lltype.typeOf(ll_msg) == lltype.Ptr(rstr.STR) + msg = ''.join(ll_msg.chars) + raise LLFatalError(msg) + # ____________________________________________________________ def get_op_impl(opname): From noreply at buildbot.pypy.org Mon Apr 8 21:38:53 2013 From: noreply at buildbot.pypy.org (arigo) Date: Mon, 8 Apr 2013 21:38:53 +0200 (CEST) Subject: [pypy-commit] pypy default: Attach this argument as an attribute here, to help debugging in case Message-ID: <20130408193853.6D2031C1465@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63155:972e776a277f Date: 2013-04-08 21:38 +0200 http://bitbucket.org/pypy/pypy/changeset/972e776a277f/ Log: Attach this argument as an attribute here, to help debugging in case I ever get the same translation crash again. diff --git a/rpython/rtyper/rptr.py b/rpython/rtyper/rptr.py --- a/rpython/rtyper/rptr.py +++ b/rpython/rtyper/rptr.py @@ -234,6 +234,7 @@ class InteriorPtrRepr(Repr): def __init__(self, ptrtype): assert isinstance(ptrtype, lltype.InteriorPtr) + self._ptrtype = ptrtype # for debugging self.v_offsets = [] numitemoffsets = 0 for i, offset in enumerate(ptrtype.offsets): From noreply at buildbot.pypy.org Tue Apr 9 00:39:06 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Tue, 9 Apr 2013 00:39:06 +0200 (CEST) Subject: [pypy-commit] pypy default: py3 compat Message-ID: <20130408223906.BEEAA1C019F@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: Changeset: r63156:0c26a447f302 Date: 2013-04-08 15:34 -0700 http://bitbucket.org/pypy/pypy/changeset/0c26a447f302/ Log: py3 compat diff --git a/pypy/module/pyexpat/test/test_parser.py b/pypy/module/pyexpat/test/test_parser.py --- a/pypy/module/pyexpat/test/test_parser.py +++ b/pypy/module/pyexpat/test/test_parser.py @@ -40,7 +40,7 @@ import pyexpat for encoding_arg in (None, 'utf-8', 'iso-8859-1'): for namespace_arg in (None, '{'): - print encoding_arg, namespace_arg + print(encoding_arg, namespace_arg) p = pyexpat.ParserCreate(encoding_arg, namespace_arg) data = [] p.CharacterDataHandler = lambda s: data.append(s) @@ -205,7 +205,7 @@ try: for event, node in stream: - print event, node + print(event, node) except DTDForbidden: pass else: From noreply at buildbot.pypy.org Tue Apr 9 00:39:08 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Tue, 9 Apr 2013 00:39:08 +0200 (CEST) Subject: [pypy-commit] pypy py3k: merge default Message-ID: <20130408223908.CB3981C0723@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63157:3d53acc6c795 Date: 2013-04-08 15:38 -0700 http://bitbucket.org/pypy/pypy/changeset/3d53acc6c795/ Log: merge default diff --git a/.hgignore b/.hgignore --- a/.hgignore +++ b/.hgignore @@ -70,6 +70,7 @@ ^rpython/translator/cli/src/pypylib\.dll$ ^rpython/translator/cli/src/query\.exe$ ^rpython/translator/cli/src/main\.exe$ +^lib_pypy/__pycache__$ ^lib_pypy/ctypes_config_cache/_.+_cache\.py$ ^lib_pypy/ctypes_config_cache/_.+_.+_\.py$ ^rpython/translator/cli/query-descriptions$ diff --git a/lib_pypy/_ctypes/function.py b/lib_pypy/_ctypes/function.py --- a/lib_pypy/_ctypes/function.py +++ b/lib_pypy/_ctypes/function.py @@ -8,7 +8,6 @@ import _ffi import sys import traceback -import warnings try: from __pypy__ import builtinify except ImportError: builtinify = lambda f: f @@ -315,8 +314,12 @@ return if argtypes is None: - warnings.warn('C function without declared arguments called', - RuntimeWarning, stacklevel=2) + # XXX this warning was originally meaning "it's going to be + # really slow". Now we don't worry that much about slowness + # of ctypes, and it's strange to get warnings for perfectly- + # legal code. + #warnings.warn('C function without declared arguments called', + # RuntimeWarning, stacklevel=2) argtypes = [] if self._com_index: @@ -342,6 +345,7 @@ if not outargs: return result + from ctypes import c_void_p simple_cdata = type(c_void_p()).__bases__[0] outargs = [x.value if type(x).__bases__[0] is simple_cdata else x for x in outargs] diff --git a/lib_pypy/_curses.py b/lib_pypy/_curses.py --- a/lib_pypy/_curses.py +++ b/lib_pypy/_curses.py @@ -364,7 +364,9 @@ key_n = ffi.string(key_n) if key_n == b"UNKNOWN KEY": continue - key_n = key_n.decode().replace('(', '').replace(')', '') + if not isinstance(key_n, str): # python 3 + key_n = key_n.decode() + key_n = key_n.replace('(', '').replace(')', '') globals()[key_n] = key _setup() diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -256,7 +256,12 @@ typedef ... sqlite3; int sqlite3_enable_load_extension(sqlite3 *db, int onoff); """) - unverified_lib = unverified_ffi.dlopen('sqlite3') + libname = 'sqlite3' + if sys.platform == 'win32': + _libname = os.path.join(os.path.dirname(sys.executable), libname) + if os.path.exists(_libname + '.dll'): + libname = _libname + unverified_lib = unverified_ffi.dlopen(libname) return hasattr(unverified_lib, 'sqlite3_enable_load_extension') if _has_load_extension(): diff --git a/pypy/doc/release-2.0.0-beta2.rst b/pypy/doc/release-2.0.0-beta2.rst --- a/pypy/doc/release-2.0.0-beta2.rst +++ b/pypy/doc/release-2.0.0-beta2.rst @@ -82,3 +82,13 @@ * we now have special strategies for ``dict``/``set``/``list`` which contain unicode strings, which means that now such collections will be both faster and more compact. + +.. _`eventlet`: http://eventlet.net/ +.. _`gevent`: http://www.gevent.org/ +.. _`cffi`: http://cffi.readthedocs.org/en/release-0.6/ +.. _`JIT hooks`: http://doc.pypy.org/en/latest/jit-hooks.html +.. _`pypycore`: https://github.com/gevent-on-pypy/pypycore +.. _`pypy-hacks`: https://github.com/schmir/gevent/tree/pypy-hacks +.. _`_curses.py`: https://bitbucket.org/pypy/pypy/src/aefddd47f224e3c12e2ea74f5c796d76f4355bdb/lib_pypy/_curses.py?at=default +.. _`_sqlite3.py`: https://bitbucket.org/pypy/pypy/src/aefddd47f224e3c12e2ea74f5c796d76f4355bdb/lib_pypy/_sqlite3.py?at=default + diff --git a/pypy/doc/stackless.rst b/pypy/doc/stackless.rst --- a/pypy/doc/stackless.rst +++ b/pypy/doc/stackless.rst @@ -17,8 +17,8 @@ Continulets can be directly used by application code, or it is possible to write (entirely at app-level) more user-friendly interfaces. -Currently PyPy implements greenlets_ on top of continulets. It would be -easy to implement tasklets and channels as well, emulating the model +Currently PyPy implements greenlets_ on top of continulets. It also +implements (an approximation of) tasklets and channels, emulating the model of `Stackless Python`_. Continulets are extremely light-weight, which means that PyPy should be diff --git a/pypy/goal/getnightly.py b/pypy/goal/getnightly.py --- a/pypy/goal/getnightly.py +++ b/pypy/goal/getnightly.py @@ -13,8 +13,13 @@ if sys.maxint == 2**63 - 1: arch += '64' +hg = py.path.local.sysfind('hg') +branch = hg.sysexec('branch').strip() +if branch == 'default': + branch = 'trunk' + filename = 'pypy-c-jit-latest-%s.tar.bz2' % arch -url = 'http://buildbot.pypy.org/nightly/trunk/%s' % filename +url = 'http://buildbot.pypy.org/nightly/%s/%s' % (branch, filename) tmp = py.path.local.mkdtemp() mydir = tmp.chdir() print 'Downloading pypy to', tmp diff --git a/pypy/interpreter/astcompiler/misc.py b/pypy/interpreter/astcompiler/misc.py --- a/pypy/interpreter/astcompiler/misc.py +++ b/pypy/interpreter/astcompiler/misc.py @@ -1,5 +1,4 @@ from pypy.interpreter import gateway -from pypy.interpreter.astcompiler import ast from rpython.rlib.objectmodel import we_are_translated from rpython.rlib.unroll import unrolling_iterable @@ -28,6 +27,7 @@ def parse_future(tree, feature_flags): + from pypy.interpreter.astcompiler import ast future_lineno = 0 future_column = 0 flags = 0 @@ -91,13 +91,9 @@ return lookup -MANGLE_LEN = 256 # magic constant from compile.c - def mangle(name, klass): if not name.startswith('__'): return name - if len(name) + 2 >= MANGLE_LEN: - return name # Don't mangle __id__ or names with dots. The only time a name with a dot # can occur is when we are compiling an import statement that has a package # name. @@ -109,17 +105,7 @@ i = i + 1 except IndexError: return name - klass = klass[i:] - - tlen = len(klass) + len(name) - if tlen > MANGLE_LEN: - end = len(klass) + MANGLE_LEN-tlen - if end < 0: - klass = '' # slices of negative length are invalid in RPython - else: - klass = klass[:end] - - return "_%s%s" % (klass, name) + return "_%s%s" % (klass[i:], name) def new_identifier(space, name): diff --git a/pypy/interpreter/astcompiler/test/test_misc.py b/pypy/interpreter/astcompiler/test/test_misc.py new file mode 100644 --- /dev/null +++ b/pypy/interpreter/astcompiler/test/test_misc.py @@ -0,0 +1,14 @@ +from pypy.interpreter.astcompiler.misc import mangle + +def test_mangle(): + assert mangle("foo", "Bar") == "foo" + assert mangle("__foo__", "Bar") == "__foo__" + assert mangle("foo.baz", "Bar") == "foo.baz" + assert mangle("__", "Bar") == "__" + assert mangle("___", "Bar") == "___" + assert mangle("____", "Bar") == "____" + assert mangle("__foo", "Bar") == "_Bar__foo" + assert mangle("__foo", "_Bar") == "_Bar__foo" + assert mangle("__foo", "__Bar") == "_Bar__foo" + assert mangle("__foo", "___") == "__foo" + assert mangle("___foo", "__Bar") == "_Bar___foo" diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py --- a/pypy/interpreter/baseobjspace.py +++ b/pypy/interpreter/baseobjspace.py @@ -723,6 +723,8 @@ def new_interned_w_str(self, w_s): s = self.str_w(w_s) + if not we_are_translated(): + assert type(s) is str try: return self.interned_strings[s] except KeyError: @@ -731,6 +733,8 @@ return w_s def new_interned_str(self, s): + if not we_are_translated(): + assert type(s) is str try: return self.interned_strings[s] except KeyError: diff --git a/pypy/module/__pypy__/interp_time.py b/pypy/module/__pypy__/interp_time.py --- a/pypy/module/__pypy__/interp_time.py +++ b/pypy/module/__pypy__/interp_time.py @@ -61,7 +61,7 @@ ret = c_clock_gettime(clk_id, tp) if ret != 0: raise exception_from_errno(space, space.w_IOError) - return space.wrap(tp.c_tv_sec + tp.c_tv_nsec * 1e-9) + return space.wrap(int(tp.c_tv_sec) + 1e-9 * int(tp.c_tv_nsec)) @unwrap_spec(clk_id="c_int") def clock_getres(space, clk_id): @@ -69,4 +69,4 @@ ret = c_clock_getres(clk_id, tp) if ret != 0: raise exception_from_errno(space, space.w_IOError) - return space.wrap(tp.c_tv_sec + tp.c_tv_nsec * 1e-9) + return space.wrap(int(tp.c_tv_sec) + 1e-9 * int(tp.c_tv_nsec)) diff --git a/pypy/module/_cffi_backend/ctypeprim.py b/pypy/module/_cffi_backend/ctypeprim.py --- a/pypy/module/_cffi_backend/ctypeprim.py +++ b/pypy/module/_cffi_backend/ctypeprim.py @@ -162,7 +162,7 @@ def __init__(self, *args): W_CTypePrimitive.__init__(self, *args) self.value_fits_long = self.size <= rffi.sizeof(lltype.Signed) - if self.size < rffi.sizeof(lltype.SignedLongLong): + if self.size < rffi.sizeof(lltype.Signed): assert self.value_fits_long sh = self.size * 8 self.vmin = r_uint(-1) << (sh - 1) diff --git a/pypy/module/_minimal_curses/__init__.py b/pypy/module/_minimal_curses/__init__.py --- a/pypy/module/_minimal_curses/__init__.py +++ b/pypy/module/_minimal_curses/__init__.py @@ -27,6 +27,7 @@ } for i in dir(_curses): + i = str(i) # workaround for pypy 2.0-beta2 val = getattr(_curses, i) if i.isupper() and type(val) is int: Module.interpleveldefs[i] = "space.wrap(%s)" % val diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py --- a/pypy/module/micronumpy/interp_numarray.py +++ b/pypy/module/micronumpy/interp_numarray.py @@ -772,6 +772,16 @@ return space.int(self.descr_getitem(space, space.wrap(0))) raise OperationError(space.w_TypeError, space.wrap("only length-1 arrays can be converted to Python scalars")) + def descr_float(self, space): + shape = self.get_shape() + if len(shape) == 0: + assert isinstance(self.implementation, scalar.Scalar) + return space.float(space.wrap(self.implementation.get_scalar_value())) + if shape == [1]: + return space.float(self.descr_getitem(space, space.wrap(0))) + raise OperationError(space.w_TypeError, space.wrap("only length-1 arrays can be converted to Python scalars")) + + @unwrap_spec(offset=int) def descr_new_array(space, w_subtype, w_shape, w_dtype=None, w_buffer=None, @@ -813,6 +823,7 @@ __repr__ = interp2app(W_NDimArray.descr_repr), __str__ = interp2app(W_NDimArray.descr_str), __int__ = interp2app(W_NDimArray.descr_int), + __float__ = interp2app(W_NDimArray.descr_float), __pos__ = interp2app(W_NDimArray.descr_pos), __neg__ = interp2app(W_NDimArray.descr_neg), diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py --- a/pypy/module/micronumpy/test/test_numarray.py +++ b/pypy/module/micronumpy/test/test_numarray.py @@ -422,6 +422,18 @@ assert a[4] == 5.0 raises(IndexError, "a[5] = 0.0") raises(IndexError, "a[-6] = 3.0") + a[1] = array(100) + a[2] = array([100]) + assert a[1] == 100 + assert a[2] == 100 + a = array(range(5), dtype=float) + a[0] = 0.005 + assert a[0] == 0.005 + a[1] = array(-0.005) + a[2] = array([-0.005]) + assert a[1] == -0.005 + assert a[2] == -0.005 + def test_setitem_tuple(self): from numpypy import array diff --git a/pypy/module/pyexpat/test/test_parser.py b/pypy/module/pyexpat/test/test_parser.py --- a/pypy/module/pyexpat/test/test_parser.py +++ b/pypy/module/pyexpat/test/test_parser.py @@ -219,7 +219,7 @@ try: for event, node in stream: - print event, node + print(event, node) except DTDForbidden: pass else: diff --git a/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py b/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py --- a/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py +++ b/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py @@ -510,6 +510,7 @@ assert seen == ["yadda"] def test_warnings(self): + py.test.skip("warnings are disabled") import warnings warnings.simplefilter("always") with warnings.catch_warnings(record=True) as w: diff --git a/pypy/module/test_lib_pypy/test_sqlite3.py b/pypy/module/test_lib_pypy/test_sqlite3.py --- a/pypy/module/test_lib_pypy/test_sqlite3.py +++ b/pypy/module/test_lib_pypy/test_sqlite3.py @@ -1,16 +1,25 @@ """Tests for _sqlite3.py""" -import sys +import pytest, sys + if sys.version_info < (2, 7): - skip("lib_pypy._sqlite3 doesn't work with python < 2.7") + pytest.skip("_sqlite3 requires Python 2.7") +try: + import _cffi_backend +except ImportError: + # On CPython, "pip install cffi". On old PyPy's, no chance + pytest.skip("_sqlite3 requires _cffi_backend to be installed") -import pytest from lib_pypy import _sqlite3 -def test_list_ddl(): +def pytest_funcarg__con(request): + con = _sqlite3.connect(':memory:') + request.addfinalizer(lambda: con.close()) + return con + +def test_list_ddl(con): """From issue996. Mostly just looking for lack of exceptions.""" - connection = _sqlite3.connect(':memory:') - cursor = connection.cursor() + cursor = con.cursor() cursor.execute('CREATE TABLE foo (bar INTEGER)') result = list(cursor) assert result == [] @@ -21,8 +30,7 @@ result = list(cursor) assert result == [(42,)] -def test_total_changes_after_close(): - con = _sqlite3.connect(':memory:') +def test_total_changes_after_close(con): con.close() pytest.raises(_sqlite3.ProgrammingError, "con.total_changes") @@ -35,25 +43,22 @@ e = pytest.raises(_sqlite3.ProgrammingError, "con.cursor()") assert '__init__' in e.value.message -def test_cursor_check_init(): +def test_cursor_check_init(con): class Cursor(_sqlite3.Cursor): def __init__(self, name): pass - con = _sqlite3.connect(":memory:") cur = Cursor(con) e = pytest.raises(_sqlite3.ProgrammingError, "cur.execute('select 1')") assert '__init__' in e.value.message -def test_connection_after_close(): - con = _sqlite3.connect(':memory:') +def test_connection_after_close(con): pytest.raises(TypeError, "con()") con.close() # raises ProgrammingError because should check closed before check args pytest.raises(_sqlite3.ProgrammingError, "con()") -def test_cursor_iter(): - con = _sqlite3.connect(':memory:') +def test_cursor_iter(con): cur = con.cursor() with pytest.raises(StopIteration): next(cur) @@ -85,8 +90,7 @@ with pytest.raises(StopIteration): next(cur) -def test_cursor_after_close(): - con = _sqlite3.connect(':memory:') +def test_cursor_after_close(con): cur = con.execute('select 1') cur.close() con.close() @@ -131,11 +135,10 @@ finally: resource.setrlimit(resource.RLIMIT_NOFILE, limit) -def test_on_conflict_rollback_executemany(): +def test_on_conflict_rollback_executemany(con): major, minor, micro = _sqlite3.sqlite_version.split('.') if (int(major), int(minor), int(micro)) < (3, 2, 2): pytest.skip("requires sqlite3 version >= 3.2.2") - con = _sqlite3.connect(":memory:") con.execute("create table foo(x, unique(x) on conflict rollback)") con.execute("insert into foo(x) values (1)") try: @@ -147,10 +150,8 @@ con.commit() except _sqlite3.OperationalError: pytest.fail("_sqlite3 knew nothing about the implicit ROLLBACK") - con.close() -def test_statement_arg_checking(): - con = _sqlite3.connect(':memory:') +def test_statement_arg_checking(con): with pytest.raises(_sqlite3.Warning) as e: con(123) assert str(e.value) == 'SQL is of wrong type. Must be string or unicode.' @@ -164,8 +165,7 @@ con.executescript(123) assert str(e.value) == 'script argument must be unicode or string.' -def test_statement_param_checking(): - con = _sqlite3.connect(':memory:') +def test_statement_param_checking(con): con.execute('create table foo(x)') con.execute('insert into foo(x) values (?)', [2]) con.execute('insert into foo(x) values (?)', (2,)) @@ -183,10 +183,8 @@ with pytest.raises(ValueError) as e: con.execute('insert into foo(x) values (?)', 2) assert str(e.value) == 'parameters are of unsupported type' - con.close() -def test_explicit_begin(): - con = _sqlite3.connect(':memory:') +def test_explicit_begin(con): con.execute('BEGIN') con.execute('BEGIN ') con.execute('BEGIN') @@ -194,31 +192,32 @@ con.execute('BEGIN') con.commit() -def test_row_factory_use(): - con = _sqlite3.connect(':memory:') +def test_row_factory_use(con): con.row_factory = 42 con.execute('select 1') -def test_returning_blob_must_own_memory(): +def test_returning_blob_must_own_memory(con): import gc - con = _sqlite3.connect(":memory:") con.create_function("returnblob", 0, lambda: buffer("blob")) - cur = con.cursor() - cur.execute("select returnblob()") + cur = con.execute("select returnblob()") val = cur.fetchone()[0] for i in range(5): gc.collect() got = (val[0], val[1], val[2], val[3]) assert got == ('b', 'l', 'o', 'b') + # in theory 'val' should be a read-write buffer + # but it's not right now + pytest.skip("in theory 'val' should be a read-write buffer") + val[1] = 'X' + got = (val[0], val[1], val[2], val[3]) + assert got == ('b', 'X', 'o', 'b') -def test_description_after_fetchall(): - con = _sqlite3.connect(":memory:") +def test_description_after_fetchall(con): cur = con.cursor() cur.execute("select 42").fetchall() assert cur.description is not None -def test_executemany_lastrowid(): - con = _sqlite3.connect(':memory:') +def test_executemany_lastrowid(con): cur = con.cursor() cur.execute("create table test(a)") cur.executemany("insert into test values (?)", [[1], [2], [3]]) diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py --- a/pypy/objspace/std/typeobject.py +++ b/pypy/objspace/std/typeobject.py @@ -4,6 +4,7 @@ from pypy.interpreter.function import Function, StaticMethod from pypy.interpreter.typedef import weakref_descr, GetSetProperty,\ descr_get_dict +from pypy.interpreter.astcompiler.misc import mangle from pypy.objspace.std.model import W_Object from pypy.objspace.std.register_all import register_all from pypy.objspace.std.stdtypedef import std_dict_descr, issubtypedef, Member @@ -26,34 +27,6 @@ return w_value.w_value return w_value -# from compiler/misc.py - -MANGLE_LEN = 256 # magic constant from compile.c - -def _mangle(name, klass): - if not name.startswith('__'): - return name - if len(name) + 2 >= MANGLE_LEN: - return name - if name.endswith('__'): - return name - try: - i = 0 - while klass[i] == '_': - i = i + 1 - except IndexError: - return name - klass = klass[i:] - - tlen = len(klass) + len(name) - if tlen > MANGLE_LEN: - end = len(klass) + MANGLE_LEN-tlen - if end < 0: - klass = '' # annotator hint - else: - klass = klass[:end] - - return "_%s%s" % (klass, name) class VersionTag(object): pass @@ -989,7 +962,7 @@ raise OperationError(space.w_TypeError, space.wrap('__slots__ must be identifiers')) # create member - slot_name = _mangle(slot_name, w_self.name) + slot_name = mangle(slot_name, w_self.name) if slot_name not in w_self.dict_w: # Force interning of slot names. slot_name = space.str_w(space.new_interned_str(slot_name)) diff --git a/pypy/tool/release/package.py b/pypy/tool/release/package.py --- a/pypy/tool/release/package.py +++ b/pypy/tool/release/package.py @@ -67,7 +67,8 @@ 'Bogus path: %r does not exist (see docstring for more info)' % (os.path.dirname(str(pypy_c)),)) subprocess.check_call([str(pypy_c), '-c', 'import _sqlite3']) - subprocess.check_call([str(pypy_c), '-c', 'import _curses']) + if not sys.platform == 'win32': + subprocess.check_call([str(pypy_c), '-c', 'import _curses']) if sys.platform == 'win32' and not rename_pypy_c.lower().endswith('.exe'): rename_pypy_c += '.exe' binaries = [(pypy_c, rename_pypy_c)] diff --git a/rpython/config/translationoption.py b/rpython/config/translationoption.py --- a/rpython/config/translationoption.py +++ b/rpython/config/translationoption.py @@ -115,7 +115,7 @@ ("translation.gcrootfinder", DEFL_ROOTFINDER_WITHJIT), ("translation.list_comprehension_operations", True)]), ChoiceOption("jit_backend", "choose the backend for the JIT", - ["auto", "x86", "x86-without-sse2", 'armv7'], + ["auto", "x86", "x86-without-sse2", 'armv7', 'armv7hf', 'armv6hf'], default="auto", cmdline="--jit-backend"), ChoiceOption("jit_profiler", "integrate profiler support into the JIT", ["off", "oprofile"], diff --git a/rpython/flowspace/framestate.py b/rpython/flowspace/framestate.py --- a/rpython/flowspace/framestate.py +++ b/rpython/flowspace/framestate.py @@ -2,7 +2,7 @@ from rpython.rlib.unroll import SpecTag -class FrameState: +class FrameState(object): def __init__(self, mergeable, blocklist, next_instr): self.mergeable = mergeable self.blocklist = blocklist @@ -63,6 +63,7 @@ class UnionError(Exception): "The two states should be merged." + def union(w1, w2): "Union of two variables or constants." if w1 is None or w2 is None: @@ -117,7 +118,7 @@ key = unroller.__class__, len(vars) try: tag = PICKLE_TAGS[key] - except: + except KeyError: tag = PICKLE_TAGS[key] = Constant(PickleTag()) UNPICKLE_TAGS[tag] = key lst[i:i + 1] = [tag] + vars diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -1035,7 +1035,8 @@ assert 0, 'unsupported case' def _mov_stack_to_loc(self, prev_loc, loc, cond=c.AL): - helper = self._regalloc.get_free_reg() + # disabled for now, has side effects in combination with remap_frame_layout when called from a jump + helper = None # self._regalloc.get_free_reg() if loc.is_reg(): assert prev_loc.type != FLOAT, 'trying to load from an \ incompatible location into a core register' diff --git a/rpython/jit/backend/arm/test/test_runner.py b/rpython/jit/backend/arm/test/test_runner.py --- a/rpython/jit/backend/arm/test/test_runner.py +++ b/rpython/jit/backend/arm/test/test_runner.py @@ -34,11 +34,11 @@ else: bridge_loop_instructions = ['ldr', 'mov', 'nop', 'nop', 'nop', 'cmp', 'bge', 'push', 'ldr', 'mov', - '', # inline constant + '*', # inline constant 'push', 'ldr', 'mov', - 'ldrsblt', #inline constant (decodes as instruction) + '*', # inline constant 'blx', 'ldr', 'mov', - '', # inline constant + '*', # inline constant 'bx'] def get_cpu(self): diff --git a/rpython/jit/backend/test/runner_test.py b/rpython/jit/backend/test/runner_test.py --- a/rpython/jit/backend/test/runner_test.py +++ b/rpython/jit/backend/test/runner_test.py @@ -3475,6 +3475,8 @@ def checkops(mc, ops): assert len(mc) == len(ops) for i in range(len(mc)): + if ops[i] == '*': + continue # ingore ops marked as '*', i.e. inline constants assert mc[i].split("\t")[2].startswith(ops[i]) data = ctypes.string_at(info.asmaddr, info.asmlen) diff --git a/rpython/jit/metainterp/blackhole.py b/rpython/jit/metainterp/blackhole.py --- a/rpython/jit/metainterp/blackhole.py +++ b/rpython/jit/metainterp/blackhole.py @@ -857,6 +857,8 @@ @arguments("r") def bhimpl_debug_fatalerror(msg): + from rpython.rtyper.lltypesystem import rstr + msg = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), msg) llop.debug_fatalerror(lltype.Void, msg) @arguments("r", "i", "i", "i", "i") diff --git a/rpython/jit/metainterp/optimizeopt/rewrite.py b/rpython/jit/metainterp/optimizeopt/rewrite.py --- a/rpython/jit/metainterp/optimizeopt/rewrite.py +++ b/rpython/jit/metainterp/optimizeopt/rewrite.py @@ -456,7 +456,7 @@ [op.getarg(1), ConstInt(index + source_start)], resbox, descr=arraydescr) - self.optimizer.propagate_forward(newop) + self.optimizer.send_extra_operation(newop) val = self.getvalue(resbox) if dest_value.is_virtual(): dest_value.setitem(index + dest_start, val) diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py --- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py @@ -7621,10 +7621,9 @@ """ expected = """ [i1, i2] + # operations are not all removed because this new_array() is var-sized p1 = new_array(i1, descr=arraydescr) - # operations are not all removed because this new_array() is var-sized - # unsure exactly which operations should be left, but right now it's - # really buggy + setarrayitem_gc(p1, 0, i2, descr=arraydescr) jump(i1, i2) """ self.optimize_loop(ops, expected) diff --git a/rpython/jit/metainterp/test/test_blackhole.py b/rpython/jit/metainterp/test/test_blackhole.py --- a/rpython/jit/metainterp/test/test_blackhole.py +++ b/rpython/jit/metainterp/test/test_blackhole.py @@ -228,5 +228,15 @@ assert BlackholeInterpreter.bhimpl_int_lshift.im_func(100, 3) == 100<<3 assert BlackholeInterpreter.bhimpl_int_rshift.im_func(100, 3) == 100>>3 - assert BlackholeInterpreter.bhimpl_uint_rshift.im_func(100, 3) == 100>>3 - + assert BlackholeInterpreter.bhimpl_uint_rshift.im_func(100, 3) == 100>>3 + +def test_debug_fatalerror(): + from rpython.rtyper.lltypesystem import lltype, llmemory, rstr + from rpython.rtyper.llinterp import LLFatalError + msg = rstr.mallocstr(1) + msg.chars[0] = "!" + msg = lltype.cast_opaque_ptr(llmemory.GCREF, msg) + e = py.test.raises(LLFatalError, + BlackholeInterpreter.bhimpl_debug_fatalerror.im_func, + msg) + assert str(e.value) == '!' diff --git a/rpython/jit/tl/tla/tla_assembler.py b/rpython/jit/tl/tla/tla_assembler.py --- a/rpython/jit/tl/tla/tla_assembler.py +++ b/rpython/jit/tl/tla/tla_assembler.py @@ -2,8 +2,8 @@ import sys import py +from rpython.jit.tl.tla.test_tla import assemble py.path.local(__file__) -from rpython.jit.tl.tla.test_tla import assemble def usage(): print >> sys.stderr, 'Usage: tla_assembler.py filename.tla.py' diff --git a/rpython/rtyper/lltypesystem/lloperation.py b/rpython/rtyper/lltypesystem/lloperation.py --- a/rpython/rtyper/lltypesystem/lloperation.py +++ b/rpython/rtyper/lltypesystem/lloperation.py @@ -555,7 +555,7 @@ 'debug_offset': LLOp(canrun=True), 'debug_flush': LLOp(canrun=True), 'debug_assert': LLOp(tryfold=True), - 'debug_fatalerror': LLOp(), + 'debug_fatalerror': LLOp(canrun=True), 'debug_llinterpcall': LLOp(canraise=(Exception,)), # Python func call 'res=arg[0](*arg[1:])' # in backends, abort() or whatever is fine diff --git a/rpython/rtyper/lltypesystem/lltype.py b/rpython/rtyper/lltypesystem/lltype.py --- a/rpython/rtyper/lltypesystem/lltype.py +++ b/rpython/rtyper/lltypesystem/lltype.py @@ -503,7 +503,7 @@ return obj def __init__(self, OF, length, **kwds): - if hasattr(self, '_name'): + if '_name' in self.__dict__: assert self.OF == OF assert self.length == length return diff --git a/rpython/rtyper/lltypesystem/opimpl.py b/rpython/rtyper/lltypesystem/opimpl.py --- a/rpython/rtyper/lltypesystem/opimpl.py +++ b/rpython/rtyper/lltypesystem/opimpl.py @@ -654,6 +654,13 @@ from rpython.rlib.rtimer import read_timestamp return read_timestamp() +def op_debug_fatalerror(ll_msg): + from rpython.rtyper.lltypesystem import lltype, rstr + from rpython.rtyper.llinterp import LLFatalError + assert lltype.typeOf(ll_msg) == lltype.Ptr(rstr.STR) + msg = ''.join(ll_msg.chars) + raise LLFatalError(msg) + # ____________________________________________________________ def get_op_impl(opname): diff --git a/rpython/rtyper/rptr.py b/rpython/rtyper/rptr.py --- a/rpython/rtyper/rptr.py +++ b/rpython/rtyper/rptr.py @@ -234,6 +234,7 @@ class InteriorPtrRepr(Repr): def __init__(self, ptrtype): assert isinstance(ptrtype, lltype.InteriorPtr) + self._ptrtype = ptrtype # for debugging self.v_offsets = [] numitemoffsets = 0 for i, offset in enumerate(ptrtype.offsets): diff --git a/rpython/translator/c/gcc/test/elf64/track_basic_argument_registers.s b/rpython/translator/c/gcc/test/elf64/track_basic_argument_registers.s --- a/rpython/translator/c/gcc/test/elf64/track_basic_argument_registers.s +++ b/rpython/translator/c/gcc/test/elf64/track_basic_argument_registers.s @@ -25,7 +25,8 @@ /* GCROOT -48(%rbp) */ movq -24(%rbp), %rax leave - ret + ; try out a "rep ret" instead of just a "ret", for bad reasons + rep ret .cfi_endproc .LFE0: .size foobar, .-foobar diff --git a/rpython/translator/c/gcc/trackgcroot.py b/rpython/translator/c/gcc/trackgcroot.py --- a/rpython/translator/c/gcc/trackgcroot.py +++ b/rpython/translator/c/gcc/trackgcroot.py @@ -664,6 +664,12 @@ def visit_ret(self, line): return InsnRet(self.CALLEE_SAVE_REGISTERS) + def visit_rep(self, line): + # 'rep ret': bad reasons for this bogus 'rep' here + if line.split()[:2] == ['rep', 'ret']: + return self.visit_ret(line) + return [] + def visit_jmp(self, line): tablelabels = [] match = self.r_jmp_switch.match(line) diff --git a/rpython/translator/goal/translate.py b/rpython/translator/goal/translate.py --- a/rpython/translator/goal/translate.py +++ b/rpython/translator/goal/translate.py @@ -50,7 +50,7 @@ return result translate_optiondescr = OptionDescription("translate", "XXX", [ - StrOption("targetspec", "XXX", default='../../../pypy/goal/targetpypystandalone', + StrOption("targetspec", "XXX", default='targetpypystandalone', cmdline=None), ChoiceOption("opt", "optimization level", OPT_LEVELS, default=DEFAULT_OPT_LEVEL, diff --git a/rpython/translator/platform/arm.py b/rpython/translator/platform/arm.py --- a/rpython/translator/platform/arm.py +++ b/rpython/translator/platform/arm.py @@ -47,11 +47,12 @@ return ExecutionResult(returncode, stdout, stderr) def include_dirs_for_libffi(self): - return [SB2 + '/usr/include/arm-linux-gnueabi/'] + return [SB2 + '/usr/include/arm-linux-gnueabi/', + SB2 + '/usr/include/arm-linux-gnueabihf/'] def library_dirs_for_libffi(self): - # on the other hand, library lands in usual place... - return [] + return [SB2 + '/usr/lib/arm-linux-gnueabi/', + SB2 + '/usr/lib/arm-linux-gnueabihf/'] def execute_makefile(self, path_to_makefile, extra_opts=[]): if isinstance(path_to_makefile, GnuMakefile): From noreply at buildbot.pypy.org Tue Apr 9 00:42:06 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Tue, 9 Apr 2013 00:42:06 +0200 (CEST) Subject: [pypy-commit] pypy py3k: int_typedef -> long_typedef Message-ID: <20130408224206.8E5D41C0723@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63158:561319b8dde4 Date: 2013-04-08 15:41 -0700 http://bitbucket.org/pypy/pypy/changeset/561319b8dde4/ Log: int_typedef -> long_typedef diff --git a/pypy/module/micronumpy/interp_boxes.py b/pypy/module/micronumpy/interp_boxes.py --- a/pypy/module/micronumpy/interp_boxes.py +++ b/pypy/module/micronumpy/interp_boxes.py @@ -5,15 +5,15 @@ from pypy.objspace.std.floattype import float_typedef from pypy.objspace.std.stringtype import str_typedef from pypy.objspace.std.unicodetype import unicode_typedef, unicode_from_object -from pypy.objspace.std.inttype import int_typedef +from pypy.objspace.std.longtype import long_typedef from pypy.objspace.std.complextype import complex_typedef from rpython.rlib.rarithmetic import LONG_BIT from rpython.rtyper.lltypesystem import rffi from rpython.tool.sourcetools import func_with_new_name from pypy.module.micronumpy.arrayimpl.voidbox import VoidBoxStorage -MIXIN_32 = (int_typedef,) if LONG_BIT == 32 else () -MIXIN_64 = (int_typedef,) if LONG_BIT == 64 else () +MIXIN_32 = (long_typedef,) if LONG_BIT == 32 else () +MIXIN_64 = (long_typedef,) if LONG_BIT == 64 else () # Is this the proper place for this? ENABLED_LONG_DOUBLE = False From noreply at buildbot.pypy.org Tue Apr 9 05:18:46 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Tue, 9 Apr 2013 05:18:46 +0200 (CEST) Subject: [pypy-commit] pypy default: fix 341a34c7d62f Message-ID: <20130409031846.4395F1C010B@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63159:3781a93fc433 Date: 2013-04-08 23:18 -0400 http://bitbucket.org/pypy/pypy/changeset/3781a93fc433/ Log: fix 341a34c7d62f diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -258,6 +258,7 @@ """) libname = 'sqlite3' if sys.platform == 'win32': + import os _libname = os.path.join(os.path.dirname(sys.executable), libname) if os.path.exists(_libname + '.dll'): libname = _libname From noreply at buildbot.pypy.org Tue Apr 9 11:02:40 2013 From: noreply at buildbot.pypy.org (bivab) Date: Tue, 9 Apr 2013 11:02:40 +0200 (CEST) Subject: [pypy-commit] pypy default: update tests to reflect currently disabled use of free regs list items as temps Message-ID: <20130409090240.B94451C02E8@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63160:d7a9c0c2825c Date: 2013-04-09 11:01 +0200 http://bitbucket.org/pypy/pypy/changeset/d7a9c0c2825c/ Log: update tests to reflect currently disabled use of free regs list items as temps diff --git a/rpython/jit/backend/arm/test/test_regalloc_mov.py b/rpython/jit/backend/arm/test/test_regalloc_mov.py --- a/rpython/jit/backend/arm/test/test_regalloc_mov.py +++ b/rpython/jit/backend/arm/test/test_regalloc_mov.py @@ -174,8 +174,11 @@ s = stack(8191) r6 = r(6) expected = [ - mi('gen_load_int', 'helper', s.value, cond=AL), - mi('LDR_rr', r6.value, fp.value, 'helper', cond=AL)] + mi('PUSH', [lr.value], cond=AL), + mi('gen_load_int', lr.value, 32940, cond=AL), + mi('LDR_rr', r6.value, fp.value, lr.value, cond=AL), + mi('POP', [lr.value], cond=AL), + ] self.mov(s, r6, expected) def test_mov_float_imm_to_vfp_reg(self): @@ -422,8 +425,11 @@ def test_push_big_stack(self): s = stack(1025) - e = [mi('gen_load_int', 'helper', s.value, cond=AL), - mi('LDR_rr', ip.value, fp.value, 'helper', cond=AL), + e = [ + mi('PUSH', [lr.value], cond=AL), + mi('gen_load_int', lr.value, s.value, cond=AL), + mi('LDR_rr', ip.value, fp.value, lr.value, cond=AL), + mi('POP', [lr.value], cond=AL), mi('PUSH', [ip.value], cond=AL) ] self.push(s, e) @@ -444,9 +450,11 @@ def test_push_large_stackfloat(self): sf = stack_float(100) e = [ - mi('gen_load_int', 'helper', sf.value, cond=AL), - mi('ADD_rr', 'helper', fp.value, 'helper', cond=AL), - mi('VLDR', vfp_ip.value, 'helper', cond=AL), + mi('PUSH', [ip.value], cond=AL), + mi('gen_load_int', ip.value, sf.value, cond=AL), + mi('ADD_rr', ip.value, fp.value, ip.value, cond=AL), + mi('VLDR', vfp_ip.value, ip.value, cond=AL), + mi('POP', [ip.value], cond=AL), mi('VPUSH', [vfp_ip.value], cond=AL), ] self.push(sf, e) From noreply at buildbot.pypy.org Tue Apr 9 11:24:14 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Tue, 9 Apr 2013 11:24:14 +0200 (CEST) Subject: [pypy-commit] pypy vendor/stdlib: update python 2 stdlib to v2.7.4 Message-ID: <20130409092414.147DD1C0723@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: vendor/stdlib Changeset: r63161:67ce647ac7f3 Date: 2013-04-09 02:57 -0400 http://bitbucket.org/pypy/pypy/changeset/67ce647ac7f3/ Log: update python 2 stdlib to v2.7.4 diff too long, truncating to 2000 out of 25899 lines diff --git a/lib-python/2.7/BaseHTTPServer.py b/lib-python/2.7/BaseHTTPServer.py --- a/lib-python/2.7/BaseHTTPServer.py +++ b/lib-python/2.7/BaseHTTPServer.py @@ -447,13 +447,13 @@ specified as subsequent arguments (it's just like printf!). - The client host and current date/time are prefixed to - every message. + The client ip address and current date/time are prefixed to every + message. """ sys.stderr.write("%s - - [%s] %s\n" % - (self.address_string(), + (self.client_address[0], self.log_date_time_string(), format%args)) diff --git a/lib-python/2.7/CGIHTTPServer.py b/lib-python/2.7/CGIHTTPServer.py --- a/lib-python/2.7/CGIHTTPServer.py +++ b/lib-python/2.7/CGIHTTPServer.py @@ -84,9 +84,11 @@ path begins with one of the strings in self.cgi_directories (and the next character is a '/' or the end of the string). """ - splitpath = _url_collapse_path_split(self.path) - if splitpath[0] in self.cgi_directories: - self.cgi_info = splitpath + collapsed_path = _url_collapse_path(self.path) + dir_sep = collapsed_path.find('/', 1) + head, tail = collapsed_path[:dir_sep], collapsed_path[dir_sep+1:] + if head in self.cgi_directories: + self.cgi_info = head, tail return True return False @@ -298,44 +300,46 @@ self.log_message("CGI script exited OK") -# TODO(gregory.p.smith): Move this into an appropriate library. -def _url_collapse_path_split(path): +def _url_collapse_path(path): """ Given a URL path, remove extra '/'s and '.' path elements and collapse - any '..' references. + any '..' references and returns a colllapsed path. Implements something akin to RFC-2396 5.2 step 6 to parse relative paths. + The utility of this function is limited to is_cgi method and helps + preventing some security attacks. Returns: A tuple of (head, tail) where tail is everything after the final / and head is everything before it. Head will always start with a '/' and, if it contains anything else, never have a trailing '/'. Raises: IndexError if too many '..' occur within the path. + """ # Similar to os.path.split(os.path.normpath(path)) but specific to URL # path semantics rather than local operating system semantics. - path_parts = [] - for part in path.split('/'): - if part == '.': - path_parts.append('') - else: - path_parts.append(part) - # Filter out blank non trailing parts before consuming the '..'. - path_parts = [part for part in path_parts[:-1] if part] + path_parts[-1:] + path_parts = path.split('/') + head_parts = [] + for part in path_parts[:-1]: + if part == '..': + head_parts.pop() # IndexError if more '..' than prior parts + elif part and part != '.': + head_parts.append( part ) if path_parts: tail_part = path_parts.pop() + if tail_part: + if tail_part == '..': + head_parts.pop() + tail_part = '' + elif tail_part == '.': + tail_part = '' else: tail_part = '' - head_parts = [] - for part in path_parts: - if part == '..': - head_parts.pop() - else: - head_parts.append(part) - if tail_part and tail_part == '..': - head_parts.pop() - tail_part = '' - return ('/' + '/'.join(head_parts), tail_part) + + splitpath = ('/' + '/'.join(head_parts), tail_part) + collapsed_path = "/".join(splitpath) + + return collapsed_path nobody = None diff --git a/lib-python/2.7/Cookie.py b/lib-python/2.7/Cookie.py --- a/lib-python/2.7/Cookie.py +++ b/lib-python/2.7/Cookie.py @@ -390,7 +390,7 @@ from time import gmtime, time now = time() year, month, day, hh, mm, ss, wd, y, z = gmtime(now + future) - return "%s, %02d-%3s-%4d %02d:%02d:%02d GMT" % \ + return "%s, %02d %3s %4d %02d:%02d:%02d GMT" % \ (weekdayname[wd], day, monthname[month], year, hh, mm, ss) @@ -539,7 +539,7 @@ r"(?P" # Start of group 'val' r'"(?:[^\\"]|\\.)*"' # Any doublequoted string r"|" # or - r"\w{3},\s[\w\d-]{9,11}\s[\d:]{8}\sGMT" # Special case for "expires" attr + r"\w{3},\s[\s\w\d-]{9,11}\s[\d:]{8}\sGMT" # Special case for "expires" attr r"|" # or ""+ _LegalCharsPatt +"*" # Any word or empty string r")" # End of group 'val' diff --git a/lib-python/2.7/HTMLParser.py b/lib-python/2.7/HTMLParser.py --- a/lib-python/2.7/HTMLParser.py +++ b/lib-python/2.7/HTMLParser.py @@ -22,13 +22,13 @@ starttagopen = re.compile('<[a-zA-Z]') piclose = re.compile('>') commentclose = re.compile(r'--\s*>') -tagfind = re.compile('[a-zA-Z][-.a-zA-Z0-9:_]*') +tagfind = re.compile('([a-zA-Z][-.a-zA-Z0-9:_]*)(?:\s|/(?!>))*') # see http://www.w3.org/TR/html5/tokenization.html#tag-open-state # and http://www.w3.org/TR/html5/tokenization.html#tag-name-state tagfind_tolerant = re.compile('[a-zA-Z][^\t\n\r\f />\x00]*') attrfind = re.compile( - r'[\s/]*((?<=[\'"\s/])[^\s/>][^\s/=>]*)(\s*=+\s*' + r'((?<=[\'"\s/])[^\s/>][^\s/=>]*)(\s*=+\s*' r'(\'[^\']*\'|"[^"]*"|(?![\'"])[^>\s]*))?(?:\s|/(?!>))*') locatestarttagend = re.compile(r""" @@ -289,7 +289,7 @@ match = tagfind.match(rawdata, i+1) assert match, 'unexpected call to parse_starttag()' k = match.end() - self.lasttag = tag = rawdata[i+1:k].lower() + self.lasttag = tag = match.group(1).lower() while k < endpos: m = attrfind.match(rawdata, k) diff --git a/lib-python/2.7/SimpleXMLRPCServer.py b/lib-python/2.7/SimpleXMLRPCServer.py --- a/lib-python/2.7/SimpleXMLRPCServer.py +++ b/lib-python/2.7/SimpleXMLRPCServer.py @@ -1,4 +1,4 @@ -"""Simple XML-RPC Server. +r"""Simple XML-RPC Server. This module can be used to create simple XML-RPC servers by creating a server and either installing functions, a diff --git a/lib-python/2.7/SocketServer.py b/lib-python/2.7/SocketServer.py --- a/lib-python/2.7/SocketServer.py +++ b/lib-python/2.7/SocketServer.py @@ -133,6 +133,7 @@ import select import sys import os +import errno try: import threading except ImportError: @@ -147,6 +148,15 @@ "ThreadingUnixStreamServer", "ThreadingUnixDatagramServer"]) +def _eintr_retry(func, *args): + """restart a system call interrupted by EINTR""" + while True: + try: + return func(*args) + except (OSError, select.error) as e: + if e.args[0] != errno.EINTR: + raise + class BaseServer: """Base class for server classes. @@ -222,7 +232,8 @@ # connecting to the socket to wake this up instead of # polling. Polling reduces our responsiveness to a # shutdown request and wastes cpu at all other times. - r, w, e = select.select([self], [], [], poll_interval) + r, w, e = _eintr_retry(select.select, [self], [], [], + poll_interval) if self in r: self._handle_request_noblock() finally: @@ -262,7 +273,7 @@ timeout = self.timeout elif self.timeout is not None: timeout = min(timeout, self.timeout) - fd_sets = select.select([self], [], [], timeout) + fd_sets = _eintr_retry(select.select, [self], [], [], timeout) if not fd_sets[0]: self.handle_timeout() return @@ -690,7 +701,12 @@ def finish(self): if not self.wfile.closed: - self.wfile.flush() + try: + self.wfile.flush() + except socket.error: + # An final socket error may have occurred here, such as + # the local error ECONNABORTED. + pass self.wfile.close() self.rfile.close() diff --git a/lib-python/2.7/StringIO.py b/lib-python/2.7/StringIO.py --- a/lib-python/2.7/StringIO.py +++ b/lib-python/2.7/StringIO.py @@ -158,7 +158,7 @@ newpos = self.len else: newpos = i+1 - if length is not None and length > 0: + if length is not None and length >= 0: if self.pos + length < newpos: newpos = self.pos + length r = self.buf[self.pos:newpos] diff --git a/lib-python/2.7/_LWPCookieJar.py b/lib-python/2.7/_LWPCookieJar.py --- a/lib-python/2.7/_LWPCookieJar.py +++ b/lib-python/2.7/_LWPCookieJar.py @@ -48,7 +48,7 @@ class LWPCookieJar(FileCookieJar): """ - The LWPCookieJar saves a sequence of"Set-Cookie3" lines. + The LWPCookieJar saves a sequence of "Set-Cookie3" lines. "Set-Cookie3" is the format used by the libwww-perl libary, not known to be compatible with any browser, but which is easy to read and doesn't lose information about RFC 2965 cookies. @@ -60,7 +60,7 @@ """ def as_lwp_str(self, ignore_discard=True, ignore_expires=True): - """Return cookies as a string of "\n"-separated "Set-Cookie3" headers. + """Return cookies as a string of "\\n"-separated "Set-Cookie3" headers. ignore_discard and ignore_expires: see docstring for FileCookieJar.save diff --git a/lib-python/2.7/__future__.py b/lib-python/2.7/__future__.py --- a/lib-python/2.7/__future__.py +++ b/lib-python/2.7/__future__.py @@ -112,7 +112,7 @@ CO_FUTURE_DIVISION) absolute_import = _Feature((2, 5, 0, "alpha", 1), - (2, 7, 0, "alpha", 0), + (3, 0, 0, "alpha", 0), CO_FUTURE_ABSOLUTE_IMPORT) with_statement = _Feature((2, 5, 0, "alpha", 1), diff --git a/lib-python/2.7/_osx_support.py b/lib-python/2.7/_osx_support.py new file mode 100644 --- /dev/null +++ b/lib-python/2.7/_osx_support.py @@ -0,0 +1,488 @@ +"""Shared OS X support functions.""" + +import os +import re +import sys + +__all__ = [ + 'compiler_fixup', + 'customize_config_vars', + 'customize_compiler', + 'get_platform_osx', +] + +# configuration variables that may contain universal build flags, +# like "-arch" or "-isdkroot", that may need customization for +# the user environment +_UNIVERSAL_CONFIG_VARS = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS', 'BASECFLAGS', + 'BLDSHARED', 'LDSHARED', 'CC', 'CXX', + 'PY_CFLAGS', 'PY_LDFLAGS', 'PY_CPPFLAGS', + 'PY_CORE_CFLAGS') + +# configuration variables that may contain compiler calls +_COMPILER_CONFIG_VARS = ('BLDSHARED', 'LDSHARED', 'CC', 'CXX') + +# prefix added to original configuration variable names +_INITPRE = '_OSX_SUPPORT_INITIAL_' + + +def _find_executable(executable, path=None): + """Tries to find 'executable' in the directories listed in 'path'. + + A string listing directories separated by 'os.pathsep'; defaults to + os.environ['PATH']. Returns the complete filename or None if not found. + """ + if path is None: + path = os.environ['PATH'] + + paths = path.split(os.pathsep) + base, ext = os.path.splitext(executable) + + if (sys.platform == 'win32' or os.name == 'os2') and (ext != '.exe'): + executable = executable + '.exe' + + if not os.path.isfile(executable): + for p in paths: + f = os.path.join(p, executable) + if os.path.isfile(f): + # the file exists, we have a shot at spawn working + return f + return None + else: + return executable + + +def _read_output(commandstring): + """Output from succesful command execution or None""" + # Similar to os.popen(commandstring, "r").read(), + # but without actually using os.popen because that + # function is not usable during python bootstrap. + # tempfile is also not available then. + import contextlib + try: + import tempfile + fp = tempfile.NamedTemporaryFile() + except ImportError: + fp = open("/tmp/_osx_support.%s"%( + os.getpid(),), "w+b") + + with contextlib.closing(fp) as fp: + cmd = "%s 2>/dev/null >'%s'" % (commandstring, fp.name) + return fp.read().decode('utf-8').strip() if not os.system(cmd) else None + + +def _find_build_tool(toolname): + """Find a build tool on current path or using xcrun""" + return (_find_executable(toolname) + or _read_output("/usr/bin/xcrun -find %s" % (toolname,)) + or '' + ) + +_SYSTEM_VERSION = None + +def _get_system_version(): + """Return the OS X system version as a string""" + # Reading this plist is a documented way to get the system + # version (see the documentation for the Gestalt Manager) + # We avoid using platform.mac_ver to avoid possible bootstrap issues during + # the build of Python itself (distutils is used to build standard library + # extensions). + + global _SYSTEM_VERSION + + if _SYSTEM_VERSION is None: + _SYSTEM_VERSION = '' + try: + f = open('/System/Library/CoreServices/SystemVersion.plist') + except IOError: + # We're on a plain darwin box, fall back to the default + # behaviour. + pass + else: + try: + m = re.search(r'ProductUserVisibleVersion\s*' + r'(.*?)', f.read()) + finally: + f.close() + if m is not None: + _SYSTEM_VERSION = '.'.join(m.group(1).split('.')[:2]) + # else: fall back to the default behaviour + + return _SYSTEM_VERSION + +def _remove_original_values(_config_vars): + """Remove original unmodified values for testing""" + # This is needed for higher-level cross-platform tests of get_platform. + for k in list(_config_vars): + if k.startswith(_INITPRE): + del _config_vars[k] + +def _save_modified_value(_config_vars, cv, newvalue): + """Save modified and original unmodified value of configuration var""" + + oldvalue = _config_vars.get(cv, '') + if (oldvalue != newvalue) and (_INITPRE + cv not in _config_vars): + _config_vars[_INITPRE + cv] = oldvalue + _config_vars[cv] = newvalue + +def _supports_universal_builds(): + """Returns True if universal builds are supported on this system""" + # As an approximation, we assume that if we are running on 10.4 or above, + # then we are running with an Xcode environment that supports universal + # builds, in particular -isysroot and -arch arguments to the compiler. This + # is in support of allowing 10.4 universal builds to run on 10.3.x systems. + + osx_version = _get_system_version() + if osx_version: + try: + osx_version = tuple(int(i) for i in osx_version.split('.')) + except ValueError: + osx_version = '' + return bool(osx_version >= (10, 4)) if osx_version else False + + +def _find_appropriate_compiler(_config_vars): + """Find appropriate C compiler for extension module builds""" + + # Issue #13590: + # The OSX location for the compiler varies between OSX + # (or rather Xcode) releases. With older releases (up-to 10.5) + # the compiler is in /usr/bin, with newer releases the compiler + # can only be found inside Xcode.app if the "Command Line Tools" + # are not installed. + # + # Futhermore, the compiler that can be used varies between + # Xcode releases. Upto Xcode 4 it was possible to use 'gcc-4.2' + # as the compiler, after that 'clang' should be used because + # gcc-4.2 is either not present, or a copy of 'llvm-gcc' that + # miscompiles Python. + + # skip checks if the compiler was overriden with a CC env variable + if 'CC' in os.environ: + return _config_vars + + # The CC config var might contain additional arguments. + # Ignore them while searching. + cc = oldcc = _config_vars['CC'].split()[0] + if not _find_executable(cc): + # Compiler is not found on the shell search PATH. + # Now search for clang, first on PATH (if the Command LIne + # Tools have been installed in / or if the user has provided + # another location via CC). If not found, try using xcrun + # to find an uninstalled clang (within a selected Xcode). + + # NOTE: Cannot use subprocess here because of bootstrap + # issues when building Python itself (and os.popen is + # implemented on top of subprocess and is therefore not + # usable as well) + + cc = _find_build_tool('clang') + + elif os.path.basename(cc).startswith('gcc'): + # Compiler is GCC, check if it is LLVM-GCC + data = _read_output("'%s' --version" + % (cc.replace("'", "'\"'\"'"),)) + if 'llvm-gcc' in data: + # Found LLVM-GCC, fall back to clang + cc = _find_build_tool('clang') + + if not cc: + raise SystemError( + "Cannot locate working compiler") + + if cc != oldcc: + # Found a replacement compiler. + # Modify config vars using new compiler, if not already explictly + # overriden by an env variable, preserving additional arguments. + for cv in _COMPILER_CONFIG_VARS: + if cv in _config_vars and cv not in os.environ: + cv_split = _config_vars[cv].split() + cv_split[0] = cc if cv != 'CXX' else cc + '++' + _save_modified_value(_config_vars, cv, ' '.join(cv_split)) + + return _config_vars + + +def _remove_universal_flags(_config_vars): + """Remove all universal build arguments from config vars""" + + for cv in _UNIVERSAL_CONFIG_VARS: + # Do not alter a config var explicitly overriden by env var + if cv in _config_vars and cv not in os.environ: + flags = _config_vars[cv] + flags = re.sub('-arch\s+\w+\s', ' ', flags) + flags = re.sub('-isysroot [^ \t]*', ' ', flags) + _save_modified_value(_config_vars, cv, flags) + + return _config_vars + + +def _remove_unsupported_archs(_config_vars): + """Remove any unsupported archs from config vars""" + # Different Xcode releases support different sets for '-arch' + # flags. In particular, Xcode 4.x no longer supports the + # PPC architectures. + # + # This code automatically removes '-arch ppc' and '-arch ppc64' + # when these are not supported. That makes it possible to + # build extensions on OSX 10.7 and later with the prebuilt + # 32-bit installer on the python.org website. + + # skip checks if the compiler was overriden with a CC env variable + if 'CC' in os.environ: + return _config_vars + + if re.search('-arch\s+ppc', _config_vars['CFLAGS']) is not None: + # NOTE: Cannot use subprocess here because of bootstrap + # issues when building Python itself + status = os.system("'%s' -arch ppc -x c /dev/null 2>/dev/null"%( + _config_vars['CC'].replace("'", "'\"'\"'"),)) + # The Apple compiler drivers return status 255 if no PPC + if (status >> 8) == 255: + # Compiler doesn't support PPC, remove the related + # '-arch' flags if not explicitly overridden by an + # environment variable + for cv in _UNIVERSAL_CONFIG_VARS: + if cv in _config_vars and cv not in os.environ: + flags = _config_vars[cv] + flags = re.sub('-arch\s+ppc\w*\s', ' ', flags) + _save_modified_value(_config_vars, cv, flags) + + return _config_vars + + +def _override_all_archs(_config_vars): + """Allow override of all archs with ARCHFLAGS env var""" + # NOTE: This name was introduced by Apple in OSX 10.5 and + # is used by several scripting languages distributed with + # that OS release. + if 'ARCHFLAGS' in os.environ: + arch = os.environ['ARCHFLAGS'] + for cv in _UNIVERSAL_CONFIG_VARS: + if cv in _config_vars and '-arch' in _config_vars[cv]: + flags = _config_vars[cv] + flags = re.sub('-arch\s+\w+\s', ' ', flags) + flags = flags + ' ' + arch + _save_modified_value(_config_vars, cv, flags) + + return _config_vars + + +def _check_for_unavailable_sdk(_config_vars): + """Remove references to any SDKs not available""" + # If we're on OSX 10.5 or later and the user tries to + # compile an extension using an SDK that is not present + # on the current machine it is better to not use an SDK + # than to fail. This is particularly important with + # the standalong Command Line Tools alternative to a + # full-blown Xcode install since the CLT packages do not + # provide SDKs. If the SDK is not present, it is assumed + # that the header files and dev libs have been installed + # to /usr and /System/Library by either a standalone CLT + # package or the CLT component within Xcode. + cflags = _config_vars.get('CFLAGS', '') + m = re.search(r'-isysroot\s+(\S+)', cflags) + if m is not None: + sdk = m.group(1) + if not os.path.exists(sdk): + for cv in _UNIVERSAL_CONFIG_VARS: + # Do not alter a config var explicitly overriden by env var + if cv in _config_vars and cv not in os.environ: + flags = _config_vars[cv] + flags = re.sub(r'-isysroot\s+\S+(?:\s|$)', ' ', flags) + _save_modified_value(_config_vars, cv, flags) + + return _config_vars + + +def compiler_fixup(compiler_so, cc_args): + """ + This function will strip '-isysroot PATH' and '-arch ARCH' from the + compile flags if the user has specified one them in extra_compile_flags. + + This is needed because '-arch ARCH' adds another architecture to the + build, without a way to remove an architecture. Furthermore GCC will + barf if multiple '-isysroot' arguments are present. + """ + stripArch = stripSysroot = False + + compiler_so = list(compiler_so) + + if not _supports_universal_builds(): + # OSX before 10.4.0, these don't support -arch and -isysroot at + # all. + stripArch = stripSysroot = True + else: + stripArch = '-arch' in cc_args + stripSysroot = '-isysroot' in cc_args + + if stripArch or 'ARCHFLAGS' in os.environ: + while True: + try: + index = compiler_so.index('-arch') + # Strip this argument and the next one: + del compiler_so[index:index+2] + except ValueError: + break + + if 'ARCHFLAGS' in os.environ and not stripArch: + # User specified different -arch flags in the environ, + # see also distutils.sysconfig + compiler_so = compiler_so + os.environ['ARCHFLAGS'].split() + + if stripSysroot: + while True: + try: + index = compiler_so.index('-isysroot') + # Strip this argument and the next one: + del compiler_so[index:index+2] + except ValueError: + break + + # Check if the SDK that is used during compilation actually exists, + # the universal build requires the usage of a universal SDK and not all + # users have that installed by default. + sysroot = None + if '-isysroot' in cc_args: + idx = cc_args.index('-isysroot') + sysroot = cc_args[idx+1] + elif '-isysroot' in compiler_so: + idx = compiler_so.index('-isysroot') + sysroot = compiler_so[idx+1] + + if sysroot and not os.path.isdir(sysroot): + from distutils import log + log.warn("Compiling with an SDK that doesn't seem to exist: %s", + sysroot) + log.warn("Please check your Xcode installation") + + return compiler_so + + +def customize_config_vars(_config_vars): + """Customize Python build configuration variables. + + Called internally from sysconfig with a mutable mapping + containing name/value pairs parsed from the configured + makefile used to build this interpreter. Returns + the mapping updated as needed to reflect the environment + in which the interpreter is running; in the case of + a Python from a binary installer, the installed + environment may be very different from the build + environment, i.e. different OS levels, different + built tools, different available CPU architectures. + + This customization is performed whenever + distutils.sysconfig.get_config_vars() is first + called. It may be used in environments where no + compilers are present, i.e. when installing pure + Python dists. Customization of compiler paths + and detection of unavailable archs is deferred + until the first extention module build is + requested (in distutils.sysconfig.customize_compiler). + + Currently called from distutils.sysconfig + """ + + if not _supports_universal_builds(): + # On Mac OS X before 10.4, check if -arch and -isysroot + # are in CFLAGS or LDFLAGS and remove them if they are. + # This is needed when building extensions on a 10.3 system + # using a universal build of python. + _remove_universal_flags(_config_vars) + + # Allow user to override all archs with ARCHFLAGS env var + _override_all_archs(_config_vars) + + # Remove references to sdks that are not found + _check_for_unavailable_sdk(_config_vars) + + return _config_vars + + +def customize_compiler(_config_vars): + """Customize compiler path and configuration variables. + + This customization is performed when the first + extension module build is requested + in distutils.sysconfig.customize_compiler). + """ + + # Find a compiler to use for extension module builds + _find_appropriate_compiler(_config_vars) + + # Remove ppc arch flags if not supported here + _remove_unsupported_archs(_config_vars) + + # Allow user to override all archs with ARCHFLAGS env var + _override_all_archs(_config_vars) + + return _config_vars + + +def get_platform_osx(_config_vars, osname, release, machine): + """Filter values for get_platform()""" + # called from get_platform() in sysconfig and distutils.util + # + # For our purposes, we'll assume that the system version from + # distutils' perspective is what MACOSX_DEPLOYMENT_TARGET is set + # to. This makes the compatibility story a bit more sane because the + # machine is going to compile and link as if it were + # MACOSX_DEPLOYMENT_TARGET. + + macver = _config_vars.get('MACOSX_DEPLOYMENT_TARGET', '') + macrelease = _get_system_version() or macver + macver = macver or macrelease + + if macver: + release = macver + osname = "macosx" + + # Use the original CFLAGS value, if available, so that we + # return the same machine type for the platform string. + # Otherwise, distutils may consider this a cross-compiling + # case and disallow installs. + cflags = _config_vars.get(_INITPRE+'CFLAGS', + _config_vars.get('CFLAGS', '')) + if ((macrelease + '.') >= '10.4.' and + '-arch' in cflags.strip()): + # The universal build will build fat binaries, but not on + # systems before 10.4 + + machine = 'fat' + + archs = re.findall('-arch\s+(\S+)', cflags) + archs = tuple(sorted(set(archs))) + + if len(archs) == 1: + machine = archs[0] + elif archs == ('i386', 'ppc'): + machine = 'fat' + elif archs == ('i386', 'x86_64'): + machine = 'intel' + elif archs == ('i386', 'ppc', 'x86_64'): + machine = 'fat3' + elif archs == ('ppc64', 'x86_64'): + machine = 'fat64' + elif archs == ('i386', 'ppc', 'ppc64', 'x86_64'): + machine = 'universal' + else: + raise ValueError( + "Don't know machine value for archs=%r" % (archs,)) + + elif machine == 'i386': + # On OSX the machine type returned by uname is always the + # 32-bit variant, even if the executable architecture is + # the 64-bit variant + if sys.maxint >= 2**32: + machine = 'x86_64' + + elif machine in ('PowerPC', 'Power_Macintosh'): + # Pick a sane name for the PPC architecture. + # See 'i386' case + if sys.maxint >= 2**32: + machine = 'ppc64' + else: + machine = 'ppc' + + return (osname, release, machine) diff --git a/lib-python/2.7/_pyio.py b/lib-python/2.7/_pyio.py --- a/lib-python/2.7/_pyio.py +++ b/lib-python/2.7/_pyio.py @@ -298,7 +298,7 @@ def seek(self, pos, whence=0): """Change stream position. - Change the stream position to byte offset offset. offset is + Change the stream position to byte offset pos. Argument pos is interpreted relative to the position indicated by whence. Values for whence are: @@ -340,8 +340,10 @@ This method has no effect if the file is already closed. """ if not self.__closed: - self.flush() - self.__closed = True + try: + self.flush() + finally: + self.__closed = True def __del__(self): """Destructor. Calls close().""" @@ -883,12 +885,18 @@ return pos def readable(self): + if self.closed: + raise ValueError("I/O operation on closed file.") return True def writable(self): + if self.closed: + raise ValueError("I/O operation on closed file.") return True def seekable(self): + if self.closed: + raise ValueError("I/O operation on closed file.") return True @@ -1451,7 +1459,7 @@ enabled. With this enabled, on input, the lines endings '\n', '\r', or '\r\n' are translated to '\n' before being returned to the caller. Conversely, on output, '\n' is translated to the system - default line seperator, os.linesep. If newline is any other of its + default line separator, os.linesep. If newline is any other of its legal values, that newline becomes the newline when the file is read and it is returned untranslated. On output, '\n' is converted to the newline. @@ -1546,6 +1554,8 @@ return self._buffer def seekable(self): + if self.closed: + raise ValueError("I/O operation on closed file.") return self._seekable def readable(self): @@ -1560,8 +1570,10 @@ def close(self): if self.buffer is not None and not self.closed: - self.flush() - self.buffer.close() + try: + self.flush() + finally: + self.buffer.close() @property def closed(self): diff --git a/lib-python/2.7/_strptime.py b/lib-python/2.7/_strptime.py --- a/lib-python/2.7/_strptime.py +++ b/lib-python/2.7/_strptime.py @@ -326,7 +326,8 @@ if len(data_string) != found.end(): raise ValueError("unconverted data remains: %s" % data_string[found.end():]) - year = 1900 + + year = None month = day = 1 hour = minute = second = fraction = 0 tz = -1 @@ -425,6 +426,12 @@ else: tz = value break + leap_year_fix = False + if year is None and month == 2 and day == 29: + year = 1904 # 1904 is first leap year of 20th century + leap_year_fix = True + elif year is None: + year = 1900 # If we know the week of the year and what day of that week, we can figure # out the Julian day of the year. if julian == -1 and week_of_year != -1 and weekday != -1: @@ -446,6 +453,12 @@ day = datetime_result.day if weekday == -1: weekday = datetime_date(year, month, day).weekday() + if leap_year_fix: + # the caller didn't supply a year but asked for Feb 29th. We couldn't + # use the default of 1900 for computations. We set it back to ensure + # that February 29th is smaller than March 1st. + year = 1900 + return (time.struct_time((year, month, day, hour, minute, second, weekday, julian, tz)), fraction) diff --git a/lib-python/2.7/_weakrefset.py b/lib-python/2.7/_weakrefset.py --- a/lib-python/2.7/_weakrefset.py +++ b/lib-python/2.7/_weakrefset.py @@ -63,7 +63,7 @@ yield item def __len__(self): - return sum(x() is not None for x in self.data) + return len(self.data) - len(self._pending_removals) def __contains__(self, item): try: @@ -116,36 +116,21 @@ def update(self, other): if self._pending_removals: self._commit_removals() - if isinstance(other, self.__class__): - self.data.update(other.data) - else: - for element in other: - self.add(element) + for element in other: + self.add(element) def __ior__(self, other): self.update(other) return self - # Helper functions for simple delegating methods. - def _apply(self, other, method): - if not isinstance(other, self.__class__): - other = self.__class__(other) - newdata = method(other.data) - newset = self.__class__() - newset.data = newdata + def difference(self, other): + newset = self.copy() + newset.difference_update(other) return newset - - def difference(self, other): - return self._apply(other, self.data.difference) __sub__ = difference def difference_update(self, other): - if self._pending_removals: - self._commit_removals() - if self is other: - self.data.clear() - else: - self.data.difference_update(ref(item) for item in other) + self.__isub__(other) def __isub__(self, other): if self._pending_removals: self._commit_removals() @@ -156,13 +141,11 @@ return self def intersection(self, other): - return self._apply(other, self.data.intersection) + return self.__class__(item for item in other if item in self) __and__ = intersection def intersection_update(self, other): - if self._pending_removals: - self._commit_removals() - self.data.intersection_update(ref(item) for item in other) + self.__iand__(other) def __iand__(self, other): if self._pending_removals: self._commit_removals() @@ -171,17 +154,17 @@ def issubset(self, other): return self.data.issubset(ref(item) for item in other) - __lt__ = issubset + __le__ = issubset - def __le__(self, other): - return self.data <= set(ref(item) for item in other) + def __lt__(self, other): + return self.data < set(ref(item) for item in other) def issuperset(self, other): return self.data.issuperset(ref(item) for item in other) - __gt__ = issuperset + __ge__ = issuperset - def __ge__(self, other): - return self.data >= set(ref(item) for item in other) + def __gt__(self, other): + return self.data > set(ref(item) for item in other) def __eq__(self, other): if not isinstance(other, self.__class__): @@ -189,27 +172,24 @@ return self.data == set(ref(item) for item in other) def symmetric_difference(self, other): - return self._apply(other, self.data.symmetric_difference) + newset = self.copy() + newset.symmetric_difference_update(other) + return newset __xor__ = symmetric_difference def symmetric_difference_update(self, other): - if self._pending_removals: - self._commit_removals() - if self is other: - self.data.clear() - else: - self.data.symmetric_difference_update(ref(item) for item in other) + self.__ixor__(other) def __ixor__(self, other): if self._pending_removals: self._commit_removals() if self is other: self.data.clear() else: - self.data.symmetric_difference_update(ref(item) for item in other) + self.data.symmetric_difference_update(ref(item, self._remove) for item in other) return self def union(self, other): - return self._apply(other, self.data.union) + return self.__class__(e for s in (self, other) for e in s) __or__ = union def isdisjoint(self, other): diff --git a/lib-python/2.7/aifc.py b/lib-python/2.7/aifc.py --- a/lib-python/2.7/aifc.py +++ b/lib-python/2.7/aifc.py @@ -732,22 +732,28 @@ self._patchheader() def close(self): - self._ensure_header_written(0) - if self._datawritten & 1: - # quick pad to even size - self._file.write(chr(0)) - self._datawritten = self._datawritten + 1 - self._writemarkers() - if self._nframeswritten != self._nframes or \ - self._datalength != self._datawritten or \ - self._marklength: - self._patchheader() - if self._comp: - self._comp.CloseCompressor() - self._comp = None - # Prevent ref cycles - self._convert = None - self._file.close() + if self._file is None: + return + try: + self._ensure_header_written(0) + if self._datawritten & 1: + # quick pad to even size + self._file.write(chr(0)) + self._datawritten = self._datawritten + 1 + self._writemarkers() + if self._nframeswritten != self._nframes or \ + self._datalength != self._datawritten or \ + self._marklength: + self._patchheader() + if self._comp: + self._comp.CloseCompressor() + self._comp = None + finally: + # Prevent ref cycles + self._convert = None + f = self._file + self._file = None + f.close() # # Internal methods. diff --git a/lib-python/2.7/argparse.py b/lib-python/2.7/argparse.py --- a/lib-python/2.7/argparse.py +++ b/lib-python/2.7/argparse.py @@ -740,10 +740,10 @@ - default -- The value to be produced if the option is not specified. - - type -- The type which the command-line arguments should be converted - to, should be one of 'string', 'int', 'float', 'complex' or a - callable object that accepts a single string argument. If None, - 'string' is assumed. + - type -- A callable that accepts a single string argument, and + returns the converted value. The standard Python types str, int, + float, and complex are useful examples of such callables. If None, + str is used. - choices -- A container of values that should be allowed. If not None, after a command-line argument has been converted to the appropriate @@ -1692,9 +1692,12 @@ return args def parse_known_args(self, args=None, namespace=None): - # args default to the system args if args is None: + # args default to the system args args = _sys.argv[1:] + else: + # make sure that args are mutable + args = list(args) # default Namespace built from parser defaults if namespace is None: @@ -1705,10 +1708,7 @@ if action.dest is not SUPPRESS: if not hasattr(namespace, action.dest): if action.default is not SUPPRESS: - default = action.default - if isinstance(action.default, basestring): - default = self._get_value(action, default) - setattr(namespace, action.dest, default) + setattr(namespace, action.dest, action.default) # add any parser defaults that aren't present for dest in self._defaults: @@ -1936,12 +1936,23 @@ if positionals: self.error(_('too few arguments')) - # make sure all required actions were present + # make sure all required actions were present, and convert defaults. for action in self._actions: - if action.required: - if action not in seen_actions: + if action not in seen_actions: + if action.required: name = _get_action_name(action) self.error(_('argument %s is required') % name) + else: + # Convert action default now instead of doing it before + # parsing arguments to avoid calling convert functions + # twice (which may fail) if the argument was given, but + # only if it was defined already in the namespace + if (action.default is not None and + isinstance(action.default, basestring) and + hasattr(namespace, action.dest) and + action.default is getattr(namespace, action.dest)): + setattr(namespace, action.dest, + self._get_value(action, action.default)) # make sure all required groups had one option present for group in self._mutually_exclusive_groups: @@ -1967,7 +1978,7 @@ for arg_string in arg_strings: # for regular arguments, just add them back into the list - if arg_string[0] not in self.fromfile_prefix_chars: + if not arg_string or arg_string[0] not in self.fromfile_prefix_chars: new_arg_strings.append(arg_string) # replace arguments referencing files with the file content @@ -2174,9 +2185,12 @@ # Value conversion methods # ======================== def _get_values(self, action, arg_strings): - # for everything but PARSER args, strip out '--' + # for everything but PARSER, REMAINDER args, strip out first '--' if action.nargs not in [PARSER, REMAINDER]: - arg_strings = [s for s in arg_strings if s != '--'] + try: + arg_strings.remove('--') + except ValueError: + pass # optional argument produces a default when not present if not arg_strings and action.nargs == OPTIONAL: diff --git a/lib-python/2.7/asyncore.py b/lib-python/2.7/asyncore.py --- a/lib-python/2.7/asyncore.py +++ b/lib-python/2.7/asyncore.py @@ -225,6 +225,7 @@ debug = False connected = False accepting = False + connecting = False closing = False addr = None ignore_log_types = frozenset(['warning']) @@ -248,7 +249,7 @@ try: self.addr = sock.getpeername() except socket.error, err: - if err.args[0] == ENOTCONN: + if err.args[0] in (ENOTCONN, EINVAL): # To handle the case where we got an unconnected # socket. self.connected = False @@ -342,9 +343,11 @@ def connect(self, address): self.connected = False + self.connecting = True err = self.socket.connect_ex(address) if err in (EINPROGRESS, EALREADY, EWOULDBLOCK) \ or err == EINVAL and os.name in ('nt', 'ce'): + self.addr = address return if err in (0, EISCONN): self.addr = address @@ -390,7 +393,7 @@ else: return data except socket.error, why: - # winsock sometimes throws ENOTCONN + # winsock sometimes raises ENOTCONN if why.args[0] in _DISCONNECTED: self.handle_close() return '' @@ -400,6 +403,7 @@ def close(self): self.connected = False self.accepting = False + self.connecting = False self.del_channel() try: self.socket.close() @@ -438,7 +442,8 @@ # sockets that are connected self.handle_accept() elif not self.connected: - self.handle_connect_event() + if self.connecting: + self.handle_connect_event() self.handle_read() else: self.handle_read() @@ -449,6 +454,7 @@ raise socket.error(err, _strerror(err)) self.handle_connect() self.connected = True + self.connecting = False def handle_write_event(self): if self.accepting: @@ -457,12 +463,8 @@ return if not self.connected: - #check for errors - err = self.socket.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR) - if err != 0: - raise socket.error(err, _strerror(err)) - - self.handle_connect_event() + if self.connecting: + self.handle_connect_event() self.handle_write() def handle_expt_event(self): diff --git a/lib-python/2.7/bdb.py b/lib-python/2.7/bdb.py --- a/lib-python/2.7/bdb.py +++ b/lib-python/2.7/bdb.py @@ -24,6 +24,7 @@ self.skip = set(skip) if skip else None self.breaks = {} self.fncache = {} + self.frame_returning = None def canonic(self, filename): if filename == "<" + filename[1:-1] + ">": @@ -82,7 +83,11 @@ def dispatch_return(self, frame, arg): if self.stop_here(frame) or frame == self.returnframe: - self.user_return(frame, arg) + try: + self.frame_returning = frame + self.user_return(frame, arg) + finally: + self.frame_returning = None if self.quitting: raise BdbQuit return self.trace_dispatch @@ -186,6 +191,14 @@ def set_step(self): """Stop after one line of code.""" + # Issue #13183: pdb skips frames after hitting a breakpoint and running + # step commands. + # Restore the trace function in the caller (that may not have been set + # for performance reasons) when returning from the current frame. + if self.frame_returning: + caller_frame = self.frame_returning.f_back + if caller_frame and not caller_frame.f_trace: + caller_frame.f_trace = self.trace_dispatch self._set_stopinfo(None, None) def set_next(self, frame): diff --git a/lib-python/2.7/bsddb/__init__.py b/lib-python/2.7/bsddb/__init__.py --- a/lib-python/2.7/bsddb/__init__.py +++ b/lib-python/2.7/bsddb/__init__.py @@ -33,7 +33,7 @@ #---------------------------------------------------------------------- -"""Support for Berkeley DB 4.1 through 4.8 with a simple interface. +"""Support for Berkeley DB 4.3 through 5.3 with a simple interface. For the full featured object oriented interface use the bsddb.db module instead. It mirrors the Oracle Berkeley DB C API. @@ -138,7 +138,7 @@ except _bsddb.DBCursorClosedError: # the database was modified during iteration. abort. pass -# When Python 2.3 not supported in bsddb3, we can change this to "finally" +# When Python 2.4 not supported in bsddb3, we can change this to "finally" except : self._in_iter -= 1 raise @@ -181,7 +181,7 @@ except _bsddb.DBCursorClosedError: # the database was modified during iteration. abort. pass -# When Python 2.3 not supported in bsddb3, we can change this to "finally" +# When Python 2.4 not supported in bsddb3, we can change this to "finally" except : self._in_iter -= 1 raise diff --git a/lib-python/2.7/bsddb/dbobj.py b/lib-python/2.7/bsddb/dbobj.py --- a/lib-python/2.7/bsddb/dbobj.py +++ b/lib-python/2.7/bsddb/dbobj.py @@ -30,12 +30,7 @@ import db if sys.version_info < (2, 6) : - try: - from UserDict import DictMixin - except ImportError: - # DictMixin is new in Python 2.3 - class DictMixin: pass - MutableMapping = DictMixin + from UserDict import DictMixin as MutableMapping else : import collections MutableMapping = collections.MutableMapping @@ -196,6 +191,8 @@ return self._cobj.set_bt_compare(*args, **kwargs) def set_cachesize(self, *args, **kwargs): return self._cobj.set_cachesize(*args, **kwargs) + def set_dup_compare(self, *args, **kwargs) : + return self._cobj.set_dup_compare(*args, **kwargs) def set_flags(self, *args, **kwargs): return self._cobj.set_flags(*args, **kwargs) def set_h_ffactor(self, *args, **kwargs): diff --git a/lib-python/2.7/bsddb/dbshelve.py b/lib-python/2.7/bsddb/dbshelve.py --- a/lib-python/2.7/bsddb/dbshelve.py +++ b/lib-python/2.7/bsddb/dbshelve.py @@ -43,7 +43,7 @@ if sys.version_info < (2, 6) : import cPickle else : - # When we drop support for python 2.3 and 2.4 + # When we drop support for python 2.4 # we could use: (in 2.5 we need a __future__ statement) # # with warnings.catch_warnings(): @@ -51,7 +51,7 @@ # ... # # We can not use "with" as is, because it would be invalid syntax - # in python 2.3, 2.4 and (with no __future__) 2.5. + # in python 2.4 and (with no __future__) 2.5. # Here we simulate "with" following PEP 343 : import warnings w = warnings.catch_warnings() @@ -65,32 +65,12 @@ w.__exit__() del w -#At version 2.3 cPickle switched to using protocol instead of bin -if sys.version_info >= (2, 3): - HIGHEST_PROTOCOL = cPickle.HIGHEST_PROTOCOL -# In python 2.3.*, "cPickle.dumps" accepts no -# named parameters. "pickle.dumps" accepts them, -# so this seems a bug. - if sys.version_info < (2, 4): - def _dumps(object, protocol): - return cPickle.dumps(object, protocol) - else : - def _dumps(object, protocol): - return cPickle.dumps(object, protocol=protocol) - -else: - HIGHEST_PROTOCOL = None - def _dumps(object, protocol): - return cPickle.dumps(object, bin=protocol) - +HIGHEST_PROTOCOL = cPickle.HIGHEST_PROTOCOL +def _dumps(object, protocol): + return cPickle.dumps(object, protocol=protocol) if sys.version_info < (2, 6) : - try: - from UserDict import DictMixin - except ImportError: - # DictMixin is new in Python 2.3 - class DictMixin: pass - MutableMapping = DictMixin + from UserDict import DictMixin as MutableMapping else : import collections MutableMapping = collections.MutableMapping diff --git a/lib-python/2.7/bsddb/dbtables.py b/lib-python/2.7/bsddb/dbtables.py --- a/lib-python/2.7/bsddb/dbtables.py +++ b/lib-python/2.7/bsddb/dbtables.py @@ -30,7 +30,7 @@ if sys.version_info < (2, 6) : import cPickle as pickle else : - # When we drop support for python 2.3 and 2.4 + # When we drop support for python 2.4 # we could use: (in 2.5 we need a __future__ statement) # # with warnings.catch_warnings(): @@ -38,7 +38,7 @@ # ... # # We can not use "with" as is, because it would be invalid syntax - # in python 2.3, 2.4 and (with no __future__) 2.5. + # in python 2.4 and (with no __future__) 2.5. # Here we simulate "with" following PEP 343 : import warnings w = warnings.catch_warnings() diff --git a/lib-python/2.7/bsddb/test/test_all.py b/lib-python/2.7/bsddb/test/test_all.py --- a/lib-python/2.7/bsddb/test/test_all.py +++ b/lib-python/2.7/bsddb/test/test_all.py @@ -392,10 +392,8 @@ return self._dbenv.get_tmp_dir().decode(charset) def get_data_dirs(self) : - # Have to use a list comprehension and not - # generators, because we are supporting Python 2.3. return tuple( - [i.decode(charset) for i in self._dbenv.get_data_dirs()]) + (i.decode(charset) for i in self._dbenv.get_data_dirs())) class DBSequence_py3k(object) : def __init__(self, db, *args, **kwargs) : @@ -484,6 +482,8 @@ print '-=' * 38 print db.DB_VERSION_STRING print 'bsddb.db.version(): %s' % (db.version(), ) + if db.version() >= (5, 0) : + print 'bsddb.db.full_version(): %s' %repr(db.full_version()) print 'bsddb.db.__version__: %s' % db.__version__ print 'bsddb.db.cvsid: %s' % db.cvsid @@ -528,7 +528,8 @@ # This path can be overriden via "set_test_path_prefix()". import os, os.path -get_new_path.prefix=os.path.join(os.sep,"tmp","z-Berkeley_DB") +get_new_path.prefix=os.path.join(os.environ.get("TMPDIR", + os.path.join(os.sep,"tmp")), "z-Berkeley_DB") get_new_path.num=0 def get_test_path_prefix() : diff --git a/lib-python/2.7/bsddb/test/test_basics.py b/lib-python/2.7/bsddb/test/test_basics.py --- a/lib-python/2.7/bsddb/test/test_basics.py +++ b/lib-python/2.7/bsddb/test/test_basics.py @@ -9,6 +9,7 @@ from pprint import pprint import unittest import time +import sys from test_all import db, test_support, verbose, get_new_environment_path, \ get_new_database_path @@ -44,13 +45,6 @@ _numKeys = 1002 # PRIVATE. NOTE: must be an even value - import sys - if sys.version_info < (2, 4): - def assertTrue(self, expr, msg=None): - self.failUnless(expr,msg=msg) - def assertFalse(self, expr, msg=None): - self.failIf(expr,msg=msg) - def setUp(self): if self.useEnv: self.homeDir=get_new_environment_path() @@ -74,14 +68,13 @@ # create and open the DB self.d = db.DB(self.env) if not self.useEnv : - if db.version() >= (4, 2) : - self.d.set_cachesize(*self.cachesize) - cachesize = self.d.get_cachesize() - self.assertEqual(cachesize[0], self.cachesize[0]) - self.assertEqual(cachesize[2], self.cachesize[2]) - # Berkeley DB expands the cache 25% accounting overhead, - # if the cache is small. - self.assertEqual(125, int(100.0*cachesize[1]/self.cachesize[1])) + self.d.set_cachesize(*self.cachesize) + cachesize = self.d.get_cachesize() + self.assertEqual(cachesize[0], self.cachesize[0]) + self.assertEqual(cachesize[2], self.cachesize[2]) + # Berkeley DB expands the cache 25% accounting overhead, + # if the cache is small. + self.assertEqual(125, int(100.0*cachesize[1]/self.cachesize[1])) self.d.set_flags(self.dbsetflags) if self.dbname: self.d.open(self.filename, self.dbname, self.dbtype, @@ -161,7 +154,6 @@ try: d.delete('abcd') except db.DBNotFoundError, val: - import sys if sys.version_info < (2, 6) : self.assertEqual(val[0], db.DB_NOTFOUND) else : @@ -184,7 +176,6 @@ try: d.put('abcd', 'this should fail', flags=db.DB_NOOVERWRITE) except db.DBKeyExistError, val: - import sys if sys.version_info < (2, 6) : self.assertEqual(val[0], db.DB_KEYEXIST) else : @@ -338,7 +329,6 @@ rec = c.next() except db.DBNotFoundError, val: if get_raises_error: - import sys if sys.version_info < (2, 6) : self.assertEqual(val[0], db.DB_NOTFOUND) else : @@ -363,7 +353,6 @@ rec = c.prev() except db.DBNotFoundError, val: if get_raises_error: - import sys if sys.version_info < (2, 6) : self.assertEqual(val[0], db.DB_NOTFOUND) else : @@ -390,7 +379,6 @@ try: n = c.set('bad key') except db.DBNotFoundError, val: - import sys if sys.version_info < (2, 6) : self.assertEqual(val[0], db.DB_NOTFOUND) else : @@ -408,7 +396,6 @@ try: n = c.get_both('0404', 'bad data') except db.DBNotFoundError, val: - import sys if sys.version_info < (2, 6) : self.assertEqual(val[0], db.DB_NOTFOUND) else : @@ -441,7 +428,6 @@ rec = c.current() except db.DBKeyEmptyError, val: if get_raises_error: - import sys if sys.version_info < (2, 6) : self.assertEqual(val[0], db.DB_KEYEMPTY) else : @@ -490,7 +476,6 @@ # a bug may cause a NULL pointer dereference... getattr(c, method)(*args) except db.DBError, val: - import sys if sys.version_info < (2, 6) : self.assertEqual(val[0], 0) else : @@ -712,11 +697,6 @@ #---------------------------------------------------------------------- class BasicTransactionTestCase(BasicTestCase): - import sys - if sys.version_info < (2, 4): - def assertTrue(self, expr, msg=None): - return self.failUnless(expr,msg=msg) - if (sys.version_info < (2, 7)) or ((sys.version_info >= (3, 0)) and (sys.version_info < (3, 2))) : def assertIn(self, a, b, msg=None) : @@ -792,7 +772,6 @@ for log in logs: if verbose: print 'log file: ' + log - if db.version() >= (4,2): logs = self.env.log_archive(db.DB_ARCH_REMOVE) self.assertTrue(not logs) @@ -875,7 +854,6 @@ #---------------------------------------- - if db.version() >= (4, 2) : def test_get_tx_max(self) : self.assertEqual(self.env.get_tx_max(), 30) @@ -1098,11 +1076,6 @@ class PrivateObject(unittest.TestCase) : - import sys - if sys.version_info < (2, 4): - def assertTrue(self, expr, msg=None): - self.failUnless(expr,msg=msg) - def tearDown(self) : del self.obj @@ -1116,7 +1089,6 @@ self.assertTrue(a is b) # Object identity def test03_leak_assignment(self) : - import sys a = "example of private object" refcount = sys.getrefcount(a) self.obj.set_private(a) @@ -1125,7 +1097,6 @@ self.assertEqual(refcount, sys.getrefcount(a)) def test04_leak_GC(self) : - import sys a = "example of private object" refcount = sys.getrefcount(a) self.obj.set_private(a) @@ -1141,11 +1112,6 @@ self.obj = db.DB() class CrashAndBurn(unittest.TestCase) : - import sys - if sys.version_info < (2, 4): - def assertTrue(self, expr, msg=None): - self.failUnless(expr,msg=msg) - #def test01_OpenCrash(self) : # # See http://bugs.python.org/issue3307 # self.assertRaises(db.DBInvalidArgError, db.DB, None, 65535) diff --git a/lib-python/2.7/bsddb/test/test_compare.py b/lib-python/2.7/bsddb/test/test_compare.py --- a/lib-python/2.7/bsddb/test/test_compare.py +++ b/lib-python/2.7/bsddb/test/test_compare.py @@ -1,5 +1,5 @@ """ -TestCases for python DB Btree key comparison function. +TestCases for python DB duplicate and Btree key comparison function. """ import sys, os, re @@ -20,31 +20,24 @@ lexical_cmp = cmp -def lowercase_cmp(left, right): - return cmp (left.lower(), right.lower()) +def lowercase_cmp(left, right) : + return cmp(left.lower(), right.lower()) -def make_reverse_comparator (cmp): - def reverse (left, right, delegate=cmp): - return - delegate (left, right) +def make_reverse_comparator(cmp) : + def reverse(left, right, delegate=cmp) : + return - delegate(left, right) return reverse _expected_lexical_test_data = ['', 'CCCP', 'a', 'aaa', 'b', 'c', 'cccce', 'ccccf'] _expected_lowercase_test_data = ['', 'a', 'aaa', 'b', 'c', 'CC', 'cccce', 'ccccf', 'CCCP'] -class ComparatorTests (unittest.TestCase): - if sys.version_info < (2, 4) : - def assertTrue(self, expr, msg=None) : - return self.failUnless(expr,msg=msg) - - def comparator_test_helper (self, comparator, expected_data): +class ComparatorTests(unittest.TestCase) : + def comparator_test_helper(self, comparator, expected_data) : data = expected_data[:] import sys if sys.version_info < (2, 6) : - if sys.version_info < (2, 4) : - data.sort(comparator) - else : - data.sort(cmp=comparator) + data.sort(cmp=comparator) else : # Insertion Sort. Please, improve data2 = [] for i in data : @@ -60,143 +53,139 @@ self.assertEqual(data, expected_data, "comparator `%s' is not right: %s vs. %s" % (comparator, expected_data, data)) - def test_lexical_comparator (self): - self.comparator_test_helper (lexical_cmp, _expected_lexical_test_data) - def test_reverse_lexical_comparator (self): + def test_lexical_comparator(self) : + self.comparator_test_helper(lexical_cmp, _expected_lexical_test_data) + def test_reverse_lexical_comparator(self) : rev = _expected_lexical_test_data[:] - rev.reverse () - self.comparator_test_helper (make_reverse_comparator (lexical_cmp), + rev.reverse() + self.comparator_test_helper(make_reverse_comparator(lexical_cmp), rev) - def test_lowercase_comparator (self): - self.comparator_test_helper (lowercase_cmp, + def test_lowercase_comparator(self) : + self.comparator_test_helper(lowercase_cmp, _expected_lowercase_test_data) -class AbstractBtreeKeyCompareTestCase (unittest.TestCase): +class AbstractBtreeKeyCompareTestCase(unittest.TestCase) : env = None db = None - if sys.version_info < (2, 4) : - def assertTrue(self, expr, msg=None): - self.failUnless(expr,msg=msg) - if (sys.version_info < (2, 7)) or ((sys.version_info >= (3,0)) and (sys.version_info < (3, 2))) : def assertLess(self, a, b, msg=None) : return self.assertTrue(a= (3,0)) and + (sys.version_info < (3, 2))) : + def assertLess(self, a, b, msg=None) : + return self.assertTrue(a Author: Brian Kearns Branch: vendor/stdlib Changeset: r63162:7d29d5e39734 Date: 2013-04-09 02:57 -0400 http://bitbucket.org/pypy/pypy/changeset/7d29d5e39734/ Log: merge heads From noreply at buildbot.pypy.org Tue Apr 9 12:35:47 2013 From: noreply at buildbot.pypy.org (mattip) Date: Tue, 9 Apr 2013 12:35:47 +0200 (CEST) Subject: [pypy-commit] pypy py3k: start to pass pypy/module/_ssl tests on win32, may help translation too Message-ID: <20130409103547.5A3621C02E8@cobra.cs.uni-duesseldorf.de> Author: mattip Branch: py3k Changeset: r63166:95c610ea4aed Date: 2013-04-09 13:35 +0300 http://bitbucket.org/pypy/pypy/changeset/95c610ea4aed/ Log: start to pass pypy/module/_ssl tests on win32, may help translation too diff --git a/rpython/rlib/ropenssl.py b/rpython/rlib/ropenssl.py --- a/rpython/rlib/ropenssl.py +++ b/rpython/rlib/ropenssl.py @@ -10,7 +10,7 @@ testonly_libraries = [] include_dirs = [] if sys.platform == 'win32' and platform.name != 'mingw32': - libraries = ['libeay32', 'ssleay32', + libraries = ['libeay32', 'ssleay32', 'zlib', 'user32', 'advapi32', 'gdi32', 'msvcrt', 'ws2_32'] includes = [ # ssl.h includes winsock.h, which will conflict with our own From noreply at buildbot.pypy.org Tue Apr 9 13:40:21 2013 From: noreply at buildbot.pypy.org (arigo) Date: Tue, 9 Apr 2013 13:40:21 +0200 (CEST) Subject: [pypy-commit] cffi default: Try to work around issues when running in a buildbot: only writes to stderr. Message-ID: <20130409114021.4B33E1C15A7@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r1244:2a392bc4cede Date: 2013-04-09 13:39 +0200 http://bitbucket.org/cffi/cffi/changeset/2a392bc4cede/ Log: Try to work around issues when running in a buildbot: only writes to stderr. diff --git a/testing/test_function.py b/testing/test_function.py --- a/testing/test_function.py +++ b/testing/test_function.py @@ -15,7 +15,7 @@ """xxx limited to capture at most 512 bytes of output, according to the Posix manual.""" - def __init__(self, capture_fd=1): # stdout, by default + def __init__(self, capture_fd): self.capture_fd = capture_fd def __enter__(self): @@ -108,80 +108,66 @@ y = lib.TlsFree(x) assert y != 0 - def test_puts(self): + def test_fputs(self): + if not sys.platform.startswith('linux'): + py.test.skip("probably no symbol 'stderr' in the lib") ffi = FFI(backend=self.Backend()) ffi.cdef(""" - int puts(const char *); - int fflush(void *); + int fputs(const char *, void *); + void *stderr; """) ffi.C = ffi.dlopen(None) - ffi.C.puts # fetch before capturing, for easier debugging - with FdWriteCapture() as fd: - ffi.C.puts(b"hello") - ffi.C.puts(b" world") - ffi.C.fflush(ffi.NULL) + ffi.C.fputs # fetch before capturing, for easier debugging + with FdWriteCapture(2) as fd: + ffi.C.fputs(b"hello\n", ffi.C.stderr) + ffi.C.fputs(b" world\n", ffi.C.stderr) res = fd.getvalue() assert res == b'hello\n world\n' - def test_puts_without_const(self): + def test_fputs_without_const(self): + if not sys.platform.startswith('linux'): + py.test.skip("probably no symbol 'stderr' in the lib") ffi = FFI(backend=self.Backend()) ffi.cdef(""" - int puts(char *); - int fflush(void *); + int fputs(char *, void *); + void *stderr; """) ffi.C = ffi.dlopen(None) - ffi.C.puts # fetch before capturing, for easier debugging - with FdWriteCapture() as fd: - ffi.C.puts(b"hello") - ffi.C.puts(b" world") - ffi.C.fflush(ffi.NULL) + ffi.C.fputs # fetch before capturing, for easier debugging + with FdWriteCapture(2) as fd: + ffi.C.fputs(b"hello\n", ffi.C.stderr) + ffi.C.fputs(b" world\n", ffi.C.stderr) res = fd.getvalue() assert res == b'hello\n world\n' - def test_fputs(self): + def test_vararg(self): if not sys.platform.startswith('linux'): - py.test.skip("probably no symbol 'stdout' in the lib") + py.test.skip("probably no symbol 'stderr' in the lib") ffi = FFI(backend=self.Backend()) ffi.cdef(""" - int fputs(const char *, void *); - void *stdout, *stderr; + int fprintf(void *, const char *format, ...); + void *stderr; """) ffi.C = ffi.dlopen(None) with FdWriteCapture(2) as fd: - ffi.C.fputs(b"hello from stderr\n", ffi.C.stderr) + ffi.C.fprintf(ffi.C.stderr, b"hello with no arguments\n") + ffi.C.fprintf(ffi.C.stderr, + b"hello, %s!\n", ffi.new("char[]", b"world")) + ffi.C.fprintf(ffi.C.stderr, + ffi.new("char[]", b"hello, %s!\n"), + ffi.new("char[]", b"world2")) + ffi.C.fprintf(ffi.C.stderr, + b"hello int %d long %ld long long %lld\n", + ffi.cast("int", 42), + ffi.cast("long", 84), + ffi.cast("long long", 168)) + ffi.C.fprintf(ffi.C.stderr, b"hello %p\n", ffi.NULL) res = fd.getvalue() - assert res == b'hello from stderr\n' - - def test_vararg(self): - ffi = FFI(backend=self.Backend()) - ffi.cdef(""" - int printf(const char *format, ...); - int fflush(void *); - """) - ffi.C = ffi.dlopen(None) - with FdWriteCapture() as fd: - ffi.C.printf(b"hello with no arguments\n") - ffi.C.printf(b"hello, %s!\n", ffi.new("char[]", b"world")) - ffi.C.printf(ffi.new("char[]", b"hello, %s!\n"), - ffi.new("char[]", b"world2")) - ffi.C.printf(b"hello int %d long %ld long long %lld\n", - ffi.cast("int", 42), - ffi.cast("long", 84), - ffi.cast("long long", 168)) - ffi.C.printf(b"hello %p\n", ffi.NULL) - ffi.C.fflush(ffi.NULL) - res = fd.getvalue() - if sys.platform == 'win32': - NIL = b"00000000" - elif sys.platform.startswith(('linux', 'gnu')): - NIL = b"(nil)" - else: - NIL = b"0x0" # OS/X at least assert res == (b"hello with no arguments\n" b"hello, world!\n" b"hello, world2!\n" b"hello int 42 long 84 long long 168\n" - b"hello " + NIL + b"\n") + b"hello (nil)\n") def test_must_specify_type_of_vararg(self): ffi = FFI(backend=self.Backend()) @@ -215,17 +201,18 @@ res = fptr(b"Hello") assert res == 42 # + if not sys.platform.startswith('linux'): + py.test.skip("probably no symbol 'stderr' in the lib") ffi.cdef(""" - int puts(const char *); - int fflush(void *); + int fputs(const char *, void *); + void *stderr; """) ffi.C = ffi.dlopen(None) - fptr = ffi.cast("int(*)(const char *txt)", ffi.C.puts) - assert fptr == ffi.C.puts - assert repr(fptr).startswith(" Author: Armin Rigo Branch: Changeset: r63167:c8d474348b03 Date: 2013-04-09 13:40 +0200 http://bitbucket.org/pypy/pypy/changeset/c8d474348b03/ Log: Try to work around the issues shown in the tannit32 buildbot, by only writing to stderr. Hack. diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_function.py b/pypy/module/test_lib_pypy/cffi_tests/test_function.py --- a/pypy/module/test_lib_pypy/cffi_tests/test_function.py +++ b/pypy/module/test_lib_pypy/cffi_tests/test_function.py @@ -16,7 +16,7 @@ """xxx limited to capture at most 512 bytes of output, according to the Posix manual.""" - def __init__(self, capture_fd=1): # stdout, by default + def __init__(self, capture_fd): self.capture_fd = capture_fd def __enter__(self): @@ -109,80 +109,66 @@ y = lib.TlsFree(x) assert y != 0 - def test_puts(self): + def test_fputs(self): + if not sys.platform.startswith('linux'): + py.test.skip("probably no symbol 'stderr' in the lib") ffi = FFI(backend=self.Backend()) ffi.cdef(""" - int puts(const char *); - int fflush(void *); + int fputs(const char *, void *); + void *stderr; """) ffi.C = ffi.dlopen(None) - ffi.C.puts # fetch before capturing, for easier debugging - with FdWriteCapture() as fd: - ffi.C.puts(b"hello") - ffi.C.puts(b" world") - ffi.C.fflush(ffi.NULL) + ffi.C.fputs # fetch before capturing, for easier debugging + with FdWriteCapture(2) as fd: + ffi.C.fputs(b"hello\n", ffi.C.stderr) + ffi.C.fputs(b" world\n", ffi.C.stderr) res = fd.getvalue() assert res == b'hello\n world\n' - def test_puts_without_const(self): + def test_fputs_without_const(self): + if not sys.platform.startswith('linux'): + py.test.skip("probably no symbol 'stderr' in the lib") ffi = FFI(backend=self.Backend()) ffi.cdef(""" - int puts(char *); - int fflush(void *); + int fputs(char *, void *); + void *stderr; """) ffi.C = ffi.dlopen(None) - ffi.C.puts # fetch before capturing, for easier debugging - with FdWriteCapture() as fd: - ffi.C.puts(b"hello") - ffi.C.puts(b" world") - ffi.C.fflush(ffi.NULL) + ffi.C.fputs # fetch before capturing, for easier debugging + with FdWriteCapture(2) as fd: + ffi.C.fputs(b"hello\n", ffi.C.stderr) + ffi.C.fputs(b" world\n", ffi.C.stderr) res = fd.getvalue() assert res == b'hello\n world\n' - def test_fputs(self): + def test_vararg(self): if not sys.platform.startswith('linux'): - py.test.skip("probably no symbol 'stdout' in the lib") + py.test.skip("probably no symbol 'stderr' in the lib") ffi = FFI(backend=self.Backend()) ffi.cdef(""" - int fputs(const char *, void *); - void *stdout, *stderr; + int fprintf(void *, const char *format, ...); + void *stderr; """) ffi.C = ffi.dlopen(None) with FdWriteCapture(2) as fd: - ffi.C.fputs(b"hello from stderr\n", ffi.C.stderr) + ffi.C.fprintf(ffi.C.stderr, b"hello with no arguments\n") + ffi.C.fprintf(ffi.C.stderr, + b"hello, %s!\n", ffi.new("char[]", b"world")) + ffi.C.fprintf(ffi.C.stderr, + ffi.new("char[]", b"hello, %s!\n"), + ffi.new("char[]", b"world2")) + ffi.C.fprintf(ffi.C.stderr, + b"hello int %d long %ld long long %lld\n", + ffi.cast("int", 42), + ffi.cast("long", 84), + ffi.cast("long long", 168)) + ffi.C.fprintf(ffi.C.stderr, b"hello %p\n", ffi.NULL) res = fd.getvalue() - assert res == b'hello from stderr\n' - - def test_vararg(self): - ffi = FFI(backend=self.Backend()) - ffi.cdef(""" - int printf(const char *format, ...); - int fflush(void *); - """) - ffi.C = ffi.dlopen(None) - with FdWriteCapture() as fd: - ffi.C.printf(b"hello with no arguments\n") - ffi.C.printf(b"hello, %s!\n", ffi.new("char[]", b"world")) - ffi.C.printf(ffi.new("char[]", b"hello, %s!\n"), - ffi.new("char[]", b"world2")) - ffi.C.printf(b"hello int %d long %ld long long %lld\n", - ffi.cast("int", 42), - ffi.cast("long", 84), - ffi.cast("long long", 168)) - ffi.C.printf(b"hello %p\n", ffi.NULL) - ffi.C.fflush(ffi.NULL) - res = fd.getvalue() - if sys.platform == 'win32': - NIL = b"00000000" - elif sys.platform.startswith(('linux', 'gnu')): - NIL = b"(nil)" - else: - NIL = b"0x0" # OS/X at least assert res == (b"hello with no arguments\n" b"hello, world!\n" b"hello, world2!\n" b"hello int 42 long 84 long long 168\n" - b"hello " + NIL + b"\n") + b"hello (nil)\n") def test_must_specify_type_of_vararg(self): ffi = FFI(backend=self.Backend()) @@ -216,17 +202,18 @@ res = fptr(b"Hello") assert res == 42 # + if not sys.platform.startswith('linux'): + py.test.skip("probably no symbol 'stderr' in the lib") ffi.cdef(""" - int puts(const char *); - int fflush(void *); + int fputs(const char *, void *); + void *stderr; """) ffi.C = ffi.dlopen(None) - fptr = ffi.cast("int(*)(const char *txt)", ffi.C.puts) - assert fptr == ffi.C.puts - assert repr(fptr).startswith(" Author: Antonio Cuni Branch: refactor-call_release_gil Changeset: r63168:2507dbb27234 Date: 2013-04-09 17:35 +0200 http://bitbucket.org/pypy/pypy/changeset/2507dbb27234/ Log: add jit_libffi support for longlongs on 32bit, and make it fail with an AssertionError in case we have a return type which is not supported by the jit diff --git a/rpython/jit/metainterp/test/test_fficall.py b/rpython/jit/metainterp/test/test_fficall.py --- a/rpython/jit/metainterp/test/test_fficall.py +++ b/rpython/jit/metainterp/test/test_fficall.py @@ -1,15 +1,18 @@ import py from _pytest.monkeypatch import monkeypatch +import sys import ctypes, math from rpython.rtyper.lltypesystem import lltype, rffi from rpython.rtyper.annlowlevel import llhelper from rpython.jit.metainterp.test.support import LLJitMixin +from rpython.jit.codewriter.longlong import is_longlong from rpython.rlib import jit from rpython.rlib import jit_libffi from rpython.rlib.jit_libffi import (types, CIF_DESCRIPTION, FFI_TYPE_PP, jit_ffi_call, jit_ffi_save_result) from rpython.rlib.unroll import unrolling_iterable -from rpython.rlib.rarithmetic import intmask +from rpython.rlib.rarithmetic import intmask, r_longlong +from rpython.rlib.longlong2float import float2longlong def get_description(atypes, rtype): p = lltype.malloc(CIF_DESCRIPTION, len(atypes), @@ -99,6 +102,10 @@ res = f() assert res == rvalue or (res, rvalue) == (654321, None) res = self.interp_operations(f, []) + if is_longlong(FUNC.RESULT): + # longlongs are passed around as floats inside the JIT, we + # need to convert it back before checking the value + res = float2longlong(res) assert res == rvalue or (res, rvalue) == (654321, None) self.check_operations_history(call_may_force=0, call_release_gil=1) @@ -115,6 +122,12 @@ def test_simple_call_float(self): self._run([types.double] * 2, types.double, [45.6, 78.9], -4.2) + def test_simple_call_longlong(self): + maxint32 = 2147483647 + a = r_longlong(maxint32) + 1 + b = r_longlong(maxint32) + 2 + self._run([types.slonglong] * 2, types.slonglong, [a, b], a) + def test_returns_none(self): self._run([types.signed] * 2, types.void, [456, 789], None) diff --git a/rpython/rlib/jit_libffi.py b/rpython/rlib/jit_libffi.py --- a/rpython/rlib/jit_libffi.py +++ b/rpython/rlib/jit_libffi.py @@ -104,14 +104,17 @@ """Wrapper around ffi_call(). Must receive a CIF_DESCRIPTION_P that describes the layout of the 'exchange_buffer'. """ - if cif_description.rtype == types.void: + reskind = types.getkind(cif_description.rtype) + if reskind == 'v': jit_ffi_call_impl_void(cif_description, func_addr, exchange_buffer) - elif cif_description.rtype == types.double: + elif reskind == 'f' or reskind == 'L': # L is for longlongs, on 32bit result = jit_ffi_call_impl_float(cif_description, func_addr, exchange_buffer) jit_ffi_save_result('float', cif_description, exchange_buffer, result) - else: + elif reskind == 'i' or reskind == 'u': result = jit_ffi_call_impl_int(cif_description, func_addr, exchange_buffer) jit_ffi_save_result('int', cif_description, exchange_buffer, result) + else: + assert False, 'Unsupported result kind' # we must return a NonConstant else we get the constant -1 as the result of From noreply at buildbot.pypy.org Tue Apr 9 17:50:20 2013 From: noreply at buildbot.pypy.org (antocuni) Date: Tue, 9 Apr 2013 17:50:20 +0200 (CEST) Subject: [pypy-commit] pypy refactor-call_release_gil: dont' crash if the result kind is not supported: instead, we just disable the optimization Message-ID: <20130409155020.45FB71C30E8@cobra.cs.uni-duesseldorf.de> Author: Antonio Cuni Branch: refactor-call_release_gil Changeset: r63169:841ab5d999ac Date: 2013-04-09 16:49 +0100 http://bitbucket.org/pypy/pypy/changeset/841ab5d999ac/ Log: dont' crash if the result kind is not supported: instead, we just disable the optimization diff --git a/rpython/jit/metainterp/test/test_fficall.py b/rpython/jit/metainterp/test/test_fficall.py --- a/rpython/jit/metainterp/test/test_fficall.py +++ b/rpython/jit/metainterp/test/test_fficall.py @@ -45,7 +45,7 @@ class FfiCallTests(object): - def _run(self, atypes, rtype, avalues, rvalue): + def _run(self, atypes, rtype, avalues, rvalue, expected_call_release_gil=1): cif_description = get_description(atypes, rtype) def verify(*args): @@ -108,7 +108,7 @@ res = float2longlong(res) assert res == rvalue or (res, rvalue) == (654321, None) self.check_operations_history(call_may_force=0, - call_release_gil=1) + call_release_gil=expected_call_release_gil) def test_simple_call_int(self): self._run([types.signed] * 2, types.signed, [456, 789], -42) @@ -128,6 +128,11 @@ b = r_longlong(maxint32) + 2 self._run([types.slonglong] * 2, types.slonglong, [a, b], a) + def test_simple_call_longdouble(self): + # longdouble is not supported, so we expect NOT to generate a call_release_gil + self._run([types.longdouble] * 2, types.longdouble, [12.3, 45.6], 78.9, + expected_call_release_gil=0) + def test_returns_none(self): self._run([types.signed] * 2, types.void, [456, 789], None) diff --git a/rpython/rlib/jit_libffi.py b/rpython/rlib/jit_libffi.py --- a/rpython/rlib/jit_libffi.py +++ b/rpython/rlib/jit_libffi.py @@ -114,7 +114,13 @@ result = jit_ffi_call_impl_int(cif_description, func_addr, exchange_buffer) jit_ffi_save_result('int', cif_description, exchange_buffer, result) else: - assert False, 'Unsupported result kind' + # the result kind is not supported: we disable the jit_ffi_call + # optimization by calling directly jit_ffi_call_impl_any, so the JIT + # does not see any libffi_call oopspec. + # + # Since call_release_gil is not generated, there is no need to + # jit_ffi_save_result + jit_ffi_call_impl_any(cif_description, func_addr, exchange_buffer) # we must return a NonConstant else we get the constant -1 as the result of From noreply at buildbot.pypy.org Tue Apr 9 20:11:45 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Tue, 9 Apr 2013 20:11:45 +0200 (CEST) Subject: [pypy-commit] pypy py3k: handle windows unicode results Message-ID: <20130409181145.493511C1559@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63170:40bcfcc5aae5 Date: 2013-04-09 11:10 -0700 http://bitbucket.org/pypy/pypy/changeset/40bcfcc5aae5/ Log: handle windows unicode results diff --git a/pypy/module/posix/interp_posix.py b/pypy/module/posix/interp_posix.py --- a/pypy/module/posix/interp_posix.py +++ b/pypy/module/posix/interp_posix.py @@ -533,8 +533,11 @@ len_result = len(result) result_w = [None] * len_result for i in range(len_result): - w_bytes = space.wrapbytes(result[i]) - result_w[i] = space.fsdecode(w_bytes) + if _WIN32: + result_w[i] = space.wrap(result[i]) + else: + w_bytes = space.wrapbytes(result[i]) + result_w[i] = space.fsdecode(w_bytes) else: dirname = space.str0_w(w_dirname) result = rposix.listdir(dirname) From noreply at buildbot.pypy.org Tue Apr 9 20:11:46 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Tue, 9 Apr 2013 20:11:46 +0200 (CEST) Subject: [pypy-commit] pypy py3k: adapt to py3 Message-ID: <20130409181146.83A661C1559@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63171:9c84a04b7efd Date: 2013-04-09 11:11 -0700 http://bitbucket.org/pypy/pypy/changeset/9c84a04b7efd/ Log: adapt to py3 diff --git a/pypy/module/pyexpat/test/test_parser.py b/pypy/module/pyexpat/test/test_parser.py --- a/pypy/module/pyexpat/test/test_parser.py +++ b/pypy/module/pyexpat/test/test_parser.py @@ -183,8 +183,8 @@ assert fake_reader.read_count == 4 class AppTestPyexpat2: - spaceconfig = dict(usemodules=['pyexpat', 'itertools', '_socket', - 'rctime', 'struct', 'binascii']) + spaceconfig = dict(usemodules=['_ffi', '_rawffi', 'pyexpat', 'itertools', + '_socket', 'rctime', 'struct', 'binascii']) def test_django_bug(self): xml_str = '' @@ -192,7 +192,7 @@ from xml.dom import pulldom from xml.sax import handler from xml.sax.expatreader import ExpatParser as _ExpatParser - from StringIO import StringIO + from io import StringIO class DefusedExpatParser(_ExpatParser): def start_doctype_decl(self, name, sysid, pubid, has_internal_subset): From noreply at buildbot.pypy.org Wed Apr 10 00:02:13 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Wed, 10 Apr 2013 00:02:13 +0200 (CEST) Subject: [pypy-commit] pypy stdlib-2.7.4: test and fix for repr(file) to escape file name (cpython issue14161) Message-ID: <20130409220213.B1DB61C30EE@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: stdlib-2.7.4 Changeset: r63172:6185cc1d30fc Date: 2013-04-09 16:55 -0400 http://bitbucket.org/pypy/pypy/changeset/6185cc1d30fc/ Log: test and fix for repr(file) to escape file name (cpython issue14161) diff --git a/pypy/module/_file/interp_file.py b/pypy/module/_file/interp_file.py --- a/pypy/module/_file/interp_file.py +++ b/pypy/module/_file/interp_file.py @@ -440,9 +440,6 @@ w_name = self.w_name if w_name is None: return '?' - elif self.space.is_true(self.space.isinstance(w_name, - self.space.w_str)): - return "'%s'" % self.space.str_w(w_name) else: return self.space.str_w(self.space.repr(w_name)) diff --git a/pypy/module/_file/test/test_file_extra.py b/pypy/module/_file/test/test_file_extra.py --- a/pypy/module/_file/test/test_file_extra.py +++ b/pypy/module/_file/test/test_file_extra.py @@ -607,10 +607,16 @@ assert file.closed.__doc__ == 'True if the file is closed' def test_repr_unicode_filename(self): - f = open(unicode(self.temptestfile), 'w') - assert repr(f).startswith(" Author: Brian Kearns Branch: stdlib-2.7.4 Changeset: r63173:6c338908391b Date: 2013-04-09 16:52 -0400 http://bitbucket.org/pypy/pypy/changeset/6c338908391b/ Log: test and fix for mmap of empty file (cpython issue15676) diff --git a/pypy/module/mmap/test/test_mmap.py b/pypy/module/mmap/test/test_mmap.py --- a/pypy/module/mmap/test/test_mmap.py +++ b/pypy/module/mmap/test/test_mmap.py @@ -812,3 +812,17 @@ assert m.read(10) == "ABCDEABCDE" m.close() f.close() + + def test_empty_file(self): + import mmap + f = open(self.tmpname, 'w+b') + f.close() + with open(self.tmpname, 'rb') as f: + try: + m = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) + m.close() + assert False, "should not have been able to mmap empty file" + except ValueError as e: + assert e.message == "cannot mmap an empty file" + except BaseException as e: + assert False, "unexpected exception: " + str(e) diff --git a/rpython/rlib/rmmap.py b/rpython/rlib/rmmap.py --- a/rpython/rlib/rmmap.py +++ b/rpython/rlib/rmmap.py @@ -657,6 +657,8 @@ size = st[stat.ST_SIZE] if stat.S_ISREG(mode): if map_size == 0: + if size == 0: + raise RValueError("cannot mmap an empty file") if offset > size: raise RValueError( "mmap offset is greater than file size") @@ -778,6 +780,8 @@ size = (high << 32) + low size = rffi.cast(lltype.Signed, size) if map_size == 0: + if size == 0: + raise RValueError("cannot mmap an empty file") if offset > size: raise RValueError( "mmap offset is greater than file size") From noreply at buildbot.pypy.org Wed Apr 10 00:02:16 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Wed, 10 Apr 2013 00:02:16 +0200 (CEST) Subject: [pypy-commit] pypy stdlib-2.7.4: verify fd in signal.set_wakeup_fd (cpython issue16992) Message-ID: <20130409220216.332D51C30EE@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: stdlib-2.7.4 Changeset: r63174:172b279b88eb Date: 2013-04-09 17:28 -0400 http://bitbucket.org/pypy/pypy/changeset/172b279b88eb/ Log: verify fd in signal.set_wakeup_fd (cpython issue16992) diff --git a/pypy/module/signal/interp_signal.py b/pypy/module/signal/interp_signal.py --- a/pypy/module/signal/interp_signal.py +++ b/pypy/module/signal/interp_signal.py @@ -2,6 +2,8 @@ import signal as cpy_signal import sys +import os +import errno from pypy.interpreter.error import OperationError, exception_from_errno from pypy.interpreter.executioncontext import (AsyncAction, AbstractActionFlag, @@ -236,6 +238,12 @@ space.w_ValueError, space.wrap("set_wakeup_fd only works in main thread " "or with __pypy__.thread.enable_signals()")) + if fd != -1: + try: + os.fstat(fd) + except OSError, e: + if e.errno == errno.EBADF: + raise OperationError(space.w_ValueError, space.wrap("invalid fd")) old_fd = pypysig_set_wakeup_fd(fd) return space.wrap(intmask(old_fd)) diff --git a/pypy/module/signal/test/test_signal.py b/pypy/module/signal/test/test_signal.py --- a/pypy/module/signal/test/test_signal.py +++ b/pypy/module/signal/test/test_signal.py @@ -41,6 +41,8 @@ def setup_class(cls): cls.w_signal = cls.space.getbuiltinmodule('signal') + cls.w_temppath = cls.space.wrap( + str(py.test.ensuretemp("signal").join("foo.txt"))) def test_exported_names(self): import os @@ -217,6 +219,12 @@ # signal.signal(signal.SIGINT, signal.SIG_DFL) + def test_set_wakeup_fd_invalid(self): + import signal + with open(self.temppath, 'wb') as f: + fd = f.fileno() + raises(ValueError, signal.set_wakeup_fd, fd) + def test_siginterrupt(self): import signal, os, time if not hasattr(signal, 'siginterrupt'): From noreply at buildbot.pypy.org Wed Apr 10 00:02:18 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Wed, 10 Apr 2013 00:02:18 +0200 (CEST) Subject: [pypy-commit] pypy stdlib-2.7.4: allow socket.getaddrinfo port to be a long, test (cpython issue8853) Message-ID: <20130409220218.002981C30EE@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: stdlib-2.7.4 Changeset: r63175:2a7832d3e68f Date: 2013-04-09 17:54 -0400 http://bitbucket.org/pypy/pypy/changeset/2a7832d3e68f/ Log: allow socket.getaddrinfo port to be a long, test (cpython issue8853) diff --git a/pypy/module/_socket/interp_func.py b/pypy/module/_socket/interp_func.py --- a/pypy/module/_socket/interp_func.py +++ b/pypy/module/_socket/interp_func.py @@ -268,13 +268,14 @@ # port can be None, int or string if space.is_w(w_port, space.w_None): port = None - elif space.isinstance_w(w_port, space.w_int): + elif space.isinstance_w(w_port, space.w_int) or space.isinstance_w(w_port, space.w_long): port = str(space.int_w(w_port)) elif space.isinstance_w(w_port, space.w_str): port = space.str_w(w_port) else: raise OperationError(space.w_TypeError, - space.wrap("Int or String expected")) + space.wrap( + "getaddrinfo() argument 2 must be integer or string")) try: lst = rsocket.getaddrinfo(host, port, family, socktype, proto, flags) diff --git a/pypy/module/_socket/test/test_sock_app.py b/pypy/module/_socket/test/test_sock_app.py --- a/pypy/module/_socket/test/test_sock_app.py +++ b/pypy/module/_socket/test/test_sock_app.py @@ -226,6 +226,9 @@ w_l = space.appexec([w_socket, space.wrap(host), space.wrap(port)], "(_socket, host, port): return _socket.getaddrinfo(host, port)") assert space.unwrap(w_l) == info + w_l = space.appexec([w_socket, space.wrap(host), space.wrap(port)], + "(_socket, host, port): return _socket.getaddrinfo(host, long(port))") + assert space.unwrap(w_l) == info py.test.skip("Unicode conversion is too slow") w_l = space.appexec([w_socket, space.wrap(unicode(host)), space.wrap(port)], "(_socket, host, port): return _socket.getaddrinfo(host, port)") From noreply at buildbot.pypy.org Wed Apr 10 00:02:19 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Wed, 10 Apr 2013 00:02:19 +0200 (CEST) Subject: [pypy-commit] pypy stdlib-2.7.4: fix for renamed import upstream Message-ID: <20130409220219.1FC541C30EE@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: stdlib-2.7.4 Changeset: r63176:daf35bc42622 Date: 2013-04-09 18:00 -0400 http://bitbucket.org/pypy/pypy/changeset/daf35bc42622/ Log: fix for renamed import upstream diff --git a/lib-python/2.7/test/test_tempfile.py b/lib-python/2.7/test/test_tempfile.py --- a/lib-python/2.7/test/test_tempfile.py +++ b/lib-python/2.7/test/test_tempfile.py @@ -27,8 +27,8 @@ # TEST_FILES may need to be tweaked for systems depending on the maximum # number of files that can be opened at one time (see ulimit -n) -if sys.platform.startswith("openbsd"): - TEST_FILES = 64 # ulimit -n defaults to 128 for normal users +if sys.platform in ('openbsd3', 'openbsd4'): + TEST_FILES = 48 else: TEST_FILES = 100 @@ -322,7 +322,7 @@ dir = tempfile.mkdtemp() try: self.do_create(dir=dir).write("blat") - test_support.gc_collect() + support.gc_collect() finally: os.rmdir(dir) @@ -607,7 +607,7 @@ self.do_create(suf="b") self.do_create(pre="a", suf="b") self.do_create(pre="aa", suf=".txt") - test_support.gc_collect() + support.gc_collect() def test_many(self): # mktemp can choose many usable file names (stochastic) @@ -615,7 +615,7 @@ for i in extant: extant[i] = self.do_create(pre="aa") del extant - test_support.gc_collect() + support.gc_collect() ## def test_warning(self): ## # mktemp issues a warning when used From noreply at buildbot.pypy.org Wed Apr 10 00:41:26 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Wed, 10 Apr 2013 00:41:26 +0200 (CEST) Subject: [pypy-commit] pypy stdlib-2.7.4: reduce diffs with upstream Message-ID: <20130409224126.4CC801C1559@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: stdlib-2.7.4 Changeset: r63177:36f57b47802b Date: 2013-04-09 18:41 -0400 http://bitbucket.org/pypy/pypy/changeset/36f57b47802b/ Log: reduce diffs with upstream diff --git a/lib-python/2.7/ctypes/test/test_cfuncs.py b/lib-python/2.7/ctypes/test/test_cfuncs.py --- a/lib-python/2.7/ctypes/test/test_cfuncs.py +++ b/lib-python/2.7/ctypes/test/test_cfuncs.py @@ -3,6 +3,7 @@ import unittest from ctypes import * + import _ctypes_test from test.test_support import impl_detail @@ -164,7 +165,7 @@ self._dll.tf_D.argtypes = (c_longdouble,) self.assertEqual(self._dll.tf_D(42.), 14.) self.assertEqual(self.S(), 42) - + @impl_detail('long double not supported by PyPy', pypy=False) def test_longdouble_plus(self): self._dll.tf_bD.restype = c_longdouble diff --git a/lib-python/2.7/idlelib/ReplaceDialog.py b/lib-python/2.7/idlelib/ReplaceDialog.py --- a/lib-python/2.7/idlelib/ReplaceDialog.py +++ b/lib-python/2.7/idlelib/ReplaceDialog.py @@ -122,6 +122,7 @@ text.undo_block_stop() if first and last: self.show_hit(first, last) + self.close() def do_find(self, ok=0): if not self.engine.getprog(): diff --git a/lib-python/2.7/test/ssl_cert.pem b/lib-python/2.7/test/ssl_cert.pem deleted file mode 100644 --- a/lib-python/2.7/test/ssl_cert.pem +++ /dev/null @@ -1,14 +0,0 @@ ------BEGIN CERTIFICATE----- -MIICLDCCAdYCAQAwDQYJKoZIhvcNAQEEBQAwgaAxCzAJBgNVBAYTAlBUMRMwEQYD -VQQIEwpRdWVlbnNsYW5kMQ8wDQYDVQQHEwZMaXNib2ExFzAVBgNVBAoTDk5ldXJv -bmlvLCBMZGEuMRgwFgYDVQQLEw9EZXNlbnZvbHZpbWVudG8xGzAZBgNVBAMTEmJy -dXR1cy5uZXVyb25pby5wdDEbMBkGCSqGSIb3DQEJARYMc2FtcG9AaWtpLmZpMB4X -DTk2MDkwNTAzNDI0M1oXDTk2MTAwNTAzNDI0M1owgaAxCzAJBgNVBAYTAlBUMRMw -EQYDVQQIEwpRdWVlbnNsYW5kMQ8wDQYDVQQHEwZMaXNib2ExFzAVBgNVBAoTDk5l -dXJvbmlvLCBMZGEuMRgwFgYDVQQLEw9EZXNlbnZvbHZpbWVudG8xGzAZBgNVBAMT -EmJydXR1cy5uZXVyb25pby5wdDEbMBkGCSqGSIb3DQEJARYMc2FtcG9AaWtpLmZp -MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAL7+aty3S1iBA/+yxjxv4q1MUTd1kjNw -L4lYKbpzzlmC5beaQXeQ2RmGMTXU+mDvuqItjVHOK3DvPK7lTcSGftUCAwEAATAN -BgkqhkiG9w0BAQQFAANBAFqPEKFjk6T6CKTHvaQeEAsX0/8YHPHqH/9AnhSjrwuX -9EBc0n6bVGhN7XaXd6sJ7dym9sbsWxb+pJdurnkxjx4= ------END CERTIFICATE----- diff --git a/lib-python/2.7/test/ssl_key.pem b/lib-python/2.7/test/ssl_key.pem deleted file mode 100644 --- a/lib-python/2.7/test/ssl_key.pem +++ /dev/null @@ -1,9 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIBPAIBAAJBAL7+aty3S1iBA/+yxjxv4q1MUTd1kjNwL4lYKbpzzlmC5beaQXeQ -2RmGMTXU+mDvuqItjVHOK3DvPK7lTcSGftUCAwEAAQJBALjkK+jc2+iihI98riEF -oudmkNziSRTYjnwjx8mCoAjPWviB3c742eO3FG4/soi1jD9A5alihEOXfUzloenr -8IECIQD3B5+0l+68BA/6d76iUNqAAV8djGTzvxnCxycnxPQydQIhAMXt4trUI3nc -a+U8YL2HPFA3gmhBsSICbq2OptOCnM7hAiEA6Xi3JIQECob8YwkRj29DU3/4WYD7 -WLPgsQpwo1GuSpECICGsnWH5oaeD9t9jbFoSfhJvv0IZmxdcLpRcpslpeWBBAiEA -6/5B8J0GHdJq89FHwEG/H2eVVUYu5y/aD6sgcm+0Avg= ------END RSA PRIVATE KEY----- diff --git a/lib-python/2.7/test/test_set.py b/lib-python/2.7/test/test_set.py --- a/lib-python/2.7/test/test_set.py +++ b/lib-python/2.7/test/test_set.py @@ -784,10 +784,9 @@ for v in self.set: self.assertIn(v, self.values) setiter = iter(self.set) - if test_support.check_impl_detail(): - # note: __length_hint__ is an internal undocumented API, - # don't rely on it in your own programs - self.assertEqual(setiter.__length_hint__(), len(self.set)) + # note: __length_hint__ is an internal undocumented API, + # don't rely on it in your own programs + self.assertEqual(setiter.__length_hint__(), len(self.set)) def test_pickling(self): p = pickle.dumps(self.set) From noreply at buildbot.pypy.org Wed Apr 10 01:40:27 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Wed, 10 Apr 2013 01:40:27 +0200 (CEST) Subject: [pypy-commit] pypy default: kill the cpython-like unicodehelper function names. base encode off Message-ID: <20130409234027.DF07D1C010B@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: Changeset: r63180:5f4123d40311 Date: 2013-04-09 16:23 -0700 http://bitbucket.org/pypy/pypy/changeset/5f4123d40311/ Log: kill the cpython-like unicodehelper function names. base encode off unicodetype's similar function w/ shortcuts for common encodings diff --git a/pypy/interpreter/pyparser/parsestring.py b/pypy/interpreter/pyparser/parsestring.py --- a/pypy/interpreter/pyparser/parsestring.py +++ b/pypy/interpreter/pyparser/parsestring.py @@ -91,9 +91,9 @@ assert 0 <= bufp <= bufq substr = buf[bufp:bufq] if rawmode: - v = unicodehelper.PyUnicode_DecodeRawUnicodeEscape(space, substr) + v = unicodehelper.decode_raw_unicode_escape(space, substr) else: - v = unicodehelper.PyUnicode_DecodeUnicodeEscape(space, substr) + v = unicodehelper.decode_unicode_escape(space, substr) return space.wrap(v) need_encoding = (encoding is not None and @@ -103,8 +103,8 @@ substr = s[ps : q] if rawmode or '\\' not in s[ps:]: if need_encoding: - w_u = space.wrap(unicodehelper.PyUnicode_DecodeUTF8(space, substr)) - w_v = unicodehelper.PyUnicode_AsEncodedString(space, w_u, space.wrap(encoding)) + w_u = space.wrap(unicodehelper.decode_utf8(space, substr)) + w_v = unicodehelper.encode(space, w_u, encoding) return w_v else: return space.wrap(substr) @@ -219,8 +219,8 @@ # while (s < end && *s != '\\') s++; */ /* inefficient for u".." while ps < end and ord(s[ps]) & 0x80: ps += 1 - w_u = space.wrap(unicodehelper.PyUnicode_DecodeUTF8(space, s[pt:ps])) - w_v = unicodehelper.PyUnicode_AsEncodedString(space, w_u, space.wrap(encoding)) + w_u = space.wrap(unicodehelper.decode_utf8(space, s[pt:ps])) + w_v = unicodehelper.encode(space, w_u, encoding) v = space.str_w(w_v) return v, ps diff --git a/pypy/interpreter/unicodehelper.py b/pypy/interpreter/unicodehelper.py --- a/pypy/interpreter/unicodehelper.py +++ b/pypy/interpreter/unicodehelper.py @@ -29,11 +29,12 @@ # ____________________________________________________________ -def PyUnicode_AsEncodedString(space, w_data, w_encoding): - return interp_codecs.encode(space, w_data, w_encoding) +def encode(space, w_data, encoding=None, errors='strict'): + from pypy.objspace.std.unicodetype import encode_object + return encode_object(space, w_data, encoding, errors) # These functions take and return unwrapped rpython strings and unicodes -def PyUnicode_DecodeUnicodeEscape(space, string): +def decode_unicode_escape(space, string): state = space.fromcache(interp_codecs.CodecState) unicodedata_handler = state.get_unicodedata_handler(space) result, consumed = runicode.str_decode_unicode_escape( @@ -42,20 +43,20 @@ unicodedata_handler=unicodedata_handler) return result -def PyUnicode_DecodeRawUnicodeEscape(space, string): +def decode_raw_unicode_escape(space, string): result, consumed = runicode.str_decode_raw_unicode_escape( string, len(string), "strict", final=True, errorhandler=decode_error_handler(space)) return result -def PyUnicode_DecodeUTF8(space, string): +def decode_utf8(space, string): result, consumed = runicode.str_decode_utf_8( string, len(string), "strict", final=True, errorhandler=decode_error_handler(space), allow_surrogates=True) return result -def PyUnicode_EncodeUTF8(space, uni): +def encode_utf8(space, uni): return runicode.unicode_encode_utf_8( uni, len(uni), "strict", errorhandler=encode_error_handler(space), diff --git a/pypy/module/pyexpat/interp_pyexpat.py b/pypy/module/pyexpat/interp_pyexpat.py --- a/pypy/module/pyexpat/interp_pyexpat.py +++ b/pypy/module/pyexpat/interp_pyexpat.py @@ -475,8 +475,8 @@ def w_convert(self, space, s): if self.returns_unicode: - from pypy.interpreter.unicodehelper import PyUnicode_DecodeUTF8 - return space.wrap(PyUnicode_DecodeUTF8(space, s)) + from pypy.interpreter.unicodehelper import decode_utf8 + return space.wrap(decode_utf8(space, s)) else: return space.wrap(s) diff --git a/pypy/objspace/std/marshal_impl.py b/pypy/objspace/std/marshal_impl.py --- a/pypy/objspace/std/marshal_impl.py +++ b/pypy/objspace/std/marshal_impl.py @@ -405,11 +405,11 @@ register(TYPE_CODE, unmarshal_pycode) def marshal_w__Unicode(space, w_unicode, m): - s = unicodehelper.PyUnicode_EncodeUTF8(space, space.unicode_w(w_unicode)) + s = unicodehelper.encode_utf8(space, space.unicode_w(w_unicode)) m.atom_str(TYPE_UNICODE, s) def unmarshal_Unicode(space, u, tc): - return space.wrap(unicodehelper.PyUnicode_DecodeUTF8(space, u.get_str())) + return space.wrap(unicodehelper.decode_utf8(space, u.get_str())) register(TYPE_UNICODE, unmarshal_Unicode) app = gateway.applevel(r''' From noreply at buildbot.pypy.org Wed Apr 10 01:40:29 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Wed, 10 Apr 2013 01:40:29 +0200 (CEST) Subject: [pypy-commit] pypy py3k: merge default Message-ID: <20130409234029.468E31C010B@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63181:74807be9d93d Date: 2013-04-09 16:31 -0700 http://bitbucket.org/pypy/pypy/changeset/74807be9d93d/ Log: merge default diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -258,6 +258,7 @@ """) libname = 'sqlite3' if sys.platform == 'win32': + import os _libname = os.path.join(os.path.dirname(sys.executable), libname) if os.path.exists(_libname + '.dll'): libname = _libname diff --git a/pypy/interpreter/pyparser/parsestring.py b/pypy/interpreter/pyparser/parsestring.py --- a/pypy/interpreter/pyparser/parsestring.py +++ b/pypy/interpreter/pyparser/parsestring.py @@ -91,7 +91,7 @@ bufq = len(buf) assert 0 <= bufp <= bufq substr = buf[bufp:bufq] - v = unicodehelper.PyUnicode_DecodeUnicodeEscape(space, substr) + v = unicodehelper.decode_unicode_escape(space, substr) return space.wrap(v) assert 0 <= ps <= q @@ -108,7 +108,7 @@ if not unicode_literal: return space.wrapbytes(substr) else: - v = unicodehelper.PyUnicode_DecodeUTF8(space, substr) + v = unicodehelper.decode_utf8(space, substr) return space.wrap(v) v = PyString_DecodeEscape(space, substr, encoding) @@ -218,8 +218,8 @@ # while (s < end && *s != '\\') s++; */ /* inefficient for u".." while ps < end and ord(s[ps]) & 0x80: ps += 1 - w_u = space.wrap(unicodehelper.PyUnicode_DecodeUTF8(space, s[pt:ps])) - w_v = unicodehelper.PyUnicode_AsEncodedString(space, w_u, space.wrap(encoding)) + w_u = space.wrap(unicodehelper.decode_utf8(space, s[pt:ps])) + w_v = unicodehelper.encode(space, w_u, encoding) v = space.bytes_w(w_v) return v, ps diff --git a/pypy/interpreter/unicodehelper.py b/pypy/interpreter/unicodehelper.py --- a/pypy/interpreter/unicodehelper.py +++ b/pypy/interpreter/unicodehelper.py @@ -91,11 +91,12 @@ space.wrap('surrogateescape')) return space.wrapbytes(bytes) -def PyUnicode_AsEncodedString(space, w_data, w_encoding): - return interp_codecs.encode(space, w_data, w_encoding) +def encode(space, w_data, encoding=None, errors='strict'): + from pypy.objspace.std.unicodetype import encode_object + return encode_object(space, w_data, encoding, errors) # These functions take and return unwrapped rpython strings and unicodes -def PyUnicode_DecodeUnicodeEscape(space, string): +def decode_unicode_escape(space, string): state = space.fromcache(interp_codecs.CodecState) unicodedata_handler = state.get_unicodedata_handler(space) result, consumed = runicode.str_decode_unicode_escape( @@ -104,20 +105,20 @@ unicodedata_handler=unicodedata_handler) return result -def PyUnicode_DecodeRawUnicodeEscape(space, string): +def decode_raw_unicode_escape(space, string): result, consumed = runicode.str_decode_raw_unicode_escape( string, len(string), "strict", final=True, errorhandler=decode_error_handler(space)) return result -def PyUnicode_DecodeUTF8(space, string, allow_surrogates=False): +def decode_utf8(space, string, allow_surrogates=False): result, consumed = runicode.str_decode_utf_8( string, len(string), "strict", final=True, errorhandler=decode_error_handler(space), allow_surrogates=allow_surrogates) return result -def PyUnicode_EncodeUTF8(space, uni, allow_surrogates=False): +def encode_utf8(space, uni, allow_surrogates=False): return runicode.unicode_encode_utf_8( uni, len(uni), "strict", errorhandler=encode_error_handler(space), diff --git a/pypy/module/pyexpat/interp_pyexpat.py b/pypy/module/pyexpat/interp_pyexpat.py --- a/pypy/module/pyexpat/interp_pyexpat.py +++ b/pypy/module/pyexpat/interp_pyexpat.py @@ -473,8 +473,8 @@ # Handlers management def w_convert(self, space, s): - from pypy.interpreter.unicodehelper import PyUnicode_DecodeUTF8 - return space.wrap(PyUnicode_DecodeUTF8(space, s)) + from pypy.interpreter.unicodehelper import decode_utf8 + return space.wrap(decode_utf8(space, s)) def w_convert_charp(self, space, data): if data: diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_function.py b/pypy/module/test_lib_pypy/cffi_tests/test_function.py --- a/pypy/module/test_lib_pypy/cffi_tests/test_function.py +++ b/pypy/module/test_lib_pypy/cffi_tests/test_function.py @@ -16,7 +16,7 @@ """xxx limited to capture at most 512 bytes of output, according to the Posix manual.""" - def __init__(self, capture_fd=1): # stdout, by default + def __init__(self, capture_fd): self.capture_fd = capture_fd def __enter__(self): @@ -109,80 +109,66 @@ y = lib.TlsFree(x) assert y != 0 - def test_puts(self): + def test_fputs(self): + if not sys.platform.startswith('linux'): + py.test.skip("probably no symbol 'stderr' in the lib") ffi = FFI(backend=self.Backend()) ffi.cdef(""" - int puts(const char *); - int fflush(void *); + int fputs(const char *, void *); + void *stderr; """) ffi.C = ffi.dlopen(None) - ffi.C.puts # fetch before capturing, for easier debugging - with FdWriteCapture() as fd: - ffi.C.puts(b"hello") - ffi.C.puts(b" world") - ffi.C.fflush(ffi.NULL) + ffi.C.fputs # fetch before capturing, for easier debugging + with FdWriteCapture(2) as fd: + ffi.C.fputs(b"hello\n", ffi.C.stderr) + ffi.C.fputs(b" world\n", ffi.C.stderr) res = fd.getvalue() assert res == b'hello\n world\n' - def test_puts_without_const(self): + def test_fputs_without_const(self): + if not sys.platform.startswith('linux'): + py.test.skip("probably no symbol 'stderr' in the lib") ffi = FFI(backend=self.Backend()) ffi.cdef(""" - int puts(char *); - int fflush(void *); + int fputs(char *, void *); + void *stderr; """) ffi.C = ffi.dlopen(None) - ffi.C.puts # fetch before capturing, for easier debugging - with FdWriteCapture() as fd: - ffi.C.puts(b"hello") - ffi.C.puts(b" world") - ffi.C.fflush(ffi.NULL) + ffi.C.fputs # fetch before capturing, for easier debugging + with FdWriteCapture(2) as fd: + ffi.C.fputs(b"hello\n", ffi.C.stderr) + ffi.C.fputs(b" world\n", ffi.C.stderr) res = fd.getvalue() assert res == b'hello\n world\n' - def test_fputs(self): + def test_vararg(self): if not sys.platform.startswith('linux'): - py.test.skip("probably no symbol 'stdout' in the lib") + py.test.skip("probably no symbol 'stderr' in the lib") ffi = FFI(backend=self.Backend()) ffi.cdef(""" - int fputs(const char *, void *); - void *stdout, *stderr; + int fprintf(void *, const char *format, ...); + void *stderr; """) ffi.C = ffi.dlopen(None) with FdWriteCapture(2) as fd: - ffi.C.fputs(b"hello from stderr\n", ffi.C.stderr) + ffi.C.fprintf(ffi.C.stderr, b"hello with no arguments\n") + ffi.C.fprintf(ffi.C.stderr, + b"hello, %s!\n", ffi.new("char[]", b"world")) + ffi.C.fprintf(ffi.C.stderr, + ffi.new("char[]", b"hello, %s!\n"), + ffi.new("char[]", b"world2")) + ffi.C.fprintf(ffi.C.stderr, + b"hello int %d long %ld long long %lld\n", + ffi.cast("int", 42), + ffi.cast("long", 84), + ffi.cast("long long", 168)) + ffi.C.fprintf(ffi.C.stderr, b"hello %p\n", ffi.NULL) res = fd.getvalue() - assert res == b'hello from stderr\n' - - def test_vararg(self): - ffi = FFI(backend=self.Backend()) - ffi.cdef(""" - int printf(const char *format, ...); - int fflush(void *); - """) - ffi.C = ffi.dlopen(None) - with FdWriteCapture() as fd: - ffi.C.printf(b"hello with no arguments\n") - ffi.C.printf(b"hello, %s!\n", ffi.new("char[]", b"world")) - ffi.C.printf(ffi.new("char[]", b"hello, %s!\n"), - ffi.new("char[]", b"world2")) - ffi.C.printf(b"hello int %d long %ld long long %lld\n", - ffi.cast("int", 42), - ffi.cast("long", 84), - ffi.cast("long long", 168)) - ffi.C.printf(b"hello %p\n", ffi.NULL) - ffi.C.fflush(ffi.NULL) - res = fd.getvalue() - if sys.platform == 'win32': - NIL = b"00000000" - elif sys.platform.startswith(('linux', 'gnu')): - NIL = b"(nil)" - else: - NIL = b"0x0" # OS/X at least assert res == (b"hello with no arguments\n" b"hello, world!\n" b"hello, world2!\n" b"hello int 42 long 84 long long 168\n" - b"hello " + NIL + b"\n") + b"hello (nil)\n") def test_must_specify_type_of_vararg(self): ffi = FFI(backend=self.Backend()) @@ -216,17 +202,18 @@ res = fptr(b"Hello") assert res == 42 # + if not sys.platform.startswith('linux'): + py.test.skip("probably no symbol 'stderr' in the lib") ffi.cdef(""" - int puts(const char *); - int fflush(void *); + int fputs(const char *, void *); + void *stderr; """) ffi.C = ffi.dlopen(None) - fptr = ffi.cast("int(*)(const char *txt)", ffi.C.puts) - assert fptr == ffi.C.puts - assert repr(fptr).startswith(" Author: Philip Jenvey Branch: py3k Changeset: r63182:089c32b3f248 Date: 2013-04-09 16:38 -0700 http://bitbucket.org/pypy/pypy/changeset/089c32b3f248/ Log: kill more cpython-like unicodehelper function names diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py --- a/pypy/interpreter/baseobjspace.py +++ b/pypy/interpreter/baseobjspace.py @@ -1382,12 +1382,12 @@ return w_obj.identifier_w(self) def fsencode(space, w_obj): - from pypy.interpreter.unicodehelper import PyUnicode_EncodeFSDefault - return PyUnicode_EncodeFSDefault(space, w_obj) + from pypy.interpreter.unicodehelper import fsencode + return fsencode(space, w_obj) def fsdecode(space, w_obj): - from pypy.interpreter.unicodehelper import PyUnicode_DecodeFSDefault - return PyUnicode_DecodeFSDefault(space, w_obj) + from pypy.interpreter.unicodehelper import fsdecode + return fsdecode(space, w_obj) def fsencode_w(self, w_obj): if self.isinstance_w(w_obj, self.w_unicode): diff --git a/pypy/interpreter/unicodehelper.py b/pypy/interpreter/unicodehelper.py --- a/pypy/interpreter/unicodehelper.py +++ b/pypy/interpreter/unicodehelper.py @@ -37,7 +37,7 @@ # ____________________________________________________________ -def PyUnicode_DecodeFSDefault(space, w_string): +def fsdecode(space, w_string): state = space.fromcache(interp_codecs.CodecState) if _WIN32: bytes = space.bytes_w(w_string) @@ -64,7 +64,7 @@ space.wrap('surrogateescape')) return space.wrap(uni) -def PyUnicode_EncodeFSDefault(space, w_uni): +def fsencode(space, w_uni): state = space.fromcache(interp_codecs.CodecState) if _WIN32: uni = space.unicode_w(w_uni) From noreply at buildbot.pypy.org Wed Apr 10 01:40:31 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Wed, 10 Apr 2013 01:40:31 +0200 (CEST) Subject: [pypy-commit] pypy py3k: unicodehelper.encode is easier here Message-ID: <20130409234031.AE5CF1C010B@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63183:cce7fe52fb0a Date: 2013-04-09 16:40 -0700 http://bitbucket.org/pypy/pypy/changeset/cce7fe52fb0a/ Log: unicodehelper.encode is easier here diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py --- a/pypy/interpreter/pyopcode.py +++ b/pypy/interpreter/pyopcode.py @@ -1401,8 +1401,8 @@ from pypy.interpreter.astcompiler import consts if space.isinstance_w(w_source, space.w_unicode): - from pypy.objspace.std.unicodetype import encode_object - w_source = encode_object(space, w_source, None, None) + from pypy.interpreter.unicodehelper import encode + w_source = encode(space, w_source) source = space.bytes0_w(w_source) flags |= consts.PyCF_IGNORE_COOKIE elif space.isinstance_w(w_source, space.w_bytes): From noreply at buildbot.pypy.org Wed Apr 10 01:46:28 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Wed, 10 Apr 2013 01:46:28 +0200 (CEST) Subject: [pypy-commit] pypy py3k: have the code module display chained exceptions since our repl uses it Message-ID: <20130409234628.CB0B11C010B@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63184:1341a432e134 Date: 2013-04-09 16:45 -0700 http://bitbucket.org/pypy/pypy/changeset/1341a432e134/ Log: have the code module display chained exceptions since our repl uses it diff --git a/lib-python/3/code.py b/lib-python/3/code.py --- a/lib-python/3/code.py +++ b/lib-python/3/code.py @@ -130,19 +130,29 @@ The output is written by self.write(), below. """ + sys.last_type, sys.last_value, last_tb = ei = sys.exc_info() + sys.last_traceback = last_tb try: - type, value, tb = sys.exc_info() - sys.last_type = type - sys.last_value = value - sys.last_traceback = tb - tblist = traceback.extract_tb(tb) - del tblist[:1] - lines = traceback.format_list(tblist) - if lines: - lines.insert(0, "Traceback (most recent call last):\n") - lines.extend(traceback.format_exception_only(type, value)) + lines = [] + for value, tb in traceback._iter_chain(*ei[1:]): + if isinstance(value, str): + lines.append(value) + lines.append('\n') + continue + if tb: + tblist = traceback.extract_tb(tb) + if tb is last_tb: + # The last traceback includes the frame we + # exec'd in + del tblist[:1] + tblines = traceback.format_list(tblist) + if tblines: + lines.append("Traceback (most recent call last):\n") + lines.extend(tblines) + lines.extend(traceback.format_exception_only(type(value), + value)) finally: - tblist = tb = None + tblist = last_tb = ei = None self.write(''.join(lines)) def write(self, data): diff --git a/pypy/module/test_lib_pypy/test_code_module.py b/pypy/module/test_lib_pypy/test_code_module.py new file mode 100644 --- /dev/null +++ b/pypy/module/test_lib_pypy/test_code_module.py @@ -0,0 +1,42 @@ +class AppTestCodeModule: + + def w_get_interp(self): + import code + import io + class MockedInterpreter(code.InteractiveInterpreter): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.out = io.StringIO() + + def write(self, data): + self.out.write(data) + return MockedInterpreter() + + def test_cause_tb(self): + interp = self.get_interp() + interp.runsource('raise IOError from OSError') + result = interp.out.getvalue() + expected_header = """OSError + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): +""" + assert expected_header in result + assert result.endswith("IOError\n") + + def test_context_tb(self): + interp = self.get_interp() + interp.runsource("""\ +try: zzzeek +except: _diana_ +""") + result = interp.out.getvalue() + expected_header = """NameError: name 'zzzeek' is not defined + +During handling of the above exception, another exception occurred: + +Traceback (most recent call last): +""" + assert expected_header in result + assert result.endswith("NameError: name '_diana_' is not defined\n") From noreply at buildbot.pypy.org Wed Apr 10 02:26:22 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Wed, 10 Apr 2013 02:26:22 +0200 (CEST) Subject: [pypy-commit] pypy py3k: translation fix Message-ID: <20130410002622.5D5831C010B@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63185:8b49abe5e41a Date: 2013-04-09 17:25 -0700 http://bitbucket.org/pypy/pypy/changeset/8b49abe5e41a/ Log: translation fix diff --git a/pypy/module/pypyjit/interp_jit.py b/pypy/module/pypyjit/interp_jit.py --- a/pypy/module/pypyjit/interp_jit.py +++ b/pypy/module/pypyjit/interp_jit.py @@ -29,10 +29,12 @@ def get_printable_location(next_instr, is_being_profiled, bytecode): from pypy.tool.stdlib_opcode import opcode_method_names + from rpython.rlib.runicode import unicode_encode_utf_8 name = opcode_method_names[ord(bytecode.co_code[next_instr])] + repru = bytecode.get_repr() # XXX: lame - repre = bytecode.get_repr().encode('utf-8', 'backslashreplace') - return '%s #%d %s' % (repre, next_instr, name) + reprs = unicode_encode_utf_8(repru, len(repru), "replace") + return '%s #%d %s' % (reprs, next_instr, name) def get_jitcell_at(next_instr, is_being_profiled, bytecode): return bytecode.jit_cells.get((next_instr, is_being_profiled), None) From noreply at buildbot.pypy.org Wed Apr 10 04:53:28 2013 From: noreply at buildbot.pypy.org (alex_gaynor) Date: Wed, 10 Apr 2013 04:53:28 +0200 (CEST) Subject: [pypy-commit] pypy default: make looking up encodings free with the JIT Message-ID: <20130410025328.9B3601C30E8@cobra.cs.uni-duesseldorf.de> Author: Alex Gaynor Branch: Changeset: r63186:c514bbc4c086 Date: 2013-04-09 19:53 -0700 http://bitbucket.org/pypy/pypy/changeset/c514bbc4c086/ Log: make looking up encodings free with the JIT diff --git a/pypy/module/_codecs/interp_codecs.py b/pypy/module/_codecs/interp_codecs.py --- a/pypy/module/_codecs/interp_codecs.py +++ b/pypy/module/_codecs/interp_codecs.py @@ -1,10 +1,18 @@ +from rpython.rlib import jit +from rpython.rlib.objectmodel import we_are_translated +from rpython.rlib.rstring import UnicodeBuilder + from pypy.interpreter.error import OperationError, operationerrfmt from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault -from rpython.rlib.rstring import UnicodeBuilder -from rpython.rlib.objectmodel import we_are_translated + + +class VersionTag(object): + pass class CodecState(object): + _immutable_fields_ = ["version?"] + def __init__(self, space): self.codec_search_path = [] self.codec_search_cache = {} @@ -14,6 +22,7 @@ self.encode_error_handler = self.make_encode_errorhandler(space) self.unicodedata_handler = None + self.modified() def _make_errorhandler(self, space, decode): def call_errorhandler(errors, encoding, reason, input, startpos, @@ -86,9 +95,20 @@ self.unicodedata_handler = UnicodeData_Handler(space, w_getcode) return self.unicodedata_handler + def modified(self): + self.version = VersionTag() + + def get_codec_from_cache(self, key): + return self._get_codec_with_version(key, self.version) + + @jit.elidable + def _get_codec_with_version(self, key, version): + return self.codec_search_cache.get(key, None) + def _cleanup_(self): assert not self.codec_search_path + def register_codec(space, w_search_function): """register(search_function) @@ -115,11 +135,12 @@ "lookup_codec() should not be called during translation" state = space.fromcache(CodecState) normalized_encoding = encoding.replace(" ", "-").lower() - w_result = state.codec_search_cache.get(normalized_encoding, None) + w_result = state.get_codec_from_cache(normalized_encoding) if w_result is not None: return w_result return _lookup_codec_loop(space, encoding, normalized_encoding) + def _lookup_codec_loop(space, encoding, normalized_encoding): state = space.fromcache(CodecState) if state.codec_need_encodings: @@ -143,6 +164,7 @@ space.wrap("codec search functions must return 4-tuples")) else: state.codec_search_cache[normalized_encoding] = w_result + state.modified() return w_result raise operationerrfmt( space.w_LookupError, From noreply at buildbot.pypy.org Wed Apr 10 06:33:26 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Wed, 10 Apr 2013 06:33:26 +0200 (CEST) Subject: [pypy-commit] pypy stdlib-2.7.4: have rsre use MAXREPEAT var instead of hard coding Message-ID: <20130410043326.E8AE61C30E9@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: stdlib-2.7.4 Changeset: r63187:1fe1d53b3311 Date: 2013-04-09 22:42 -0400 http://bitbucket.org/pypy/pypy/changeset/1fe1d53b3311/ Log: have rsre use MAXREPEAT var instead of hard coding diff --git a/rpython/rlib/rsre/rsre_char.py b/rpython/rlib/rsre/rsre_char.py --- a/rpython/rlib/rsre/rsre_char.py +++ b/rpython/rlib/rsre/rsre_char.py @@ -26,6 +26,8 @@ # Identifying as _sre from Python 2.3 and onwards (at least up to 2.7) MAGIC = 20031017 +MAXREPEAT = 65535 + # In _sre.c this is bytesize of the code word type of the C implementation. # There it's 2 for normal Python builds and more for wide unicode builds (large # enough to hold a 32-bit UCS-4 encoded character). Since here in pure Python @@ -48,9 +50,6 @@ SRE_INFO_CHARSET = 4 SRE_FLAG_LOCALE = 4 # honour system locale SRE_FLAG_UNICODE = 32 # use unicode locale -OPCODE_INFO = 17 -OPCODE_LITERAL = 19 -MAXREPEAT = 65535 def getlower(char_ord, flags): diff --git a/rpython/rlib/rsre/rsre_core.py b/rpython/rlib/rsre/rsre_core.py --- a/rpython/rlib/rsre/rsre_core.py +++ b/rpython/rlib/rsre/rsre_core.py @@ -374,7 +374,7 @@ ptr=ptr, marks=marks, self=self, ctx=ctx) if match_more: max = ctx.pat(ppos+2) - if max == 65535 or self.num_pending < max: + if max == rsre_char.MAXREPEAT or self.num_pending < max: # try to match one more 'item' enum = sre_match(ctx, ppos + 3, ptr, marks) else: @@ -442,7 +442,7 @@ return self resume = False - if max == 65535 or self.num_pending < max: + if max == rsre_char.MAXREPEAT or self.num_pending < max: # try to match one more 'item' enum = sre_match(ctx, ppos + 3, ptr, marks) # @@ -721,7 +721,7 @@ maxptr = ctx.end max = ctx.pat(ppos+2) - if max != 65535: + if max != rsre_char.MAXREPEAT: maxptr1 = start + max if maxptr1 <= maxptr: maxptr = maxptr1 @@ -784,7 +784,7 @@ if maxcount == 1: return ptrp1 # Else we really need to count how many times it matches. - if maxcount != 65535: + if maxcount != rsre_char.MAXREPEAT: # adjust end end1 = ptr + maxcount if end1 <= end: diff --git a/rpython/rtyper/lltypesystem/rffi.py b/rpython/rtyper/lltypesystem/rffi.py --- a/rpython/rtyper/lltypesystem/rffi.py +++ b/rpython/rtyper/lltypesystem/rffi.py @@ -446,7 +446,7 @@ TYPES += ['__int128_t'] except CompilationError: pass - + _TYPES_ARE_UNSIGNED = set(['size_t', 'uintptr_t']) # plus "unsigned *" if os.name != 'nt': TYPES.append('mode_t') From noreply at buildbot.pypy.org Wed Apr 10 06:33:28 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Wed, 10 Apr 2013 06:33:28 +0200 (CEST) Subject: [pypy-commit] pypy default: whitespace Message-ID: <20130410043328.4FFC91C30E9@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63188:4209120e319d Date: 2013-04-09 23:01 -0400 http://bitbucket.org/pypy/pypy/changeset/4209120e319d/ Log: whitespace diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -765,9 +765,9 @@ if isinstance(name, unicode): name = name.encode('utf-8') ret = _lib.sqlite3_create_collation(self._db, name, - _lib.SQLITE_UTF8, - _ffi.NULL, - collation_callback) + _lib.SQLITE_UTF8, + _ffi.NULL, + collation_callback) if ret != _lib.SQLITE_OK: raise self._get_exception(ret) @@ -786,9 +786,7 @@ return _lib.SQLITE_DENY self.__func_cache[callback] = authorizer - ret = _lib.sqlite3_set_authorizer(self._db, - authorizer, - _ffi.NULL) + ret = _lib.sqlite3_set_authorizer(self._db, authorizer, _ffi.NULL) if ret != _lib.SQLITE_OK: raise self._get_exception(ret) @@ -804,15 +802,13 @@ @_ffi.callback("int(void*)") def progress_handler(userdata): try: - ret = callable() - return bool(ret) + return bool(callable()) except Exception: # abort query if error occurred return 1 self.__func_cache[callable] = progress_handler - _lib.sqlite3_progress_handler(self._db, nsteps, - progress_handler, - _ffi.NULL) + _lib.sqlite3_progress_handler(self._db, nsteps, progress_handler, + _ffi.NULL) if sys.version_info[0] >= 3: def __get_in_transaction(self): @@ -894,8 +890,8 @@ def __check_reset(self): if self._reset: raise InterfaceError( - "Cursor needed to be reset because of commit/rollback " - "and can no longer be fetched from.") + "Cursor needed to be reset because of commit/rollback " + "and can no longer be fetched from.") def __build_row_cast_map(self): if not self.__connection._detect_types: From noreply at buildbot.pypy.org Wed Apr 10 06:33:29 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Wed, 10 Apr 2013 06:33:29 +0200 (CEST) Subject: [pypy-commit] pypy stdlib-2.7.4: fix sqlite3 CheckCollationReturnsLargeInteger Message-ID: <20130410043329.74CD11C30E9@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: stdlib-2.7.4 Changeset: r63189:87013e33e1f1 Date: 2013-04-09 23:24 -0400 http://bitbucket.org/pypy/pypy/changeset/87013e33e1f1/ Log: fix sqlite3 CheckCollationReturnsLargeInteger diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -757,8 +757,12 @@ def collation_callback(context, len1, str1, len2, str2): text1 = _ffi.buffer(str1, len1)[:] text2 = _ffi.buffer(str2, len2)[:] - - return callback(text1, text2) + try: + ret = callback(text1, text2) + assert isinstance(ret, (int, long)) + return cmp(ret, 0) + except Exception: + return 0 self.__collations[name] = collation_callback From noreply at buildbot.pypy.org Wed Apr 10 06:33:30 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Wed, 10 Apr 2013 06:33:30 +0200 (CEST) Subject: [pypy-commit] pypy stdlib-2.7.4: fix sqlite3 AuthorizerTests Message-ID: <20130410043330.926851C30E9@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: stdlib-2.7.4 Changeset: r63190:7f1b3bcda3a5 Date: 2013-04-10 00:31 -0400 http://bitbucket.org/pypy/pypy/changeset/7f1b3bcda3a5/ Log: fix sqlite3 AuthorizerTests diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -785,7 +785,10 @@ "const char*, const char*)") def authorizer(userdata, action, arg1, arg2, dbname, source): try: - return int(callback(action, arg1, arg2, dbname, source)) + ret = callback(action, arg1, arg2, dbname, source) + assert isinstance(ret, int) + assert ret in (_lib.SQLITE_OK, _lib.SQLITE_DENY, _lib.SQLITE_IGNORE) + return ret except Exception: return _lib.SQLITE_DENY self.__func_cache[callback] = authorizer From noreply at buildbot.pypy.org Wed Apr 10 06:33:31 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Wed, 10 Apr 2013 06:33:31 +0200 (CEST) Subject: [pypy-commit] pypy stdlib-2.7.4: merge default Message-ID: <20130410043331.AB1321C30E9@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: stdlib-2.7.4 Changeset: r63191:d2616064a70f Date: 2013-04-10 00:31 -0400 http://bitbucket.org/pypy/pypy/changeset/d2616064a70f/ Log: merge default diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -769,9 +769,9 @@ if isinstance(name, unicode): name = name.encode('utf-8') ret = _lib.sqlite3_create_collation(self._db, name, - _lib.SQLITE_UTF8, - _ffi.NULL, - collation_callback) + _lib.SQLITE_UTF8, + _ffi.NULL, + collation_callback) if ret != _lib.SQLITE_OK: raise self._get_exception(ret) @@ -793,9 +793,7 @@ return _lib.SQLITE_DENY self.__func_cache[callback] = authorizer - ret = _lib.sqlite3_set_authorizer(self._db, - authorizer, - _ffi.NULL) + ret = _lib.sqlite3_set_authorizer(self._db, authorizer, _ffi.NULL) if ret != _lib.SQLITE_OK: raise self._get_exception(ret) @@ -811,15 +809,13 @@ @_ffi.callback("int(void*)") def progress_handler(userdata): try: - ret = callable() - return bool(ret) + return bool(callable()) except Exception: # abort query if error occurred return 1 self.__func_cache[callable] = progress_handler - _lib.sqlite3_progress_handler(self._db, nsteps, - progress_handler, - _ffi.NULL) + _lib.sqlite3_progress_handler(self._db, nsteps, progress_handler, + _ffi.NULL) if sys.version_info[0] >= 3: def __get_in_transaction(self): @@ -901,8 +897,8 @@ def __check_reset(self): if self._reset: raise InterfaceError( - "Cursor needed to be reset because of commit/rollback " - "and can no longer be fetched from.") + "Cursor needed to be reset because of commit/rollback " + "and can no longer be fetched from.") def __build_row_cast_map(self): if not self.__connection._detect_types: From noreply at buildbot.pypy.org Wed Apr 10 06:33:33 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Wed, 10 Apr 2013 06:33:33 +0200 (CEST) Subject: [pypy-commit] pypy default: merge heads Message-ID: <20130410043333.030231C30E9@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63192:007e2e9fca39 Date: 2013-04-10 00:33 -0400 http://bitbucket.org/pypy/pypy/changeset/007e2e9fca39/ Log: merge heads diff --git a/pypy/interpreter/pyparser/parsestring.py b/pypy/interpreter/pyparser/parsestring.py --- a/pypy/interpreter/pyparser/parsestring.py +++ b/pypy/interpreter/pyparser/parsestring.py @@ -91,9 +91,9 @@ assert 0 <= bufp <= bufq substr = buf[bufp:bufq] if rawmode: - v = unicodehelper.PyUnicode_DecodeRawUnicodeEscape(space, substr) + v = unicodehelper.decode_raw_unicode_escape(space, substr) else: - v = unicodehelper.PyUnicode_DecodeUnicodeEscape(space, substr) + v = unicodehelper.decode_unicode_escape(space, substr) return space.wrap(v) need_encoding = (encoding is not None and @@ -103,8 +103,8 @@ substr = s[ps : q] if rawmode or '\\' not in s[ps:]: if need_encoding: - w_u = space.wrap(unicodehelper.PyUnicode_DecodeUTF8(space, substr)) - w_v = unicodehelper.PyUnicode_AsEncodedString(space, w_u, space.wrap(encoding)) + w_u = space.wrap(unicodehelper.decode_utf8(space, substr)) + w_v = unicodehelper.encode(space, w_u, encoding) return w_v else: return space.wrap(substr) @@ -219,8 +219,8 @@ # while (s < end && *s != '\\') s++; */ /* inefficient for u".." while ps < end and ord(s[ps]) & 0x80: ps += 1 - w_u = space.wrap(unicodehelper.PyUnicode_DecodeUTF8(space, s[pt:ps])) - w_v = unicodehelper.PyUnicode_AsEncodedString(space, w_u, space.wrap(encoding)) + w_u = space.wrap(unicodehelper.decode_utf8(space, s[pt:ps])) + w_v = unicodehelper.encode(space, w_u, encoding) v = space.str_w(w_v) return v, ps diff --git a/pypy/interpreter/unicodehelper.py b/pypy/interpreter/unicodehelper.py --- a/pypy/interpreter/unicodehelper.py +++ b/pypy/interpreter/unicodehelper.py @@ -29,11 +29,12 @@ # ____________________________________________________________ -def PyUnicode_AsEncodedString(space, w_data, w_encoding): - return interp_codecs.encode(space, w_data, w_encoding) +def encode(space, w_data, encoding=None, errors='strict'): + from pypy.objspace.std.unicodetype import encode_object + return encode_object(space, w_data, encoding, errors) # These functions take and return unwrapped rpython strings and unicodes -def PyUnicode_DecodeUnicodeEscape(space, string): +def decode_unicode_escape(space, string): state = space.fromcache(interp_codecs.CodecState) unicodedata_handler = state.get_unicodedata_handler(space) result, consumed = runicode.str_decode_unicode_escape( @@ -42,20 +43,20 @@ unicodedata_handler=unicodedata_handler) return result -def PyUnicode_DecodeRawUnicodeEscape(space, string): +def decode_raw_unicode_escape(space, string): result, consumed = runicode.str_decode_raw_unicode_escape( string, len(string), "strict", final=True, errorhandler=decode_error_handler(space)) return result -def PyUnicode_DecodeUTF8(space, string): +def decode_utf8(space, string): result, consumed = runicode.str_decode_utf_8( string, len(string), "strict", final=True, errorhandler=decode_error_handler(space), allow_surrogates=True) return result -def PyUnicode_EncodeUTF8(space, uni): +def encode_utf8(space, uni): return runicode.unicode_encode_utf_8( uni, len(uni), "strict", errorhandler=encode_error_handler(space), diff --git a/pypy/module/_codecs/interp_codecs.py b/pypy/module/_codecs/interp_codecs.py --- a/pypy/module/_codecs/interp_codecs.py +++ b/pypy/module/_codecs/interp_codecs.py @@ -1,10 +1,18 @@ +from rpython.rlib import jit +from rpython.rlib.objectmodel import we_are_translated +from rpython.rlib.rstring import UnicodeBuilder + from pypy.interpreter.error import OperationError, operationerrfmt from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault -from rpython.rlib.rstring import UnicodeBuilder -from rpython.rlib.objectmodel import we_are_translated + + +class VersionTag(object): + pass class CodecState(object): + _immutable_fields_ = ["version?"] + def __init__(self, space): self.codec_search_path = [] self.codec_search_cache = {} @@ -14,6 +22,7 @@ self.encode_error_handler = self.make_encode_errorhandler(space) self.unicodedata_handler = None + self.modified() def _make_errorhandler(self, space, decode): def call_errorhandler(errors, encoding, reason, input, startpos, @@ -86,9 +95,20 @@ self.unicodedata_handler = UnicodeData_Handler(space, w_getcode) return self.unicodedata_handler + def modified(self): + self.version = VersionTag() + + def get_codec_from_cache(self, key): + return self._get_codec_with_version(key, self.version) + + @jit.elidable + def _get_codec_with_version(self, key, version): + return self.codec_search_cache.get(key, None) + def _cleanup_(self): assert not self.codec_search_path + def register_codec(space, w_search_function): """register(search_function) @@ -115,11 +135,12 @@ "lookup_codec() should not be called during translation" state = space.fromcache(CodecState) normalized_encoding = encoding.replace(" ", "-").lower() - w_result = state.codec_search_cache.get(normalized_encoding, None) + w_result = state.get_codec_from_cache(normalized_encoding) if w_result is not None: return w_result return _lookup_codec_loop(space, encoding, normalized_encoding) + def _lookup_codec_loop(space, encoding, normalized_encoding): state = space.fromcache(CodecState) if state.codec_need_encodings: @@ -143,6 +164,7 @@ space.wrap("codec search functions must return 4-tuples")) else: state.codec_search_cache[normalized_encoding] = w_result + state.modified() return w_result raise operationerrfmt( space.w_LookupError, diff --git a/pypy/module/pyexpat/interp_pyexpat.py b/pypy/module/pyexpat/interp_pyexpat.py --- a/pypy/module/pyexpat/interp_pyexpat.py +++ b/pypy/module/pyexpat/interp_pyexpat.py @@ -475,8 +475,8 @@ def w_convert(self, space, s): if self.returns_unicode: - from pypy.interpreter.unicodehelper import PyUnicode_DecodeUTF8 - return space.wrap(PyUnicode_DecodeUTF8(space, s)) + from pypy.interpreter.unicodehelper import decode_utf8 + return space.wrap(decode_utf8(space, s)) else: return space.wrap(s) diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_function.py b/pypy/module/test_lib_pypy/cffi_tests/test_function.py --- a/pypy/module/test_lib_pypy/cffi_tests/test_function.py +++ b/pypy/module/test_lib_pypy/cffi_tests/test_function.py @@ -16,7 +16,7 @@ """xxx limited to capture at most 512 bytes of output, according to the Posix manual.""" - def __init__(self, capture_fd=1): # stdout, by default + def __init__(self, capture_fd): self.capture_fd = capture_fd def __enter__(self): @@ -109,80 +109,66 @@ y = lib.TlsFree(x) assert y != 0 - def test_puts(self): + def test_fputs(self): + if not sys.platform.startswith('linux'): + py.test.skip("probably no symbol 'stderr' in the lib") ffi = FFI(backend=self.Backend()) ffi.cdef(""" - int puts(const char *); - int fflush(void *); + int fputs(const char *, void *); + void *stderr; """) ffi.C = ffi.dlopen(None) - ffi.C.puts # fetch before capturing, for easier debugging - with FdWriteCapture() as fd: - ffi.C.puts(b"hello") - ffi.C.puts(b" world") - ffi.C.fflush(ffi.NULL) + ffi.C.fputs # fetch before capturing, for easier debugging + with FdWriteCapture(2) as fd: + ffi.C.fputs(b"hello\n", ffi.C.stderr) + ffi.C.fputs(b" world\n", ffi.C.stderr) res = fd.getvalue() assert res == b'hello\n world\n' - def test_puts_without_const(self): + def test_fputs_without_const(self): + if not sys.platform.startswith('linux'): + py.test.skip("probably no symbol 'stderr' in the lib") ffi = FFI(backend=self.Backend()) ffi.cdef(""" - int puts(char *); - int fflush(void *); + int fputs(char *, void *); + void *stderr; """) ffi.C = ffi.dlopen(None) - ffi.C.puts # fetch before capturing, for easier debugging - with FdWriteCapture() as fd: - ffi.C.puts(b"hello") - ffi.C.puts(b" world") - ffi.C.fflush(ffi.NULL) + ffi.C.fputs # fetch before capturing, for easier debugging + with FdWriteCapture(2) as fd: + ffi.C.fputs(b"hello\n", ffi.C.stderr) + ffi.C.fputs(b" world\n", ffi.C.stderr) res = fd.getvalue() assert res == b'hello\n world\n' - def test_fputs(self): + def test_vararg(self): if not sys.platform.startswith('linux'): - py.test.skip("probably no symbol 'stdout' in the lib") + py.test.skip("probably no symbol 'stderr' in the lib") ffi = FFI(backend=self.Backend()) ffi.cdef(""" - int fputs(const char *, void *); - void *stdout, *stderr; + int fprintf(void *, const char *format, ...); + void *stderr; """) ffi.C = ffi.dlopen(None) with FdWriteCapture(2) as fd: - ffi.C.fputs(b"hello from stderr\n", ffi.C.stderr) + ffi.C.fprintf(ffi.C.stderr, b"hello with no arguments\n") + ffi.C.fprintf(ffi.C.stderr, + b"hello, %s!\n", ffi.new("char[]", b"world")) + ffi.C.fprintf(ffi.C.stderr, + ffi.new("char[]", b"hello, %s!\n"), + ffi.new("char[]", b"world2")) + ffi.C.fprintf(ffi.C.stderr, + b"hello int %d long %ld long long %lld\n", + ffi.cast("int", 42), + ffi.cast("long", 84), + ffi.cast("long long", 168)) + ffi.C.fprintf(ffi.C.stderr, b"hello %p\n", ffi.NULL) res = fd.getvalue() - assert res == b'hello from stderr\n' - - def test_vararg(self): - ffi = FFI(backend=self.Backend()) - ffi.cdef(""" - int printf(const char *format, ...); - int fflush(void *); - """) - ffi.C = ffi.dlopen(None) - with FdWriteCapture() as fd: - ffi.C.printf(b"hello with no arguments\n") - ffi.C.printf(b"hello, %s!\n", ffi.new("char[]", b"world")) - ffi.C.printf(ffi.new("char[]", b"hello, %s!\n"), - ffi.new("char[]", b"world2")) - ffi.C.printf(b"hello int %d long %ld long long %lld\n", - ffi.cast("int", 42), - ffi.cast("long", 84), - ffi.cast("long long", 168)) - ffi.C.printf(b"hello %p\n", ffi.NULL) - ffi.C.fflush(ffi.NULL) - res = fd.getvalue() - if sys.platform == 'win32': - NIL = b"00000000" - elif sys.platform.startswith(('linux', 'gnu')): - NIL = b"(nil)" - else: - NIL = b"0x0" # OS/X at least assert res == (b"hello with no arguments\n" b"hello, world!\n" b"hello, world2!\n" b"hello int 42 long 84 long long 168\n" - b"hello " + NIL + b"\n") + b"hello (nil)\n") def test_must_specify_type_of_vararg(self): ffi = FFI(backend=self.Backend()) @@ -216,17 +202,18 @@ res = fptr(b"Hello") assert res == 42 # + if not sys.platform.startswith('linux'): + py.test.skip("probably no symbol 'stderr' in the lib") ffi.cdef(""" - int puts(const char *); - int fflush(void *); + int fputs(const char *, void *); + void *stderr; """) ffi.C = ffi.dlopen(None) - fptr = ffi.cast("int(*)(const char *txt)", ffi.C.puts) - assert fptr == ffi.C.puts - assert repr(fptr).startswith(" Author: Brian Kearns Branch: stdlib-2.7.4 Changeset: r63193:d01cf553b1f0 Date: 2013-04-10 00:41 -0400 http://bitbucket.org/pypy/pypy/changeset/d01cf553b1f0/ Log: io.BytesIO/StringIO status methods now check_closed before returning (cpython issue15841) diff --git a/pypy/module/_io/interp_bytesio.py b/pypy/module/_io/interp_bytesio.py --- a/pypy/module/_io/interp_bytesio.py +++ b/pypy/module/_io/interp_bytesio.py @@ -179,12 +179,15 @@ return space.wrap(self.pos) def readable_w(self, space): + self._check_closed(space) return space.w_True def writable_w(self, space): + self._check_closed(space) return space.w_True def seekable_w(self, space): + self._check_closed(space) return space.w_True def close_w(self, space): diff --git a/pypy/module/_io/interp_stringio.py b/pypy/module/_io/interp_stringio.py --- a/pypy/module/_io/interp_stringio.py +++ b/pypy/module/_io/interp_stringio.py @@ -246,12 +246,15 @@ return space.wrap(u''.join(self.buf)) def readable_w(self, space): + self._check_closed(space) return space.w_True def writable_w(self, space): + self._check_closed(space) return space.w_True def seekable_w(self, space): + self._check_closed(space) return space.w_True def close_w(self, space): diff --git a/pypy/module/_io/test/test_bytesio.py b/pypy/module/_io/test/test_bytesio.py --- a/pypy/module/_io/test/test_bytesio.py +++ b/pypy/module/_io/test/test_bytesio.py @@ -20,6 +20,9 @@ assert f.writable() assert f.seekable() f.close() + raises(ValueError, f.readable) + raises(ValueError, f.writable) + raises(ValueError, f.seekable) def test_write(self): import _io diff --git a/pypy/module/_io/test/test_stringio.py b/pypy/module/_io/test/test_stringio.py --- a/pypy/module/_io/test/test_stringio.py +++ b/pypy/module/_io/test/test_stringio.py @@ -18,9 +18,9 @@ assert not sio.closed assert not sio.line_buffering sio.close() - assert sio.readable() - assert sio.writable() - assert sio.seekable() + raises(ValueError, sio.readable) + raises(ValueError, sio.writable) + raises(ValueError, sio.seekable) raises(ValueError, sio.isatty) assert sio.closed assert sio.errors is None From noreply at buildbot.pypy.org Wed Apr 10 08:43:03 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Wed, 10 Apr 2013 08:43:03 +0200 (CEST) Subject: [pypy-commit] pypy stdlib-2.7.4: fix test_descr by reapplying change lost in merge Message-ID: <20130410064303.393511C0651@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: stdlib-2.7.4 Changeset: r63194:61e7b219942c Date: 2013-04-10 02:16 -0400 http://bitbucket.org/pypy/pypy/changeset/61e7b219942c/ Log: fix test_descr by reapplying change lost in merge diff --git a/lib-python/2.7/test/test_descr.py b/lib-python/2.7/test/test_descr.py --- a/lib-python/2.7/test/test_descr.py +++ b/lib-python/2.7/test/test_descr.py @@ -1130,7 +1130,7 @@ self.assertEqual(Counted.counter, 0) # Test lookup leaks [SF bug 572567] - if hasattr(gc, 'get_objects'): + if test_support.check_impl_detail(): class G(object): def __cmp__(self, other): return 0 From noreply at buildbot.pypy.org Wed Apr 10 08:43:04 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Wed, 10 Apr 2013 08:43:04 +0200 (CEST) Subject: [pypy-commit] pypy stdlib-2.7.4: fix fileio testUnclosedFDOnException Message-ID: <20130410064304.78DDE1C1477@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: stdlib-2.7.4 Changeset: r63195:f0ec8a1cddcf Date: 2013-04-10 02:42 -0400 http://bitbucket.org/pypy/pypy/changeset/f0ec8a1cddcf/ Log: fix fileio testUnclosedFDOnException diff --git a/pypy/module/_io/interp_fileio.py b/pypy/module/_io/interp_fileio.py --- a/pypy/module/_io/interp_fileio.py +++ b/pypy/module/_io/interp_fileio.py @@ -179,7 +179,7 @@ fd_is_own = True self._dircheck(space, w_name) - self.w_name = w_name + space.setattr(self, space.wrap("name"), w_name) if append: # For consistent behaviour, we explicitly seek to the end of file diff --git a/pypy/module/_io/test/test_fileio.py b/pypy/module/_io/test/test_fileio.py --- a/pypy/module/_io/test/test_fileio.py +++ b/pypy/module/_io/test/test_fileio.py @@ -165,6 +165,19 @@ f.close() assert repr(f) == "<_io.FileIO [closed]>" + def test_unclosed_fd_on_exception(self): + import _io + import os + class MyException(Exception): pass + class MyFileIO(_io.FileIO): + def __setattr__(self, name, value): + if name == "name": + raise MyException("blocked setting name") + return super(MyFileIO, self).__setattr__(name, value) + fd = os.open(self.tmpfile, os.O_RDONLY) + raises(MyException, MyFileIO, fd) + os.close(fd) # should not raise OSError(EBADF) + def test_flush_at_exit(): from pypy import conftest from pypy.tool.option import make_config, make_objspace From noreply at buildbot.pypy.org Wed Apr 10 09:33:11 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Wed, 10 Apr 2013 09:33:11 +0200 (CEST) Subject: [pypy-commit] pypy stdlib-2.7.4: fix test_marshal (no sys.getsizeof on pypy) Message-ID: <20130410073311.074A51C1495@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: stdlib-2.7.4 Changeset: r63196:4899736f152f Date: 2013-04-10 03:32 -0400 http://bitbucket.org/pypy/pypy/changeset/4899736f152f/ Log: fix test_marshal (no sys.getsizeof on pypy) diff --git a/lib-python/2.7/test/test_marshal.py b/lib-python/2.7/test/test_marshal.py --- a/lib-python/2.7/test/test_marshal.py +++ b/lib-python/2.7/test/test_marshal.py @@ -245,13 +245,13 @@ self.check_unmarshallable([None] * size) @test_support.precisionbigmemtest(size=LARGE_SIZE, - memuse=pointer_size*12 + sys.getsizeof(LARGE_SIZE-1), + memuse=pointer_size*12, # + sys.getsizeof(LARGE_SIZE-1), dry_run=False) def test_set(self, size): self.check_unmarshallable(set(range(size))) @test_support.precisionbigmemtest(size=LARGE_SIZE, - memuse=pointer_size*12 + sys.getsizeof(LARGE_SIZE-1), + memuse=pointer_size*12, # + sys.getsizeof(LARGE_SIZE-1), dry_run=False) def test_frozenset(self, size): self.check_unmarshallable(frozenset(range(size))) From noreply at buildbot.pypy.org Wed Apr 10 09:49:16 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Wed, 10 Apr 2013 09:49:16 +0200 (CEST) Subject: [pypy-commit] pypy stdlib-2.7.4: fix settrace: SETUP_WITH acts like SETUP_FINALLY for setting f_lineno (cpython issue14612) Message-ID: <20130410074916.6F7171C010B@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: stdlib-2.7.4 Changeset: r63197:9fd06caad8aa Date: 2013-04-10 03:48 -0400 http://bitbucket.org/pypy/pypy/changeset/9fd06caad8aa/ Log: fix settrace: SETUP_WITH acts like SETUP_FINALLY for setting f_lineno (cpython issue14612) diff --git a/pypy/interpreter/pyframe.py b/pypy/interpreter/pyframe.py --- a/pypy/interpreter/pyframe.py +++ b/pypy/interpreter/pyframe.py @@ -17,7 +17,7 @@ # Define some opcodes used g = globals() -for op in '''DUP_TOP POP_TOP SETUP_LOOP SETUP_EXCEPT SETUP_FINALLY +for op in '''DUP_TOP POP_TOP SETUP_LOOP SETUP_EXCEPT SETUP_FINALLY SETUP_WITH POP_BLOCK END_FINALLY'''.split(): g[op] = stdlib_opcode.opmap[op] HAVE_ARGUMENT = stdlib_opcode.HAVE_ARGUMENT @@ -518,7 +518,7 @@ if ord(code[new_lasti]) in (DUP_TOP, POP_TOP): raise OperationError(space.w_ValueError, space.wrap("can't jump to 'except' line as there's no exception")) - + # Don't jump into or out of a finally block. f_lasti_setup_addr = -1 new_lasti_setup_addr = -1 @@ -526,18 +526,18 @@ addr = 0 while addr < len(code): op = ord(code[addr]) - if op in (SETUP_LOOP, SETUP_EXCEPT, SETUP_FINALLY): + if op in (SETUP_LOOP, SETUP_EXCEPT, SETUP_FINALLY, SETUP_WITH): blockstack.append([addr, False]) elif op == POP_BLOCK: setup_op = ord(code[blockstack[-1][0]]) - if setup_op == SETUP_FINALLY: + if setup_op == SETUP_FINALLY or setup_op == SETUP_WITH: blockstack[-1][1] = True else: blockstack.pop() elif op == END_FINALLY: if len(blockstack) > 0: setup_op = ord(code[blockstack[-1][0]]) - if setup_op == SETUP_FINALLY: + if setup_op == SETUP_FINALLY or setup_op == SETUP_WITH: blockstack.pop() if addr == new_lasti or addr == self.last_instr: @@ -549,12 +549,12 @@ if addr == self.last_instr: f_lasti_setup_addr = setup_addr break - + if op >= HAVE_ARGUMENT: addr += 3 else: addr += 1 - + assert len(blockstack) == 0 if new_lasti_setup_addr != f_lasti_setup_addr: @@ -574,7 +574,7 @@ while addr < max_addr: op = ord(code[addr]) - if op in (SETUP_LOOP, SETUP_EXCEPT, SETUP_FINALLY): + if op in (SETUP_LOOP, SETUP_EXCEPT, SETUP_FINALLY, SETUP_WITH): delta_iblock += 1 elif op == POP_BLOCK: delta_iblock -= 1 diff --git a/pypy/interpreter/test/test_pyframe.py b/pypy/interpreter/test/test_pyframe.py --- a/pypy/interpreter/test/test_pyframe.py +++ b/pypy/interpreter/test/test_pyframe.py @@ -66,8 +66,10 @@ def function(): xyz + with open(self.tempfile1, 'w') as f: + pass return 3 - + import sys sys.settrace(tracer) function() @@ -241,7 +243,7 @@ def test_trace_ignore_hidden(self): import sys import _testing - + l = [] def trace(a,b,c): l.append((a,b,c)) @@ -293,7 +295,7 @@ return trace def g(): - raise Exception + raise Exception def f(): try: g() @@ -381,7 +383,6 @@ assert len(l) == 2 assert issubclass(l[0][0], Exception) assert issubclass(l[1][0], Exception) - def test_trace_generator_finalisation(self): import sys From noreply at buildbot.pypy.org Wed Apr 10 10:14:17 2013 From: noreply at buildbot.pypy.org (bivab) Date: Wed, 10 Apr 2013 10:14:17 +0200 (CEST) Subject: [pypy-commit] buildbot default: fix missing rename of test factory Message-ID: <20130410081417.9E4461C0F12@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r776:f0a28727a5c2 Date: 2013-04-10 10:14 +0200 http://bitbucket.org/pypy/buildbot/changeset/f0a28727a5c2/ Log: fix missing rename of test factory diff --git a/bot2/pypybuildbot/arm_master.py b/bot2/pypybuildbot/arm_master.py --- a/bot2/pypybuildbot/arm_master.py +++ b/bot2/pypybuildbot/arm_master.py @@ -69,7 +69,7 @@ platform='linux-armel', ) -pypyARMJITTranslatedTestFactory = pypybuilds.TranslatedTests( +pypyARMHF_RASPBIAN_JITTranslatedTestFactory = pypybuilds.TranslatedTests( translationArgs=(crosstranslationargs + jit_translation_args + crosstranslationjitargs), @@ -78,7 +78,7 @@ app_tests=True, platform='linux-armhf-raspbian', ) -pypyARMTranslatedAppLevelTestFactory = pypybuilds.TranslatedTests( +pypyARMHF_RASPBIAN_TranslatedAppLevelTestFactory = pypybuilds.TranslatedTests( translationArgs=crosstranslationargs + ['-O2'], lib_python=True, app_tests=True, @@ -163,14 +163,14 @@ {"name": APPLVLLINUXARMHF_RASPBIAN, "slavenames": ["hhu-raspberry-pi"], "builddir": APPLVLLINUXARMHF_RASPBIAN, - "factory": pypyARMTranslatedAppLevelTestFactory, + "factory": pypyARMHF_RASPBIAN_TranslatedAppLevelTestFactory, "category": "linux-armhf", "locks": [ARMBoardLock.access('counting')], }, {"name": JITLINUXARMHF_RASPBIAN, "slavenames": ["hhu-raspberry-pi"], 'builddir': JITLINUXARMHF_RASPBIAN, - 'factory': pypyARMJITTranslatedTestFactory, + 'factory': pypyARMHF_RASPBIAN_JITTranslatedTestFactory, 'category': 'linux-armhf', "locks": [ARMBoardLock.access('counting')], }, From noreply at buildbot.pypy.org Wed Apr 10 13:24:28 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Wed, 10 Apr 2013 13:24:28 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: fixed drawing error by implementing shift using polymorphism. The main problem was rightshift for 'negative' large integers shifting in ones instead of zeros Message-ID: <20130410112428.4A1BA1C1494@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r249:413ad48ead1f Date: 2013-04-09 21:00 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/413ad48ead1f/ Log: fixed drawing error by implementing shift using polymorphism. The main problem was rightshift for 'negative' large integers shifting in ones instead of zeros diff --git a/spyvm/interpreter.py b/spyvm/interpreter.py --- a/spyvm/interpreter.py +++ b/spyvm/interpreter.py @@ -32,7 +32,7 @@ virtualizables=['s_context'], get_printable_location=get_printable_location ) - + def __init__(self, space, image=None, image_name="", trace=False, max_stack_depth=constants.MAX_LOOP_DEPTH): self.space = space @@ -380,6 +380,8 @@ try: s_method = s_class.lookup(self.space.objtable["w_doesNotUnderstand"]) except MethodNotFound: + from spyvm.shadow import ClassShadow + assert isinstance(s_class, ClassShadow) print "Missing doesDoesNotUnderstand in hierarchy of %s" % s_class.getname() raise s_frame = s_method.create_frame(self.space, receiver, [w_message], self) diff --git a/spyvm/model.py b/spyvm/model.py --- a/spyvm/model.py +++ b/spyvm/model.py @@ -121,6 +121,12 @@ def as_repr_string(self): return "%r" % self + def lshift(self, space, shift): + raise error.PrimitiveFailedError() + + def rshift(self, space, shift): + raise error.PrimitiveFailedError() + class W_SmallInteger(W_Object): """Boxed integer value""" # TODO can we tell pypy that its never larger then 31-bit? @@ -140,6 +146,25 @@ def invariant(self): return isinstance(self.value, int) and self.value < 0x8000 + def lshift(self, space, shift): + from rpython.rlib.rarithmetic import ovfcheck, intmask, r_uint + # shift > 0, therefore the highest bit of upperbound is not set, + # i.e. upperbound is positive + upperbound = intmask(r_uint(-1) >> shift) + if 0 <= self.value <= upperbound: + shifted = intmask(self.value << shift) + return space.wrap_positive_32bit_int(shifted) + else: + try: + shifted = ovfcheck(self.value << shift) + except OverflowError: + raise error.PrimitiveFailedError() + return space.wrap_int(shifted) + raise PrimitiveFailedError + + def rshift(self, space, shift): + return space.wrap_int(self.value >> shift) + @jit.elidable def as_repr_string(self): return "W_SmallInteger(%d)" % self.value @@ -217,6 +242,26 @@ def __repr__(self): return "W_LargePositiveInteger1Word(%d)" % r_uint(self.value) + def lshift(self, space, shift): + from rpython.rlib.rarithmetic import intmask, r_uint + # shift > 0, therefore the highest bit of upperbound is not set, + # i.e. upperbound is positive + upperbound = intmask(r_uint(-1) >> shift) + if 0 <= self.value <= upperbound: + shifted = intmask(self.value << shift) + return space.wrap_positive_32bit_int(shifted) + else: + raise error.PrimitiveFailedError() + + def rshift(self, space, shift): + if shift == 0: + return self + # a problem might arrise, because we may shift in ones from left + mask = (1 << (32 - shift))- 1 + # the mask is only valid if the highest bit of self.value is set + # and only in this case we do need such a mask + return space.wrap_int((self.value >> shift) & mask) + def clone(self, space): return W_LargePositiveInteger1Word(self.value) diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -217,33 +217,14 @@ return interp.space.wrap_int(receiver // argument) # #bitShift: -- return the shifted value - at expose_primitive(BIT_SHIFT, unwrap_spec=[pos_32bit_int, int]) + at expose_primitive(BIT_SHIFT, unwrap_spec=[object, int]) def func(interp, s_frame, receiver, argument): - - # TODO: 1 << 100 will overflow to 0. Catch this gracefully by Primitive # Failing! Use ovfcheck_lfshift # (http://codespeak.net/pypy/dist/pypy/doc/coding-guide.html#integer-types) - - # left shift, must fail if we lose bits beyond 32 - from rpython.rlib.rarithmetic import intmask, r_uint, ovfcheck, int_between if argument > 0: - # argument > 0, therefore the highest bit of upperbound is not set, - # i.e. upperbound is positive - upperbound = intmask(r_uint(-1) >> argument) - if 0 <= receiver <= upperbound: - shifted = intmask(receiver << argument) - return interp.space.wrap_positive_32bit_int(shifted) - else: - try: - shifted = ovfcheck(receiver << argument) - except OverflowError: - raise PrimitiveFailedError() - return interp.space.wrap_int(shifted) - - # right shift, ok to lose bits + return receiver.lshift(interp.space, argument) else: - return interp.space.wrap_int(receiver >> -argument) - + return receiver.rshift(interp.space, -argument) # ___________________________________________________________________________ # Float Primitives @@ -578,7 +559,6 @@ except Return: w_dest_form = w_rcvr.fetch(space, 0) if w_dest_form.is_same_object(space.objtable['w_display']): - #import pdb; pdb.set_trace() w_bitmap = w_dest_form.fetch(space, 0) assert isinstance(w_bitmap, model.W_DisplayBitmap) w_bitmap.flush_to_screen() diff --git a/spyvm/test/test_primitives.py b/spyvm/test/test_primitives.py --- a/spyvm/test/test_primitives.py +++ b/spyvm/test/test_primitives.py @@ -157,7 +157,6 @@ assert prim(primitives.BIT_SHIFT, [4, 27]).value == 536870912 def test_small_int_bit_shift_negative(): - py.test.skip("While this would make sense, because of the specification, we dont shift negative numbers") assert prim(primitives.BIT_SHIFT, [-4, -3]).value == -1 assert prim(primitives.BIT_SHIFT, [-4, -2]).value == -1 assert prim(primitives.BIT_SHIFT, [-4, -1]).value == -2 From noreply at buildbot.pypy.org Wed Apr 10 14:01:41 2013 From: noreply at buildbot.pypy.org (antocuni) Date: Wed, 10 Apr 2013 14:01:41 +0200 (CEST) Subject: [pypy-commit] pypy refactor-call_release_gil: fix for float vs longlong on 32bit Message-ID: <20130410120141.A49B11C1495@cobra.cs.uni-duesseldorf.de> Author: Antonio Cuni Branch: refactor-call_release_gil Changeset: r63198:4d0e47f211ed Date: 2013-04-10 14:03 +0200 http://bitbucket.org/pypy/pypy/changeset/4d0e47f211ed/ Log: fix for float vs longlong on 32bit diff --git a/rpython/jit/metainterp/blackhole.py b/rpython/jit/metainterp/blackhole.py --- a/rpython/jit/metainterp/blackhole.py +++ b/rpython/jit/metainterp/blackhole.py @@ -1360,6 +1360,7 @@ @arguments("cpu", "i", "i", "f") def bhimpl_libffi_save_result_float(self, cif_description, exchange_buffer, result): + result = longlong.getrealfloat(result) ARRAY = lltype.Ptr(rffi.CArray(lltype.Float)) cif_description = self.cast_int_to_ptr(cif_description, CIF_DESCRIPTION_P) exchange_buffer = self.cast_int_to_ptr(exchange_buffer, rffi.CCHARP) From noreply at buildbot.pypy.org Wed Apr 10 16:50:39 2013 From: noreply at buildbot.pypy.org (alex_gaynor) Date: Wed, 10 Apr 2013 16:50:39 +0200 (CEST) Subject: [pypy-commit] pypy default: a JIT test for codecs lookup Message-ID: <20130410145039.B07A71C010B@cobra.cs.uni-duesseldorf.de> Author: Alex Gaynor Branch: Changeset: r63199:4c7feafa28c3 Date: 2013-04-10 07:50 -0700 http://bitbucket.org/pypy/pypy/changeset/4c7feafa28c3/ Log: a JIT test for codecs lookup diff --git a/pypy/module/pypyjit/test_pypy_c/test_string.py b/pypy/module/pypyjit/test_pypy_c/test_string.py --- a/pypy/module/pypyjit/test_pypy_c/test_string.py +++ b/pypy/module/pypyjit/test_pypy_c/test_string.py @@ -237,3 +237,15 @@ loops = log.loops_by_filename(self.filepath) loop, = loops loop.match_by_id('callone', '') # nothing + + def test_lookup_codec(self): + log = self.run(""" + import codecs + + def main(n): + for i in xrange(n): + codecs.lookup('utf8') # ID: codecs + return i + """, [1000]) + loop, = log.loops_by_filename(self.filepath) + loop.match_by_id('codecs', '') From noreply at buildbot.pypy.org Wed Apr 10 17:49:32 2013 From: noreply at buildbot.pypy.org (mattip) Date: Wed, 10 Apr 2013 17:49:32 +0200 (CEST) Subject: [pypy-commit] pypy default: fix failing c_dup test on windows Message-ID: <20130410154932.314411C0F12@cobra.cs.uni-duesseldorf.de> Author: mattip Branch: Changeset: r63200:1b764ce510d6 Date: 2013-04-10 18:49 +0300 http://bitbucket.org/pypy/pypy/changeset/1b764ce510d6/ Log: fix failing c_dup test on windows diff --git a/rpython/rlib/_rsocket_rffi.py b/rpython/rlib/_rsocket_rffi.py --- a/rpython/rlib/_rsocket_rffi.py +++ b/rpython/rlib/_rsocket_rffi.py @@ -346,7 +346,7 @@ ]) CConfig.WSAPROTOCOL_INFO = platform.Struct( - 'WSAPROTOCOL_INFO', + 'WSAPROTOCOL_INFOA', []) # Struct is just passed between functions CConfig.FROM_PROTOCOL_INFO = platform.DefinedConstantInteger( 'FROM_PROTOCOL_INFO') @@ -612,11 +612,11 @@ WSAPROTOCOL_INFO = cConfig.WSAPROTOCOL_INFO FROM_PROTOCOL_INFO = cConfig.FROM_PROTOCOL_INFO - WSADuplicateSocket = external('WSADuplicateSocket', + WSADuplicateSocket = external('WSADuplicateSocketA', [socketfd_type, rwin32.DWORD, lltype.Ptr(WSAPROTOCOL_INFO)], rffi.INT) - WSASocket = external('WSASocket', + WSASocket = external('WSASocketA', [rffi.INT, rffi.INT, rffi.INT, lltype.Ptr(WSAPROTOCOL_INFO), rwin32.DWORD, rwin32.DWORD], diff --git a/rpython/rlib/rsocket.py b/rpython/rlib/rsocket.py --- a/rpython/rlib/rsocket.py +++ b/rpython/rlib/rsocket.py @@ -1053,7 +1053,7 @@ if _c.WIN32: def dup(fd): - with lltype.scoped_alloc(_c.WSAData, zero=True) as info: + with lltype.scoped_alloc(_c.WSAPROTOCOL_INFO, zero=True) as info: if _c.WSADuplicateSocket(fd, rwin32.GetCurrentProcessId(), info): raise last_error() result = _c.WSASocket( From noreply at buildbot.pypy.org Wed Apr 10 17:58:31 2013 From: noreply at buildbot.pypy.org (mattip) Date: Wed, 10 Apr 2013 17:58:31 +0200 (CEST) Subject: [pypy-commit] pypy py3k: fix failing c_dup test on windows Message-ID: <20130410155831.7BBBC1C016E@cobra.cs.uni-duesseldorf.de> Author: mattip Branch: py3k Changeset: r63201:44c4ed072af2 Date: 2013-04-10 18:49 +0300 http://bitbucket.org/pypy/pypy/changeset/44c4ed072af2/ Log: fix failing c_dup test on windows diff --git a/rpython/rlib/_rsocket_rffi.py b/rpython/rlib/_rsocket_rffi.py --- a/rpython/rlib/_rsocket_rffi.py +++ b/rpython/rlib/_rsocket_rffi.py @@ -346,7 +346,7 @@ ]) CConfig.WSAPROTOCOL_INFO = platform.Struct( - 'WSAPROTOCOL_INFO', + 'WSAPROTOCOL_INFOA', []) # Struct is just passed between functions CConfig.FROM_PROTOCOL_INFO = platform.DefinedConstantInteger( 'FROM_PROTOCOL_INFO') @@ -612,11 +612,11 @@ WSAPROTOCOL_INFO = cConfig.WSAPROTOCOL_INFO FROM_PROTOCOL_INFO = cConfig.FROM_PROTOCOL_INFO - WSADuplicateSocket = external('WSADuplicateSocket', + WSADuplicateSocket = external('WSADuplicateSocketA', [socketfd_type, rwin32.DWORD, lltype.Ptr(WSAPROTOCOL_INFO)], rffi.INT) - WSASocket = external('WSASocket', + WSASocket = external('WSASocketA', [rffi.INT, rffi.INT, rffi.INT, lltype.Ptr(WSAPROTOCOL_INFO), rwin32.DWORD, rwin32.DWORD], diff --git a/rpython/rlib/rsocket.py b/rpython/rlib/rsocket.py --- a/rpython/rlib/rsocket.py +++ b/rpython/rlib/rsocket.py @@ -1053,7 +1053,7 @@ if _c.WIN32: def dup(fd): - with lltype.scoped_alloc(_c.WSAData, zero=True) as info: + with lltype.scoped_alloc(_c.WSAPROTOCOL_INFO, zero=True) as info: if _c.WSADuplicateSocket(fd, rwin32.GetCurrentProcessId(), info): raise last_error() result = _c.WSASocket( From noreply at buildbot.pypy.org Wed Apr 10 18:36:58 2013 From: noreply at buildbot.pypy.org (arigo) Date: Wed, 10 Apr 2013 18:36:58 +0200 (CEST) Subject: [pypy-commit] pypy default: Fix Message-ID: <20130410163658.82C1E1C010B@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63202:4943ac67b80c Date: 2013-04-10 18:36 +0200 http://bitbucket.org/pypy/pypy/changeset/4943ac67b80c/ Log: Fix diff --git a/rpython/translator/c/gcc/instruction.py b/rpython/translator/c/gcc/instruction.py --- a/rpython/translator/c/gcc/instruction.py +++ b/rpython/translator/c/gcc/instruction.py @@ -57,11 +57,11 @@ def getlocation(self, framesize, uses_frame_pointer, wordsize): if (self.hint == 'esp' or not uses_frame_pointer - or self.ofs_from_frame_end % 2 != 0): + or self.ofs_from_frame_end % 1 != 0): # try to use esp-relative addressing ofs_from_esp = framesize + self.ofs_from_frame_end - if ofs_from_esp % 2 == 0: - return frameloc_esp(ofs_from_esp, wordsize) + if ofs_from_esp % 1 == 0: + return frameloc_esp(int(ofs_from_esp), wordsize) # we can get an odd value if the framesize is marked as bogus # by visit_andl() assert uses_frame_pointer @@ -177,12 +177,12 @@ class InsnStackAdjust(Insn): _args_ = ['delta'] def __init__(self, delta): - assert delta % 2 == 0 # should be "% 4", but there is the special - self.delta = delta # case of 'pushw' to handle + #assert delta % 4 == 0 --- but not really, gcc generates strange code + self.delta = delta class InsnCannotFollowEsp(InsnStackAdjust): def __init__(self): - self.delta = -7 # use an odd value as marker + self.delta = -7.25 # use this non-integer value as a marker class InsnStop(Insn): _args_ = ['reason'] diff --git a/rpython/translator/c/gcc/test/elf/track_odd_esp.s b/rpython/translator/c/gcc/test/elf/track_odd_esp.s new file mode 100644 --- /dev/null +++ b/rpython/translator/c/gcc/test/elf/track_odd_esp.s @@ -0,0 +1,97 @@ + .type pypy_g_copy_flags_from_bases, @function +pypy_g_copy_flags_from_bases: +.LFB188: + .cfi_startproc + pushl %ebp + .cfi_def_cfa_offset 8 + .cfi_offset 5, -8 + xorl %edx, %edx + pushl %edi + .cfi_def_cfa_offset 12 + .cfi_offset 7, -12 + pushl %esi + .cfi_def_cfa_offset 16 + .cfi_offset 6, -16 + pushl %ebx + .cfi_def_cfa_offset 20 + .cfi_offset 3, -20 + subl $1, %esp + .cfi_def_cfa_offset 21 + movl 21(%esp), %ebx + movb $0, (%esp) + movl 16(%ebx), %ebp + movl 4(%ebp), %edi + .p2align 4,,7 + .p2align 3 +.L572: + cmpl %edi, %edx + jge .L573 +.L590: +.L574: + addl $1, %edx + movl 4(%ebp,%edx,4), %ecx + testl %ecx, %ecx + je .L585 +.L576: + movl 4(%ecx), %esi + movl (%esi), %esi + subl $404, %esi + cmpl $10, %esi + ja .L585 +.L577: + cmpb $0, 443(%ebx) + movl $1, %esi + jne .L578 +.L579: + movzbl 443(%ecx), %esi +.L578: + cmpb $0, 444(%ebx) + movl %esi, %eax + movb %al, 443(%ebx) + movl $1, %esi + jne .L580 +.L581: + movzbl 444(%ecx), %esi +.L580: + cmpb $0, 446(%ebx) + movl %esi, %eax + movb %al, 444(%ebx) + movl $1, %esi + jne .L582 +.L583: + movzbl 446(%ecx), %esi +.L582: + movl %esi, %eax + cmpl %edi, %edx + movb %al, 446(%ebx) + jl .L590 +.L573: + movl 25(%esp), %edx + movzbl (%esp), %eax + movl 420(%edx), %edx + movl %edx, 420(%ebx) + addl $1, %esp + .cfi_remember_state + .cfi_def_cfa_offset 20 + popl %ebx + .cfi_restore 3 + .cfi_def_cfa_offset 16 + popl %esi + .cfi_restore 6 + .cfi_def_cfa_offset 12 + popl %edi + .cfi_restore 7 + .cfi_def_cfa_offset 8 + popl %ebp + .cfi_restore 5 + .cfi_def_cfa_offset 4 + ret + .p2align 4,,7 + .p2align 3 +.L585: + .cfi_restore_state + movb $1, (%esp) + jmp .L572 + .cfi_endproc +.LFE188: + .size pypy_g_copy_flags_from_bases, .-pypy_g_copy_flags_from_bases From noreply at buildbot.pypy.org Wed Apr 10 20:12:24 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Wed, 10 Apr 2013 20:12:24 +0200 (CEST) Subject: [pypy-commit] pypy stdlib-2.7.4: cleanup _subprocess constants, add STILL_ACTIVE Message-ID: <20130410181224.A3BD31C0F12@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: stdlib-2.7.4 Changeset: r63203:4436949b7f40 Date: 2013-04-10 14:12 -0400 http://bitbucket.org/pypy/pypy/changeset/4436949b7f40/ Log: cleanup _subprocess constants, add STILL_ACTIVE diff --git a/lib_pypy/_subprocess.py b/lib_pypy/_subprocess.py --- a/lib_pypy/_subprocess.py +++ b/lib_pypy/_subprocess.py @@ -33,7 +33,7 @@ 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_uint] _WaitForSingleObject.restype = ctypes.c_int @@ -85,7 +85,7 @@ del ctypes -# Now the _subprocess module implementation +# Now the _subprocess module implementation from ctypes import c_int as _c_int, byref as _byref, WinError as _WinError @@ -123,7 +123,6 @@ def GetCurrentProcess(): return _handle(_GetCurrentProcess()) - def DuplicateHandle(source_process, source, target_process, access, inherit, options=0): target = _c_int() @@ -135,8 +134,6 @@ raise _WinError() return _handle(target.value) -DUPLICATE_SAME_ACCESS = 2 - def CreateProcess(name, command_line, process_attr, thread_attr, inherit, flags, env, start_dir, startup_info): @@ -168,11 +165,6 @@ raise _WinError() return _handle(pi.hProcess), _handle(pi.hThread), pi.dwProcessID, pi.dwThreadID -STARTF_USESHOWWINDOW = 0x001 -STARTF_USESTDHANDLES = 0x100 -SW_HIDE = 0 -CREATE_NEW_CONSOLE = 0x010 -CREATE_NEW_PROCESS_GROUP = 0x200 def WaitForSingleObject(handle, milliseconds): res = _WaitForSingleObject(int(handle), milliseconds) @@ -181,12 +173,10 @@ raise _WinError() return res -INFINITE = 0xffffffff -WAIT_OBJECT_0 = 0 def GetExitCodeProcess(handle): code = _c_int() - + res = _GetExitCodeProcess(int(handle), _byref(code)) if not res: @@ -207,6 +197,16 @@ return None else: return res -STD_INPUT_HANDLE = -10 + +STD_INPUT_HANDLE = -10 STD_OUTPUT_HANDLE = -11 -STD_ERROR_HANDLE = -12 +STD_ERROR_HANDLE = -12 +DUPLICATE_SAME_ACCESS = 2 +STARTF_USESTDHANDLES = 0x100 +STARTF_USESHOWWINDOW = 0x001 +SW_HIDE = 0 +INFINITE = 0xffffffff +WAIT_OBJECT_0 = 0 +CREATE_NEW_CONSOLE = 0x010 +CREATE_NEW_PROCESS_GROUP = 0x200 +STILL_ACTIVE = 259 From noreply at buildbot.pypy.org Wed Apr 10 20:19:04 2013 From: noreply at buildbot.pypy.org (arigo) Date: Wed, 10 Apr 2013 20:19:04 +0200 (CEST) Subject: [pypy-commit] pypy stm-gc-2: in-progress Message-ID: <20130410181904.63A291C016E@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: stm-gc-2 Changeset: r63204:8a6a4348b8c4 Date: 2013-04-10 20:18 +0200 http://bitbucket.org/pypy/pypy/changeset/8a6a4348b8c4/ Log: in-progress diff --git a/rpython/memory/gc/stmshared.py b/rpython/memory/gc/stmshared.py --- a/rpython/memory/gc/stmshared.py +++ b/rpython/memory/gc/stmshared.py @@ -27,18 +27,11 @@ PAGE_PTR = lltype.Ptr(lltype.ForwardReference()) PAGE_HEADER = lltype.Struct('PageHeader', - # -- The following pointer makes a chained list of pages. For non-full - # pages, it is a chained list of pages having the same size class, - # rooted in 'page_for_size[size_class]'. For full pages, it is a - # different chained list rooted in 'full_page_for_size[size_class]'. + # -- The following pointer makes a chained list of pages. ('nextpage', PAGE_PTR), - # -- The number of free blocks. The numbers of uninitialized and - # allocated blocks can be deduced from the context if needed. - ('nfree', lltype.Signed), - # -- The chained list of free blocks. It ends as a pointer to the - # first uninitialized block (pointing to data that is uninitialized, - # or to the end of the page). - ('freeblock', llmemory.Address), + # -- XXX + ('xxx1', lltype.Signed), + ('xxx2', llmemory.Address), # -- The structure above is 3 words, which is a good value: # '(1023-3) % N' is zero or very small for various small N's, # i.e. there is not much wasted space. @@ -96,93 +89,88 @@ self.sharedarea = sharedarea self.chained_list = NULL # - # These two arrays contain each 'length' chained lists of pages. + # The array 'pages_for_size' contains 'length' chained lists + # of pages currently managed by this thread. # For each size N between WORD and 'small_request_threshold' # (included), the corresponding chained list contains pages - # which store objects of size N. The 'page_for_size' lists are - # for pages which still have room for at least one more object, - # and the 'full_page_for_size' lists are for full pages. + # which store objects of size N. length = sharedarea.small_request_threshold / WORD + 1 - self.page_for_size = lltype.malloc(rffi.CArray(PAGE_PTR), length, - flavor='raw', zero=True, - immortal=True) - self.full_page_for_size = lltype.malloc(rffi.CArray(PAGE_PTR), length, - flavor='raw', zero=True, - immortal=True) + self.pages_for_size = lltype.malloc( + rffi.CArray(PAGE_PTR), length, flavor='raw', zero=True) + # + # This array contains 'length' chained lists of free object locations. + self.free_objects_for_size = lltype.malloc( + rffi.CArray(llmemory.Address), length, flavor='raw', zero=True) # if not we_are_translated(): self._seen_pages = set() + def free(self): + lltype.free(self.free_objects_for_size, flavor='raw') + lltype.free(self.pages_for_size, flavor='raw') + self.delete() + def _malloc_size_class(self, size_class): """Malloc one object of the given size_class (== number of WORDs).""" ll_assert(size_class > 0, "malloc_size_class: null or neg size_class") ll_assert(size_class <= self.sharedarea.small_request_threshold, "malloc_size_class: too big") # - # Get the page to use - page = self.page_for_size[size_class] - if page == PAGE_NULL: - page = self._allocate_new_page(size_class) - # - # The result is simply 'page.freeblock' - result = page.freeblock - nsize = size_class << WORD_POWER_2 - if page.nfree > 0: - # - # The 'result' was part of the chained list; read the next. - page.nfree -= 1 - freeblock = result.address[0] - llarena.arena_reset(result, - llmemory.sizeof(llmemory.Address), - 0) - # - else: - # The 'result' is part of the uninitialized blocks. - freeblock = result + nsize - # - page.freeblock = freeblock - # - pageaddr = llarena.getfakearenaaddress(llmemory.cast_ptr_to_adr(page)) - if freeblock - pageaddr > self.sharedarea.page_size - nsize: - # This was the last free block, so unlink the page from the - # chained list and put it in the 'full_page_for_size' list. - self.page_for_size[size_class] = page.nextpage - page.nextpage = self.full_page_for_size[size_class] - self.full_page_for_size[size_class] = page - # + # The result is simply 'free_objects_for_size[size_class]' + result = self.free_objects_for_size[size_class] + if not result: + result = self._allocate_new_page(size_class) + self.free_objects_for_size[size_class] = result.address[0] + llarena.arena_reset(result, llmemory.sizeof(llmemory.Address), 0) return result + _malloc_size_class._always_inline_ = True + def _free_size_class(self, obj, size_class): + """Free a single object 'obj', which is of the given size_class.""" + # just link 'obj' to the start of 'free_objects_for_size[size_class]' + obj = llarena.getfakearenaaddress(obj) + llarena.arena_reset(obj, size_class << WORD_POWER_2, 0) + llarena.arena_reserve(obj, llmemory.sizeof(llmemory.Address)) + obj.address[0] = self.free_objects_for_size[size_class] + self.free_objects_for_size[size_class] = obj + _free_size_class._always_inline_ = True def _allocate_new_page(self, size_class): """Allocate and return a new page for the given size_class.""" # - # If 'low_usage_page' has pages ready, return one of them. - # Check both before acquiring the lock (NULL is the common case - # and getting it occasionally wrong is not a problem), and after. - result = NULL - sharedarea = self.sharedarea - if sharedarea.low_usage_page[size_class] != PAGE_NULL: - XXX # self.ll_low_usage_lock... - # - # If unsuccessful, just raw-malloc a new page. + result = llarena.arena_malloc(self.sharedarea.page_size, 0) if not result: - result = llarena.arena_malloc(sharedarea.page_size, 0) - if not result: - fatalerror("FIXME: Out of memory! (should raise MemoryError)") - return PAGE_NULL - if not we_are_translated(): - self._seen_pages.add(result) - llarena.arena_reserve(result, llmemory.sizeof(PAGE_HEADER)) + fatalerror("FIXME: Out of memory! (should raise MemoryError)") + return PAGE_NULL + if not we_are_translated(): + self._seen_pages.add(result) + llarena.arena_reserve(result, llmemory.sizeof(PAGE_HEADER)) # # Initialize the fields of the resulting page page = llmemory.cast_adr_to_ptr(result, PAGE_PTR) - page.nfree = 0 - page.freeblock = result + sharedarea.hdrsize - page.nextpage = PAGE_NULL - ll_assert(self.page_for_size[size_class] == PAGE_NULL, - "allocate_new_page() called but a page is already waiting") - self.page_for_size[size_class] = page - return page + page.nextpage = self.pages_for_size[size_class] + self.pages_for_size[size_class] = page + # + # Initialize the chained list in the page + head = result + llmemory.sizeof(PAGE_HEADER) + ll_assert(not self.free_objects_for_size[size_class], + "free_objects_for_size is supposed to contain NULL here") + self.free_objects_for_size[size_class] = head + # + i = self.sharedarea.nblocks_for_size[size_class] + nsize = size_class << WORD_POWER_2 + current = head + while True: + llarena.arena_reserve(current, llmemory.sizeof(llmemory.Address)) + i -= 1 + if i == 0: + break + next = current + nsize + current.address[0] = next + current = next + current.address[0] = llmemory.NULL + # + return head def malloc_object(self, totalsize): @@ -204,9 +192,14 @@ self.gc.set_obj_revision(obj, self.chained_list) self.chained_list = obj - def free_object(self, adr2): - adr1 = adr2 - self.gc.gcheaderbuilder.size_gc_header - llarena.arena_free(llarena.getfakearenaaddress(adr1)) + def free_object(self, obj): + osize = self.gc.get_size_incl_hash(obj) + if osize <= self.sharedarea.small_request_threshold: + size_class = (osize + WORD_POWER_2 - 1) >> WORD_POWER_2 + self._free_size_class(obj, size_class) + else: + adr1 = obj - self.gc.gcheaderbuilder.size_gc_header + llarena.arena_free(llarena.getfakearenaaddress(adr1)) def free_and_clear(self): obj = self.chained_list diff --git a/rpython/memory/gc/stmtls.py b/rpython/memory/gc/stmtls.py --- a/rpython/memory/gc/stmtls.py +++ b/rpython/memory/gc/stmtls.py @@ -77,7 +77,7 @@ self._cleanup_state() self._unregister_with_C_code() self.local_weakrefs.delete() - self.sharedarea_tls.delete() + self.sharedarea_tls.free() self._free_nursery(self.nursery_start) free_non_gc_object(self) diff --git a/rpython/memory/gc/test/test_stmshared.py b/rpython/memory/gc/test/test_stmshared.py --- a/rpython/memory/gc/test/test_stmshared.py +++ b/rpython/memory/gc/test/test_stmshared.py @@ -19,3 +19,25 @@ assert len(thl1._seen_pages) == 3 thl1.malloc_object(2*WORD) assert len(thl1._seen_pages) == 3 + thl1.free() + +class FakeGC: + def __init__(self): + self._object_sizes = {} + def set_size(self, obj, size): + assert obj not in self._object_sizes + self._object_sizes[obj] = size + def get_size_incl_hash(self, obj): + return self._object_sizes[obj] + +def test_free(): + gc = FakeGC() + shared = StmGCSharedArea(gc, 10*WORD, 2*WORD) + shared.setup() + thl1 = StmGCThreadLocalAllocator(shared) + obj = thl1.malloc_object(2*WORD) + gc.set_size(obj, 2*WORD) + thl1.free_object(obj) + obj2 = thl1.malloc_object(2*WORD) + assert obj2 == obj # reusing the same location + thl1.free() From noreply at buildbot.pypy.org Wed Apr 10 21:03:10 2013 From: noreply at buildbot.pypy.org (bivab) Date: Wed, 10 Apr 2013 21:03:10 +0200 (CEST) Subject: [pypy-commit] pypy default: port _check_frame_depth_debug for ARM Message-ID: <20130410190310.DD0661C0651@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63205:318f2b360814 Date: 2013-04-10 21:01 +0200 http://bitbucket.org/pypy/pypy/changeset/318f2b360814/ Log: port _check_frame_depth_debug for ARM diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -30,6 +30,7 @@ class AssemblerARM(ResOpAssembler): debug = False + DEBUG_FRAME_DEPTH = False def __init__(self, cpu, translate_support_code=False): ResOpAssembler.__init__(self, cpu, translate_support_code) @@ -67,6 +68,7 @@ allblocks) self.mc.datablockwrapper = self.datablockwrapper self.target_tokens_currently_compiling = {} + self.frame_depth_to_patch = [] def teardown(self): self.current_clt = None @@ -597,6 +599,7 @@ 'e', looptoken.number) self._call_header_with_stack_check() + self._check_frame_depth_debug(self.mc) regalloc = Regalloc(assembler=self) operations = regalloc.prepare_loop(inputargs, operations, looptoken, @@ -670,8 +673,7 @@ self.current_clt.allgcrefs, self.current_clt.frame_info) - stack_check_patch_ofs = self._check_frame_depth(self.mc, - regalloc.get_gcmap()) + self._check_frame_depth(self.mc, regalloc.get_gcmap()) frame_depth_no_fixed_size = self._assemble(regalloc, inputargs, operations) @@ -687,6 +689,8 @@ self.patch_trace(faildescr, original_loop_token, rawstart, regalloc) + self.patch_stack_checks(frame_depth_no_fixed_size + JITFRAME_FIXED_SIZE, + rawstart) if not we_are_translated(): if log: self.mc._dump_trace(rawstart, 'bridge.asm') @@ -695,7 +699,6 @@ frame_depth = max(self.current_clt.frame_info.jfi_frame_depth, frame_depth_no_fixed_size + JITFRAME_FIXED_SIZE) self.fixup_target_tokens(rawstart) - self._patch_stackadjust(stack_check_patch_ofs + rawstart, frame_depth) self.update_frame_depth(frame_depth) self.teardown() @@ -719,6 +722,11 @@ self._check_frame_depth(self.mc, self._regalloc.get_gcmap(), expected_size=expected_size) + def _patch_frame_depth(self, adr, allocated_depth): + mc = InstrBuilder(self.cpu.arch_version) + mc.gen_load_int(r.lr.value, allocated_depth) + mc.copy_to_raw_memory(adr) + def _check_frame_depth(self, mc, gcmap, expected_size=-1): """ check if the frame is of enough depth to follow this bridge. Otherwise reallocate the frame in a helper. @@ -751,7 +759,35 @@ pmc = OverwritingBuilder(mc, jg_location, WORD) pmc.B_offs(currpos, c.GE) - return stack_check_cmp_ofs + self.frame_depth_to_patch.append(stack_check_cmp_ofs) + + def _check_frame_depth_debug(self, mc): + """ double check the depth size. It prints the error (and potentially + segfaults later) + """ + if not self.DEBUG_FRAME_DEPTH: + return + descrs = self.cpu.gc_ll_descr.getframedescrs(self.cpu) + ofs = self.cpu.unpack_fielddescr(descrs.arraydescr.lendescr) + mc.LDR_ri(r.ip.value, r.fp.value, imm=ofs) + stack_check_cmp_ofs = mc.currpos() + for _ in range(mc.get_max_size_of_gen_load_int()): + mc.NOP() + mc.CMP_rr(r.ip.value, r.lr.value) + + jg_location = mc.currpos() + mc.BKPT() + + mc.MOV_rr(r.r0.value, r.fp.value) + mc.MOV_ri(r.r1.value, r.lr.value) + + self.mc.BL(self.cpu.realloc_frame_crash) + # patch the JG above + currpos = self.mc.currpos() + pmc = OverwritingBuilder(mc, jg_location, WORD) + pmc.B_offs(currpos, c.GE) + + self.frame_depth_to_patch.append(stack_check_cmp_ofs) def build_frame_realloc_slowpath(self): # this code should do the following steps @@ -827,6 +863,10 @@ mc.gen_load_int(r.lr.value, allocated_depth) mc.copy_to_raw_memory(adr) + def patch_stack_checks(self, framedepth, rawstart): + for ofs in self.frame_depth_to_patch: + self._patch_frame_depth(ofs + rawstart, framedepth) + def target_arglocs(self, loop_token): return loop_token._arm_arglocs diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -298,6 +298,10 @@ return self._emit_guard(op, locs, fcond, save_exc=False, is_guard_not_invalidated=True) + def emit_op_label(self, op, arglocs, regalloc, fcond): + self._check_frame_depth_debug(self.mc) + return fcond + def emit_op_jump(self, op, arglocs, regalloc, fcond): target_token = op.getdescr() assert isinstance(target_token, TargetToken) diff --git a/rpython/jit/backend/arm/regalloc.py b/rpython/jit/backend/arm/regalloc.py --- a/rpython/jit/backend/arm/regalloc.py +++ b/rpython/jit/backend/arm/regalloc.py @@ -1091,6 +1091,7 @@ #jump_op = self.final_jump_op #if jump_op is not None and jump_op.getdescr() is descr: # self._compute_hint_frame_locations_from_descr(descr) + return [] def prepare_guard_call_may_force(self, op, guard_op, fcond): args = self._prepare_call(op, save_all_regs=True) From noreply at buildbot.pypy.org Wed Apr 10 21:03:12 2013 From: noreply at buildbot.pypy.org (bivab) Date: Wed, 10 Apr 2013 21:03:12 +0200 (CEST) Subject: [pypy-commit] pypy default: merge heads Message-ID: <20130410190312.2E7BF1C0651@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63206:4d9490bdc460 Date: 2013-04-10 21:02 +0200 http://bitbucket.org/pypy/pypy/changeset/4d9490bdc460/ Log: merge heads diff --git a/rpython/translator/c/gcc/instruction.py b/rpython/translator/c/gcc/instruction.py --- a/rpython/translator/c/gcc/instruction.py +++ b/rpython/translator/c/gcc/instruction.py @@ -57,11 +57,11 @@ def getlocation(self, framesize, uses_frame_pointer, wordsize): if (self.hint == 'esp' or not uses_frame_pointer - or self.ofs_from_frame_end % 2 != 0): + or self.ofs_from_frame_end % 1 != 0): # try to use esp-relative addressing ofs_from_esp = framesize + self.ofs_from_frame_end - if ofs_from_esp % 2 == 0: - return frameloc_esp(ofs_from_esp, wordsize) + if ofs_from_esp % 1 == 0: + return frameloc_esp(int(ofs_from_esp), wordsize) # we can get an odd value if the framesize is marked as bogus # by visit_andl() assert uses_frame_pointer @@ -177,12 +177,12 @@ class InsnStackAdjust(Insn): _args_ = ['delta'] def __init__(self, delta): - assert delta % 2 == 0 # should be "% 4", but there is the special - self.delta = delta # case of 'pushw' to handle + #assert delta % 4 == 0 --- but not really, gcc generates strange code + self.delta = delta class InsnCannotFollowEsp(InsnStackAdjust): def __init__(self): - self.delta = -7 # use an odd value as marker + self.delta = -7.25 # use this non-integer value as a marker class InsnStop(Insn): _args_ = ['reason'] diff --git a/rpython/translator/c/gcc/test/elf/track_odd_esp.s b/rpython/translator/c/gcc/test/elf/track_odd_esp.s new file mode 100644 --- /dev/null +++ b/rpython/translator/c/gcc/test/elf/track_odd_esp.s @@ -0,0 +1,97 @@ + .type pypy_g_copy_flags_from_bases, @function +pypy_g_copy_flags_from_bases: +.LFB188: + .cfi_startproc + pushl %ebp + .cfi_def_cfa_offset 8 + .cfi_offset 5, -8 + xorl %edx, %edx + pushl %edi + .cfi_def_cfa_offset 12 + .cfi_offset 7, -12 + pushl %esi + .cfi_def_cfa_offset 16 + .cfi_offset 6, -16 + pushl %ebx + .cfi_def_cfa_offset 20 + .cfi_offset 3, -20 + subl $1, %esp + .cfi_def_cfa_offset 21 + movl 21(%esp), %ebx + movb $0, (%esp) + movl 16(%ebx), %ebp + movl 4(%ebp), %edi + .p2align 4,,7 + .p2align 3 +.L572: + cmpl %edi, %edx + jge .L573 +.L590: +.L574: + addl $1, %edx + movl 4(%ebp,%edx,4), %ecx + testl %ecx, %ecx + je .L585 +.L576: + movl 4(%ecx), %esi + movl (%esi), %esi + subl $404, %esi + cmpl $10, %esi + ja .L585 +.L577: + cmpb $0, 443(%ebx) + movl $1, %esi + jne .L578 +.L579: + movzbl 443(%ecx), %esi +.L578: + cmpb $0, 444(%ebx) + movl %esi, %eax + movb %al, 443(%ebx) + movl $1, %esi + jne .L580 +.L581: + movzbl 444(%ecx), %esi +.L580: + cmpb $0, 446(%ebx) + movl %esi, %eax + movb %al, 444(%ebx) + movl $1, %esi + jne .L582 +.L583: + movzbl 446(%ecx), %esi +.L582: + movl %esi, %eax + cmpl %edi, %edx + movb %al, 446(%ebx) + jl .L590 +.L573: + movl 25(%esp), %edx + movzbl (%esp), %eax + movl 420(%edx), %edx + movl %edx, 420(%ebx) + addl $1, %esp + .cfi_remember_state + .cfi_def_cfa_offset 20 + popl %ebx + .cfi_restore 3 + .cfi_def_cfa_offset 16 + popl %esi + .cfi_restore 6 + .cfi_def_cfa_offset 12 + popl %edi + .cfi_restore 7 + .cfi_def_cfa_offset 8 + popl %ebp + .cfi_restore 5 + .cfi_def_cfa_offset 4 + ret + .p2align 4,,7 + .p2align 3 +.L585: + .cfi_restore_state + movb $1, (%esp) + jmp .L572 + .cfi_endproc +.LFE188: + .size pypy_g_copy_flags_from_bases, .-pypy_g_copy_flags_from_bases From noreply at buildbot.pypy.org Wed Apr 10 21:54:48 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Wed, 10 Apr 2013 21:54:48 +0200 (CEST) Subject: [pypy-commit] pypy default: add reduce/setstate for functools.partial to match cpython, test Message-ID: <20130410195448.C8B7C1C016E@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63207:c7692ec6d138 Date: 2013-04-10 15:52 -0400 http://bitbucket.org/pypy/pypy/changeset/c7692ec6d138/ Log: add reduce/setstate for functools.partial to match cpython, test diff --git a/lib_pypy/_functools.py b/lib_pypy/_functools.py --- a/lib_pypy/_functools.py +++ b/lib_pypy/_functools.py @@ -20,3 +20,16 @@ if self.keywords is not None: fkeywords = dict(self.keywords, **fkeywords) return self.func(*(self.args + fargs), **fkeywords) + + def __reduce__(self): + d = dict((k, v) for k, v in self.__dict__.iteritems() if k not in + ('func', 'args', 'keywords')) + if len(d) == 0: + d = None + return (type(self), (self.func,), + (self.func, self.args, self.keywords, d)) + + def __setstate__(self, state): + self.func, self.args, self.keywords, d = state + if d is not None: + self.__dict__.update(d) diff --git a/pypy/module/test_lib_pypy/test_functools.py b/pypy/module/test_lib_pypy/test_functools.py new file mode 100644 --- /dev/null +++ b/pypy/module/test_lib_pypy/test_functools.py @@ -0,0 +1,19 @@ +from lib_pypy import _functools + +def test_partial_reduce(): + partial = _functools.partial(test_partial_reduce) + state = partial.__reduce__() + assert state == (type(partial), (test_partial_reduce,), + (test_partial_reduce, (), None, None)) + +def test_partial_setstate(): + partial = _functools.partial(object) + partial.__setstate__([test_partial_setstate, (), None, None]) + assert partial.func == test_partial_setstate + +def test_partial_pickle(): + import pickle + partial1 = _functools.partial(test_partial_pickle) + string = pickle.dumps(partial1) + partial2 = pickle.loads(string) + assert partial1.func == partial2.func From noreply at buildbot.pypy.org Wed Apr 10 21:54:50 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Wed, 10 Apr 2013 21:54:50 +0200 (CEST) Subject: [pypy-commit] pypy default: merge heads Message-ID: <20130410195450.0A9141C016E@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63208:d809fcb12c77 Date: 2013-04-10 15:54 -0400 http://bitbucket.org/pypy/pypy/changeset/d809fcb12c77/ Log: merge heads diff --git a/pypy/module/pypyjit/test_pypy_c/test_string.py b/pypy/module/pypyjit/test_pypy_c/test_string.py --- a/pypy/module/pypyjit/test_pypy_c/test_string.py +++ b/pypy/module/pypyjit/test_pypy_c/test_string.py @@ -237,3 +237,15 @@ loops = log.loops_by_filename(self.filepath) loop, = loops loop.match_by_id('callone', '') # nothing + + def test_lookup_codec(self): + log = self.run(""" + import codecs + + def main(n): + for i in xrange(n): + codecs.lookup('utf8') # ID: codecs + return i + """, [1000]) + loop, = log.loops_by_filename(self.filepath) + loop.match_by_id('codecs', '') diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -30,6 +30,7 @@ class AssemblerARM(ResOpAssembler): debug = False + DEBUG_FRAME_DEPTH = False def __init__(self, cpu, translate_support_code=False): ResOpAssembler.__init__(self, cpu, translate_support_code) @@ -67,6 +68,7 @@ allblocks) self.mc.datablockwrapper = self.datablockwrapper self.target_tokens_currently_compiling = {} + self.frame_depth_to_patch = [] def teardown(self): self.current_clt = None @@ -597,6 +599,7 @@ 'e', looptoken.number) self._call_header_with_stack_check() + self._check_frame_depth_debug(self.mc) regalloc = Regalloc(assembler=self) operations = regalloc.prepare_loop(inputargs, operations, looptoken, @@ -670,8 +673,7 @@ self.current_clt.allgcrefs, self.current_clt.frame_info) - stack_check_patch_ofs = self._check_frame_depth(self.mc, - regalloc.get_gcmap()) + self._check_frame_depth(self.mc, regalloc.get_gcmap()) frame_depth_no_fixed_size = self._assemble(regalloc, inputargs, operations) @@ -687,6 +689,8 @@ self.patch_trace(faildescr, original_loop_token, rawstart, regalloc) + self.patch_stack_checks(frame_depth_no_fixed_size + JITFRAME_FIXED_SIZE, + rawstart) if not we_are_translated(): if log: self.mc._dump_trace(rawstart, 'bridge.asm') @@ -695,7 +699,6 @@ frame_depth = max(self.current_clt.frame_info.jfi_frame_depth, frame_depth_no_fixed_size + JITFRAME_FIXED_SIZE) self.fixup_target_tokens(rawstart) - self._patch_stackadjust(stack_check_patch_ofs + rawstart, frame_depth) self.update_frame_depth(frame_depth) self.teardown() @@ -719,6 +722,11 @@ self._check_frame_depth(self.mc, self._regalloc.get_gcmap(), expected_size=expected_size) + def _patch_frame_depth(self, adr, allocated_depth): + mc = InstrBuilder(self.cpu.arch_version) + mc.gen_load_int(r.lr.value, allocated_depth) + mc.copy_to_raw_memory(adr) + def _check_frame_depth(self, mc, gcmap, expected_size=-1): """ check if the frame is of enough depth to follow this bridge. Otherwise reallocate the frame in a helper. @@ -751,7 +759,35 @@ pmc = OverwritingBuilder(mc, jg_location, WORD) pmc.B_offs(currpos, c.GE) - return stack_check_cmp_ofs + self.frame_depth_to_patch.append(stack_check_cmp_ofs) + + def _check_frame_depth_debug(self, mc): + """ double check the depth size. It prints the error (and potentially + segfaults later) + """ + if not self.DEBUG_FRAME_DEPTH: + return + descrs = self.cpu.gc_ll_descr.getframedescrs(self.cpu) + ofs = self.cpu.unpack_fielddescr(descrs.arraydescr.lendescr) + mc.LDR_ri(r.ip.value, r.fp.value, imm=ofs) + stack_check_cmp_ofs = mc.currpos() + for _ in range(mc.get_max_size_of_gen_load_int()): + mc.NOP() + mc.CMP_rr(r.ip.value, r.lr.value) + + jg_location = mc.currpos() + mc.BKPT() + + mc.MOV_rr(r.r0.value, r.fp.value) + mc.MOV_ri(r.r1.value, r.lr.value) + + self.mc.BL(self.cpu.realloc_frame_crash) + # patch the JG above + currpos = self.mc.currpos() + pmc = OverwritingBuilder(mc, jg_location, WORD) + pmc.B_offs(currpos, c.GE) + + self.frame_depth_to_patch.append(stack_check_cmp_ofs) def build_frame_realloc_slowpath(self): # this code should do the following steps @@ -827,6 +863,10 @@ mc.gen_load_int(r.lr.value, allocated_depth) mc.copy_to_raw_memory(adr) + def patch_stack_checks(self, framedepth, rawstart): + for ofs in self.frame_depth_to_patch: + self._patch_frame_depth(ofs + rawstart, framedepth) + def target_arglocs(self, loop_token): return loop_token._arm_arglocs diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -298,6 +298,10 @@ return self._emit_guard(op, locs, fcond, save_exc=False, is_guard_not_invalidated=True) + def emit_op_label(self, op, arglocs, regalloc, fcond): + self._check_frame_depth_debug(self.mc) + return fcond + def emit_op_jump(self, op, arglocs, regalloc, fcond): target_token = op.getdescr() assert isinstance(target_token, TargetToken) diff --git a/rpython/jit/backend/arm/regalloc.py b/rpython/jit/backend/arm/regalloc.py --- a/rpython/jit/backend/arm/regalloc.py +++ b/rpython/jit/backend/arm/regalloc.py @@ -1091,6 +1091,7 @@ #jump_op = self.final_jump_op #if jump_op is not None and jump_op.getdescr() is descr: # self._compute_hint_frame_locations_from_descr(descr) + return [] def prepare_guard_call_may_force(self, op, guard_op, fcond): args = self._prepare_call(op, save_all_regs=True) diff --git a/rpython/rlib/_rsocket_rffi.py b/rpython/rlib/_rsocket_rffi.py --- a/rpython/rlib/_rsocket_rffi.py +++ b/rpython/rlib/_rsocket_rffi.py @@ -346,7 +346,7 @@ ]) CConfig.WSAPROTOCOL_INFO = platform.Struct( - 'WSAPROTOCOL_INFO', + 'WSAPROTOCOL_INFOA', []) # Struct is just passed between functions CConfig.FROM_PROTOCOL_INFO = platform.DefinedConstantInteger( 'FROM_PROTOCOL_INFO') @@ -612,11 +612,11 @@ WSAPROTOCOL_INFO = cConfig.WSAPROTOCOL_INFO FROM_PROTOCOL_INFO = cConfig.FROM_PROTOCOL_INFO - WSADuplicateSocket = external('WSADuplicateSocket', + WSADuplicateSocket = external('WSADuplicateSocketA', [socketfd_type, rwin32.DWORD, lltype.Ptr(WSAPROTOCOL_INFO)], rffi.INT) - WSASocket = external('WSASocket', + WSASocket = external('WSASocketA', [rffi.INT, rffi.INT, rffi.INT, lltype.Ptr(WSAPROTOCOL_INFO), rwin32.DWORD, rwin32.DWORD], diff --git a/rpython/rlib/rsocket.py b/rpython/rlib/rsocket.py --- a/rpython/rlib/rsocket.py +++ b/rpython/rlib/rsocket.py @@ -1053,7 +1053,7 @@ if _c.WIN32: def dup(fd): - with lltype.scoped_alloc(_c.WSAData, zero=True) as info: + with lltype.scoped_alloc(_c.WSAPROTOCOL_INFO, zero=True) as info: if _c.WSADuplicateSocket(fd, rwin32.GetCurrentProcessId(), info): raise last_error() result = _c.WSASocket( diff --git a/rpython/translator/c/gcc/instruction.py b/rpython/translator/c/gcc/instruction.py --- a/rpython/translator/c/gcc/instruction.py +++ b/rpython/translator/c/gcc/instruction.py @@ -57,11 +57,11 @@ def getlocation(self, framesize, uses_frame_pointer, wordsize): if (self.hint == 'esp' or not uses_frame_pointer - or self.ofs_from_frame_end % 2 != 0): + or self.ofs_from_frame_end % 1 != 0): # try to use esp-relative addressing ofs_from_esp = framesize + self.ofs_from_frame_end - if ofs_from_esp % 2 == 0: - return frameloc_esp(ofs_from_esp, wordsize) + if ofs_from_esp % 1 == 0: + return frameloc_esp(int(ofs_from_esp), wordsize) # we can get an odd value if the framesize is marked as bogus # by visit_andl() assert uses_frame_pointer @@ -177,12 +177,12 @@ class InsnStackAdjust(Insn): _args_ = ['delta'] def __init__(self, delta): - assert delta % 2 == 0 # should be "% 4", but there is the special - self.delta = delta # case of 'pushw' to handle + #assert delta % 4 == 0 --- but not really, gcc generates strange code + self.delta = delta class InsnCannotFollowEsp(InsnStackAdjust): def __init__(self): - self.delta = -7 # use an odd value as marker + self.delta = -7.25 # use this non-integer value as a marker class InsnStop(Insn): _args_ = ['reason'] diff --git a/rpython/translator/c/gcc/test/elf/track_odd_esp.s b/rpython/translator/c/gcc/test/elf/track_odd_esp.s new file mode 100644 --- /dev/null +++ b/rpython/translator/c/gcc/test/elf/track_odd_esp.s @@ -0,0 +1,97 @@ + .type pypy_g_copy_flags_from_bases, @function +pypy_g_copy_flags_from_bases: +.LFB188: + .cfi_startproc + pushl %ebp + .cfi_def_cfa_offset 8 + .cfi_offset 5, -8 + xorl %edx, %edx + pushl %edi + .cfi_def_cfa_offset 12 + .cfi_offset 7, -12 + pushl %esi + .cfi_def_cfa_offset 16 + .cfi_offset 6, -16 + pushl %ebx + .cfi_def_cfa_offset 20 + .cfi_offset 3, -20 + subl $1, %esp + .cfi_def_cfa_offset 21 + movl 21(%esp), %ebx + movb $0, (%esp) + movl 16(%ebx), %ebp + movl 4(%ebp), %edi + .p2align 4,,7 + .p2align 3 +.L572: + cmpl %edi, %edx + jge .L573 +.L590: +.L574: + addl $1, %edx + movl 4(%ebp,%edx,4), %ecx + testl %ecx, %ecx + je .L585 +.L576: + movl 4(%ecx), %esi + movl (%esi), %esi + subl $404, %esi + cmpl $10, %esi + ja .L585 +.L577: + cmpb $0, 443(%ebx) + movl $1, %esi + jne .L578 +.L579: + movzbl 443(%ecx), %esi +.L578: + cmpb $0, 444(%ebx) + movl %esi, %eax + movb %al, 443(%ebx) + movl $1, %esi + jne .L580 +.L581: + movzbl 444(%ecx), %esi +.L580: + cmpb $0, 446(%ebx) + movl %esi, %eax + movb %al, 444(%ebx) + movl $1, %esi + jne .L582 +.L583: + movzbl 446(%ecx), %esi +.L582: + movl %esi, %eax + cmpl %edi, %edx + movb %al, 446(%ebx) + jl .L590 +.L573: + movl 25(%esp), %edx + movzbl (%esp), %eax + movl 420(%edx), %edx + movl %edx, 420(%ebx) + addl $1, %esp + .cfi_remember_state + .cfi_def_cfa_offset 20 + popl %ebx + .cfi_restore 3 + .cfi_def_cfa_offset 16 + popl %esi + .cfi_restore 6 + .cfi_def_cfa_offset 12 + popl %edi + .cfi_restore 7 + .cfi_def_cfa_offset 8 + popl %ebp + .cfi_restore 5 + .cfi_def_cfa_offset 4 + ret + .p2align 4,,7 + .p2align 3 +.L585: + .cfi_restore_state + movb $1, (%esp) + jmp .L572 + .cfi_endproc +.LFE188: + .size pypy_g_copy_flags_from_bases, .-pypy_g_copy_flags_from_bases From noreply at buildbot.pypy.org Wed Apr 10 21:54:51 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Wed, 10 Apr 2013 21:54:51 +0200 (CEST) Subject: [pypy-commit] pypy stdlib-2.7.4: merge default Message-ID: <20130410195451.65BE31C016E@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: stdlib-2.7.4 Changeset: r63209:861f1f888ff9 Date: 2013-04-10 15:54 -0400 http://bitbucket.org/pypy/pypy/changeset/861f1f888ff9/ Log: merge default diff --git a/lib_pypy/_functools.py b/lib_pypy/_functools.py --- a/lib_pypy/_functools.py +++ b/lib_pypy/_functools.py @@ -20,3 +20,16 @@ if self.keywords is not None: fkeywords = dict(self.keywords, **fkeywords) return self.func(*(self.args + fargs), **fkeywords) + + def __reduce__(self): + d = dict((k, v) for k, v in self.__dict__.iteritems() if k not in + ('func', 'args', 'keywords')) + if len(d) == 0: + d = None + return (type(self), (self.func,), + (self.func, self.args, self.keywords, d)) + + def __setstate__(self, state): + self.func, self.args, self.keywords, d = state + if d is not None: + self.__dict__.update(d) diff --git a/pypy/interpreter/pyparser/parsestring.py b/pypy/interpreter/pyparser/parsestring.py --- a/pypy/interpreter/pyparser/parsestring.py +++ b/pypy/interpreter/pyparser/parsestring.py @@ -91,9 +91,9 @@ assert 0 <= bufp <= bufq substr = buf[bufp:bufq] if rawmode: - v = unicodehelper.PyUnicode_DecodeRawUnicodeEscape(space, substr) + v = unicodehelper.decode_raw_unicode_escape(space, substr) else: - v = unicodehelper.PyUnicode_DecodeUnicodeEscape(space, substr) + v = unicodehelper.decode_unicode_escape(space, substr) return space.wrap(v) need_encoding = (encoding is not None and @@ -103,8 +103,8 @@ substr = s[ps : q] if rawmode or '\\' not in s[ps:]: if need_encoding: - w_u = space.wrap(unicodehelper.PyUnicode_DecodeUTF8(space, substr)) - w_v = unicodehelper.PyUnicode_AsEncodedString(space, w_u, space.wrap(encoding)) + w_u = space.wrap(unicodehelper.decode_utf8(space, substr)) + w_v = unicodehelper.encode(space, w_u, encoding) return w_v else: return space.wrap(substr) @@ -219,8 +219,8 @@ # while (s < end && *s != '\\') s++; */ /* inefficient for u".." while ps < end and ord(s[ps]) & 0x80: ps += 1 - w_u = space.wrap(unicodehelper.PyUnicode_DecodeUTF8(space, s[pt:ps])) - w_v = unicodehelper.PyUnicode_AsEncodedString(space, w_u, space.wrap(encoding)) + w_u = space.wrap(unicodehelper.decode_utf8(space, s[pt:ps])) + w_v = unicodehelper.encode(space, w_u, encoding) v = space.str_w(w_v) return v, ps diff --git a/pypy/interpreter/unicodehelper.py b/pypy/interpreter/unicodehelper.py --- a/pypy/interpreter/unicodehelper.py +++ b/pypy/interpreter/unicodehelper.py @@ -29,11 +29,12 @@ # ____________________________________________________________ -def PyUnicode_AsEncodedString(space, w_data, w_encoding): - return interp_codecs.encode(space, w_data, w_encoding) +def encode(space, w_data, encoding=None, errors='strict'): + from pypy.objspace.std.unicodetype import encode_object + return encode_object(space, w_data, encoding, errors) # These functions take and return unwrapped rpython strings and unicodes -def PyUnicode_DecodeUnicodeEscape(space, string): +def decode_unicode_escape(space, string): state = space.fromcache(interp_codecs.CodecState) unicodedata_handler = state.get_unicodedata_handler(space) result, consumed = runicode.str_decode_unicode_escape( @@ -42,20 +43,20 @@ unicodedata_handler=unicodedata_handler) return result -def PyUnicode_DecodeRawUnicodeEscape(space, string): +def decode_raw_unicode_escape(space, string): result, consumed = runicode.str_decode_raw_unicode_escape( string, len(string), "strict", final=True, errorhandler=decode_error_handler(space)) return result -def PyUnicode_DecodeUTF8(space, string): +def decode_utf8(space, string): result, consumed = runicode.str_decode_utf_8( string, len(string), "strict", final=True, errorhandler=decode_error_handler(space), allow_surrogates=True) return result -def PyUnicode_EncodeUTF8(space, uni): +def encode_utf8(space, uni): return runicode.unicode_encode_utf_8( uni, len(uni), "strict", errorhandler=encode_error_handler(space), diff --git a/pypy/module/_codecs/interp_codecs.py b/pypy/module/_codecs/interp_codecs.py --- a/pypy/module/_codecs/interp_codecs.py +++ b/pypy/module/_codecs/interp_codecs.py @@ -1,10 +1,18 @@ +from rpython.rlib import jit +from rpython.rlib.objectmodel import we_are_translated +from rpython.rlib.rstring import UnicodeBuilder + from pypy.interpreter.error import OperationError, operationerrfmt from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault -from rpython.rlib.rstring import UnicodeBuilder -from rpython.rlib.objectmodel import we_are_translated + + +class VersionTag(object): + pass class CodecState(object): + _immutable_fields_ = ["version?"] + def __init__(self, space): self.codec_search_path = [] self.codec_search_cache = {} @@ -14,6 +22,7 @@ self.encode_error_handler = self.make_encode_errorhandler(space) self.unicodedata_handler = None + self.modified() def _make_errorhandler(self, space, decode): def call_errorhandler(errors, encoding, reason, input, startpos, @@ -86,9 +95,20 @@ self.unicodedata_handler = UnicodeData_Handler(space, w_getcode) return self.unicodedata_handler + def modified(self): + self.version = VersionTag() + + def get_codec_from_cache(self, key): + return self._get_codec_with_version(key, self.version) + + @jit.elidable + def _get_codec_with_version(self, key, version): + return self.codec_search_cache.get(key, None) + def _cleanup_(self): assert not self.codec_search_path + def register_codec(space, w_search_function): """register(search_function) @@ -115,11 +135,12 @@ "lookup_codec() should not be called during translation" state = space.fromcache(CodecState) normalized_encoding = encoding.replace(" ", "-").lower() - w_result = state.codec_search_cache.get(normalized_encoding, None) + w_result = state.get_codec_from_cache(normalized_encoding) if w_result is not None: return w_result return _lookup_codec_loop(space, encoding, normalized_encoding) + def _lookup_codec_loop(space, encoding, normalized_encoding): state = space.fromcache(CodecState) if state.codec_need_encodings: @@ -143,6 +164,7 @@ space.wrap("codec search functions must return 4-tuples")) else: state.codec_search_cache[normalized_encoding] = w_result + state.modified() return w_result raise operationerrfmt( space.w_LookupError, diff --git a/pypy/module/pyexpat/interp_pyexpat.py b/pypy/module/pyexpat/interp_pyexpat.py --- a/pypy/module/pyexpat/interp_pyexpat.py +++ b/pypy/module/pyexpat/interp_pyexpat.py @@ -475,8 +475,8 @@ def w_convert(self, space, s): if self.returns_unicode: - from pypy.interpreter.unicodehelper import PyUnicode_DecodeUTF8 - return space.wrap(PyUnicode_DecodeUTF8(space, s)) + from pypy.interpreter.unicodehelper import decode_utf8 + return space.wrap(decode_utf8(space, s)) else: return space.wrap(s) diff --git a/pypy/module/pypyjit/test_pypy_c/test_string.py b/pypy/module/pypyjit/test_pypy_c/test_string.py --- a/pypy/module/pypyjit/test_pypy_c/test_string.py +++ b/pypy/module/pypyjit/test_pypy_c/test_string.py @@ -237,3 +237,15 @@ loops = log.loops_by_filename(self.filepath) loop, = loops loop.match_by_id('callone', '') # nothing + + def test_lookup_codec(self): + log = self.run(""" + import codecs + + def main(n): + for i in xrange(n): + codecs.lookup('utf8') # ID: codecs + return i + """, [1000]) + loop, = log.loops_by_filename(self.filepath) + loop.match_by_id('codecs', '') diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_function.py b/pypy/module/test_lib_pypy/cffi_tests/test_function.py --- a/pypy/module/test_lib_pypy/cffi_tests/test_function.py +++ b/pypy/module/test_lib_pypy/cffi_tests/test_function.py @@ -16,7 +16,7 @@ """xxx limited to capture at most 512 bytes of output, according to the Posix manual.""" - def __init__(self, capture_fd=1): # stdout, by default + def __init__(self, capture_fd): self.capture_fd = capture_fd def __enter__(self): @@ -109,80 +109,66 @@ y = lib.TlsFree(x) assert y != 0 - def test_puts(self): + def test_fputs(self): + if not sys.platform.startswith('linux'): + py.test.skip("probably no symbol 'stderr' in the lib") ffi = FFI(backend=self.Backend()) ffi.cdef(""" - int puts(const char *); - int fflush(void *); + int fputs(const char *, void *); + void *stderr; """) ffi.C = ffi.dlopen(None) - ffi.C.puts # fetch before capturing, for easier debugging - with FdWriteCapture() as fd: - ffi.C.puts(b"hello") - ffi.C.puts(b" world") - ffi.C.fflush(ffi.NULL) + ffi.C.fputs # fetch before capturing, for easier debugging + with FdWriteCapture(2) as fd: + ffi.C.fputs(b"hello\n", ffi.C.stderr) + ffi.C.fputs(b" world\n", ffi.C.stderr) res = fd.getvalue() assert res == b'hello\n world\n' - def test_puts_without_const(self): + def test_fputs_without_const(self): + if not sys.platform.startswith('linux'): + py.test.skip("probably no symbol 'stderr' in the lib") ffi = FFI(backend=self.Backend()) ffi.cdef(""" - int puts(char *); - int fflush(void *); + int fputs(char *, void *); + void *stderr; """) ffi.C = ffi.dlopen(None) - ffi.C.puts # fetch before capturing, for easier debugging - with FdWriteCapture() as fd: - ffi.C.puts(b"hello") - ffi.C.puts(b" world") - ffi.C.fflush(ffi.NULL) + ffi.C.fputs # fetch before capturing, for easier debugging + with FdWriteCapture(2) as fd: + ffi.C.fputs(b"hello\n", ffi.C.stderr) + ffi.C.fputs(b" world\n", ffi.C.stderr) res = fd.getvalue() assert res == b'hello\n world\n' - def test_fputs(self): + def test_vararg(self): if not sys.platform.startswith('linux'): - py.test.skip("probably no symbol 'stdout' in the lib") + py.test.skip("probably no symbol 'stderr' in the lib") ffi = FFI(backend=self.Backend()) ffi.cdef(""" - int fputs(const char *, void *); - void *stdout, *stderr; + int fprintf(void *, const char *format, ...); + void *stderr; """) ffi.C = ffi.dlopen(None) with FdWriteCapture(2) as fd: - ffi.C.fputs(b"hello from stderr\n", ffi.C.stderr) + ffi.C.fprintf(ffi.C.stderr, b"hello with no arguments\n") + ffi.C.fprintf(ffi.C.stderr, + b"hello, %s!\n", ffi.new("char[]", b"world")) + ffi.C.fprintf(ffi.C.stderr, + ffi.new("char[]", b"hello, %s!\n"), + ffi.new("char[]", b"world2")) + ffi.C.fprintf(ffi.C.stderr, + b"hello int %d long %ld long long %lld\n", + ffi.cast("int", 42), + ffi.cast("long", 84), + ffi.cast("long long", 168)) + ffi.C.fprintf(ffi.C.stderr, b"hello %p\n", ffi.NULL) res = fd.getvalue() - assert res == b'hello from stderr\n' - - def test_vararg(self): - ffi = FFI(backend=self.Backend()) - ffi.cdef(""" - int printf(const char *format, ...); - int fflush(void *); - """) - ffi.C = ffi.dlopen(None) - with FdWriteCapture() as fd: - ffi.C.printf(b"hello with no arguments\n") - ffi.C.printf(b"hello, %s!\n", ffi.new("char[]", b"world")) - ffi.C.printf(ffi.new("char[]", b"hello, %s!\n"), - ffi.new("char[]", b"world2")) - ffi.C.printf(b"hello int %d long %ld long long %lld\n", - ffi.cast("int", 42), - ffi.cast("long", 84), - ffi.cast("long long", 168)) - ffi.C.printf(b"hello %p\n", ffi.NULL) - ffi.C.fflush(ffi.NULL) - res = fd.getvalue() - if sys.platform == 'win32': - NIL = b"00000000" - elif sys.platform.startswith(('linux', 'gnu')): - NIL = b"(nil)" - else: - NIL = b"0x0" # OS/X at least assert res == (b"hello with no arguments\n" b"hello, world!\n" b"hello, world2!\n" b"hello int 42 long 84 long long 168\n" - b"hello " + NIL + b"\n") + b"hello (nil)\n") def test_must_specify_type_of_vararg(self): ffi = FFI(backend=self.Backend()) @@ -216,17 +202,18 @@ res = fptr(b"Hello") assert res == 42 # + if not sys.platform.startswith('linux'): + py.test.skip("probably no symbol 'stderr' in the lib") ffi.cdef(""" - int puts(const char *); - int fflush(void *); + int fputs(const char *, void *); + void *stderr; """) ffi.C = ffi.dlopen(None) - fptr = ffi.cast("int(*)(const char *txt)", ffi.C.puts) - assert fptr == ffi.C.puts - assert repr(fptr).startswith(" Author: Brian Kearns Branch: stdlib-2.7.4 Changeset: r63210:dd627c7dbe3a Date: 2013-04-10 16:01 -0400 http://bitbucket.org/pypy/pypy/changeset/dd627c7dbe3a/ Log: skip test for ref counting bug diff --git a/lib-python/2.7/test/test_functools.py b/lib-python/2.7/test/test_functools.py --- a/lib-python/2.7/test/test_functools.py +++ b/lib-python/2.7/test/test_functools.py @@ -155,6 +155,7 @@ self.assertEqual(signature(f), signature(f_copy)) # Issue 6083: Reference counting bug + @unittest.skipUnless(test_support.check_impl_detail(), "ref counting") def test_setstate_refcount(self): class BadSequence: def __len__(self): From noreply at buildbot.pypy.org Wed Apr 10 22:34:01 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Wed, 10 Apr 2013 22:34:01 +0200 (CEST) Subject: [pypy-commit] pypy stdlib-2.7.4: fix new import test for pypy implementation detail Message-ID: <20130410203401.F3C561C0F12@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: stdlib-2.7.4 Changeset: r63211:5ad480c31fe4 Date: 2013-04-10 16:33 -0400 http://bitbucket.org/pypy/pypy/changeset/5ad480c31fe4/ Log: fix new import test for pypy implementation detail diff --git a/lib-python/2.7/test/test_import.py b/lib-python/2.7/test/test_import.py --- a/lib-python/2.7/test/test_import.py +++ b/lib-python/2.7/test/test_import.py @@ -164,7 +164,8 @@ m2 = __import__(TESTFN) self.assertEqual(m2.x, 'rewritten') # Now delete the source file and check the pyc was rewritten - unlink(fname) + if check_impl_detail(pypy=False): + unlink(fname) unload(TESTFN) m3 = __import__(TESTFN) self.assertEqual(m3.x, 'rewritten') From noreply at buildbot.pypy.org Wed Apr 10 22:48:13 2013 From: noreply at buildbot.pypy.org (bivab) Date: Wed, 10 Apr 2013 22:48:13 +0200 (CEST) Subject: [pypy-commit] pypy default: (fijal, bivab) only store the gcmap in finish if we are returning a REF Message-ID: <20130410204813.6B83B1C0651@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63212:f41dea88cd33 Date: 2013-04-10 22:47 +0200 http://bitbucket.org/pypy/pypy/changeset/f41dea88cd33/ Log: (fijal, bivab) only store the gcmap in finish if we are returning a REF diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -26,7 +26,7 @@ from rpython.jit.backend.llsupport.descr import InteriorFieldDescr from rpython.jit.backend.llsupport.assembler import GuardToken, BaseAssembler from rpython.jit.metainterp.history import (Box, AbstractFailDescr, - INT, FLOAT) + INT, FLOAT, REF) from rpython.jit.metainterp.history import TargetToken from rpython.jit.metainterp.resoperation import rop from rpython.rlib.objectmodel import we_are_translated @@ -325,8 +325,15 @@ self.mc.gen_load_int(r.ip.value, fail_descr_loc.value) # XXX self.mov(fail_descr_loc, RawStackLoc(ofs)) self.store_reg(self.mc, r.ip, r.fp, ofs, helper=r.lr) - gcmap = self.gcmap_for_finish - self.push_gcmap(self.mc, gcmap, store=True) + if op.numargs() > 0 and op.getarg(0).type == REF: + gcmap = self.gcmap_for_finish + self.push_gcmap(self.mc, gcmap, store=True) + else: + # note that the 0 here is redundant, but I would rather + # keep that one and kill all the others + ofs = self.cpu.get_ofs_of_frame_field('jf_gcmap') + self.mc.gen_load_int(r.ip.value, 0) + self.store_reg(self.mc, r.ip, r.fp, ofs) self.mc.MOV_rr(r.r0.value, r.fp.value) # exit function self.gen_func_epilog() From noreply at buildbot.pypy.org Wed Apr 10 22:48:14 2013 From: noreply at buildbot.pypy.org (bivab) Date: Wed, 10 Apr 2013 22:48:14 +0200 (CEST) Subject: [pypy-commit] pypy default: merge heads Message-ID: <20130410204814.BBC251C0651@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63213:994b5a29d2cd Date: 2013-04-10 22:47 +0200 http://bitbucket.org/pypy/pypy/changeset/994b5a29d2cd/ Log: merge heads diff --git a/lib_pypy/_functools.py b/lib_pypy/_functools.py --- a/lib_pypy/_functools.py +++ b/lib_pypy/_functools.py @@ -20,3 +20,16 @@ if self.keywords is not None: fkeywords = dict(self.keywords, **fkeywords) return self.func(*(self.args + fargs), **fkeywords) + + def __reduce__(self): + d = dict((k, v) for k, v in self.__dict__.iteritems() if k not in + ('func', 'args', 'keywords')) + if len(d) == 0: + d = None + return (type(self), (self.func,), + (self.func, self.args, self.keywords, d)) + + def __setstate__(self, state): + self.func, self.args, self.keywords, d = state + if d is not None: + self.__dict__.update(d) diff --git a/pypy/module/test_lib_pypy/test_functools.py b/pypy/module/test_lib_pypy/test_functools.py new file mode 100644 --- /dev/null +++ b/pypy/module/test_lib_pypy/test_functools.py @@ -0,0 +1,19 @@ +from lib_pypy import _functools + +def test_partial_reduce(): + partial = _functools.partial(test_partial_reduce) + state = partial.__reduce__() + assert state == (type(partial), (test_partial_reduce,), + (test_partial_reduce, (), None, None)) + +def test_partial_setstate(): + partial = _functools.partial(object) + partial.__setstate__([test_partial_setstate, (), None, None]) + assert partial.func == test_partial_setstate + +def test_partial_pickle(): + import pickle + partial1 = _functools.partial(test_partial_pickle) + string = pickle.dumps(partial1) + partial2 = pickle.loads(string) + assert partial1.func == partial2.func From noreply at buildbot.pypy.org Thu Apr 11 00:19:27 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Thu, 11 Apr 2013 00:19:27 +0200 (CEST) Subject: [pypy-commit] pypy stdlib-2.7.4: _io: call close on stream even if flush raises (cpython issue16597) Message-ID: <20130410221927.81F8F1C0651@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: stdlib-2.7.4 Changeset: r63214:ab324b210044 Date: 2013-04-10 18:19 -0400 http://bitbucket.org/pypy/pypy/changeset/ab324b210044/ Log: _io: call close on stream even if flush raises (cpython issue16597) diff --git a/pypy/module/_io/interp_bufferedio.py b/pypy/module/_io/interp_bufferedio.py --- a/pypy/module/_io/interp_bufferedio.py +++ b/pypy/module/_io/interp_bufferedio.py @@ -311,9 +311,11 @@ with self.lock: if self._closed(space): return - space.call_method(self, "flush") - with self.lock: - space.call_method(self.w_raw, "close") + try: + space.call_method(self, "flush") + finally: + with self.lock: + space.call_method(self.w_raw, "close") def simple_flush_w(self, space): self._check_init(space) diff --git a/pypy/module/_io/interp_textio.py b/pypy/module/_io/interp_textio.py --- a/pypy/module/_io/interp_textio.py +++ b/pypy/module/_io/interp_textio.py @@ -494,8 +494,10 @@ self._check_init(space) if not space.is_true(space.getattr(self.w_buffer, space.wrap("closed"))): - space.call_method(self, "flush") - return space.call_method(self.w_buffer, "close") + try: + space.call_method(self, "flush") + finally: + return space.call_method(self.w_buffer, "close") # _____________________________________________________________ # read methods diff --git a/pypy/module/_io/test/test_bufferedio.py b/pypy/module/_io/test/test_bufferedio.py --- a/pypy/module/_io/test/test_bufferedio.py +++ b/pypy/module/_io/test/test_bufferedio.py @@ -513,6 +513,35 @@ exc = raises(RuntimeError, bufio.flush) assert "reentrant" in str(exc.value) # And not e.g. recursion limit. + def test_write_error_on_close(self): + import _io + class MockRawIO(_io._RawIOBase): + def writable(self): + return True + def write(self, data): + raise IOError() + raw = MockRawIO() + b = _io.BufferedWriter(raw) + b.write(b'spam') + raises(IOError, b.close) # exception not swallowed + assert b.closed + + def test_close_error_on_close(self): + import _io + class MockRawIO(_io._RawIOBase): + def writable(self): + return True + def close(self): + raise IOError('close') + def bad_flush(): + raise IOError('flush') + raw = MockRawIO() + b = _io.BufferedWriter(raw) + b.flush = bad_flush + err = raises(IOError, b.close) # exception not swallowed + assert err.value.args == ('close',) + assert not b.closed + class AppTestBufferedRWPair: def test_pair(self): import _io diff --git a/pypy/module/_io/test/test_textio.py b/pypy/module/_io/test/test_textio.py --- a/pypy/module/_io/test/test_textio.py +++ b/pypy/module/_io/test/test_textio.py @@ -201,7 +201,6 @@ class AppTestIncrementalNewlineDecoder: - def test_newline_decoder(self): import _io def check_newline_decoding_utf8(decoder): From noreply at buildbot.pypy.org Thu Apr 11 00:37:03 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Thu, 11 Apr 2013 00:37:03 +0200 (CEST) Subject: [pypy-commit] pypy stdlib-2.7.4: test and fix for some _sqlite3 behavior changes Message-ID: <20130410223703.6F81C1C0651@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: stdlib-2.7.4 Changeset: r63215:734cac0606a1 Date: 2013-04-10 18:36 -0400 http://bitbucket.org/pypy/pypy/changeset/734cac0606a1/ Log: test and fix for some _sqlite3 behavior changes diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -787,7 +787,9 @@ try: ret = callback(action, arg1, arg2, dbname, source) assert isinstance(ret, int) - assert ret in (_lib.SQLITE_OK, _lib.SQLITE_DENY, _lib.SQLITE_IGNORE) + # try to detect cases in which cffi would swallow + # OverflowError when casting the return value + assert int(_ffi.cast('int', ret)) == ret return ret except Exception: return _lib.SQLITE_DENY diff --git a/pypy/module/test_lib_pypy/test_sqlite3.py b/pypy/module/test_lib_pypy/test_sqlite3.py --- a/pypy/module/test_lib_pypy/test_sqlite3.py +++ b/pypy/module/test_lib_pypy/test_sqlite3.py @@ -222,3 +222,11 @@ cur.execute("create table test(a)") cur.executemany("insert into test values (?)", [[1], [2], [3]]) assert cur.lastrowid is None + +def test_authorizer_bad_value(con): + def authorizer_cb(action, arg1, arg2, dbname, source): + return 42 + con.set_authorizer(authorizer_cb) + with pytest.raises(_sqlite3.OperationalError) as e: + con.execute('select 42') + assert str(e.value) == 'authorizer malfunction' From noreply at buildbot.pypy.org Thu Apr 11 01:29:18 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Thu, 11 Apr 2013 01:29:18 +0200 (CEST) Subject: [pypy-commit] pypy default: test for string_escape decode errors Message-ID: <20130410232918.A05821C010B@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63216:2a1f15301125 Date: 2013-04-10 19:15 -0400 http://bitbucket.org/pypy/pypy/changeset/2a1f15301125/ Log: test for string_escape decode errors diff --git a/pypy/module/_codecs/test/test_codecs.py b/pypy/module/_codecs/test/test_codecs.py --- a/pypy/module/_codecs/test/test_codecs.py +++ b/pypy/module/_codecs/test/test_codecs.py @@ -53,26 +53,25 @@ def test_unicodedecodeerror(self): assert str(UnicodeDecodeError( "ascii", "g\xfcrk", 1, 2, "ouch")) == "'ascii' codec can't decode byte 0xfc in position 1: ouch" - + assert str(UnicodeDecodeError( "ascii", "g\xfcrk", 1, 3, "ouch")) == "'ascii' codec can't decode bytes in position 1-2: ouch" - def test_unicodetranslateerror(self): import sys assert str(UnicodeTranslateError( u"g\xfcrk", 1, 2, "ouch"))== "can't translate character u'\\xfc' in position 1: ouch" - + assert str(UnicodeTranslateError( u"g\u0100rk", 1, 2, "ouch"))== "can't translate character u'\\u0100' in position 1: ouch" - + assert str(UnicodeTranslateError( u"g\uffffrk", 1, 2, "ouch"))== "can't translate character u'\\uffff' in position 1: ouch" - + if sys.maxunicode > 0xffff and len(unichr(0x10000)) == 1: assert str(UnicodeTranslateError( u"g\U00010000rk", 1, 2, "ouch"))== "can't translate character u'\\U00010000' in position 1: ouch" - + assert str(UnicodeTranslateError( u"g\xfcrk", 1, 3, "ouch"))=="can't translate characters in position 1-2: ouch" @@ -80,22 +79,22 @@ import sys assert str(UnicodeEncodeError( "ascii", u"g\xfcrk", 1, 2, "ouch"))=="'ascii' codec can't encode character u'\\xfc' in position 1: ouch" - + assert str(UnicodeEncodeError( "ascii", u"g\xfcrk", 1, 4, "ouch"))== "'ascii' codec can't encode characters in position 1-3: ouch" - + assert str(UnicodeEncodeError( "ascii", u"\xfcx", 0, 1, "ouch"))=="'ascii' codec can't encode character u'\\xfc' in position 0: ouch" assert str(UnicodeEncodeError( "ascii", u"\u0100x", 0, 1, "ouch"))=="'ascii' codec can't encode character u'\\u0100' in position 0: ouch" - + assert str(UnicodeEncodeError( "ascii", u"\uffffx", 0, 1, "ouch"))=="'ascii' codec can't encode character u'\\uffff' in position 0: ouch" if sys.maxunicode > 0xffff and len(unichr(0x10000)) == 1: assert str(UnicodeEncodeError( "ascii", u"\U00010000x", 0, 1, "ouch")) =="'ascii' codec can't encode character u'\\U00010000' in position 0: ouch" - + def test_indexerror(self): test = "\\" # trailing backslash raises (ValueError, test.decode,'string-escape') @@ -136,7 +135,7 @@ u"\x00\xff\u07ff\u0800", u"\x00\xff\u07ff\u0800\uffff", ] - + buffer = '' result = u"" for (c, partialresult) in zip(u"\x00\xff\u07ff\u0800\uffff".encode(encoding), check_partial): @@ -173,13 +172,12 @@ assert result == partialresult def test_bug1098990_a(self): - import codecs, StringIO self.encoding = 'utf-8' s1 = u"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy\r\n" s2 = u"offending line: ladfj askldfj klasdj fskla dfzaskdj fasklfj laskd fjasklfzzzzaa%whereisthis!!!\r\n" s3 = u"next line.\r\n" - + s = (s1+s2+s3).encode(self.encoding) stream = StringIO.StringIO(s) reader = codecs.getreader(self.encoding)(stream) @@ -205,8 +203,8 @@ assert reader.readline() == s3 assert reader.readline() == s4 assert reader.readline() == s5 - assert reader.readline() == u"" - + assert reader.readline() == u"" + def test_seek_utf16le(self): # all codecs should be able to encode these import codecs, StringIO @@ -219,7 +217,6 @@ line = reader.readline() assert s[:len(line)] == line - def test_unicode_internal_encode(self): import sys class U(unicode): @@ -284,6 +281,12 @@ assert '\\0f'.decode('string_escape') == chr(0) + 'f' assert '\\08'.decode('string_escape') == chr(0) + '8' + def test_escape_decode_errors(self): + raises(ValueError, br"\x".decode, 'string_escape') + raises(ValueError, br"[\x]".decode, 'string_escape') + raises(ValueError, br"\x0".decode, 'string_escape') + raises(ValueError, br"[\x0]".decode, 'string_escape') + def test_escape_encode(self): assert '"'.encode('string_escape') == '"' assert "'".encode('string_escape') == "\\'" From noreply at buildbot.pypy.org Thu Apr 11 01:29:19 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Thu, 11 Apr 2013 01:29:19 +0200 (CEST) Subject: [pypy-commit] pypy stdlib-2.7.4: merge default Message-ID: <20130410232919.C87001C0F12@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: stdlib-2.7.4 Changeset: r63217:9d7094ca3859 Date: 2013-04-10 19:29 -0400 http://bitbucket.org/pypy/pypy/changeset/9d7094ca3859/ Log: merge default diff --git a/pypy/module/_codecs/test/test_codecs.py b/pypy/module/_codecs/test/test_codecs.py --- a/pypy/module/_codecs/test/test_codecs.py +++ b/pypy/module/_codecs/test/test_codecs.py @@ -53,26 +53,25 @@ def test_unicodedecodeerror(self): assert str(UnicodeDecodeError( "ascii", "g\xfcrk", 1, 2, "ouch")) == "'ascii' codec can't decode byte 0xfc in position 1: ouch" - + assert str(UnicodeDecodeError( "ascii", "g\xfcrk", 1, 3, "ouch")) == "'ascii' codec can't decode bytes in position 1-2: ouch" - def test_unicodetranslateerror(self): import sys assert str(UnicodeTranslateError( u"g\xfcrk", 1, 2, "ouch"))== "can't translate character u'\\xfc' in position 1: ouch" - + assert str(UnicodeTranslateError( u"g\u0100rk", 1, 2, "ouch"))== "can't translate character u'\\u0100' in position 1: ouch" - + assert str(UnicodeTranslateError( u"g\uffffrk", 1, 2, "ouch"))== "can't translate character u'\\uffff' in position 1: ouch" - + if sys.maxunicode > 0xffff and len(unichr(0x10000)) == 1: assert str(UnicodeTranslateError( u"g\U00010000rk", 1, 2, "ouch"))== "can't translate character u'\\U00010000' in position 1: ouch" - + assert str(UnicodeTranslateError( u"g\xfcrk", 1, 3, "ouch"))=="can't translate characters in position 1-2: ouch" @@ -80,22 +79,22 @@ import sys assert str(UnicodeEncodeError( "ascii", u"g\xfcrk", 1, 2, "ouch"))=="'ascii' codec can't encode character u'\\xfc' in position 1: ouch" - + assert str(UnicodeEncodeError( "ascii", u"g\xfcrk", 1, 4, "ouch"))== "'ascii' codec can't encode characters in position 1-3: ouch" - + assert str(UnicodeEncodeError( "ascii", u"\xfcx", 0, 1, "ouch"))=="'ascii' codec can't encode character u'\\xfc' in position 0: ouch" assert str(UnicodeEncodeError( "ascii", u"\u0100x", 0, 1, "ouch"))=="'ascii' codec can't encode character u'\\u0100' in position 0: ouch" - + assert str(UnicodeEncodeError( "ascii", u"\uffffx", 0, 1, "ouch"))=="'ascii' codec can't encode character u'\\uffff' in position 0: ouch" if sys.maxunicode > 0xffff and len(unichr(0x10000)) == 1: assert str(UnicodeEncodeError( "ascii", u"\U00010000x", 0, 1, "ouch")) =="'ascii' codec can't encode character u'\\U00010000' in position 0: ouch" - + def test_indexerror(self): test = "\\" # trailing backslash raises (ValueError, test.decode,'string-escape') @@ -136,7 +135,7 @@ u"\x00\xff\u07ff\u0800", u"\x00\xff\u07ff\u0800\uffff", ] - + buffer = '' result = u"" for (c, partialresult) in zip(u"\x00\xff\u07ff\u0800\uffff".encode(encoding), check_partial): @@ -173,13 +172,12 @@ assert result == partialresult def test_bug1098990_a(self): - import codecs, StringIO self.encoding = 'utf-8' s1 = u"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy\r\n" s2 = u"offending line: ladfj askldfj klasdj fskla dfzaskdj fasklfj laskd fjasklfzzzzaa%whereisthis!!!\r\n" s3 = u"next line.\r\n" - + s = (s1+s2+s3).encode(self.encoding) stream = StringIO.StringIO(s) reader = codecs.getreader(self.encoding)(stream) @@ -205,8 +203,8 @@ assert reader.readline() == s3 assert reader.readline() == s4 assert reader.readline() == s5 - assert reader.readline() == u"" - + assert reader.readline() == u"" + def test_seek_utf16le(self): # all codecs should be able to encode these import codecs, StringIO @@ -219,7 +217,6 @@ line = reader.readline() assert s[:len(line)] == line - def test_unicode_internal_encode(self): import sys class U(unicode): @@ -284,6 +281,12 @@ assert '\\0f'.decode('string_escape') == chr(0) + 'f' assert '\\08'.decode('string_escape') == chr(0) + '8' + def test_escape_decode_errors(self): + raises(ValueError, br"\x".decode, 'string_escape') + raises(ValueError, br"[\x]".decode, 'string_escape') + raises(ValueError, br"\x0".decode, 'string_escape') + raises(ValueError, br"[\x0]".decode, 'string_escape') + def test_escape_encode(self): assert '"'.encode('string_escape') == '"' assert "'".encode('string_escape') == "\\'" diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -26,7 +26,7 @@ from rpython.jit.backend.llsupport.descr import InteriorFieldDescr from rpython.jit.backend.llsupport.assembler import GuardToken, BaseAssembler from rpython.jit.metainterp.history import (Box, AbstractFailDescr, - INT, FLOAT) + INT, FLOAT, REF) from rpython.jit.metainterp.history import TargetToken from rpython.jit.metainterp.resoperation import rop from rpython.rlib.objectmodel import we_are_translated @@ -325,8 +325,15 @@ self.mc.gen_load_int(r.ip.value, fail_descr_loc.value) # XXX self.mov(fail_descr_loc, RawStackLoc(ofs)) self.store_reg(self.mc, r.ip, r.fp, ofs, helper=r.lr) - gcmap = self.gcmap_for_finish - self.push_gcmap(self.mc, gcmap, store=True) + if op.numargs() > 0 and op.getarg(0).type == REF: + gcmap = self.gcmap_for_finish + self.push_gcmap(self.mc, gcmap, store=True) + else: + # note that the 0 here is redundant, but I would rather + # keep that one and kill all the others + ofs = self.cpu.get_ofs_of_frame_field('jf_gcmap') + self.mc.gen_load_int(r.ip.value, 0) + self.store_reg(self.mc, r.ip, r.fp, ofs) self.mc.MOV_rr(r.r0.value, r.fp.value) # exit function self.gen_func_epilog() From noreply at buildbot.pypy.org Thu Apr 11 01:47:49 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Thu, 11 Apr 2013 01:47:49 +0200 (CEST) Subject: [pypy-commit] pypy stdlib-2.7.4: replace tab Message-ID: <20130410234749.2A3011C0F12@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: stdlib-2.7.4 Changeset: r63218:41e362603c2d Date: 2013-04-10 19:47 -0400 http://bitbucket.org/pypy/pypy/changeset/41e362603c2d/ Log: replace tab diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -772,7 +772,7 @@ mc.LDR_ri(r.ip.value, r.fp.value, imm=ofs) stack_check_cmp_ofs = mc.currpos() for _ in range(mc.get_max_size_of_gen_load_int()): - mc.NOP() + mc.NOP() mc.CMP_rr(r.ip.value, r.lr.value) jg_location = mc.currpos() From noreply at buildbot.pypy.org Thu Apr 11 01:52:41 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Thu, 11 Apr 2013 01:52:41 +0200 (CEST) Subject: [pypy-commit] pypy default: replace tab Message-ID: <20130410235241.B82671C1477@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63219:816e4e71734f Date: 2013-04-10 19:47 -0400 http://bitbucket.org/pypy/pypy/changeset/816e4e71734f/ Log: replace tab diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -772,7 +772,7 @@ mc.LDR_ri(r.ip.value, r.fp.value, imm=ofs) stack_check_cmp_ofs = mc.currpos() for _ in range(mc.get_max_size_of_gen_load_int()): - mc.NOP() + mc.NOP() mc.CMP_rr(r.ip.value, r.lr.value) jg_location = mc.currpos() From noreply at buildbot.pypy.org Thu Apr 11 04:10:00 2013 From: noreply at buildbot.pypy.org (alex_gaynor) Date: Thu, 11 Apr 2013 04:10:00 +0200 (CEST) Subject: [pypy-commit] pypy default: Make test correctly match what we expect Message-ID: <20130411021000.25C041C010B@cobra.cs.uni-duesseldorf.de> Author: Alex Gaynor Branch: Changeset: r63220:948f362bd750 Date: 2013-04-11 04:12 +0200 http://bitbucket.org/pypy/pypy/changeset/948f362bd750/ Log: Make test correctly match what we expect diff --git a/pypy/module/pypyjit/test_pypy_c/test_string.py b/pypy/module/pypyjit/test_pypy_c/test_string.py --- a/pypy/module/pypyjit/test_pypy_c/test_string.py +++ b/pypy/module/pypyjit/test_pypy_c/test_string.py @@ -244,8 +244,16 @@ def main(n): for i in xrange(n): - codecs.lookup('utf8') # ID: codecs + codecs.lookup('utf8') return i """, [1000]) loop, = log.loops_by_filename(self.filepath) - loop.match_by_id('codecs', '') + loop.match(""" + i45 = int_lt(i43, i26) + guard_true(i45, descr=...) + i46 = int_add(i43, 1) + setfield_gc(p15, i46, descr=) + guard_not_invalidated(descr=...) + --TICK-- + jump(..., descr=...) + """) From noreply at buildbot.pypy.org Thu Apr 11 11:25:45 2013 From: noreply at buildbot.pypy.org (antocuni) Date: Thu, 11 Apr 2013 11:25:45 +0200 (CEST) Subject: [pypy-commit] pypy refactor-call_release_gil: close to-be-merged branch Message-ID: <20130411092545.957BE1C3061@cobra.cs.uni-duesseldorf.de> Author: Antonio Cuni Branch: refactor-call_release_gil Changeset: r63221:9fcb577847af Date: 2013-04-11 11:26 +0200 http://bitbucket.org/pypy/pypy/changeset/9fcb577847af/ Log: close to-be-merged branch From noreply at buildbot.pypy.org Thu Apr 11 11:25:47 2013 From: noreply at buildbot.pypy.org (antocuni) Date: Thu, 11 Apr 2013 11:25:47 +0200 (CEST) Subject: [pypy-commit] pypy default: merge (again) the refactor-call_release_gil branch. This fixes a nasty bug Message-ID: <20130411092547.567EE1C3061@cobra.cs.uni-duesseldorf.de> Author: Antonio Cuni Branch: Changeset: r63222:cfe04a93cc3e Date: 2013-04-11 11:27 +0200 http://bitbucket.org/pypy/pypy/changeset/cfe04a93cc3e/ Log: merge (again) the refactor-call_release_gil branch. This fixes a nasty bug which occoured when JITting the call to a cffi function which calls a callback which causes the failure of guard_not_forced: in that case, during blackholing we got the wrong result from call_release_gil, because it was not passed to fail_args. The two tests which demonstrates the bug are - rpython/jit/metainterp/test/test_fficall.py::test_guard_not_forced_f ails - pypy/module/pypyjit/test_pypy_c/test__ffi.py::test_cffi_call_guard_n ot_force d_fails diff --git a/pypy/module/pypyjit/test_pypy_c/test__ffi.py b/pypy/module/pypyjit/test_pypy_c/test__ffi.py --- a/pypy/module/pypyjit/test_pypy_c/test__ffi.py +++ b/pypy/module/pypyjit/test_pypy_c/test__ffi.py @@ -110,7 +110,6 @@ loops = log.loops_by_id('sleep') assert len(loops) == 1 # make sure that we actually JITted the loop - def test_ctypes_call(self): from rpython.rlib.test.test_clibffi import get_libm_name def main(libm_name): @@ -209,3 +208,65 @@ # so far just check that call_release_gil() is produced. # later, also check that the arguments to call_release_gil() # are constants, and that the numerous raw_mallocs are removed + + def test_cffi_call_guard_not_forced_fails(self): + # this is the test_pypy_c equivalent of + # rpython/jit/metainterp/test/test_fficall::test_guard_not_forced_fails + # + # it requires cffi to be installed for pypy in order to run + def main(): + import sys + try: + import cffi + except ImportError: + sys.stderr.write('SKIP: cannot import cffi\n') + return 0 + + ffi = cffi.FFI() + + ffi.cdef(""" + typedef void (*functype)(int); + int foo(int n, functype func); + """) + + lib = ffi.verify(""" + #include + typedef void (*functype)(int); + + int foo(int n, functype func) { + if (n >= 2000) { + func(n); + } + return n*2; + } + """) + + @ffi.callback("functype") + def mycallback(n): + if n < 5000: + return + # make sure that guard_not_forced fails + d = {} + f = sys._getframe() + while f: + d.update(f.f_locals) + f = f.f_back + + n = 0 + while n < 10000: + res = lib.foo(n, mycallback) # ID: cfficall + # this is the real point of the test: before the + # refactor-call_release_gil branch, the assert failed when + # res == 5000 + assert res == n*2 + n += 1 + return n + + log = self.run(main, [], import_site=True) + assert log.result == 10000 + loop, = log.loops_by_id('cfficall') + assert loop.match_by_id('cfficall', """ + ... + f1 = call_release_gil(..., descr=) + ... + """) diff --git a/rpython/jit/backend/llgraph/runner.py b/rpython/jit/backend/llgraph/runner.py --- a/rpython/jit/backend/llgraph/runner.py +++ b/rpython/jit/backend/llgraph/runner.py @@ -840,10 +840,22 @@ # manipulation here (as a hack, instead of really doing # the aroundstate manipulation ourselves) return self.execute_call_may_force(descr, func, *args) + guard_op = self.lltrace.operations[self.current_index + 1] + assert guard_op.getopnum() == rop.GUARD_NOT_FORCED + self.force_guard_op = guard_op call_args = support.cast_call_args_in_order(descr.ARGS, args) - FUNC = lltype.FuncType(descr.ARGS, descr.RESULT) - func_to_call = rffi.cast(lltype.Ptr(FUNC), func) - result = func_to_call(*call_args) + # + func_adr = llmemory.cast_int_to_adr(func) + if hasattr(func_adr.ptr._obj, '_callable'): + # this is needed e.g. by test_fficall.test_guard_not_forced_fails, + # because to actually force the virtualref we need to llinterp the + # graph, not to directly execute the python function + result = self.cpu.maybe_on_top_of_llinterp(func, call_args, descr.RESULT) + else: + FUNC = lltype.FuncType(descr.ARGS, descr.RESULT) + func_to_call = rffi.cast(lltype.Ptr(FUNC), func) + result = func_to_call(*call_args) + del self.force_guard_op return support.cast_result(descr.RESULT, result) def execute_call_assembler(self, descr, *args): diff --git a/rpython/jit/backend/llsupport/llmodel.py b/rpython/jit/backend/llsupport/llmodel.py --- a/rpython/jit/backend/llsupport/llmodel.py +++ b/rpython/jit/backend/llsupport/llmodel.py @@ -275,6 +275,10 @@ def cast_adr_to_int(x): return rffi.cast(lltype.Signed, x) + @specialize.arg(2) + def cast_int_to_ptr(self, x, TYPE): + return rffi.cast(TYPE, x) + def sizeof(self, S): return get_size_descr(self.gc_ll_descr, S) diff --git a/rpython/jit/backend/model.py b/rpython/jit/backend/model.py --- a/rpython/jit/backend/model.py +++ b/rpython/jit/backend/model.py @@ -1,6 +1,6 @@ import weakref from rpython.rlib.debug import debug_start, debug_print, debug_stop -from rpython.rtyper.lltypesystem import lltype +from rpython.rtyper.lltypesystem import lltype, llmemory class CPUTotalTracker(object): total_compiled_loops = 0 @@ -194,6 +194,11 @@ def typedescrof(self, TYPE): raise NotImplementedError + @staticmethod + def cast_int_to_ptr(x, TYPE): + x = llmemory.cast_int_to_adr(x) + return llmemory.cast_adr_to_ptr(x, TYPE) + # ---------- the backend-dependent operations ---------- # lltype specific operations diff --git a/rpython/jit/backend/x86/test/test_fficall.py b/rpython/jit/backend/x86/test/test_fficall.py --- a/rpython/jit/backend/x86/test/test_fficall.py +++ b/rpython/jit/backend/x86/test/test_fficall.py @@ -5,4 +5,19 @@ class TestFfiCall(Jit386Mixin, test_fficall.FfiCallTests): # for the individual tests see # ====> ../../../metainterp/test/test_fficall.py - pass + + def _add_libffi_types_to_ll2types_maybe(self): + # this is needed by test_guard_not_forced_fails, because it produces a + # loop which reads the value of types.* in a variable, then a guard + # fail and we switch to blackhole: the problem is that at this point + # the blackhole interp has a real integer, but it needs to convert it + # back to a lltype pointer (which is handled by ll2ctypes, deeply in + # the logic). The workaround is to teach ll2ctypes in advance which + # are the addresses of the various types.* structures. + # Try to comment this code out and run the test to see how it fails :) + from rpython.rtyper.lltypesystem import rffi, lltype, ll2ctypes + from rpython.rlib.jit_libffi import types + for key, value in types.__dict__.iteritems(): + if isinstance(value, lltype._ptr): + addr = rffi.cast(lltype.Signed, value) + ll2ctypes._int2obj[addr] = value diff --git a/rpython/jit/codewriter/jtransform.py b/rpython/jit/codewriter/jtransform.py --- a/rpython/jit/codewriter/jtransform.py +++ b/rpython/jit/codewriter/jtransform.py @@ -1747,6 +1747,11 @@ assert False, 'unsupported oopspec: %s' % oopspec_name return self._handle_oopspec_call(op, args, oopspecindex, extraeffect) + def rewrite_op_jit_ffi_save_result(self, op): + kind = op.args[0].value + assert kind in ('int', 'float') + return SpaceOperation('libffi_save_result_%s' % kind, op.args[1:], None) + def rewrite_op_jit_force_virtual(self, op): return self._do_builtin_call(op) diff --git a/rpython/jit/metainterp/blackhole.py b/rpython/jit/metainterp/blackhole.py --- a/rpython/jit/metainterp/blackhole.py +++ b/rpython/jit/metainterp/blackhole.py @@ -8,8 +8,9 @@ from rpython.rlib.rarithmetic import intmask, LONG_BIT, r_uint, ovfcheck from rpython.rlib.rtimer import read_timestamp from rpython.rlib.unroll import unrolling_iterable -from rpython.rtyper.lltypesystem import lltype, llmemory, rclass +from rpython.rtyper.lltypesystem import lltype, llmemory, rclass, rffi from rpython.rtyper.lltypesystem.lloperation import llop +from rpython.rlib.jit_libffi import CIF_DESCRIPTION_P def arguments(*argtypes, **kwds): @@ -1350,6 +1351,26 @@ def bhimpl_ll_read_timestamp(): return read_timestamp() + @arguments("cpu", "i", "i", "i") + def bhimpl_libffi_save_result_int(self, cif_description, exchange_buffer, result): + ARRAY = lltype.Ptr(rffi.CArray(lltype.Signed)) + cif_description = self.cast_int_to_ptr(cif_description, CIF_DESCRIPTION_P) + exchange_buffer = self.cast_int_to_ptr(exchange_buffer, rffi.CCHARP) + # + data_out = rffi.ptradd(exchange_buffer, cif_description.exchange_result) + rffi.cast(ARRAY, data_out)[0] = result + + @arguments("cpu", "i", "i", "f") + def bhimpl_libffi_save_result_float(self, cif_description, exchange_buffer, result): + result = longlong.getrealfloat(result) + ARRAY = lltype.Ptr(rffi.CArray(lltype.Float)) + cif_description = self.cast_int_to_ptr(cif_description, CIF_DESCRIPTION_P) + exchange_buffer = self.cast_int_to_ptr(exchange_buffer, rffi.CCHARP) + # + data_out = rffi.ptradd(exchange_buffer, cif_description.exchange_result) + rffi.cast(ARRAY, data_out)[0] = result + + # ---------- # helpers to resume running in blackhole mode when a guard failed diff --git a/rpython/jit/metainterp/history.py b/rpython/jit/metainterp/history.py --- a/rpython/jit/metainterp/history.py +++ b/rpython/jit/metainterp/history.py @@ -775,8 +775,8 @@ def show(self, errmsg=None): "NOT_RPYTHON" - from rpython.jit.metainterp.graphpage import display_loops - display_loops([self], errmsg) + from rpython.jit.metainterp.graphpage import display_procedures + display_procedures([self], errmsg) def check_consistency(self): # for testing "NOT_RPYTHON" diff --git a/rpython/jit/metainterp/pyjitpl.py b/rpython/jit/metainterp/pyjitpl.py --- a/rpython/jit/metainterp/pyjitpl.py +++ b/rpython/jit/metainterp/pyjitpl.py @@ -1185,6 +1185,30 @@ def opimpl_ll_read_timestamp(self): return self.metainterp.execute_and_record(rop.READ_TIMESTAMP, None) + @arguments("box", "box", "box") + def opimpl_libffi_save_result_int(self, box_cif_description, box_exchange_buffer, + box_result): + from rpython.rtyper.lltypesystem import llmemory + from rpython.rlib.jit_libffi import CIF_DESCRIPTION_P + from rpython.jit.backend.llsupport.ffisupport import get_arg_descr + + cif_description = box_cif_description.getint() + cif_description = llmemory.cast_int_to_adr(cif_description) + cif_description = llmemory.cast_adr_to_ptr(cif_description, + CIF_DESCRIPTION_P) + + kind, descr, itemsize = get_arg_descr(self.metainterp.cpu, cif_description.rtype) + + if kind != 'v': + ofs = cif_description.exchange_result + assert ofs % itemsize == 0 # alignment check (result) + self.metainterp.history.record(rop.SETARRAYITEM_RAW, + [box_exchange_buffer, + ConstInt(ofs // itemsize), box_result], + None, descr) + + opimpl_libffi_save_result_float = opimpl_libffi_save_result_int + # ------------------------------ def setup_call(self, argboxes): @@ -2589,27 +2613,15 @@ box_arg, descr) arg_boxes.append(box_arg) # - kind, descr, itemsize = get_arg_descr(self.cpu, cif_description.rtype) - if kind == 'i': - box_result = history.BoxInt() - elif kind == 'f': - box_result = history.BoxFloat() - else: - assert kind == 'v' - box_result = None + box_result = op.result self.history.record(rop.CALL_RELEASE_GIL, [op.getarg(2)] + arg_boxes, box_result, calldescr) # self.history.operations.extend(extra_guards) # - if box_result is not None: - ofs = cif_description.exchange_result - assert ofs % itemsize == 0 # alignment check (result) - self.history.record(rop.SETARRAYITEM_RAW, - [box_exchange_buffer, - ConstInt(ofs // itemsize), box_result], - None, descr) + # note that the result is written back to the exchange_buffer by the + # special op libffi_save_result_{int,float} def direct_call_release_gil(self): op = self.history.operations.pop() diff --git a/rpython/jit/metainterp/test/test_fficall.py b/rpython/jit/metainterp/test/test_fficall.py --- a/rpython/jit/metainterp/test/test_fficall.py +++ b/rpython/jit/metainterp/test/test_fficall.py @@ -1,13 +1,18 @@ - import py +from _pytest.monkeypatch import monkeypatch +import sys import ctypes, math from rpython.rtyper.lltypesystem import lltype, rffi +from rpython.rtyper.annlowlevel import llhelper from rpython.jit.metainterp.test.support import LLJitMixin +from rpython.jit.codewriter.longlong import is_longlong from rpython.rlib import jit -from rpython.rlib.jit_libffi import types, CIF_DESCRIPTION, FFI_TYPE_PP +from rpython.rlib import jit_libffi +from rpython.rlib.jit_libffi import (types, CIF_DESCRIPTION, FFI_TYPE_PP, + jit_ffi_call, jit_ffi_save_result) from rpython.rlib.unroll import unrolling_iterable -from rpython.rlib.rarithmetic import intmask - +from rpython.rlib.rarithmetic import intmask, r_longlong +from rpython.rlib.longlong2float import float2longlong def get_description(atypes, rtype): p = lltype.malloc(CIF_DESCRIPTION, len(atypes), @@ -21,10 +26,26 @@ p.atypes[i] = atypes[i] return p +class FakeFFI(object): + """ + Context manager to monkey patch jit_libffi with our custom "libffi-like" + function + """ + + def __init__(self, fake_call_impl_any): + self.fake_call_impl_any = fake_call_impl_any + self.monkey = monkeypatch() + + def __enter__(self, *args): + self.monkey.setattr(jit_libffi, 'jit_ffi_call_impl_any', self.fake_call_impl_any) + + def __exit__(self, *args): + self.monkey.undo() + class FfiCallTests(object): - def _run(self, atypes, rtype, avalues, rvalue): + def _run(self, atypes, rtype, avalues, rvalue, expected_call_release_gil=1): cif_description = get_description(atypes, rtype) def verify(*args): @@ -41,8 +62,7 @@ unroll_avalues = unrolling_iterable(avalues) - @jit.oopspec("libffi_call(cif_description,func_addr,exchange_buffer)") - def fake_call(cif_description, func_addr, exchange_buffer): + def fake_call_impl_any(cif_description, func_addr, exchange_buffer): ofs = 16 for avalue in unroll_avalues: TYPE = rffi.CArray(lltype.typeOf(avalue)) @@ -67,7 +87,7 @@ rffi.cast(lltype.Ptr(TYPE), data)[0] = avalue ofs += 16 - fake_call(cif_description, func_addr, exbuf) + jit_ffi_call(cif_description, func_addr, exbuf) if rvalue is None: res = 654321 @@ -78,14 +98,19 @@ lltype.free(exbuf, flavor='raw') return res - res = f() - assert res == rvalue or (res, rvalue) == (654321, None) - res = self.interp_operations(f, []) - assert res == rvalue or (res, rvalue) == (654321, None) - self.check_operations_history(call_may_force=0, - call_release_gil=1) + with FakeFFI(fake_call_impl_any): + res = f() + assert res == rvalue or (res, rvalue) == (654321, None) + res = self.interp_operations(f, []) + if is_longlong(FUNC.RESULT): + # longlongs are passed around as floats inside the JIT, we + # need to convert it back before checking the value + res = float2longlong(res) + assert res == rvalue or (res, rvalue) == (654321, None) + self.check_operations_history(call_may_force=0, + call_release_gil=expected_call_release_gil) - def test_simple_call(self): + def test_simple_call_int(self): self._run([types.signed] * 2, types.signed, [456, 789], -42) def test_many_arguments(self): @@ -97,6 +122,17 @@ def test_simple_call_float(self): self._run([types.double] * 2, types.double, [45.6, 78.9], -4.2) + def test_simple_call_longlong(self): + maxint32 = 2147483647 + a = r_longlong(maxint32) + 1 + b = r_longlong(maxint32) + 2 + self._run([types.slonglong] * 2, types.slonglong, [a, b], a) + + def test_simple_call_longdouble(self): + # longdouble is not supported, so we expect NOT to generate a call_release_gil + self._run([types.longdouble] * 2, types.longdouble, [12.3, 45.6], 78.9, + expected_call_release_gil=0) + def test_returns_none(self): self._run([types.signed] * 2, types.void, [456, 789], None) @@ -104,6 +140,91 @@ self._run([types.signed], types.sint8, [456], rffi.cast(rffi.SIGNEDCHAR, -42)) + def _add_libffi_types_to_ll2types_maybe(self): + # not necessary on the llgraph backend, but needed for x86. + # see rpython/jit/backend/x86/test/test_fficall.py + pass + + def test_guard_not_forced_fails(self): + self._add_libffi_types_to_ll2types_maybe() + FUNC = lltype.FuncType([lltype.Signed], lltype.Signed) + + cif_description = get_description([types.slong], types.slong) + cif_description.exchange_args[0] = 16 + cif_description.exchange_result = 32 + + ARRAY = lltype.Ptr(rffi.CArray(lltype.Signed)) + + @jit.dont_look_inside + def fn(n): + if n >= 50: + exctx.m = exctx.topframeref().n # forces the frame + return n*2 + + # this function simulates what a real libffi_call does: reading from + # the buffer, calling a function (which can potentially call callbacks + # and force frames) and write back to the buffer + def fake_call_impl_any(cif_description, func_addr, exchange_buffer): + # read the args from the buffer + data_in = rffi.ptradd(exchange_buffer, 16) + n = rffi.cast(ARRAY, data_in)[0] + # + # logic of the function + func_ptr = rffi.cast(lltype.Ptr(FUNC), func_addr) + n = func_ptr(n) + # + # write the result to the buffer + data_out = rffi.ptradd(exchange_buffer, 32) + rffi.cast(ARRAY, data_out)[0] = n + + def do_call(n): + func_ptr = llhelper(lltype.Ptr(FUNC), fn) + exbuf = lltype.malloc(rffi.CCHARP.TO, 48, flavor='raw', zero=True) + data_in = rffi.ptradd(exbuf, 16) + rffi.cast(ARRAY, data_in)[0] = n + jit_ffi_call(cif_description, func_ptr, exbuf) + data_out = rffi.ptradd(exbuf, 32) + res = rffi.cast(ARRAY, data_out)[0] + lltype.free(exbuf, flavor='raw') + return res + + # + # + class XY: + pass + class ExCtx: + pass + exctx = ExCtx() + myjitdriver = jit.JitDriver(greens = [], reds = ['n']) + def f(): + n = 0 + while n < 100: + myjitdriver.jit_merge_point(n=n) + xy = XY() + xy.n = n + exctx.topframeref = vref = jit.virtual_ref(xy) + res = do_call(n) # this is equivalent of a cffi call which + # sometimes forces a frame + + # when n==50, fn() will force the frame, so guard_not_forced + # fails and we enter blackholing: this test makes sure that + # the result of call_release_gil is kept alive before the + # libffi_save_result, and that the corresponding box is passed + # in the fail_args. Before the fix, the result of + # call_release_gil was simply lost and when guard_not_forced + # failed, and the value of "res" was unpredictable. + # See commit b84ff38f34bd and subsequents. + assert res == n*2 + jit.virtual_ref_finish(vref, xy) + exctx.topframeref = jit.vref_None + n += 1 + return n + + with FakeFFI(fake_call_impl_any): + assert f() == 100 + res = self.meta_interp(f, []) + assert res == 100 + class TestFfiCall(FfiCallTests, LLJitMixin): def test_jit_ffi_vref(self): diff --git a/rpython/rlib/jit_libffi.py b/rpython/rlib/jit_libffi.py --- a/rpython/rlib/jit_libffi.py +++ b/rpython/rlib/jit_libffi.py @@ -1,6 +1,8 @@ from rpython.rtyper.lltypesystem import lltype, rffi +from rpython.rtyper.extregistry import ExtRegistryEntry from rpython.rlib import clibffi, jit +from rpython.rlib.nonconst import NonConstant FFI_CIF = clibffi.FFI_CIFP.TO @@ -65,11 +67,88 @@ return rffi.cast(lltype.Signed, res) - at jit.oopspec("libffi_call(cif_description, func_addr, exchange_buffer)") +# ============================= +# jit_ffi_call and its helpers +# ============================= + +## Problem: jit_ffi_call is turned into call_release_gil by pyjitpl. Before +## the refactor-call_release_gil branch, the resulting code looked like this: +## +## buffer = ... +## i0 = call_release_gil(...) +## guard_not_forced() +## setarray_item_raw(buffer, ..., i0) +## +## The problem is that the result box i0 was generated freshly inside pyjitpl, +## and the codewriter did not know about its liveness: the result was that i0 +## was not in the fail_args of guard_not_forced. See +## test_fficall::test_guard_not_forced_fails for a more detalied explanation +## of the problem. +## +## The solution is to create a new separate operation libffi_save_result whose +## job is to write the result in the exchange_buffer: during normal execution +## this is a no-op because the buffer is already filled by libffi, but during +## jitting the behavior is to actually write into the buffer. +## +## The result is that now the jitcode looks like this: +## +## %i0 = libffi_call_int(...) +## -live- +## libffi_save_result_int(..., %i0) +## +## the "-live-" is the key, because it make sure that the value is not lost if +## guard_not_forced fails. + + def jit_ffi_call(cif_description, func_addr, exchange_buffer): """Wrapper around ffi_call(). Must receive a CIF_DESCRIPTION_P that describes the layout of the 'exchange_buffer'. """ + reskind = types.getkind(cif_description.rtype) + if reskind == 'v': + jit_ffi_call_impl_void(cif_description, func_addr, exchange_buffer) + elif reskind == 'f' or reskind == 'L': # L is for longlongs, on 32bit + result = jit_ffi_call_impl_float(cif_description, func_addr, exchange_buffer) + jit_ffi_save_result('float', cif_description, exchange_buffer, result) + elif reskind == 'i' or reskind == 'u': + result = jit_ffi_call_impl_int(cif_description, func_addr, exchange_buffer) + jit_ffi_save_result('int', cif_description, exchange_buffer, result) + else: + # the result kind is not supported: we disable the jit_ffi_call + # optimization by calling directly jit_ffi_call_impl_any, so the JIT + # does not see any libffi_call oopspec. + # + # Since call_release_gil is not generated, there is no need to + # jit_ffi_save_result + jit_ffi_call_impl_any(cif_description, func_addr, exchange_buffer) + + +# we must return a NonConstant else we get the constant -1 as the result of +# the flowgraph, and the codewriter does not produce a box for the +# result. Note that when not-jitted, the result is unused, but when jitted the +# box of the result contains the actual value returned by the C function. + + at jit.oopspec("libffi_call(cif_description,func_addr,exchange_buffer)") +def jit_ffi_call_impl_int(cif_description, func_addr, exchange_buffer): + jit_ffi_call_impl_any(cif_description, func_addr, exchange_buffer) + return NonConstant(-1) + + at jit.oopspec("libffi_call(cif_description,func_addr,exchange_buffer)") +def jit_ffi_call_impl_float(cif_description, func_addr, exchange_buffer): + jit_ffi_call_impl_any(cif_description, func_addr, exchange_buffer) + return NonConstant(-1.0) + + at jit.oopspec("libffi_call(cif_description,func_addr,exchange_buffer)") +def jit_ffi_call_impl_void(cif_description, func_addr, exchange_buffer): + jit_ffi_call_impl_any(cif_description, func_addr, exchange_buffer) + return None + +def jit_ffi_call_impl_any(cif_description, func_addr, exchange_buffer): + """ + This is the function which actually calls libffi. All the rest if just + infrastructure to convince the JIT to pass a typed result box to + jit_ffi_save_result + """ buffer_array = rffi.cast(rffi.VOIDPP, exchange_buffer) for i in range(cif_description.nargs): data = rffi.ptradd(exchange_buffer, cif_description.exchange_args[i]) @@ -79,6 +158,31 @@ clibffi.c_ffi_call(cif_description.cif, func_addr, rffi.cast(rffi.VOIDP, resultdata), buffer_array) + return -1 + + + +def jit_ffi_save_result(kind, cif_description, exchange_buffer, result): + """ + This is a no-op during normal execution, but actually fills the buffer + when jitted + """ + pass + +class Entry(ExtRegistryEntry): + _about_ = jit_ffi_save_result + + def compute_result_annotation(self, kind_s, *args_s): + from rpython.annotator import model as annmodel + assert isinstance(kind_s, annmodel.SomeString) + assert kind_s.const in ('int', 'float') + + def specialize_call(self, hop): + hop.exception_cannot_occur() + vlist = hop.inputargs(lltype.Void, *hop.args_r[1:]) + return hop.genop('jit_ffi_save_result', vlist, + resulttype=lltype.Void) + # ____________________________________________________________ diff --git a/rpython/rtyper/lltypesystem/lloperation.py b/rpython/rtyper/lltypesystem/lloperation.py --- a/rpython/rtyper/lltypesystem/lloperation.py +++ b/rpython/rtyper/lltypesystem/lloperation.py @@ -456,6 +456,7 @@ 'jit_is_virtual': LLOp(canrun=True), 'jit_force_quasi_immutable': LLOp(canrun=True), 'jit_record_known_class' : LLOp(canrun=True), + 'jit_ffi_save_result': LLOp(canrun=True), 'get_exception_addr': LLOp(), 'get_exc_value_addr': LLOp(), 'do_malloc_fixedsize_clear':LLOp(canmallocgc=True), diff --git a/rpython/rtyper/lltypesystem/opimpl.py b/rpython/rtyper/lltypesystem/opimpl.py --- a/rpython/rtyper/lltypesystem/opimpl.py +++ b/rpython/rtyper/lltypesystem/opimpl.py @@ -597,6 +597,9 @@ def op_jit_record_known_class(x, y): pass +def op_jit_ffi_save_result(*args): + pass + def op_get_group_member(TYPE, grpptr, memberoffset): from rpython.rtyper.lltypesystem import llgroup assert isinstance(memberoffset, llgroup.GroupMemberOffset) diff --git a/rpython/translator/c/funcgen.py b/rpython/translator/c/funcgen.py --- a/rpython/translator/c/funcgen.py +++ b/rpython/translator/c/funcgen.py @@ -843,6 +843,9 @@ def OP_JIT_FORCE_QUASI_IMMUTABLE(self, op): return '/* JIT_FORCE_QUASI_IMMUTABLE %s */' % op + def OP_JIT_FFI_SAVE_RESULT(self, op): + return '/* JIT_FFI_SAVE_RESULT %s */' % op + def OP_GET_GROUP_MEMBER(self, op): typename = self.db.gettype(op.result.concretetype) return '%s = (%s)_OP_GET_GROUP_MEMBER(%s, %s);' % ( diff --git a/rpython/translator/cli/opcodes.py b/rpython/translator/cli/opcodes.py --- a/rpython/translator/cli/opcodes.py +++ b/rpython/translator/cli/opcodes.py @@ -99,6 +99,7 @@ 'jit_force_virtual': DoNothing, 'jit_force_quasi_immutable':Ignore, 'jit_is_virtual': [PushPrimitive(ootype.Bool, False)], + 'jit_ffi_save_result': Ignore, } # __________ numeric operations __________ diff --git a/rpython/translator/jvm/opcodes.py b/rpython/translator/jvm/opcodes.py --- a/rpython/translator/jvm/opcodes.py +++ b/rpython/translator/jvm/opcodes.py @@ -102,6 +102,7 @@ 'jit_force_virtual': DoNothing, 'jit_force_quasi_immutable': Ignore, 'jit_is_virtual': PushPrimitive(ootype.Bool, False), + 'jit_ffi_save_result': Ignore, 'debug_assert': [], # TODO: implement? 'debug_start_traceback': Ignore, From noreply at buildbot.pypy.org Thu Apr 11 12:04:38 2013 From: noreply at buildbot.pypy.org (antocuni) Date: Thu, 11 Apr 2013 12:04:38 +0200 (CEST) Subject: [pypy-commit] pypy virtual-raw-mallocs: fix after the renaming Message-ID: <20130411100438.7BA8C1C016E@cobra.cs.uni-duesseldorf.de> Author: Antonio Cuni Branch: virtual-raw-mallocs Changeset: r63223:5eb58cc8fa1e Date: 2013-04-09 17:02 +0100 http://bitbucket.org/pypy/pypy/changeset/5eb58cc8fa1e/ Log: fix after the renaming diff --git a/rpython/jit/metainterp/test/test_resume.py b/rpython/jit/metainterp/test/test_resume.py --- a/rpython/jit/metainterp/test/test_resume.py +++ b/rpython/jit/metainterp/test/test_resume.py @@ -249,7 +249,7 @@ reader = ResumeDataDirectReader(MyMetaInterp(None), FakeStorage(), "deadframe") cache = reader.force_all_virtuals() - assert cache.virtuals_ptr_cache == ["allocated", reader.virtual_default] + assert cache.virtuals_ptr_cache == ["allocated", reader.virtual_ptr_default] # ____________________________________________________________ From noreply at buildbot.pypy.org Thu Apr 11 12:04:39 2013 From: noreply at buildbot.pypy.org (antocuni) Date: Thu, 11 Apr 2013 12:04:39 +0200 (CEST) Subject: [pypy-commit] pypy virtual-raw-mallocs: bah, more tests in which we need to convince the annotator to see the constructor of VRawBufferValue Message-ID: <20130411100439.9DB7F1C016E@cobra.cs.uni-duesseldorf.de> Author: Antonio Cuni Branch: virtual-raw-mallocs Changeset: r63224:1eba3e30d044 Date: 2013-04-11 10:54 +0100 http://bitbucket.org/pypy/pypy/changeset/1eba3e30d044/ Log: bah, more tests in which we need to convince the annotator to see the constructor of VRawBufferValue diff --git a/rpython/jit/backend/x86/test/test_zrpy_gc_boehm.py b/rpython/jit/backend/x86/test/test_zrpy_gc_boehm.py --- a/rpython/jit/backend/x86/test/test_zrpy_gc_boehm.py +++ b/rpython/jit/backend/x86/test/test_zrpy_gc_boehm.py @@ -2,6 +2,7 @@ import weakref from rpython.rlib.jit import JitDriver, dont_look_inside from rpython.jit.backend.x86.test.test_zrpy_gc import run, get_entry, compile +from rpython.jit.backend.x86.test.test_ztranslation import fix_annotator_for_vrawbuffer class X(object): def __init__(self, x=0): @@ -31,7 +32,8 @@ g._dont_inline_ = True return g -def test_compile_boehm(): +def test_compile_boehm(monkeypatch): + fix_annotator_for_vrawbuffer(monkeypatch) myjitdriver = JitDriver(greens = [], reds = ['n', 'x']) @dont_look_inside def see(lst, n): diff --git a/rpython/jit/backend/x86/test/test_ztranslation_basic.py b/rpython/jit/backend/x86/test/test_ztranslation_basic.py --- a/rpython/jit/backend/x86/test/test_ztranslation_basic.py +++ b/rpython/jit/backend/x86/test/test_ztranslation_basic.py @@ -12,6 +12,7 @@ from rpython.jit.backend.x86.arch import IS_X86_32, IS_X86_64 from rpython.config.translationoption import DEFL_GC from rpython.rlib import rgc +from rpython.jit.backend.x86.test.test_ztranslation import fix_annotator_for_vrawbuffer class TestTranslationX86(CCompiledMixin): CPUClass = getcpuclass() @@ -22,7 +23,7 @@ assert '-msse2' in cbuilder.eci.compile_extra assert '-mfpmath=sse' in cbuilder.eci.compile_extra - def test_stuff_translates(self): + def test_stuff_translates(self, monkeypatch): # this is a basic test that tries to hit a number of features and their # translation: # - jitting of loops and bridges @@ -31,6 +32,7 @@ # - profiler # - full optimizer # - floats neg and abs + fix_annotator_for_vrawbuffer(monkeypatch) class Frame(object): _virtualizable2_ = ['i'] diff --git a/rpython/jit/backend/x86/test/test_ztranslation_call_assembler.py b/rpython/jit/backend/x86/test/test_ztranslation_call_assembler.py --- a/rpython/jit/backend/x86/test/test_ztranslation_call_assembler.py +++ b/rpython/jit/backend/x86/test/test_ztranslation_call_assembler.py @@ -12,6 +12,7 @@ from rpython.jit.backend.x86.arch import IS_X86_32, IS_X86_64 from rpython.config.translationoption import DEFL_GC from rpython.rlib import rgc +from rpython.jit.backend.x86.test.test_ztranslation import fix_annotator_for_vrawbuffer class TestTranslationX86(CCompiledMixin): CPUClass = getcpuclass() @@ -22,9 +23,10 @@ assert '-msse2' in cbuilder.eci.compile_extra assert '-mfpmath=sse' in cbuilder.eci.compile_extra - def test_direct_assembler_call_translates(self): + def test_direct_assembler_call_translates(self, monkeypatch): """Test CALL_ASSEMBLER and the recursion limit""" from rpython.rlib.rstackovf import StackOverflow + fix_annotator_for_vrawbuffer(monkeypatch) class Thing(object): def __init__(self, val): diff --git a/rpython/jit/backend/x86/test/test_ztranslation_external_exception.py b/rpython/jit/backend/x86/test/test_ztranslation_external_exception.py --- a/rpython/jit/backend/x86/test/test_ztranslation_external_exception.py +++ b/rpython/jit/backend/x86/test/test_ztranslation_external_exception.py @@ -12,7 +12,7 @@ from rpython.jit.backend.x86.arch import IS_X86_32, IS_X86_64 from rpython.config.translationoption import DEFL_GC from rpython.rlib import rgc - +from rpython.jit.backend.x86.test.test_ztranslation import fix_annotator_for_vrawbuffer class TestTranslationRemoveTypePtrX86(CCompiledMixin): CPUClass = getcpuclass() @@ -25,7 +25,9 @@ t.config.translation.gcremovetypeptr = True return t - def test_external_exception_handling_translates(self): + def test_external_exception_handling_translates(self, monkeypatch): + fix_annotator_for_vrawbuffer(monkeypatch) + jitdriver = JitDriver(greens = [], reds = ['n', 'total']) class ImDone(Exception): From noreply at buildbot.pypy.org Thu Apr 11 13:53:26 2013 From: noreply at buildbot.pypy.org (antocuni) Date: Thu, 11 Apr 2013 13:53:26 +0200 (CEST) Subject: [pypy-commit] pypy virtual-raw-mallocs: close to-be-merged branch Message-ID: <20130411115326.404641C0F12@cobra.cs.uni-duesseldorf.de> Author: Antonio Cuni Branch: virtual-raw-mallocs Changeset: r63226:bd33cfd7eba4 Date: 2013-04-11 12:48 +0100 http://bitbucket.org/pypy/pypy/changeset/bd33cfd7eba4/ Log: close to-be-merged branch From noreply at buildbot.pypy.org Thu Apr 11 13:53:27 2013 From: noreply at buildbot.pypy.org (antocuni) Date: Thu, 11 Apr 2013 13:53:27 +0200 (CEST) Subject: [pypy-commit] pypy default: Merge the virtual-raw-mallocs branch which, as the name suggests, makes it Message-ID: <20130411115327.B26341C0F12@cobra.cs.uni-duesseldorf.de> Author: Antonio Cuni Branch: Changeset: r63227:0a0a7ff924c2 Date: 2013-04-11 12:51 +0100 http://bitbucket.org/pypy/pypy/changeset/0a0a7ff924c2/ Log: Merge the virtual-raw-mallocs branch which, as the name suggests, makes it possible to make raw-malloced blocks of memory as virtual during the optimizeopt step. This is especially useful for cffi calls, because it removes all the overhead of writing the parameters into the temp buffer and then immediately reading them, before doing the actuall ffi call. diff too long, truncating to 2000 out of 2422 lines diff --git a/pypy/module/_cffi_backend/ccallback.py b/pypy/module/_cffi_backend/ccallback.py --- a/pypy/module/_cffi_backend/ccallback.py +++ b/pypy/module/_cffi_backend/ccallback.py @@ -134,7 +134,7 @@ # W_CTypePrimitiveSigned.convert_from_object() in order # to write a whole 'ffi_arg'. value = misc.as_long(space, w_res) - misc.write_raw_integer_data(ll_res, value, SIZE_OF_FFI_ARG) + misc.write_raw_signed_data(ll_res, value, SIZE_OF_FFI_ARG) return else: # zero extension: fill the '*result' with zeros, and (on big- diff --git a/pypy/module/_cffi_backend/cdataobj.py b/pypy/module/_cffi_backend/cdataobj.py --- a/pypy/module/_cffi_backend/cdataobj.py +++ b/pypy/module/_cffi_backend/cdataobj.py @@ -280,8 +280,13 @@ return self.ctype.iter(self) @specialize.argtype(1) - def write_raw_integer_data(self, source): - misc.write_raw_integer_data(self._cdata, source, self.ctype.size) + def write_raw_signed_data(self, source): + misc.write_raw_signed_data(self._cdata, source, self.ctype.size) + keepalive_until_here(self) + + @specialize.argtype(1) + def write_raw_unsigned_data(self, source): + misc.write_raw_unsigned_data(self._cdata, source, self.ctype.size) keepalive_until_here(self) def write_raw_float_data(self, source): diff --git a/pypy/module/_cffi_backend/ctypeprim.py b/pypy/module/_cffi_backend/ctypeprim.py --- a/pypy/module/_cffi_backend/ctypeprim.py +++ b/pypy/module/_cffi_backend/ctypeprim.py @@ -63,7 +63,7 @@ else: value = self._cast_generic(w_ob) w_cdata = cdataobj.W_CDataMem(space, self.size, self) - w_cdata.write_raw_integer_data(value) + self.write_raw_integer_data(w_cdata, value) return w_cdata def _cast_result(self, intvalue): @@ -94,6 +94,9 @@ from pypy.module._cffi_backend import newtype return newtype.new_primitive_type(self.space, "int") + def write_raw_integer_data(self, w_cdata, value): + w_cdata.write_raw_unsigned_data(value) + class W_CTypePrimitiveChar(W_CTypePrimitiveCharOrUniChar): _attrs_ = [] @@ -185,10 +188,10 @@ if self.size < rffi.sizeof(lltype.Signed): if r_uint(value) - self.vmin > self.vrangemax: self._overflow(w_ob) - misc.write_raw_integer_data(cdata, value, self.size) + misc.write_raw_signed_data(cdata, value, self.size) else: value = misc.as_long_long(self.space, w_ob) - misc.write_raw_integer_data(cdata, value, self.size) + misc.write_raw_signed_data(cdata, value, self.size) def get_vararg_type(self): if self.size < rffi.sizeof(rffi.INT): @@ -196,6 +199,9 @@ return newtype.new_primitive_type(self.space, "int") return self + def write_raw_integer_data(self, w_cdata, value): + w_cdata.write_raw_signed_data(value) + class W_CTypePrimitiveUnsigned(W_CTypePrimitive): _attrs_ = ['value_fits_long', 'value_fits_ulong', 'vrangemax'] @@ -222,10 +228,10 @@ if self.value_fits_long: if value > self.vrangemax: self._overflow(w_ob) - misc.write_raw_integer_data(cdata, value, self.size) + misc.write_raw_unsigned_data(cdata, value, self.size) else: value = misc.as_unsigned_long_long(self.space, w_ob, strict=True) - misc.write_raw_integer_data(cdata, value, self.size) + misc.write_raw_unsigned_data(cdata, value, self.size) def convert_to_object(self, cdata): if self.value_fits_ulong: @@ -244,6 +250,9 @@ return newtype.new_primitive_type(self.space, "int") return self + def write_raw_integer_data(self, w_cdata, value): + w_cdata.write_raw_unsigned_data(value) + class W_CTypePrimitiveBool(W_CTypePrimitiveUnsigned): _attrs_ = [] diff --git a/pypy/module/_cffi_backend/ctypestruct.py b/pypy/module/_cffi_backend/ctypestruct.py --- a/pypy/module/_cffi_backend/ctypestruct.py +++ b/pypy/module/_cffi_backend/ctypestruct.py @@ -242,11 +242,13 @@ # value = misc.as_long_long(space, w_ob) if isinstance(ctype, ctypeprim.W_CTypePrimitiveSigned): + is_signed = True fmin = -(r_longlong(1) << (self.bitsize - 1)) fmax = (r_longlong(1) << (self.bitsize - 1)) - 1 if fmax == 0: fmax = 1 # special case to let "int x:1" receive "1" else: + is_signed = False fmin = r_longlong(0) fmax = r_longlong((r_ulonglong(1) << self.bitsize) - 1) if value < fmin or value > fmax: @@ -258,7 +260,10 @@ rawvalue = r_ulonglong(value) << self.bitshift rawfielddata = misc.read_raw_unsigned_data(cdata, ctype.size) rawfielddata = (rawfielddata & ~rawmask) | (rawvalue & rawmask) - misc.write_raw_integer_data(cdata, rawfielddata, ctype.size) + if is_signed: + misc.write_raw_signed_data(cdata, rawfielddata, ctype.size) + else: + misc.write_raw_unsigned_data(cdata, rawfielddata, ctype.size) W_CField.typedef = TypeDef( diff --git a/pypy/module/_cffi_backend/misc.py b/pypy/module/_cffi_backend/misc.py --- a/pypy/module/_cffi_backend/misc.py +++ b/pypy/module/_cffi_backend/misc.py @@ -9,6 +9,7 @@ from rpython.rtyper.lltypesystem import lltype, llmemory, rffi from rpython.translator.tool.cbuild import ExternalCompilationInfo + # ____________________________________________________________ _prim_signed_types = unrolling_iterable([ @@ -65,19 +66,22 @@ return rffi.cast(rffi.LONGDOUBLEP, target)[0] @specialize.argtype(1) -def write_raw_integer_data(target, source, size): - if is_signed_integer_type(lltype.typeOf(source)): - for TP, TPP in _prim_signed_types: - if size == rffi.sizeof(TP): - rffi.cast(TPP, target)[0] = rffi.cast(TP, source) - return - else: - for TP, TPP in _prim_unsigned_types: - if size == rffi.sizeof(TP): - rffi.cast(TPP, target)[0] = rffi.cast(TP, source) - return +def write_raw_unsigned_data(target, source, size): + for TP, TPP in _prim_unsigned_types: + if size == rffi.sizeof(TP): + rffi.cast(TPP, target)[0] = rffi.cast(TP, source) + return raise NotImplementedError("bad integer size") + at specialize.argtype(1) +def write_raw_signed_data(target, source, size): + for TP, TPP in _prim_signed_types: + if size == rffi.sizeof(TP): + rffi.cast(TPP, target)[0] = rffi.cast(TP, source) + return + raise NotImplementedError("bad integer size") + + def write_raw_float_data(target, source, size): for TP, TPP in _prim_float_types: if size == rffi.sizeof(TP): diff --git a/pypy/module/pypyjit/test_pypy_c/test__ffi.py b/pypy/module/pypyjit/test_pypy_c/test_ffi.py rename from pypy/module/pypyjit/test_pypy_c/test__ffi.py rename to pypy/module/pypyjit/test_pypy_c/test_ffi.py --- a/pypy/module/pypyjit/test_pypy_c/test__ffi.py +++ b/pypy/module/pypyjit/test_pypy_c/test_ffi.py @@ -181,32 +181,39 @@ libm = _cffi_backend.load_library(libm_name) BDouble = _cffi_backend.new_primitive_type("double") - BPow = _cffi_backend.new_function_type([BDouble, BDouble], BDouble) - pow = libm.load_function(BPow, 'pow') + BInt = _cffi_backend.new_primitive_type("int") + BPow = _cffi_backend.new_function_type([BDouble, BInt], BDouble) + ldexp = libm.load_function(BPow, 'ldexp') i = 0 res = 0 while i < 300: - tmp = pow(2, 3) # ID: cfficall + tmp = ldexp(1, 3) # ID: cfficall res += tmp i += 1 BLong = _cffi_backend.new_primitive_type("long") - pow_addr = int(_cffi_backend.cast(BLong, pow)) - return pow_addr, res + ldexp_addr = int(_cffi_backend.cast(BLong, ldexp)) + return ldexp_addr, res # libm_name = get_libm_name(sys.platform) log = self.run(main, [libm_name]) - pow_addr, res = log.result + ldexp_addr, res = log.result assert res == 8.0 * 300 loop, = log.loops_by_filename(self.filepath) - if 'ConstClass(pow)' in repr(loop): # e.g. OS/X - pow_addr = 'ConstClass(pow)' + if 'ConstClass(ldexp)' in repr(loop): # e.g. OS/X + ldexp_addr = 'ConstClass(ldexp)' assert loop.match_by_id('cfficall', """ ... - f1 = call_release_gil(..., descr=) + f1 = call_release_gil(..., descr=) ... """) + ops = loop.ops_by_id('cfficall') + assert 'raw_malloc' not in str(ops) + assert 'raw_free' not in str(ops) + assert 'getarrayitem_raw' not in log.opnames(ops) + assert 'setarrayitem_raw' not in log.opnames(ops) # so far just check that call_release_gil() is produced. # later, also check that the arguments to call_release_gil() + # are constants # are constants, and that the numerous raw_mallocs are removed def test_cffi_call_guard_not_forced_fails(self): diff --git a/rpython/jit/backend/llgraph/runner.py b/rpython/jit/backend/llgraph/runner.py --- a/rpython/jit/backend/llgraph/runner.py +++ b/rpython/jit/backend/llgraph/runner.py @@ -484,6 +484,15 @@ else: return self.bh_raw_load_i(struct, offset, descr) + def unpack_arraydescr_size(self, arraydescr): + from rpython.jit.backend.llsupport.symbolic import get_array_token + from rpython.jit.backend.llsupport.descr import get_type_flag, FLAG_SIGNED + assert isinstance(arraydescr, ArrayDescr) + basesize, itemsize, _ = get_array_token(arraydescr.A, False) + flag = get_type_flag(arraydescr.A.OF) + is_signed = (flag == FLAG_SIGNED) + return basesize, itemsize, is_signed + def bh_raw_store_i(self, struct, offset, newvalue, descr): ll_p = rffi.cast(rffi.CCHARP, struct) ll_p = rffi.cast(lltype.Ptr(descr.A), rffi.ptradd(ll_p, offset)) @@ -566,10 +575,14 @@ def bh_read_timestamp(self): return read_timestamp() + def bh_new_raw_buffer(self, size): + return lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') + def store_fail_descr(self, deadframe, descr): pass # I *think* + class LLDeadFrame(object): _TYPE = llmemory.GCREF diff --git a/rpython/jit/backend/llsupport/llmodel.py b/rpython/jit/backend/llsupport/llmodel.py --- a/rpython/jit/backend/llsupport/llmodel.py +++ b/rpython/jit/backend/llsupport/llmodel.py @@ -742,6 +742,9 @@ as_array[self.vtable_offset/WORD] = vtable return res + def bh_new_raw_buffer(self, size): + return lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') + def bh_classof(self, struct): struct = lltype.cast_opaque_ptr(rclass.OBJECTPTR, struct) result_adr = llmemory.cast_ptr_to_adr(struct.typeptr) diff --git a/rpython/jit/backend/model.py b/rpython/jit/backend/model.py --- a/rpython/jit/backend/model.py +++ b/rpython/jit/backend/model.py @@ -194,11 +194,18 @@ def typedescrof(self, TYPE): raise NotImplementedError + def unpack_arraydescr_size(self, arraydescr): + """ + Return basesize, itemsize, is_signed + """ + raise NotImplementedError + @staticmethod def cast_int_to_ptr(x, TYPE): x = llmemory.cast_int_to_adr(x) return llmemory.cast_adr_to_ptr(x, TYPE) + # ---------- the backend-dependent operations ---------- # lltype specific operations @@ -235,6 +242,8 @@ raise NotImplementedError def bh_newunicode(self, length): raise NotImplementedError + def bh_new_raw_buffer(self, size): + raise NotImplementedError def bh_arraylen_gc(self, array, arraydescr): raise NotImplementedError diff --git a/rpython/jit/backend/x86/test/test_zrpy_gc_boehm.py b/rpython/jit/backend/x86/test/test_zrpy_gc_boehm.py --- a/rpython/jit/backend/x86/test/test_zrpy_gc_boehm.py +++ b/rpython/jit/backend/x86/test/test_zrpy_gc_boehm.py @@ -2,6 +2,7 @@ import weakref from rpython.rlib.jit import JitDriver, dont_look_inside from rpython.jit.backend.x86.test.test_zrpy_gc import run, get_entry, compile +from rpython.jit.backend.x86.test.test_ztranslation import fix_annotator_for_vrawbuffer class X(object): def __init__(self, x=0): @@ -31,7 +32,8 @@ g._dont_inline_ = True return g -def test_compile_boehm(): +def test_compile_boehm(monkeypatch): + fix_annotator_for_vrawbuffer(monkeypatch) myjitdriver = JitDriver(greens = [], reds = ['n', 'x']) @dont_look_inside def see(lst, n): diff --git a/rpython/jit/backend/x86/test/test_ztranslation.py b/rpython/jit/backend/x86/test/test_ztranslation.py --- a/rpython/jit/backend/x86/test/test_ztranslation.py +++ b/rpython/jit/backend/x86/test/test_ztranslation.py @@ -13,6 +13,18 @@ from rpython.config.translationoption import DEFL_GC from rpython.rlib import rgc +def fix_annotator_for_vrawbuffer(monkeypatch): + from rpython.rlib.nonconst import NonConstant + from rpython.jit.metainterp.optimizeopt.virtualize import VRawBufferValue + from rpython.jit.metainterp import warmspot + + def my_hook_for_tests(cpu): + # this is needed so that the annotator can see it + if NonConstant(False): + v = VRawBufferValue(cpu, None, -1, None, None) + monkeypatch.setattr(warmspot, 'hook_for_tests', my_hook_for_tests) + + class TestTranslationX86(CCompiledMixin): CPUClass = getcpuclass() @@ -22,7 +34,159 @@ assert '-msse2' in cbuilder.eci.compile_extra assert '-mfpmath=sse' in cbuilder.eci.compile_extra - def test_jit_get_stats(self): + def test_stuff_translates(self, monkeypatch): + fix_annotator_for_vrawbuffer(monkeypatch) + # this is a basic test that tries to hit a number of features and their + # translation: + # - jitting of loops and bridges + # - virtualizables + # - set_param interface + # - profiler + # - full optimizer + # - floats neg and abs + + class Frame(object): + _virtualizable2_ = ['i'] + + def __init__(self, i): + self.i = i + + @dont_look_inside + def myabs(x): + return abs(x) + + jitdriver = JitDriver(greens = [], + reds = ['total', 'frame', 'j'], + virtualizables = ['frame']) + def f(i, j): + for param, _ in unroll_parameters: + defl = PARAMETERS[param] + set_param(jitdriver, param, defl) + set_param(jitdriver, "threshold", 3) + set_param(jitdriver, "trace_eagerness", 2) + total = 0 + frame = Frame(i) + j = float(j) + while frame.i > 3: + jitdriver.can_enter_jit(frame=frame, total=total, j=j) + jitdriver.jit_merge_point(frame=frame, total=total, j=j) + total += frame.i + if frame.i >= 20: + frame.i -= 2 + frame.i -= 1 + j *= -0.712 + if j + (-j): raise ValueError + k = myabs(j) + if k - abs(j): raise ValueError + if k - abs(-j): raise ValueError + return chr(total % 253) + # + from rpython.rtyper.lltypesystem import lltype, rffi + from rpython.rlib.libffi import types, CDLL, ArgChain + from rpython.rlib.test.test_clibffi import get_libm_name + libm_name = get_libm_name(sys.platform) + jitdriver2 = JitDriver(greens=[], reds = ['i', 'func', 'res', 'x']) + def libffi_stuff(i, j): + lib = CDLL(libm_name) + func = lib.getpointer('fabs', [types.double], types.double) + res = 0.0 + x = float(j) + while i > 0: + jitdriver2.jit_merge_point(i=i, res=res, func=func, x=x) + promote(func) + argchain = ArgChain() + argchain.arg(x) + res = func.call(argchain, rffi.DOUBLE) + i -= 1 + return res + # + def main(i, j): + a_char = f(i, j) + a_float = libffi_stuff(i, j) + return ord(a_char) * 10 + int(a_float) + expected = main(40, -49) + res = self.meta_interp(main, [40, -49]) + assert res == expected + + def test_direct_assembler_call_translates(self, monkeypatch): + """Test CALL_ASSEMBLER and the recursion limit""" + from rpython.rlib.rstackovf import StackOverflow + fix_annotator_for_vrawbuffer(monkeypatch) + + class Thing(object): + def __init__(self, val): + self.val = val + + class Frame(object): + _virtualizable2_ = ['thing'] + + driver = JitDriver(greens = ['codeno'], reds = ['i', 'frame'], + virtualizables = ['frame'], + get_printable_location = lambda codeno: str(codeno)) + class SomewhereElse(object): + pass + + somewhere_else = SomewhereElse() + + def change(newthing): + somewhere_else.frame.thing = newthing + + def main(codeno): + frame = Frame() + somewhere_else.frame = frame + frame.thing = Thing(0) + portal(codeno, frame) + return frame.thing.val + + def portal(codeno, frame): + i = 0 + while i < 10: + driver.can_enter_jit(frame=frame, codeno=codeno, i=i) + driver.jit_merge_point(frame=frame, codeno=codeno, i=i) + nextval = frame.thing.val + if codeno == 0: + subframe = Frame() + subframe.thing = Thing(nextval) + nextval = portal(1, subframe) + elif frame.thing.val > 40: + change(Thing(13)) + nextval = 13 + frame.thing = Thing(nextval + 1) + i += 1 + return frame.thing.val + + driver2 = JitDriver(greens = [], reds = ['n']) + + def main2(bound): + try: + while portal2(bound) == -bound+1: + bound *= 2 + except StackOverflow: + pass + return bound + + def portal2(n): + while True: + driver2.jit_merge_point(n=n) + n -= 1 + if n <= 0: + return n + n = portal2(n) + assert portal2(10) == -9 + + def mainall(codeno, bound): + return main(codeno) + main2(bound) + + res = self.meta_interp(mainall, [0, 1], inline=True, + policy=StopAtXPolicy(change)) + print hex(res) + assert res & 255 == main(0) + bound = res & ~255 + assert 1024 <= bound <= 131072 + assert bound & (bound-1) == 0 # a power of two + + def test_jit_get_stats(self, monkeypatch): + fix_annotator_for_vrawbuffer(monkeypatch) driver = JitDriver(greens = [], reds = ['i']) def f(): @@ -40,3 +204,88 @@ res = self.meta_interp(main, []) assert res == 3 # one for loop, one for entry point and one for the prologue + +class TestTranslationRemoveTypePtrX86(CCompiledMixin): + CPUClass = getcpuclass() + + def _get_TranslationContext(self): + t = TranslationContext() + t.config.translation.gc = DEFL_GC # 'hybrid' or 'minimark' + t.config.translation.gcrootfinder = 'asmgcc' + t.config.translation.list_comprehension_operations = True + t.config.translation.gcremovetypeptr = True + return t + + def test_external_exception_handling_translates(self, monkeypatch): + fix_annotator_for_vrawbuffer(monkeypatch) + jitdriver = JitDriver(greens = [], reds = ['n', 'total']) + + class ImDone(Exception): + def __init__(self, resvalue): + self.resvalue = resvalue + + @dont_look_inside + def f(x, total): + if x <= 30: + raise ImDone(total * 10) + if x > 200: + return 2 + raise ValueError + @dont_look_inside + def g(x): + if x > 150: + raise ValueError + return 2 + class Base: + def meth(self): + return 2 + class Sub(Base): + def meth(self): + return 1 + @dont_look_inside + def h(x): + if x < 20000: + return Sub() + else: + return Base() + def myportal(i): + set_param(jitdriver, "threshold", 3) + set_param(jitdriver, "trace_eagerness", 2) + total = 0 + n = i + while True: + jitdriver.can_enter_jit(n=n, total=total) + jitdriver.jit_merge_point(n=n, total=total) + try: + total += f(n, total) + except ValueError: + total += 1 + try: + total += g(n) + except ValueError: + total -= 1 + n -= h(n).meth() # this is to force a GUARD_CLASS + def main(i): + try: + myportal(i) + except ImDone, e: + return e.resvalue + + # XXX custom fishing, depends on the exact env var and format + logfile = udir.join('test_ztranslation.log') + os.environ['PYPYLOG'] = 'jit-log-opt:%s' % (logfile,) + try: + res = self.meta_interp(main, [400]) + assert res == main(400) + finally: + del os.environ['PYPYLOG'] + + guard_class = 0 + for line in open(str(logfile)): + if 'guard_class' in line: + guard_class += 1 + # if we get many more guard_classes, it means that we generate + # guards that always fail (the following assert's original purpose + # is to catch the following case: each GUARD_CLASS is misgenerated + # and always fails with "gcremovetypeptr") + assert 0 < guard_class < 10 diff --git a/rpython/jit/backend/x86/test/test_ztranslation_basic.py b/rpython/jit/backend/x86/test/test_ztranslation_basic.py --- a/rpython/jit/backend/x86/test/test_ztranslation_basic.py +++ b/rpython/jit/backend/x86/test/test_ztranslation_basic.py @@ -12,6 +12,7 @@ from rpython.jit.backend.x86.arch import IS_X86_32, IS_X86_64 from rpython.config.translationoption import DEFL_GC from rpython.rlib import rgc +from rpython.jit.backend.x86.test.test_ztranslation import fix_annotator_for_vrawbuffer class TestTranslationX86(CCompiledMixin): CPUClass = getcpuclass() @@ -22,7 +23,7 @@ assert '-msse2' in cbuilder.eci.compile_extra assert '-mfpmath=sse' in cbuilder.eci.compile_extra - def test_stuff_translates(self): + def test_stuff_translates(self, monkeypatch): # this is a basic test that tries to hit a number of features and their # translation: # - jitting of loops and bridges @@ -31,6 +32,7 @@ # - profiler # - full optimizer # - floats neg and abs + fix_annotator_for_vrawbuffer(monkeypatch) class Frame(object): _virtualizable2_ = ['i'] diff --git a/rpython/jit/backend/x86/test/test_ztranslation_call_assembler.py b/rpython/jit/backend/x86/test/test_ztranslation_call_assembler.py --- a/rpython/jit/backend/x86/test/test_ztranslation_call_assembler.py +++ b/rpython/jit/backend/x86/test/test_ztranslation_call_assembler.py @@ -12,6 +12,7 @@ from rpython.jit.backend.x86.arch import IS_X86_32, IS_X86_64 from rpython.config.translationoption import DEFL_GC from rpython.rlib import rgc +from rpython.jit.backend.x86.test.test_ztranslation import fix_annotator_for_vrawbuffer class TestTranslationX86(CCompiledMixin): CPUClass = getcpuclass() @@ -22,9 +23,10 @@ assert '-msse2' in cbuilder.eci.compile_extra assert '-mfpmath=sse' in cbuilder.eci.compile_extra - def test_direct_assembler_call_translates(self): + def test_direct_assembler_call_translates(self, monkeypatch): """Test CALL_ASSEMBLER and the recursion limit""" from rpython.rlib.rstackovf import StackOverflow + fix_annotator_for_vrawbuffer(monkeypatch) class Thing(object): def __init__(self, val): diff --git a/rpython/jit/backend/x86/test/test_ztranslation_external_exception.py b/rpython/jit/backend/x86/test/test_ztranslation_external_exception.py --- a/rpython/jit/backend/x86/test/test_ztranslation_external_exception.py +++ b/rpython/jit/backend/x86/test/test_ztranslation_external_exception.py @@ -12,7 +12,7 @@ from rpython.jit.backend.x86.arch import IS_X86_32, IS_X86_64 from rpython.config.translationoption import DEFL_GC from rpython.rlib import rgc - +from rpython.jit.backend.x86.test.test_ztranslation import fix_annotator_for_vrawbuffer class TestTranslationRemoveTypePtrX86(CCompiledMixin): CPUClass = getcpuclass() @@ -25,7 +25,9 @@ t.config.translation.gcremovetypeptr = True return t - def test_external_exception_handling_translates(self): + def test_external_exception_handling_translates(self, monkeypatch): + fix_annotator_for_vrawbuffer(monkeypatch) + jitdriver = JitDriver(greens = [], reds = ['n', 'total']) class ImDone(Exception): diff --git a/rpython/jit/codewriter/effectinfo.py b/rpython/jit/codewriter/effectinfo.py --- a/rpython/jit/codewriter/effectinfo.py +++ b/rpython/jit/codewriter/effectinfo.py @@ -76,14 +76,14 @@ # OS_MATH_SQRT = 100 # - OS_RAW_MALLOC_VARSIZE = 110 + OS_RAW_MALLOC_VARSIZE_CHAR = 110 OS_RAW_FREE = 111 OS_JIT_FORCE_VIRTUAL = 120 # for debugging: _OS_CANRAISE = set([OS_NONE, OS_STR2UNICODE, OS_LIBFFI_CALL, - OS_RAW_MALLOC_VARSIZE, OS_JIT_FORCE_VIRTUAL]) + OS_RAW_MALLOC_VARSIZE_CHAR, OS_JIT_FORCE_VIRTUAL]) def __new__(cls, readonly_descrs_fields, readonly_descrs_arrays, write_descrs_fields, write_descrs_arrays, diff --git a/rpython/jit/codewriter/jtransform.py b/rpython/jit/codewriter/jtransform.py --- a/rpython/jit/codewriter/jtransform.py +++ b/rpython/jit/codewriter/jtransform.py @@ -539,9 +539,11 @@ name += '_no_track_allocation' op1 = self.prepare_builtin_call(op, name, args, (TYPE,), TYPE) if name == 'raw_malloc_varsize': - return self._handle_oopspec_call(op1, args, - EffectInfo.OS_RAW_MALLOC_VARSIZE, - EffectInfo.EF_CAN_RAISE) + ITEMTYPE = op.args[0].value.OF + if ITEMTYPE == lltype.Char: + return self._handle_oopspec_call(op1, args, + EffectInfo.OS_RAW_MALLOC_VARSIZE_CHAR, + EffectInfo.EF_CAN_RAISE) return self.rewrite_op_direct_call(op1) def rewrite_op_malloc_varsize(self, op): diff --git a/rpython/jit/codewriter/test/test_jtransform.py b/rpython/jit/codewriter/test/test_jtransform.py --- a/rpython/jit/codewriter/test/test_jtransform.py +++ b/rpython/jit/codewriter/test/test_jtransform.py @@ -126,7 +126,7 @@ INT = lltype.Signed UNICHAR = lltype.UniChar FLOAT = lltype.Float - ARRAYPTR = rffi.CArrayPtr(lltype.Signed) + ARRAYPTR = rffi.CArrayPtr(lltype.Char) argtypes = { EI.OS_MATH_SQRT: ([FLOAT], FLOAT), EI.OS_STR2UNICODE:([PSTR], PUNICODE), @@ -143,7 +143,7 @@ EI.OS_UNIEQ_NONNULL_CHAR: ([PUNICODE, UNICHAR], INT), EI.OS_UNIEQ_CHECKNULL_CHAR: ([PUNICODE, UNICHAR], INT), EI.OS_UNIEQ_LENGTHOK: ([PUNICODE, PUNICODE], INT), - EI.OS_RAW_MALLOC_VARSIZE: ([INT], ARRAYPTR), + EI.OS_RAW_MALLOC_VARSIZE_CHAR: ([INT], ARRAYPTR), EI.OS_RAW_FREE: ([ARRAYPTR], lltype.Void), } argtypes = argtypes[oopspecindex] @@ -151,7 +151,7 @@ assert argtypes[1] == op.result.concretetype if oopspecindex == EI.OS_STR2UNICODE: assert extraeffect == EI.EF_ELIDABLE_CAN_RAISE - elif oopspecindex == EI.OS_RAW_MALLOC_VARSIZE: + elif oopspecindex == EI.OS_RAW_MALLOC_VARSIZE_CHAR: assert extraeffect == EI.EF_CAN_RAISE elif oopspecindex == EI.OS_RAW_FREE: assert extraeffect == EI.EF_CANNOT_RAISE @@ -161,7 +161,7 @@ def calldescr_canraise(self, calldescr): EI = effectinfo.EffectInfo - if calldescr == 'calldescr-%d' % EI.OS_RAW_MALLOC_VARSIZE: + if calldescr == 'calldescr-%d' % EI.OS_RAW_MALLOC_VARSIZE_CHAR: return True return False @@ -555,7 +555,7 @@ assert op1.args == [] def test_raw_malloc(): - S = rffi.CArray(lltype.Signed) + S = rffi.CArray(lltype.Char) v1 = varoftype(lltype.Signed) v = varoftype(lltype.Ptr(S)) flags = Constant({'flavor': 'raw'}, lltype.Void) @@ -566,7 +566,7 @@ assert op0.opname == 'residual_call_ir_i' assert op0.args[0].value == 'raw_malloc_varsize' # pseudo-function as a str assert (op0.args[-1] == 'calldescr-%d' % - effectinfo.EffectInfo.OS_RAW_MALLOC_VARSIZE) + effectinfo.EffectInfo.OS_RAW_MALLOC_VARSIZE_CHAR) assert op1.opname == '-live-' assert op1.args == [] @@ -608,7 +608,7 @@ assert op1.args == [] def test_raw_free(): - S = rffi.CArray(lltype.Signed) + S = rffi.CArray(lltype.Char) flags = Constant({'flavor': 'raw', 'track_allocation': True}, lltype.Void) op = SpaceOperation('free', [varoftype(lltype.Ptr(S)), flags], diff --git a/rpython/jit/metainterp/compile.py b/rpython/jit/metainterp/compile.py --- a/rpython/jit/metainterp/compile.py +++ b/rpython/jit/metainterp/compile.py @@ -15,7 +15,7 @@ from rpython.jit.metainterp import history, resume from rpython.jit.metainterp.optimize import InvalidLoop from rpython.jit.metainterp.inliner import Inliner -from rpython.jit.metainterp.resume import NUMBERING, PENDINGFIELDSP +from rpython.jit.metainterp.resume import NUMBERING, PENDINGFIELDSP, ResumeDataDirectReader from rpython.jit.codewriter import heaptracker, longlong def giveup(): @@ -656,9 +656,9 @@ class AllVirtuals: llopaque = True - list = [resume.ResumeDataDirectReader.virtual_default] # annotation hack - def __init__(self, list): - self.list = list + cache = None + def __init__(self, cache): + self.cache = cache def hide(self, cpu): ptr = cpu.ts.cast_instance_to_base_ref(self) return cpu.ts.cast_to_ref(ptr) @@ -682,9 +682,9 @@ from rpython.jit.metainterp.blackhole import resume_in_blackhole hidden_all_virtuals = metainterp_sd.cpu.get_savedata_ref(deadframe) obj = AllVirtuals.show(metainterp_sd.cpu, hidden_all_virtuals) - all_virtuals = obj.list + all_virtuals = obj.cache if all_virtuals is None: - all_virtuals = [] + all_virtuals = ResumeDataDirectReader.VirtualCache([], []) assert jitdriver_sd is self.jitdriver_sd resume_in_blackhole(metainterp_sd, jitdriver_sd, self, deadframe, all_virtuals) diff --git a/rpython/jit/metainterp/history.py b/rpython/jit/metainterp/history.py --- a/rpython/jit/metainterp/history.py +++ b/rpython/jit/metainterp/history.py @@ -191,7 +191,6 @@ def get_jitcode_for_class(self, oocls): return self.jitcodes[oocls] - class Const(AbstractValue): __slots__ = () diff --git a/rpython/jit/metainterp/optimizeopt/earlyforce.py b/rpython/jit/metainterp/optimizeopt/earlyforce.py --- a/rpython/jit/metainterp/optimizeopt/earlyforce.py +++ b/rpython/jit/metainterp/optimizeopt/earlyforce.py @@ -1,15 +1,26 @@ +from rpython.jit.codewriter.effectinfo import EffectInfo from rpython.jit.metainterp.optimizeopt.optimizer import Optimization from rpython.jit.metainterp.optimizeopt.vstring import VAbstractStringValue from rpython.jit.metainterp.resoperation import rop, ResOperation +def is_raw_free(op, opnum): + if opnum != rop.CALL: + return False + einfo = op.getdescr().get_extra_info() + return einfo.oopspecindex == EffectInfo.OS_RAW_FREE + + class OptEarlyForce(Optimization): def propagate_forward(self, op): opnum = op.getopnum() + if (opnum != rop.SETFIELD_GC and opnum != rop.SETARRAYITEM_GC and + opnum != rop.SETARRAYITEM_RAW and opnum != rop.QUASIIMMUT_FIELD and opnum != rop.SAME_AS and - opnum != rop.MARK_OPAQUE_PTR): + opnum != rop.MARK_OPAQUE_PTR and + not is_raw_free(op, opnum)): for arg in op.getarglist(): if arg in self.optimizer.values: diff --git a/rpython/jit/metainterp/optimizeopt/optimizer.py b/rpython/jit/metainterp/optimizeopt/optimizer.py --- a/rpython/jit/metainterp/optimizeopt/optimizer.py +++ b/rpython/jit/metainterp/optimizeopt/optimizer.py @@ -231,6 +231,12 @@ def setitem(self, index, value): raise NotImplementedError + def getitem_raw(self, offset, length, descr): + raise NotImplementedError + + def setitem_raw(self, offset, length, descr, value): + raise NotImplementedError + def getinteriorfield(self, index, ofs, default): raise NotImplementedError diff --git a/rpython/jit/metainterp/optimizeopt/rawbuffer.py b/rpython/jit/metainterp/optimizeopt/rawbuffer.py new file mode 100644 --- /dev/null +++ b/rpython/jit/metainterp/optimizeopt/rawbuffer.py @@ -0,0 +1,134 @@ +from rpython.rlib.debug import debug_start, debug_stop, debug_print +from rpython.rlib.objectmodel import compute_unique_id, we_are_translated + +class InvalidRawOperation(Exception): + pass + +class InvalidRawWrite(InvalidRawOperation): + pass + +class InvalidRawRead(InvalidRawOperation): + pass + +class RawBuffer(object): + def __init__(self, cpu, logops=None): + # the following lists represents the writes in the buffer: values[i] + # is the value of length lengths[i] stored at offset[i]. + # + # the invariant is that they are ordered by offset, and that + # offset[i]+length[i] <= offset[i+1], i.e. that the writes never + # overlaps + self.cpu = cpu + self.logops = logops + self.offsets = [] + self.lengths = [] + self.descrs = [] + self.values = [] + + def _get_memory(self): + """ + NOT_RPYTHON + for testing only + """ + return zip(self.offsets, self.lengths, self.descrs, self.values) + + def _repr_of_descr(self, descr): + if self.logops: + s = self.logops.repr_of_descr(descr) + else: + s = str(descr) + s += " at %d" % compute_unique_id(descr) + return s + + def _repr_of_value(self, value): + if not we_are_translated() and isinstance(value, str): + return value # for tests + if self.logops: + s = self.logops.repr_of_arg(value.box) + else: + s = str(value.box) + s += " at %d" % compute_unique_id(value.box) + return s + + def _dump_to_log(self): + debug_print("RawBuffer state") + debug_print("offset, length, descr, box") + debug_print("(box == None means that the value is still virtual)") + for i in range(len(self.offsets)): + descr = self._repr_of_descr(self.descrs[i]) + box = self._repr_of_value(self.values[i]) + debug_print("%d, %d, %s, %s" % (self.offsets[i], self.lengths[i], descr, box)) + + def _invalid_write(self, message, offset, length, descr, value): + debug_start('jit-log-rawbuffer') + debug_print('Invalid write: %s' % message) + debug_print(" offset: %d" % offset) + debug_print(" length: %d" % length) + debug_print(" descr: %s" % self._repr_of_descr(descr)) + debug_print(" value: %s" % self._repr_of_value(value)) + self._dump_to_log() + debug_stop('jit-log-rawbuffer') + raise InvalidRawWrite + + def _invalid_read(self, message, offset, length, descr): + debug_start('jit-log-rawbuffer') + debug_print('Invalid read: %s' % message) + debug_print(" offset: %d" % offset) + debug_print(" length: %d" % length) + debug_print(" descr: %s" % self._repr_of_descr(descr)) + self._dump_to_log() + debug_stop('jit-log-rawbuffer') + raise InvalidRawRead + + def _descrs_are_compatible(self, d1, d2): + # two arraydescrs are compatible if they have the same basesize, + # itemsize and sign, even if they are not identical + unpack = self.cpu.unpack_arraydescr_size + return unpack(d1) == unpack(d2) + + def write_value(self, offset, length, descr, value): + i = 0 + N = len(self.offsets) + while i < N: + if self.offsets[i] == offset: + if (length != self.lengths[i] or not + self._descrs_are_compatible(descr, self.descrs[i])): + # in theory we could add support for the cases in which + # the length or descr is different, but I don't think we + # need it in practice + self._invalid_write('length or descr not compatible', + offset, length, descr, value) + # update the value at this offset + self.values[i] = value + return + elif self.offsets[i] > offset: + break + i += 1 + # + if i < len(self.offsets) and offset+length > self.offsets[i]: + self._invalid_write("overlap with next bytes", + offset, length, descr, value) + if i > 0 and self.offsets[i-1]+self.lengths[i-1] > offset: + self._invalid_write("overlap with previous bytes", + offset, length, descr, value) + # insert a new value at offset + self.offsets.insert(i, offset) + self.lengths.insert(i, length) + self.descrs.insert(i, descr) + self.values.insert(i, value) + + def read_value(self, offset, length, descr): + i = 0 + N = len(self.offsets) + while i < N: + if self.offsets[i] == offset: + if (length != self.lengths[i] or + not self._descrs_are_compatible(descr, self.descrs[i])): + self._invalid_read('length or descr not compatible', + offset, length, descr) + return self.values[i] + i += 1 + # memory location not found: this means we are reading from + # uninitialized memory, give up the optimization + self._invalid_read('uninitialized memory', + offset, length, descr) diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py --- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py @@ -770,8 +770,6 @@ """ self.optimize_loop(ops, expected) - - def test_p123_simple(self): ops = """ [i1, p2, p3] @@ -1730,6 +1728,175 @@ # We cannot track virtuals that survive for more than two iterations. self.optimize_loop(ops, expected, preamble) + def test_virtual_raw_malloc(self): + ops = """ + [i1] + i2 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) + i3 = getarrayitem_raw(i2, 0, descr=rawarraydescr) + call('free', i2, descr=raw_free_descr) + jump(i3) + """ + expected = """ + [i1] + jump(i1) + """ + self.optimize_loop(ops, expected) + + def test_virtual_raw_malloc_force(self): + ops = """ + [i1] + i2 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) + setarrayitem_raw(i2, 2, 456, descr=rawarraydescr) + setarrayitem_raw(i2, 1, 123, descr=rawarraydescr) + label('foo') # we expect the buffer to be forced *after* the label + escape(i2) + call('free', i2, descr=raw_free_descr) + jump(i1) + """ + expected = """ + [i1] + label('foo') + i2 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) + i3 = int_add(i2, 8) + setarrayitem_raw(i3, 0, 123, descr=rawarraydescr) + i4 = int_add(i2, 16) + setarrayitem_raw(i4, 0, 456, descr=rawarraydescr) + escape(i2) + call('free', i2, descr=raw_free_descr) + jump(i1) + """ + self.optimize_loop(ops, expected) + + def test_virtual_raw_malloc_invalid_write_force(self): + ops = """ + [i1] + i2 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) + label('foo') # we expect the buffer to be forced *after* the label + setarrayitem_raw(i2, 2, 456, descr=rawarraydescr_char) # overlap! + call('free', i2, descr=raw_free_descr) + jump(i1) + """ + expected = """ + [i1] + label('foo') + i2 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) + setarrayitem_raw(i2, 2, 456, descr=rawarraydescr_char) + call('free', i2, descr=raw_free_descr) + jump(i1) + """ + self.optimize_loop(ops, expected) + + def test_virtual_raw_malloc_invalid_read_force(self): + ops = """ + [i1] + i2 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) + label('foo') # we expect the buffer to be forced *after* the label + i3 = getarrayitem_raw(i2, 0, descr=rawarraydescr_char) + call('free', i2, descr=raw_free_descr) + jump(i1) + """ + expected = """ + [i1] + label('foo') + i2 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) + i3 = getarrayitem_raw(i2, 0, descr=rawarraydescr_char) + call('free', i2, descr=raw_free_descr) + jump(i1) + """ + self.optimize_loop(ops, expected) + + def test_virtual_raw_slice(self): + ops = """ + [i0, i1] + i2 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i2, 0, 42, descr=rawarraydescr_char) + i3 = int_add(i2, 1) # get a slice of the original buffer + setarrayitem_raw(i3, 0, 4242, descr=rawarraydescr) # write to the slice + i4 = getarrayitem_raw(i2, 0, descr=rawarraydescr_char) + i5 = int_add(i2, 1) + i6 = getarrayitem_raw(i5, 0, descr=rawarraydescr) + call('free', i2, descr=raw_free_descr) + jump(i0, i1) + """ + expected = """ + [i0, i1] + jump(i0, i1) + """ + self.optimize_loop(ops, expected) + + def test_virtual_raw_slice_of_a_raw_slice(self): + ops = """ + [i0, i1] + i2 = call('malloc', 10, descr=raw_malloc_descr) + i3 = int_add(i2, 1) # get a slice of the original buffer + i4 = int_add(i3, 1) # get a slice of a slice + setarrayitem_raw(i4, 0, i1, descr=rawarraydescr_char) # write to the slice + i5 = getarrayitem_raw(i2, 2, descr=rawarraydescr_char) + call('free', i2, descr=raw_free_descr) + jump(i0, i5) + """ + expected = """ + [i0, i1] + jump(i0, i1) + """ + self.optimize_loop(ops, expected) + + def test_virtual_raw_slice_force(self): + ops = """ + [i0, i1] + i2 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i2, 0, 42, descr=rawarraydescr_char) + i3 = int_add(i2, 1) # get a slice of the original buffer + setarrayitem_raw(i3, 4, 4242, descr=rawarraydescr_char) # write to the slice + label('foo') + escape(i3) + jump(i0, i1) + """ + expected = """ + [i0, i1] + label('foo') + # these ops are generated by VirtualRawBufferValue._really_force + i2 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i2, 0, 42, descr=rawarraydescr_char) + i3 = int_add(i2, 5) # 1+4*sizeof(char) + setarrayitem_raw(i3, 0, 4242, descr=rawarraydescr_char) + # this is generated by VirtualRawSliceValue._really_force + i4 = int_add(i2, 1) + escape(i4) + jump(i0, i1) + """ + self.optimize_loop(ops, expected) + + def test_virtual_raw_malloc_virtualstate(self): + ops = """ + [i0] + i1 = getarrayitem_raw(i0, 0, descr=rawarraydescr) + i2 = int_add(i1, 1) + call('free', i0, descr=raw_free_descr) + i3 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i3, 0, i2, descr=rawarraydescr) + label('foo') + jump(i3) + """ + expected = """ + [i0] + i1 = getarrayitem_raw(i0, 0, descr=rawarraydescr) + i2 = int_add(i1, 1) + call('free', i0, descr=raw_free_descr) + label('foo') + i3 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i3, 0, i2, descr=rawarraydescr) + jump(i3) + """ + self.optimize_loop(ops, expected) + def test_duplicate_getfield_1(self): ops = """ [p1, p2] diff --git a/rpython/jit/metainterp/optimizeopt/test/test_rawbuffer.py b/rpython/jit/metainterp/optimizeopt/test/test_rawbuffer.py new file mode 100644 --- /dev/null +++ b/rpython/jit/metainterp/optimizeopt/test/test_rawbuffer.py @@ -0,0 +1,90 @@ +import py +from rpython.jit.metainterp.optimizeopt.rawbuffer import (InvalidRawWrite, + InvalidRawRead, RawBuffer) + +class FakeCPU(object): + def unpack_arraydescr_size(self, descr): + return descr, 'foo', 'bar' + +def test_write_value(): + buf = RawBuffer(FakeCPU()) + buf.write_value(8, 4, 'descr3', 'three') + buf.write_value(0, 4, 'descr1', 'one') + buf.write_value(4, 2, 'descr2', 'two') + buf.write_value(12, 2, 'descr4', 'four') + assert buf._get_memory() == [ + ( 0, 4, 'descr1', 'one'), + ( 4, 2, 'descr2', 'two'), + ( 8, 4, 'descr3', 'three'), + (12, 2, 'descr4', 'four'), + ] + # + +def test_write_value_update(): + buf = RawBuffer(FakeCPU()) + buf.write_value(0, 4, 'descr', 'one') + buf.write_value(4, 2, 'descr', 'two') + buf.write_value(0, 4, 'descr', 'ONE') + assert buf._get_memory() == [ + ( 0, 4, 'descr', 'ONE'), + ( 4, 2, 'descr', 'two'), + ] + +def test_write_value_invalid_length(): + buf = RawBuffer(FakeCPU()) + buf.write_value(0, 4, 'descr1', 'one') + with py.test.raises(InvalidRawWrite): + buf.write_value(0, 5, 'descr1', 'two') + with py.test.raises(InvalidRawWrite): + buf.write_value(0, 4, 'descr2', 'two') + + +def test_write_value_overlapping_next(): + buf = RawBuffer(FakeCPU()) + buf.write_value(0, 4, 'descr', 'one') + buf.write_value(6, 4, 'descr', 'two') + with py.test.raises(InvalidRawWrite): + buf.write_value(4, 4, 'descr', 'three') + +def test_write_value_overlapping_prev(): + buf = RawBuffer(FakeCPU()) + buf.write_value(0, 4, 'descr', 'one') + with py.test.raises(InvalidRawWrite): + buf.write_value(2, 1, 'descr', 'two') + +def test_read_value(): + buf = RawBuffer(FakeCPU()) + buf.write_value(0, 4, 'descr', 'one') + buf.write_value(4, 4, 'descr', 'two') + assert buf.read_value(0, 4, 'descr') == 'one' + assert buf.read_value(4, 4, 'descr') == 'two' + with py.test.raises(InvalidRawRead): + buf.read_value(0, 2, 'descr') + with py.test.raises(InvalidRawRead): + buf.read_value(8, 2, 'descr') + with py.test.raises(InvalidRawRead): + buf.read_value(0, 4, 'another descr') + +def test_unpack_descrs(): + ArrayS_8_1 = object() + ArrayS_8_2 = object() + ArrayU_8 = object() + + class FakeCPU(object): + def unpack_arraydescr_size(self, descr): + if descr in (ArrayS_8_1, ArrayS_8_2): + return 0, 8, True + return 0, 8, False + + buf = RawBuffer(FakeCPU()) + buf.write_value(0, 4, ArrayS_8_1, 'one') + assert buf.read_value(0, 4, ArrayS_8_1) == 'one' + assert buf.read_value(0, 4, ArrayS_8_2) == 'one' # with a non-identical descr + # + buf.write_value(0, 4, ArrayS_8_2, 'two') # with a non-identical descr + assert buf.read_value(0, 4, ArrayS_8_1) == 'two' + # + with py.test.raises(InvalidRawRead): + buf.read_value(0, 4, ArrayU_8) + with py.test.raises(InvalidRawWrite): + buf.write_value(0, 4, ArrayU_8, 'three') diff --git a/rpython/jit/metainterp/optimizeopt/test/test_util.py b/rpython/jit/metainterp/optimizeopt/test/test_util.py --- a/rpython/jit/metainterp/optimizeopt/test/test_util.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_util.py @@ -196,6 +196,15 @@ EffectInfo.EF_CANNOT_RAISE, oopspecindex=EffectInfo.OS_ARRAYCOPY)) + raw_malloc_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, + EffectInfo([], [], [], [], + EffectInfo.EF_CAN_RAISE, + oopspecindex=EffectInfo.OS_RAW_MALLOC_VARSIZE_CHAR)) + raw_free_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, + EffectInfo([], [], [], [], + EffectInfo.EF_CANNOT_RAISE, + oopspecindex=EffectInfo.OS_RAW_FREE)) + # array of structs (complex data) complexarray = lltype.GcArray( @@ -208,6 +217,12 @@ complexrealdescr = cpu.interiorfielddescrof(complexarray, "real") compleximagdescr = cpu.interiorfielddescrof(complexarray, "imag") + rawarraydescr = cpu.arraydescrof(lltype.Array(lltype.Signed, + hints={'nolength': True})) + rawarraydescr_char = cpu.arraydescrof(lltype.Array(lltype.Char, + hints={'nolength': True})) + + for _name, _os in [ ('strconcatdescr', 'OS_STR_CONCAT'), ('strslicedescr', 'OS_STR_SLICE'), diff --git a/rpython/jit/metainterp/optimizeopt/virtualize.py b/rpython/jit/metainterp/optimizeopt/virtualize.py --- a/rpython/jit/metainterp/optimizeopt/virtualize.py +++ b/rpython/jit/metainterp/optimizeopt/virtualize.py @@ -6,7 +6,9 @@ from rpython.jit.metainterp.optimizeopt import optimizer from rpython.jit.metainterp.optimizeopt.optimizer import OptValue, REMOVED from rpython.jit.metainterp.optimizeopt.util import (make_dispatcher_method, - descrlist_dict, sort_descrs) + descrlist_dict, sort_descrs) + +from rpython.jit.metainterp.optimizeopt.rawbuffer import RawBuffer, InvalidRawOperation from rpython.jit.metainterp.resoperation import rop, ResOperation from rpython.rlib.objectmodel import we_are_translated @@ -236,8 +238,36 @@ def _get_descr(self): return self.structdescr +class AbstractVArrayValue(AbstractVirtualValue): + """ + Base class for VArrayValue (for normal GC arrays) and VRawBufferValue (for + malloc()ed memory) + """ -class VArrayValue(AbstractVirtualValue): + def getlength(self): + return len(self._items) + + def get_item_value(self, i): + raise NotImplementedError + + def set_item_value(self, i, newval): + raise NotImplementedError + + def get_args_for_fail(self, modifier): + if self.box is None and not modifier.already_seen_virtual(self.keybox): + # checks for recursion: it is False unless + # we have already seen the very same keybox + itemboxes = [] + for i in range(self.getlength()): + itemvalue = self.get_item_value(i) + itemboxes.append(itemvalue.get_key_box()) + modifier.register_virtual_fields(self.keybox, itemboxes) + for i in range(self.getlength()): + itemvalue = self.get_item_value(i) + itemvalue.get_args_for_fail(modifier) + + +class VArrayValue(AbstractVArrayValue): def __init__(self, arraydescr, constvalue, size, keybox, source_op=None): AbstractVirtualValue.__init__(self, keybox, source_op) @@ -248,6 +278,12 @@ def getlength(self): return len(self._items) + def get_item_value(self, i): + return self._items[i] + + def set_item_value(self, i, newval): + self._items[i] = newval + def getitem(self, index): res = self._items[index] return res @@ -257,11 +293,16 @@ self._items[index] = itemvalue def force_at_end_of_preamble(self, already_forced, optforce): + # note that this method is on VArrayValue instead of + # AbstractVArrayValue because we do not want to support virtualstate + # for rawbuffers for now if self in already_forced: return self already_forced[self] = self - for index in range(len(self._items)): - self._items[index] = self._items[index].force_at_end_of_preamble(already_forced, optforce) + for index in range(self.getlength()): + itemval = self.get_item_value(index) + itemval = itemval.force_at_end_of_preamble(already_forced, optforce) + self.set_item_value(index, itemval) return self def _really_force(self, optforce): @@ -281,29 +322,16 @@ descr=self.arraydescr) optforce.emit_operation(op) - def get_args_for_fail(self, modifier): - if self.box is None and not modifier.already_seen_virtual(self.keybox): - # checks for recursion: it is False unless - # we have already seen the very same keybox - itemboxes = [] - for itemvalue in self._items: - itemboxes.append(itemvalue.get_key_box()) - modifier.register_virtual_fields(self.keybox, itemboxes) - for itemvalue in self._items: - itemvalue.get_args_for_fail(modifier) - def _make_virtual(self, modifier): return modifier.make_varray(self.arraydescr) + class VArrayStructValue(AbstractVirtualValue): def __init__(self, arraydescr, size, keybox, source_op=None): AbstractVirtualValue.__init__(self, keybox, source_op) self.arraydescr = arraydescr self._items = [{} for _ in xrange(size)] - def getlength(self): - return len(self._items) - def getinteriorfield(self, index, ofs, default): return self._items[index].get(ofs, default) @@ -363,6 +391,90 @@ return modifier.make_varraystruct(self.arraydescr, self._get_list_of_descrs()) +class VRawBufferValue(AbstractVArrayValue): + + def __init__(self, cpu, logops, size, keybox, source_op): + AbstractVirtualValue.__init__(self, keybox, source_op) + # note that size is unused, because we assume that the buffer is big + # enough to write/read everything we need. If it's not, it's undefined + # behavior anyway, although in theory we could probably detect such + # cases here + self.size = size + self.buffer = RawBuffer(cpu, logops) + + def getlength(self): + return len(self.buffer.values) + + def get_item_value(self, i): + return self.buffer.values[i] + + def set_item_value(self, i, newval): + self.buffer.values[i] = newval + + def getitem_raw(self, offset, length, descr): + return self.buffer.read_value(offset, length, descr) + + def setitem_raw(self, offset, length, descr, value): + self.buffer.write_value(offset, length, descr, value) + + def _really_force(self, optforce): + op = self.source_op + assert op is not None + if not we_are_translated(): + op.name = 'FORCE ' + self.source_op.name + optforce.emit_operation(self.source_op) + self.box = box = self.source_op.result + for i in range(len(self.buffer.offsets)): + # get a pointer to self.box+offset + offset = self.buffer.offsets[i] + if offset == 0: + arraybox = self.box + else: + arraybox = BoxInt() + op = ResOperation(rop.INT_ADD, + [self.box, ConstInt(offset)], arraybox) + optforce.emit_operation(op) + # + # write the value + descr = self.buffer.descrs[i] + itemvalue = self.buffer.values[i] + itembox = itemvalue.force_box(optforce) + op = ResOperation(rop.SETARRAYITEM_RAW, + [arraybox, ConstInt(0), itembox], None, + descr=descr) + optforce.emit_operation(op) + + def _make_virtual(self, modifier): + # I *think* we need to make a copy of offsets and descrs because we + # want a snapshot of the virtual state right now: if we grow more + # elements later, we don't want them to go in this virtual state + return modifier.make_vrawbuffer(self.size, + self.buffer.offsets[:], + self.buffer.descrs[:]) + + +class VRawSliceValue(AbstractVirtualValue): + + def __init__(self, rawbuffer_value, offset, keybox, source_op): + AbstractVirtualValue.__init__(self, keybox, source_op) + self.rawbuffer_value = rawbuffer_value + self.offset = offset + + def _really_force(self, optforce): + op = self.source_op + assert op is not None + if not we_are_translated(): + op.name = 'FORCE ' + self.source_op.name + self.box = self.source_op.result + self.rawbuffer_value.force_box(optforce) + optforce.emit_operation(op) + + def setitem_raw(self, offset, length, descr, value): + self.rawbuffer_value.setitem_raw(self.offset+offset, length, descr, value) + + def getitem_raw(self, offset, length, descr): + return self.rawbuffer_value.getitem_raw(self.offset+offset, length, descr) + class OptVirtualize(optimizer.Optimization): "Virtualize objects until they escape." @@ -388,6 +500,17 @@ self.make_equal_to(box, vvalue) return vvalue + def make_virtual_raw_memory(self, size, box, source_op): + logops = self.optimizer.loop.logops + vvalue = VRawBufferValue(self.optimizer.cpu, logops, size, box, source_op) + self.make_equal_to(box, vvalue) + return vvalue + + def make_virtual_raw_slice(self, rawbuffer_value, offset, box, source_op): + vvalue = VRawSliceValue(rawbuffer_value, offset, box, source_op) + self.make_equal_to(box, vvalue) + return vvalue + def optimize_GUARD_NO_EXCEPTION(self, op): if self.last_emitted_operation is REMOVED: return @@ -524,6 +647,43 @@ self.getvalue(op.result).ensure_nonnull() self.emit_operation(op) + def optimize_CALL(self, op): + effectinfo = op.getdescr().get_extra_info() + if effectinfo.oopspecindex == EffectInfo.OS_RAW_MALLOC_VARSIZE_CHAR: + self.do_RAW_MALLOC_VARSIZE_CHAR(op) + elif effectinfo.oopspecindex == EffectInfo.OS_RAW_FREE: + self.do_RAW_FREE(op) + else: + self.emit_operation(op) + + def do_RAW_MALLOC_VARSIZE_CHAR(self, op): + sizebox = op.getarg(1) + if not isinstance(sizebox, ConstInt): + self.emit_operation(op) + return + size = sizebox.value + self.make_virtual_raw_memory(size, op.result, op) + + def do_RAW_FREE(self, op): + value = self.getvalue(op.getarg(1)) + if value.is_virtual(): + return + self.emit_operation(op) + + def optimize_INT_ADD(self, op): + value = self.getvalue(op.getarg(0)) + offsetbox = self.get_constant_box(op.getarg(1)) + if value.is_virtual() and offsetbox is not None: + offset = offsetbox.getint() + if isinstance(value, VRawBufferValue): + self.make_virtual_raw_slice(value, offset, op.result, op) + return + elif isinstance(value, VRawSliceValue): + offset = offset + value.offset + self.make_virtual_raw_slice(value.rawbuffer_value, offset, op.result, op) + return + self.emit_operation(op) + def optimize_ARRAYLEN_GC(self, op): value = self.getvalue(op.getarg(0)) if value.is_virtual(): @@ -558,6 +718,48 @@ value.ensure_nonnull() self.emit_operation(op) + def _unpack_arrayitem_raw_op(self, op, indexbox): + index = indexbox.getint() + cpu = self.optimizer.cpu + descr = op.getdescr() + basesize, itemsize, _ = cpu.unpack_arraydescr_size(descr) + offset = basesize + (itemsize*index) + return offset, itemsize, descr + + def optimize_GETARRAYITEM_RAW(self, op): + value = self.getvalue(op.getarg(0)) + if value.is_virtual(): + indexbox = self.get_constant_box(op.getarg(1)) + if indexbox is not None: + offset, itemsize, descr = self._unpack_arrayitem_raw_op(op, indexbox) + try: + itemvalue = value.getitem_raw(offset, itemsize, descr) + self.make_equal_to(op.result, itemvalue) + except InvalidRawOperation: + box = value.force_box(self) + op.setarg(0, box) + self.emit_operation(op) + return + value.ensure_nonnull() + self.emit_operation(op) + + def optimize_SETARRAYITEM_RAW(self, op): + value = self.getvalue(op.getarg(0)) + if value.is_virtual(): + indexbox = self.get_constant_box(op.getarg(1)) + if indexbox is not None: + offset, itemsize, descr = self._unpack_arrayitem_raw_op(op, indexbox) + itemvalue = self.getvalue(op.getarg(2)) + try: + value.setitem_raw(offset, itemsize, descr, itemvalue) + except InvalidRawOperation: + box = value.force_box(self) + op.setarg(0, box) + self.emit_operation(op) + return + value.ensure_nonnull() + self.emit_operation(op) + def optimize_GETINTERIORFIELD_GC(self, op): value = self.getvalue(op.getarg(0)) if value.is_virtual(): diff --git a/rpython/jit/metainterp/optimizeopt/virtualstate.py b/rpython/jit/metainterp/optimizeopt/virtualstate.py --- a/rpython/jit/metainterp/optimizeopt/virtualstate.py +++ b/rpython/jit/metainterp/optimizeopt/virtualstate.py @@ -158,10 +158,16 @@ def debug_header(self, indent): debug_print(indent + 'VStructStateInfo(%d):' % self.position) + class VArrayStateInfo(AbstractVirtualStateInfo): + def __init__(self, arraydescr): self.arraydescr = arraydescr + def _generalization_of(self, other): + return (isinstance(other, VArrayStateInfo) and + self.arraydescr is other.arraydescr) + def generalization_of(self, other, renum, bad): assert self.position != -1 if self.position in renum: @@ -187,10 +193,6 @@ return False return True - def _generalization_of(self, other): - return (isinstance(other, VArrayStateInfo) and - self.arraydescr is other.arraydescr) - def enum_forced_boxes(self, boxes, value, optimizer): if not isinstance(value, virtualize.VArrayValue): raise BadVirtualState @@ -198,7 +200,7 @@ raise BadVirtualState for i in range(len(self.fieldstate)): try: - v = value._items[i] + v = value.get_item_value(i) except IndexError: raise BadVirtualState s = self.fieldstate[i] @@ -212,6 +214,8 @@ def debug_header(self, indent): debug_print(indent + 'VArrayStateInfo(%d):' % self.position) + + class VArrayStructStateInfo(AbstractVirtualStateInfo): def __init__(self, arraydescr, fielddescrs): self.arraydescr = arraydescr @@ -287,6 +291,7 @@ debug_print(indent + 'VArrayStructStateInfo(%d):' % self.position) + class NotVirtualStateInfo(AbstractVirtualStateInfo): def __init__(self, value, is_opaque=False): self.is_opaque = is_opaque @@ -579,6 +584,9 @@ def make_varraystruct(self, arraydescr, fielddescrs): return VArrayStructStateInfo(arraydescr, fielddescrs) + def make_vrawbuffer(self, size, offsets, descrs): + raise NotImplementedError + class BoxNotProducable(Exception): pass diff --git a/rpython/jit/metainterp/pyjitpl.py b/rpython/jit/metainterp/pyjitpl.py --- a/rpython/jit/metainterp/pyjitpl.py +++ b/rpython/jit/metainterp/pyjitpl.py @@ -2595,6 +2595,7 @@ box_exchange_buffer = op.getarg(3) self.history.operations.pop() arg_boxes = [] + for i in range(cif_description.nargs): kind, descr, itemsize = get_arg_descr(self.cpu, cif_description.atypes[i]) diff --git a/rpython/jit/metainterp/resume.py b/rpython/jit/metainterp/resume.py --- a/rpython/jit/metainterp/resume.py +++ b/rpython/jit/metainterp/resume.py @@ -275,6 +275,9 @@ def make_varraystruct(self, arraydescr, fielddescrs): return VArrayStructInfo(arraydescr, fielddescrs) + def make_vrawbuffer(self, size, offsets, descrs): + return VRawBufferStateInfo(size, offsets, descrs) + def make_vstrplain(self, is_unicode=False): if is_unicode: return VUniPlainInfo() @@ -446,8 +449,8 @@ return self.liveboxes_from_env[box] return self.liveboxes[box] - class AbstractVirtualInfo(object): + kind = REF #def allocate(self, decoder, index): # raise NotImplementedError def equals(self, fieldnums): @@ -458,6 +461,7 @@ def debug_prints(self): raise NotImplementedError + class AbstractVirtualStructInfo(AbstractVirtualInfo): def __init__(self, fielddescrs): @@ -486,7 +490,7 @@ @specialize.argtype(1) def allocate(self, decoder, index): struct = decoder.allocate_with_vtable(self.known_class) - decoder.virtuals_cache[index] = struct + decoder.virtuals_cache.set_ptr(index, struct) return self.setfields(decoder, struct) def debug_prints(self): @@ -502,7 +506,7 @@ @specialize.argtype(1) def allocate(self, decoder, index): struct = decoder.allocate_struct(self.typedescr) - decoder.virtuals_cache[index] = struct + decoder.virtuals_cache.set_ptr(index, struct) return self.setfields(decoder, struct) def debug_prints(self): @@ -519,7 +523,7 @@ length = len(self.fieldnums) arraydescr = self.arraydescr array = decoder.allocate_array(length, arraydescr) - decoder.virtuals_cache[index] = array + decoder.virtuals_cache.set_ptr(index, array) # NB. the check for the kind of array elements is moved out of the loop if arraydescr.is_array_of_pointers(): for i in range(length): @@ -541,6 +545,31 @@ debug_print("\t\t", str(untag(i))) +class VRawBufferStateInfo(AbstractVirtualInfo): + kind = INT + + def __init__(self, size, offsets, descrs): + self.size = size + self.offsets = offsets + self.descrs = descrs + + @specialize.argtype(1) + def allocate_int(self, decoder, index): + length = len(self.fieldnums) + buffer = decoder.allocate_raw_buffer(self.size) + decoder.virtuals_cache.set_int(index, buffer) + for i in range(len(self.offsets)): + offset = self.offsets[i] + descr = self.descrs[i] + decoder.setrawbuffer_item(buffer, self.fieldnums[i], offset, descr) + return buffer + + def debug_prints(self): + debug_print("\tvrawbufferinfo", " at ", compute_unique_id(self)) + for i in self.fieldnums: + debug_print("\t\t", str(untag(i))) + + class VArrayStructInfo(AbstractVirtualInfo): def __init__(self, arraydescr, fielddescrs): self.arraydescr = arraydescr @@ -554,7 +583,7 @@ @specialize.argtype(1) def allocate(self, decoder, index): array = decoder.allocate_array(len(self.fielddescrs), self.arraydescr) - decoder.virtuals_cache[index] = array + decoder.virtuals_cache.set_ptr(index, array) p = 0 for i in range(len(self.fielddescrs)): for j in range(len(self.fielddescrs[i])): @@ -571,7 +600,7 @@ def allocate(self, decoder, index): length = len(self.fieldnums) string = decoder.allocate_string(length) - decoder.virtuals_cache[index] = string + decoder.virtuals_cache.set_ptr(index, string) for i in range(length): charnum = self.fieldnums[i] if not tagged_eq(charnum, UNINITIALIZED): @@ -593,7 +622,7 @@ # efficient. Not sure we care. left, right = self.fieldnums string = decoder.concat_strings(left, right) - decoder.virtuals_cache[index] = string + decoder.virtuals_cache.set_ptr(index, string) return string def debug_prints(self): @@ -609,7 +638,7 @@ def allocate(self, decoder, index): largerstr, start, length = self.fieldnums string = decoder.slice_string(largerstr, start, length) - decoder.virtuals_cache[index] = string + decoder.virtuals_cache.set_ptr(index, string) return string def debug_prints(self): @@ -626,7 +655,7 @@ def allocate(self, decoder, index): length = len(self.fieldnums) string = decoder.allocate_unicode(length) - decoder.virtuals_cache[index] = string + decoder.virtuals_cache.set_ptr(index, string) for i in range(length): charnum = self.fieldnums[i] if not tagged_eq(charnum, UNINITIALIZED): @@ -648,7 +677,7 @@ # efficient. Not sure we care. left, right = self.fieldnums string = decoder.concat_unicodes(left, right) - decoder.virtuals_cache[index] = string + decoder.virtuals_cache.set_ptr(index, string) return string def debug_prints(self): @@ -665,7 +694,7 @@ def allocate(self, decoder, index): largerstr, start, length = self.fieldnums string = decoder.slice_unicode(largerstr, start, length) - decoder.virtuals_cache[index] = string + decoder.virtuals_cache.set_ptr(index, string) return string def debug_prints(self): @@ -675,6 +704,33 @@ # ____________________________________________________________ +class AbstractVirtualCache(object): + pass + +def get_VirtualCache_class(suffix): + # we need to create two copy of this class, because virtuals_*_cache will + # be lists of different types (one for ResumeDataDirectReader and one for + # ResumeDataBoxReader) + class VirtualCache(AbstractVirtualCache): + def __init__(self, virtuals_ptr_cache, virtuals_int_cache): + self.virtuals_ptr_cache = virtuals_ptr_cache + self.virtuals_int_cache = virtuals_int_cache + + def get_ptr(self, i): + return self.virtuals_ptr_cache[i] + + def get_int(self, i): + return self.virtuals_int_cache[i] + + def set_ptr(self, i, v): + self.virtuals_ptr_cache[i] = v + + def set_int(self, i, v): + self.virtuals_int_cache[i] = v + + VirtualCache.__name__ += suffix + return VirtualCache + class AbstractResumeDataReader(object): """A base mixin containing the logic to reconstruct virtuals out of guard failure. There are two implementations of this mixin: @@ -685,7 +741,9 @@ _mixin_ = True rd_virtuals = None virtuals_cache = None - virtual_default = None + virtual_ptr_default = None + virtual_int_default = None + def _init(self, cpu, storage): self.cpu = cpu @@ -697,31 +755,50 @@ self._prepare_virtuals(storage.rd_virtuals) self._prepare_pendingfields(storage.rd_pendingfields) - def getvirtual(self, index): + def getvirtual_ptr(self, index): # Returns the index'th virtual, building it lazily if needed. # Note that this may be called recursively; that's why the # allocate() methods must fill in the cache as soon as they # have the object, before they fill its fields. assert self.virtuals_cache is not None - v = self.virtuals_cache[index] + v = self.virtuals_cache.get_ptr(index) if not v: assert self.rd_virtuals is not None v = self.rd_virtuals[index].allocate(self, index) - ll_assert(v == self.virtuals_cache[index], "resume.py: bad cache") + ll_assert(v == self.virtuals_cache.get_ptr(index), "resume.py: bad cache") + return v + + def getvirtual_int(self, index): + assert self.virtuals_cache is not None + v = self.virtuals_cache.get_int(index) + if not v: + v = self.rd_virtuals[index].allocate_int(self, index) + ll_assert(v == self.virtuals_cache.get_int(index), "resume.py: bad cache") return v def force_all_virtuals(self): rd_virtuals = self.rd_virtuals if rd_virtuals: for i in range(len(rd_virtuals)): - if rd_virtuals[i] is not None: - self.getvirtual(i) + rd_virtual = rd_virtuals[i] + if rd_virtual is not None: + if rd_virtual.kind == REF: + self.getvirtual_ptr(i) + elif rd_virtual.kind == INT: + self.getvirtual_int(i) + else: + assert False return self.virtuals_cache def _prepare_virtuals(self, virtuals): if virtuals: self.rd_virtuals = virtuals - self.virtuals_cache = [self.virtual_default] * len(virtuals) + # XXX: this is suboptimal, because we are creating two lists, one + # for REFs and one for INTs: but for each index, we are using + # either one or the other, so we should think of a way to + # "compact" them + self.virtuals_cache = self.VirtualCache([self.virtual_ptr_default] * len(virtuals), + [self.virtual_int_default] * len(virtuals)) def _prepare_pendingfields(self, pendingfields): if pendingfields: @@ -791,6 +868,7 @@ class ResumeDataBoxReader(AbstractResumeDataReader): unique_id = lambda: None + VirtualCache = get_VirtualCache_class('BoxReader') def __init__(self, storage, deadframe, metainterp): self._init(metainterp.cpu, storage) @@ -848,6 +926,12 @@ return self.metainterp.execute_and_record(rop.NEW_ARRAY, arraydescr, ConstInt(length)) + def allocate_raw_buffer(self, size): + cic = self.metainterp.staticdata.callinfocollection + calldescr, func = cic.callinfo_for_oopspec(EffectInfo.OS_RAW_MALLOC_VARSIZE_CHAR) + return self.metainterp.execute_and_record_varargs( + rop.CALL, [ConstInt(func), ConstInt(size)], calldescr) + def allocate_string(self, length): return self.metainterp.execute_and_record(rop.NEWSTR, None, ConstInt(length)) @@ -941,6 +1025,17 @@ arraydescr, arraybox, ConstInt(index), itembox) From noreply at buildbot.pypy.org Thu Apr 11 13:53:28 2013 From: noreply at buildbot.pypy.org (antocuni) Date: Thu, 11 Apr 2013 13:53:28 +0200 (CEST) Subject: [pypy-commit] pypy default: fix test_whatsnew Message-ID: <20130411115328.D37981C0F12@cobra.cs.uni-duesseldorf.de> Author: Antonio Cuni Branch: Changeset: r63228:8cb41911f59c Date: 2013-04-11 12:53 +0100 http://bitbucket.org/pypy/pypy/changeset/8cb41911f59c/ Log: fix test_whatsnew diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -46,6 +46,10 @@ Fix a bug which casused cffi to return the wrong result when calling a C function which calls a Python callback which forces the frames +.. branch: virtual-raw-mallocs +JIT optimizations which makes cffi calls even faster, by removing the need to +allocate a temporary buffer where to store the arguments. + .. branches we don't care about .. branch: autoreds .. branch: reflex-support From noreply at buildbot.pypy.org Thu Apr 11 15:43:14 2013 From: noreply at buildbot.pypy.org (fijal) Date: Thu, 11 Apr 2013 15:43:14 +0200 (CEST) Subject: [pypy-commit] extradoc extradoc: A draft for a blog post Message-ID: <20130411134314.52DA11C0F12@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: extradoc Changeset: r4965:415fa824cb16 Date: 2013-04-11 15:43 +0200 http://bitbucket.org/pypy/extradoc/changeset/415fa824cb16/ Log: A draft for a blog post diff --git a/blog/draft/web-server-survey.rst b/blog/draft/web-server-survey.rst new file mode 100644 --- /dev/null +++ b/blog/draft/web-server-survey.rst @@ -0,0 +1,104 @@ + +Hello everyone. + +This is a small survey of performance of various wsgi servers available +under CPython and PyPy. Note that while this is of high interest to me, since +it stressed the underlaying runtime quite a lot, there is a high chance +the underlaying web server really does not matter all that much for the +performance of your application. **Measure** first if the web server is +actually the problem. + +The actual benchmark consists of sending a `relatively complex HTTP query`_ +(which is roughly what chrome sends by default if issuing a GET) and +then awaiting response without keeping the connection alive. I wrote +a very crude `benchmarking tool`_ and I would not recommend anyone using it. +In principle, it's broken and assumes fragmentation of packages that happened +to happen on my test machine, but will not happen in the wild. I suggest use +`locust.io`_ or similar. The benchmarks can be found inside +`asynchammer's repository`_. Note that this is precisely a benchmark of +pure (or mostly in case of gevent) Python web servers. In this stupid benchmark, +if you run uWSGI and CPython, it'll be faster, because there is no Python code +involved (it just really executes one function). If you want to benchmark +a full web application, you should do just that and not only a server. + +The benchmarks were run like that:: + + python asynchammer.py --workers=4 --max=120000 --warmup=30000 --host=localhost: + +Using pypy. The servers were run either ``python`` ``example name`` or +``gunicorn -w 1 gunicorn_example:app``. In all cases the newest released +versions as of today were used, except gevent where a recent git clone +was used of gevent 1.0. Additionally PyPy version used `pypycore`_ for the +gevent loop. You run it like this: +``GEVENT_LOOP=pypycore.loop pypy gevent_example.py`` assuming everything is on +path. PyPy 2.0 beta 2 was used vs CPython 2.7.3. + +What this benchmark does? +------------------------- + +We issue 120k requests on a machine that has enough cores (and dies) to run +client and server relatively separated (there is no cache sharing between dies). +First 30k is discarded, in order to warm up the JIT, both on the client and +on the server side. +The requests are issued 10 at once (for each of the 4 workers) and then when +a request finishes, a new one is issued. The workers max out at around 11k req/s +which is what I could get out of apache serving static files. That amount of +load makes 2 apache processes run at around 150% CPU time each. All python +servers were run in a single process. I did run benchmark multiple times +to make sure that the results are at least roughly reproducible, but I did +not run any formal statistics. + +How relevant are those results for me? +-------------------------------------- + +If you're looking for a website performance enhancements, unlikely they're +any relevant. If you're getting (say) 500 req/s from a single worker on your +website, then the web server consumes less than 25% of the time. If you're +seeing numbers in thousands per second than very relevant. If you don't happen +to have benchmarks, then it really doesn't matter. + +CPython: + +twisted.web: 2300 +cyclone.io: 2400 +tornado: 3200 +gunicorn (sync): 3700 +gevent: 4100 +eventlet: 3200 + +PyPy: + +twisted.web: 8300 +cyclone: 7400 +tornado: 7600 +gunicorn (sync): 6900 +gevent: 6400 +eventlet: 6700 + +Giveaways +--------- + +There are a few obvious results. One is that parsing HTTP headers is quite +a bit of work. PyPy does some work there, but looking at traces it can clearly +be improved. Expect some work in that area. Another one is that an actual +choice of the web server does not quite matter what you choose (as long as it's +running under PyPy :)). Note that the difference here +is that we used a relatively real-life example of HTTP headers, as opposed +to ``ab`` which uses a very simple one. In the case of simple HTTP headers, +it matters more and you get drastically different results, which I'm not going +to publish because I claim they're even less relevant. + +It also looks like the choice for CPython and the choice for PyPy are quite +drastically different, with work from twisted folks helping us a lot, while +with CPython "running a loop in C" is still very important. + +To summarize, it seems that Python, and especially PyPy, is quite fast. +With 11k req/s, apache is running at around 300% CPU in total, +while none of the examples run above 120% CPU, which is normal CPU + +loopback costs. uWSGI in my benchmarks also scored + +I hope this will be one of the series of articles about +"how to compose a fast web stack using PyPy", but who knows what future holds. + +Cheers, +fijal From noreply at buildbot.pypy.org Thu Apr 11 15:59:51 2013 From: noreply at buildbot.pypy.org (sthalik) Date: Thu, 11 Apr 2013 15:59:51 +0200 (CEST) Subject: [pypy-commit] pypy unbreak-freebsd: Use proper linker script on all that is FreeBSD, not just 7.x Message-ID: <20130411135951.CB6571C0F12@cobra.cs.uni-duesseldorf.de> Author: Stanislaw Halik Branch: unbreak-freebsd Changeset: r63229:5689b2860a13 Date: 2013-04-11 15:34 +0200 http://bitbucket.org/pypy/pypy/changeset/5689b2860a13/ Log: Use proper linker script on all that is FreeBSD, not just 7.x diff --git a/rpython/translator/platform/posix.py b/rpython/translator/platform/posix.py --- a/rpython/translator/platform/posix.py +++ b/rpython/translator/platform/posix.py @@ -47,7 +47,7 @@ if not eci.export_symbols: return [] - if sys.platform == 'freebsd7': + if sys.platform.startswith('freebsd'): eci.export_symbols += ('__progname', 'environ') response_file = self._make_response_file("dynamic-symbols-") From noreply at buildbot.pypy.org Thu Apr 11 15:59:53 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Thu, 11 Apr 2013 15:59:53 +0200 (CEST) Subject: [pypy-commit] pypy default: Merged in sthalik/pypy/unbreak-freebsd (pull request #148) Message-ID: <20130411135953.087E21C0F12@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63230:42042ff3b88a Date: 2013-04-11 06:59 -0700 http://bitbucket.org/pypy/pypy/changeset/42042ff3b88a/ Log: Merged in sthalik/pypy/unbreak-freebsd (pull request #148) Use proper linker script on all that is FreeBSD, not just 7.x diff --git a/rpython/translator/platform/posix.py b/rpython/translator/platform/posix.py --- a/rpython/translator/platform/posix.py +++ b/rpython/translator/platform/posix.py @@ -47,7 +47,7 @@ if not eci.export_symbols: return [] - if sys.platform == 'freebsd7': + if sys.platform.startswith('freebsd'): eci.export_symbols += ('__progname', 'environ') response_file = self._make_response_file("dynamic-symbols-") From noreply at buildbot.pypy.org Thu Apr 11 16:09:55 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Thu, 11 Apr 2013 16:09:55 +0200 (CEST) Subject: [pypy-commit] pypy default: fix whatsnew Message-ID: <20130411140955.73B631C0149@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63231:d0619faead05 Date: 2013-04-11 10:09 -0400 http://bitbucket.org/pypy/pypy/changeset/d0619faead05/ Log: fix whatsnew diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -125,3 +125,4 @@ cffi implementation of sqlite3 .. branch: release-2.0-beta2 +.. branch: unbreak-freebsd From noreply at buildbot.pypy.org Thu Apr 11 16:58:21 2013 From: noreply at buildbot.pypy.org (bivab) Date: Thu, 11 Apr 2013 16:58:21 +0200 (CEST) Subject: [pypy-commit] pypy default: move shared code to llsupport Message-ID: <20130411145821.84F6B1C23C8@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63232:9482149b527a Date: 2013-04-11 16:56 +0200 http://bitbucket.org/pypy/pypy/changeset/9482149b527a/ Log: move shared code to llsupport diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -111,26 +111,6 @@ self.loop_run_counters.append(struct) return struct - @specialize.argtype(1) - def _inject_debugging_code(self, looptoken, operations, tp, number): - if self._debug: - # before doing anything, let's increase a counter - s = 0 - for op in operations: - s += op.getopnum() - looptoken._arm_debug_checksum = s - - newoperations = [] - self._append_debugging_code(newoperations, tp, number, - None) - for op in operations: - newoperations.append(op) - if op.getopnum() == rop.LABEL: - self._append_debugging_code(newoperations, 'l', number, - op.getdescr()) - operations = newoperations - return operations - @staticmethod def _release_gil_shadowstack(): before = rffi.aroundstate.before diff --git a/rpython/jit/backend/llsupport/assembler.py b/rpython/jit/backend/llsupport/assembler.py --- a/rpython/jit/backend/llsupport/assembler.py +++ b/rpython/jit/backend/llsupport/assembler.py @@ -8,6 +8,7 @@ from rpython.rlib.debug import (debug_start, debug_stop, have_debug_prints, debug_print) from rpython.rlib.rarithmetic import r_uint +from rpython.rlib.objectmodel import specialize from rpython.rtyper.annlowlevel import cast_instance_to_gcref from rpython.rtyper.lltypesystem import rffi, lltype @@ -214,6 +215,24 @@ # to incompatibilities in how it's done, we leave it for the # caller to deal with + @specialize.argtype(1) + def _inject_debugging_code(self, looptoken, operations, tp, number): + if self._debug: + s = 0 + for op in operations: + s += op.getopnum() + + newoperations = [] + self._append_debugging_code(newoperations, tp, number, + None) + for op in operations: + newoperations.append(op) + if op.getopnum() == rop.LABEL: + self._append_debugging_code(newoperations, 'l', number, + op.getdescr()) + operations = newoperations + return operations + def _append_debugging_code(self, operations, tp, number, token): counter = self._register_counter(tp, number, token) c_adr = ConstInt(rffi.cast(lltype.Signed, counter)) diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -743,24 +743,6 @@ targettoken._ll_loop_code += rawstart self.target_tokens_currently_compiling = None - @specialize.argtype(1) - def _inject_debugging_code(self, looptoken, operations, tp, number): - if self._debug: - s = 0 - for op in operations: - s += op.getopnum() - - newoperations = [] - self._append_debugging_code(newoperations, tp, number, - None) - for op in operations: - newoperations.append(op) - if op.getopnum() == rop.LABEL: - self._append_debugging_code(newoperations, 'l', number, - op.getdescr()) - operations = newoperations - return operations - def _assemble(self, regalloc, inputargs, operations): self._regalloc = regalloc regalloc.compute_hint_frame_locations(operations) From noreply at buildbot.pypy.org Thu Apr 11 17:11:53 2013 From: noreply at buildbot.pypy.org (bivab) Date: Thu, 11 Apr 2013 17:11:53 +0200 (CEST) Subject: [pypy-commit] pypy default: more backend cleanup Message-ID: <20130411151153.84CBD1C0149@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63233:5d1d12a617b0 Date: 2013-04-11 17:11 +0200 http://bitbucket.org/pypy/pypy/changeset/5d1d12a617b0/ Log: more backend cleanup diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -47,14 +47,8 @@ self.stack_check_slowpath = 0 self._debug = False self.loop_run_counters = [] - self.debug_counter_descr = cpu.fielddescrof(DEBUG_COUNTER, 'i') self.gcrootmap_retaddr_forced = 0 - def set_debug(self, v): - r = self._debug - self._debug = v - return r - def setup(self, looptoken): assert self.memcpy_addr != 0, 'setup_once() not called?' if we_are_translated(): @@ -80,37 +74,6 @@ def setup_failure_recovery(self): self.failure_recovery_code = [0, 0, 0, 0] - def finish_once(self): - if self._debug: - debug_start('jit-backend-counts') - for i in range(len(self.loop_run_counters)): - struct = self.loop_run_counters[i] - if struct.type == 'l': - prefix = 'TargetToken(%d)' % struct.number - elif struct.type == 'b': - prefix = 'bridge ' + str(struct.number) - else: - prefix = 'entry ' + str(struct.number) - debug_print(prefix + ':' + str(struct.i)) - debug_stop('jit-backend-counts') - - # XXX: merge with x86 - def _register_counter(self, tp, number, token): - # YYY very minor leak -- we need the counters to stay alive - # forever, just because we want to report them at the end - # of the process - struct = lltype.malloc(DEBUG_COUNTER, flavor='raw', - track_allocation=False) - struct.i = 0 - struct.type = tp - if tp == 'b' or tp == 'e': - struct.number = number - else: - assert token - struct.number = compute_unique_id(token) - self.loop_run_counters.append(struct) - return struct - @staticmethod def _release_gil_shadowstack(): before = rffi.aroundstate.before diff --git a/rpython/jit/backend/llsupport/assembler.py b/rpython/jit/backend/llsupport/assembler.py --- a/rpython/jit/backend/llsupport/assembler.py +++ b/rpython/jit/backend/llsupport/assembler.py @@ -8,7 +8,7 @@ from rpython.rlib.debug import (debug_start, debug_stop, have_debug_prints, debug_print) from rpython.rlib.rarithmetic import r_uint -from rpython.rlib.objectmodel import specialize +from rpython.rlib.objectmodel import specialize, compute_unique_id from rpython.rtyper.annlowlevel import cast_instance_to_gcref from rpython.rtyper.lltypesystem import rffi, lltype @@ -63,6 +63,8 @@ self.cpu = cpu self.memcpy_addr = 0 self.rtyper = cpu.rtyper + self.debug_counter_descr = cpu.fielddescrof(DEBUG_COUNTER, 'i') + self._debug = False def setup_once(self): # the address of the function called by 'new' @@ -100,6 +102,11 @@ track_allocation=False) self.gcmap_for_finish[0] = r_uint(1) + def set_debug(self, v): + r = self._debug + self._debug = v + return r + def rebuild_faillocs_from_descr(self, descr, inputargs): locs = [] GPR_REGS = len(self.cpu.gen_regs) @@ -245,6 +252,37 @@ None, descr=self.debug_counter_descr)] operations.extend(ops) + def _register_counter(self, tp, number, token): + # YYY very minor leak -- we need the counters to stay alive + # forever, just because we want to report them at the end + # of the process + struct = lltype.malloc(DEBUG_COUNTER, flavor='raw', + track_allocation=False) + struct.i = 0 + struct.type = tp + if tp == 'b' or tp == 'e': + struct.number = number + else: + assert token + struct.number = compute_unique_id(token) + self.loop_run_counters.append(struct) + return struct + + def finish_once(self): + if self._debug: + debug_start('jit-backend-counts') + for i in range(len(self.loop_run_counters)): + struct = self.loop_run_counters[i] + if struct.type == 'l': + prefix = 'TargetToken(%d)' % struct.number + elif struct.type == 'b': + prefix = 'bridge ' + str(struct.number) + else: + prefix = 'entry ' + str(struct.number) + debug_print(prefix + ':' + str(struct.i)) + debug_stop('jit-backend-counts') + + def debug_bridge(descr_number, rawstart, codeendpos): debug_start("jit-backend-addr") diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -23,7 +23,7 @@ r12, r13, r14, r15, X86_64_SCRATCH_REG, X86_64_XMM_SCRATCH_REG, RegLoc, FrameLoc, ConstFloatLoc, ImmedLoc, AddressLoc, imm, imm0, imm1, FloatImmedLoc, RawEbpLoc, RawEspLoc) -from rpython.rlib.objectmodel import we_are_translated, specialize +from rpython.rlib.objectmodel import we_are_translated from rpython.jit.backend.x86 import rx86, codebuf from rpython.jit.metainterp.resoperation import rop from rpython.jit.backend.x86 import support @@ -62,18 +62,11 @@ self.malloc_slowpath = 0 self.wb_slowpath = [0, 0, 0, 0, 0] self.setup_failure_recovery() - self._debug = False - self.debug_counter_descr = cpu.fielddescrof(DEBUG_COUNTER, 'i') self.datablockwrapper = None self.stack_check_slowpath = 0 self.propagate_exception_path = 0 self.teardown() - def set_debug(self, v): - r = self._debug - self._debug = v - return r - def setup_once(self): BaseAssembler.setup_once(self) if self.cpu.supports_floats: @@ -103,20 +96,6 @@ self.mc = None self.current_clt = None - def finish_once(self): - if self._debug: - debug_start('jit-backend-counts') - for i in range(len(self.loop_run_counters)): - struct = self.loop_run_counters[i] - if struct.type == 'l': - prefix = 'TargetToken(%d)' % struct.number - elif struct.type == 'b': - prefix = 'bridge ' + str(struct.number) - else: - prefix = 'entry ' + str(struct.number) - debug_print(prefix + ':' + str(struct.i)) - debug_stop('jit-backend-counts') - def _build_float_constants(self): datablockwrapper = MachineDataBlockWrapper(self.cpu.asmmemmgr, []) float_constants = datablockwrapper.malloc_aligned(32, alignment=16) @@ -698,22 +677,6 @@ allblocks = self.get_asmmemmgr_blocks(looptoken) return self.mc.materialize(self.cpu.asmmemmgr, allblocks, self.cpu.gc_ll_descr.gcrootmap) - - def _register_counter(self, tp, number, token): - # YYY very minor leak -- we need the counters to stay alive - # forever, just because we want to report them at the end - # of the process - struct = lltype.malloc(DEBUG_COUNTER, flavor='raw', - track_allocation=False) - struct.i = 0 - struct.type = tp - if tp == 'b' or tp == 'e': - struct.number = number - else: - assert token - struct.number = compute_unique_id(token) - self.loop_run_counters.append(struct) - return struct def patch_jump_for_descr(self, faildescr, adr_new_target): adr_jump_offset = faildescr._x86_adr_jump_offset From noreply at buildbot.pypy.org Thu Apr 11 18:45:38 2013 From: noreply at buildbot.pypy.org (rlamy) Date: Thu, 11 Apr 2013 18:45:38 +0200 (CEST) Subject: [pypy-commit] pypy longdouble2: Clean up remnants of NonNativeXXX Message-ID: <20130411164538.AFF421C0149@cobra.cs.uni-duesseldorf.de> Author: Ronan Lamy Branch: longdouble2 Changeset: r63234:1229ee4da9dc Date: 2013-04-11 17:44 +0100 http://bitbucket.org/pypy/pypy/changeset/1229ee4da9dc/ Log: Clean up remnants of NonNativeXXX diff --git a/pypy/module/micronumpy/types.py b/pypy/module/micronumpy/types.py --- a/pypy/module/micronumpy/types.py +++ b/pypy/module/micronumpy/types.py @@ -329,9 +329,6 @@ def min(self, v1, v2): return min(v1, v2) -class NonNativePrimitive(Primitive): - _mixin_ = True - class Bool(BaseType, Primitive): _attrs_ = () @@ -419,7 +416,6 @@ return 1 return 0 -NonNativeBool = Bool class Integer(Primitive): _mixin_ = True @@ -540,22 +536,17 @@ def signbit(self, v): return v < 0 -class NonNativeInteger(NonNativePrimitive, Integer): - _mixin_ = True - class Int8(BaseType, Integer): _attrs_ = () spec = int8_spec BoxType = interp_boxes.W_Int8Box format_code = "b" -NonNativeInt8 = Int8 class UInt8(BaseType, Integer): _attrs_ = () spec = uint8_spec BoxType = interp_boxes.W_UInt8Box format_code = "B" -NonNativeUInt8 = UInt8 class Int16(BaseType, Integer): _attrs_ = () @@ -563,113 +554,55 @@ BoxType = interp_boxes.W_Int16Box format_code = "h" -class NonNativeInt16(BaseType, NonNativeInteger): - _attrs_ = () - spec = int16_spec - BoxType = interp_boxes.W_Int16Box - format_code = "h" - class UInt16(BaseType, Integer): _attrs_ = () spec = uint16_spec BoxType = interp_boxes.W_UInt16Box format_code = "H" -class NonNativeUInt16(BaseType, NonNativeInteger): - _attrs_ = () - spec = uint16_spec - BoxType = interp_boxes.W_UInt16Box - format_code = "H" - class Int32(BaseType, Integer): _attrs_ = () spec = int32_spec BoxType = interp_boxes.W_Int32Box format_code = "i" -class NonNativeInt32(BaseType, NonNativeInteger): - _attrs_ = () - spec = int32_spec - BoxType = interp_boxes.W_Int32Box - format_code = "i" - class UInt32(BaseType, Integer): _attrs_ = () spec = uint32_spec BoxType = interp_boxes.W_UInt32Box format_code = "I" -class NonNativeUInt32(BaseType, NonNativeInteger): - _attrs_ = () - spec = uint32_spec - BoxType = interp_boxes.W_UInt32Box - format_code = "I" - class Long(BaseType, Integer): _attrs_ = () spec = long_spec BoxType = interp_boxes.W_LongBox format_code = "l" -class NonNativeLong(BaseType, NonNativeInteger): - _attrs_ = () - spec = long_spec - BoxType = interp_boxes.W_LongBox - format_code = "l" - class ULong(BaseType, Integer): _attrs_ = () spec = ulong_spec BoxType = interp_boxes.W_ULongBox format_code = "L" -class NonNativeULong(BaseType, NonNativeInteger): - _attrs_ = () - spec = ulong_spec - BoxType = interp_boxes.W_ULongBox - format_code = "L" - -def _int64_coerce(self, space, w_item): - try: - return self._base_coerce(space, w_item) - except OperationError, e: - if not e.match(space, space.w_OverflowError): - raise - bigint = space.bigint_w(w_item) - try: - value = bigint.tolonglong() - except OverflowError: - raise OperationError(space.w_OverflowError, space.w_None) - return self.box(value) - class Int64(BaseType, Integer): _attrs_ = () spec = int64_spec BoxType = interp_boxes.W_Int64Box format_code = "q" - _coerce = func_with_new_name(_int64_coerce, '_coerce') + def _coerce(self, space, w_item): + try: + return self._base_coerce(space, w_item) + except OperationError, e: + if not e.match(space, space.w_OverflowError): + raise + bigint = space.bigint_w(w_item) + try: + value = bigint.tolonglong() + except OverflowError: + raise OperationError(space.w_OverflowError, space.w_None) + return self.box(value) -class NonNativeInt64(BaseType, NonNativeInteger): - _attrs_ = () - spec = int64_spec - BoxType = interp_boxes.W_Int64Box - format_code = "q" - - _coerce = func_with_new_name(_int64_coerce, '_coerce') - -def _uint64_coerce(self, space, w_item): - try: - return self._base_coerce(space, w_item) - except OperationError, e: - if not e.match(space, space.w_OverflowError): - raise - bigint = space.bigint_w(w_item) - try: - value = bigint.toulonglong() - except OverflowError: - raise OperationError(space.w_OverflowError, space.w_None) - return self.box(value) class UInt64(BaseType, Integer): _attrs_ = () @@ -677,15 +610,19 @@ BoxType = interp_boxes.W_UInt64Box format_code = "Q" - _coerce = func_with_new_name(_uint64_coerce, '_coerce') + def _coerce(self, space, w_item): + try: + return self._base_coerce(space, w_item) + except OperationError, e: + if not e.match(space, space.w_OverflowError): + raise + bigint = space.bigint_w(w_item) + try: + value = bigint.toulonglong() + except OverflowError: + raise OperationError(space.w_OverflowError, space.w_None) + return self.box(value) -class NonNativeUInt64(BaseType, NonNativeInteger): - _attrs_ = () - spec = uint64_spec - BoxType = interp_boxes.W_UInt64Box - format_code = "Q" - - _coerce = func_with_new_name(_uint64_coerce, '_coerce') class Float(Primitive): _mixin_ = True @@ -1519,15 +1456,11 @@ BoxType = interp_boxes.W_Complex64Box FloatType = Float32_instance -NonNativeComplex64 = Complex64 - class Complex128(ComplexFloating, BaseType): _attrs_ = () BoxType = interp_boxes.W_Complex128Box FloatType = Float64_instance -NonNativeComplex128 = Complex128 - if interp_boxes.ENABLED_LONG_DOUBLE and interp_boxes.long_double_size > 8: class Float80(BaseType, Float): _attrs_ = () @@ -1546,14 +1479,11 @@ pack_float80(result, value, 10, not native_is_bigendian) return self.box(unpack_float80(result.build(), native_is_bigendian)) Float80_instance = Float80() - NonNativeFloat80 = Float80 - class Complex160(ComplexFloating, BaseType): _attrs_ = () BoxType = interp_boxes.W_CLongDoubleBox FloatType = Float80_instance - NonNativeComplex160 = Complex160 if interp_boxes.long_double_size in (12, 16): Float80.storage_bytes = interp_boxes.long_double_size @@ -1639,16 +1569,10 @@ class VoidType(BaseType, BaseStringType): T = lltype.Char -NonNativeVoidType = VoidType -NonNativeStringType = StringType - class UnicodeType(BaseType, BaseStringType): T = lltype.UniChar -NonNativeUnicodeType = UnicodeType - class RecordType(BaseType): - T = lltype.Char def __init__(self, offsets_and_fields, size): From noreply at buildbot.pypy.org Thu Apr 11 19:09:02 2013 From: noreply at buildbot.pypy.org (fijal) Date: Thu, 11 Apr 2013 19:09:02 +0200 (CEST) Subject: [pypy-commit] pypy improve-docs-2: shuffle stuff around Message-ID: <20130411170902.B91C61C030D@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: improve-docs-2 Changeset: r63235:2c6afe71e2e8 Date: 2013-04-11 19:08 +0200 http://bitbucket.org/pypy/pypy/changeset/2c6afe71e2e8/ Log: shuffle stuff around diff --git a/pypy/doc/index.rst b/pypy/doc/index.rst --- a/pypy/doc/index.rst +++ b/pypy/doc/index.rst @@ -49,6 +49,9 @@ * `potential project ideas`_: In case you want to get your feet wet... +* `more stuff`_: this is a collection of documentation that's there, but not + particularly organized + Documentation for the PyPy Python Interpreter ============================================= @@ -112,202 +115,6 @@ .. _`speed.pypy.org`: http://speed.pypy.org .. _`RPython toolchain`: translation.html .. _`potential project ideas`: project-ideas.html - -Project Documentation -===================================== - -`architecture`_ gives a complete view of PyPy's basic design. - -`coding guide`_ helps you to write code for PyPy (especially also describes -coding in RPython a bit). - -`sprint reports`_ lists reports written at most of our sprints, from -2003 to the present. - -`papers, talks and related projects`_ lists presentations -and related projects as well as our published papers. - -`PyPy video documentation`_ is a page linking to the videos (e.g. of talks and -introductions) that are available. - -`Technical reports`_ is a page that contains links to the -reports that we submitted to the European Union. - -`development methodology`_ describes our sprint-driven approach. - -`LICENSE`_ contains licensing details (basically a straight MIT-license). - -`Glossary`_ of PyPy words to help you align your inner self with -the PyPy universe. - -Status -=================================== - -PyPy can be used to run Python programs on Linux, OS/X, -Windows. -To dig into PyPy it is recommended to try out the current -Mercurial default branch, which is always working or mostly working, -instead of the latest release, which is `2.0 beta1`__. - -.. __: release-2.0.0-beta1.html - -PyPy is mainly developed on Linux and Mac OS X. Windows is supported, -but platform-specific bugs tend to take longer before we notice and fix -them. Linux 64-bit machines are supported (though it may also take some -time before we notice and fix bugs). - -PyPy's own tests `summary`_, daily updated, run through BuildBot infrastructure. -You can also find CPython's compliance tests run with compiled ``pypy-c`` -executables there. - - -Source Code Documentation -=============================================== - -`object spaces`_ discusses the object space interface -and several implementations. - -`bytecode interpreter`_ explains the basic mechanisms -of the bytecode interpreter and virtual machine. - -`interpreter optimizations`_ describes our various strategies for -improving the performance of our interpreter, including alternative -object implementations (for strings, dictionaries and lists) in the -standard object space. - -`translation`_ is a detailed overview of our translation process. The -rtyper_ is the largest component of our translation process. - -`dynamic-language translation`_ is a paper that describes -the translation process, especially the flow object space -and the annotator in detail. (This document is one -of the `EU reports`_.) - -`low-level encapsulation`_ describes how our approach hides -away a lot of low level details. This document is also part -of the `EU reports`_. - -`translation aspects`_ describes how we weave different -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. - -`rlib`_ describes some modules that can be used when implementing programs in -RPython. - -`configuration documentation`_ describes the various configuration options that -allow you to customize PyPy. - -`pypy on windows`_ - -`command line reference`_ - -`CLI backend`_ describes the details of the .NET backend. - -`JIT Generation in PyPy`_ describes how we produce the Python Just-in-time Compiler -from our Python interpreter. - -`directory cross-reference`_ - -.. _`garbage collector`: garbage_collection.html -.. _`directory cross-reference`: dir-reference.html -.. _`pypy on windows`: windows.html -.. _`command line reference`: commandline_ref.html -.. _`FAQ`: faq.html -.. _Glossary: glossary.html -.. _`PyPy video documentation`: video-index.html -.. _parser: parser.html -.. _`development methodology`: dev_method.html -.. _`sprint reports`: sprint-reports.html -.. _`papers, talks and related projects`: extradoc.html -.. _`object spaces`: objspace.html -.. _`interpreter optimizations`: interpreter-optimizations.html -.. _`translation`: translation.html -.. _`dynamic-language translation`: https://bitbucket.org/pypy/extradoc/raw/tip/eu-report/D05.1_Publish_on_translating_a_very-high-level_description.pdf -.. _`low-level encapsulation`: low-level-encapsulation.html -.. _`translation aspects`: translation-aspects.html -.. _`configuration documentation`: config/ -.. _`coding guide`: coding-guide.html -.. _`Architecture`: architecture.html -.. _`getting started`: getting-started.html -.. _`bytecode interpreter`: interpreter.html -.. _`EU reports`: index-report.html -.. _`Technical reports`: index-report.html -.. _`summary`: http://buildbot.pypy.org/summary -.. _`ideas for PyPy related projects`: project-ideas.html -.. _`Nightly builds and benchmarks`: http://tuatara.cs.uni-duesseldorf.de/benchmark.html -.. _`directory reference`: -.. _`rlib`: rlib.html -.. _`Sandboxing Python code`: sandbox.html -.. _`LICENSE`: https://bitbucket.org/pypy/pypy/src/default/LICENSE - -.. The following documentation is important and reasonably up-to-date: - -.. extradoc: should this be integrated one level up: dcolish? - -.. toctree:: - :maxdepth: 1 - :hidden: - - interpreter.rst - objspace.rst - __pypy__-module.rst - objspace-proxies.rst - config/index.rst - - dev_method.rst - extending.rst - - extradoc.rst - video-index.rst - - glossary.rst - - contributor.rst - - interpreter-optimizations.rst - configuration.rst - parser.rst - rlib.rst - rtyper.rst - rffi.rst - - translation.rst - jit/index.rst - jit/overview.rst - jit/pyjitpl5.rst - - index-of-release-notes.rst - - ctypes-implementation.rst - - how-to-release.rst - - index-report.rst - - stackless.rst - sandbox.rst - - discussions.rst - - cleanup.rst - - sprint-reports.rst - - eventhistory.rst - statistic/index.rst - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`search` -* :ref:`glossary` - +.. _`more stuff`: project-documentation.html .. include:: _ref.txt diff --git a/pypy/doc/project-documentation.rst b/pypy/doc/project-documentation.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/project-documentation.rst @@ -0,0 +1,177 @@ + +Project Documentation +===================================== + +`architecture`_ gives a complete view of PyPy's basic design. + +`coding guide`_ helps you to write code for PyPy (especially also describes +coding in RPython a bit). + +`sprint reports`_ lists reports written at most of our sprints, from +2003 to the present. + +`papers, talks and related projects`_ lists presentations +and related projects as well as our published papers. + +`PyPy video documentation`_ is a page linking to the videos (e.g. of talks and +introductions) that are available. + +`Technical reports`_ is a page that contains links to the +reports that we submitted to the European Union. + +`development methodology`_ describes our sprint-driven approach. + +`LICENSE`_ contains licensing details (basically a straight MIT-license). + +`Glossary`_ of PyPy words to help you align your inner self with +the PyPy universe. + +Source Code Documentation +=============================================== + +`object spaces`_ discusses the object space interface +and several implementations. + +`bytecode interpreter`_ explains the basic mechanisms +of the bytecode interpreter and virtual machine. + +`interpreter optimizations`_ describes our various strategies for +improving the performance of our interpreter, including alternative +object implementations (for strings, dictionaries and lists) in the +standard object space. + +`translation`_ is a detailed overview of our translation process. The +rtyper_ is the largest component of our translation process. + +`dynamic-language translation`_ is a paper that describes +the translation process, especially the flow object space +and the annotator in detail. (This document is one +of the `EU reports`_.) + +`low-level encapsulation`_ describes how our approach hides +away a lot of low level details. This document is also part +of the `EU reports`_. + +`translation aspects`_ describes how we weave different +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. + +`rlib`_ describes some modules that can be used when implementing programs in +RPython. + +`configuration documentation`_ describes the various configuration options that +allow you to customize PyPy. + +`pypy on windows`_ + +`command line reference`_ + +`CLI backend`_ describes the details of the .NET backend. + +`JIT Generation in PyPy`_ describes how we produce the Python Just-in-time Compiler +from our Python interpreter. + +`directory cross-reference`_ + +.. _`garbage collector`: garbage_collection.html +.. _`directory cross-reference`: dir-reference.html +.. _`pypy on windows`: windows.html +.. _`command line reference`: commandline_ref.html +.. _`FAQ`: faq.html +.. _Glossary: glossary.html +.. _`PyPy video documentation`: video-index.html +.. _parser: parser.html +.. _`development methodology`: dev_method.html +.. _`sprint reports`: sprint-reports.html +.. _`papers, talks and related projects`: extradoc.html +.. _`object spaces`: objspace.html +.. _`interpreter optimizations`: interpreter-optimizations.html +.. _`translation`: translation.html +.. _`dynamic-language translation`: https://bitbucket.org/pypy/extradoc/raw/tip/eu-report/D05.1_Publish_on_translating_a_very-high-level_description.pdf +.. _`low-level encapsulation`: low-level-encapsulation.html +.. _`translation aspects`: translation-aspects.html +.. _`configuration documentation`: config/ +.. _`coding guide`: coding-guide.html +.. _`Architecture`: architecture.html +.. _`getting started`: getting-started.html +.. _`bytecode interpreter`: interpreter.html +.. _`EU reports`: index-report.html +.. _`Technical reports`: index-report.html +.. _`summary`: http://buildbot.pypy.org/summary +.. _`ideas for PyPy related projects`: project-ideas.html +.. _`Nightly builds and benchmarks`: http://tuatara.cs.uni-duesseldorf.de/benchmark.html +.. _`directory reference`: +.. _`rlib`: rlib.html +.. _`Sandboxing Python code`: sandbox.html +.. _`LICENSE`: https://bitbucket.org/pypy/pypy/src/default/LICENSE + +.. The following documentation is important and reasonably up-to-date: + +.. extradoc: should this be integrated one level up: dcolish? + +.. toctree:: + :maxdepth: 1 + :hidden: + + interpreter.rst + objspace.rst + __pypy__-module.rst + objspace-proxies.rst + config/index.rst + + dev_method.rst + extending.rst + + extradoc.rst + video-index.rst + + glossary.rst + + contributor.rst + + interpreter-optimizations.rst + configuration.rst + parser.rst + rlib.rst + rtyper.rst + rffi.rst + + translation.rst + jit/index.rst + jit/overview.rst + jit/pyjitpl5.rst + + index-of-release-notes.rst + + ctypes-implementation.rst + + how-to-release.rst + + index-report.rst + + stackless.rst + sandbox.rst + + discussions.rst + + cleanup.rst + + sprint-reports.rst + + eventhistory.rst + statistic/index.rst + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`search` +* :ref:`glossary` + +.. include:: _ref.txt From noreply at buildbot.pypy.org Thu Apr 11 19:31:10 2013 From: noreply at buildbot.pypy.org (fijal) Date: Thu, 11 Apr 2013 19:31:10 +0200 (CEST) Subject: [pypy-commit] pypy improve-docs-2: change the sentence after alex suggestion Message-ID: <20130411173110.B512C1C3061@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: improve-docs-2 Changeset: r63237:106a992b99f0 Date: 2013-04-11 19:30 +0200 http://bitbucket.org/pypy/pypy/changeset/106a992b99f0/ Log: change the sentence after alex suggestion diff --git a/pypy/doc/how-to-contribute.rst b/pypy/doc/how-to-contribute.rst --- a/pypy/doc/how-to-contribute.rst +++ b/pypy/doc/how-to-contribute.rst @@ -21,8 +21,8 @@ of very high quality requirements for compilers and partly because there is simply no other way to get around such complex project, that will keep you sane. There are probably people out there who are smart enough not to need it, we're -not one of those. Familiarity with `pytest`_ is a must-have before -doing anything else. +not one of those. You may consider familiarizing yourself with `pytest`_, +since this is a tool we use for tests. This leads to the next issue: Layers From noreply at buildbot.pypy.org Thu Apr 11 19:42:19 2013 From: noreply at buildbot.pypy.org (fijal) Date: Thu, 11 Apr 2013 19:42:19 +0200 (CEST) Subject: [pypy-commit] pypy improve-docs-2: address a giant XXX, needs expanding but it's better than before Message-ID: <20130411174219.3212B1C016E@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: improve-docs-2 Changeset: r63238:a69e4ae03353 Date: 2013-04-11 19:42 +0200 http://bitbucket.org/pypy/pypy/changeset/a69e4ae03353/ Log: address a giant XXX, needs expanding but it's better than before diff --git a/pypy/doc/getting-started-dev.rst b/pypy/doc/getting-started-dev.rst --- a/pypy/doc/getting-started-dev.rst +++ b/pypy/doc/getting-started-dev.rst @@ -4,14 +4,50 @@ .. contents:: +RPython is a subset of Python that can be statically compiled. The PyPy +interpreter is written mostly in RPython (with pieces in Python), while +the RPython compiler is written in Python. The hard to understand part +is that Python is a meta-programming language for RPython, that is, +RPython is considered from live objects **after** the imports are done. +This might require more explanation. You start writing RPython from +``entry_point``, a good starting point is +``rpython/translator/goal/targetnopstandalone.py``. This does not do all that +much, but is a start. Now if code analyzed (in this case ``entry_point``) +calls some functions, those calls will be followed. Those followed calls +have to be RPython themselves (and everything they call etc.), however not +entire module files. To show how you can use metaprogramming, we can do +a silly example (note that closures are not RPython):: -This should really write a word of two about **WHAT** is RPython + def generator(operation): + if operation == 'add': + def f(a, b): + return a + b + else: + def f(a, b): + return a - b + return f -XXX ltratt blog post -XXX "how to write interpreters" links -XXX -XXX -XXX + add = generator('add') + sub = generator('sub') + + def entry_point(argv): + print add(sub(int(argv[1]), 3) 4) + return 0 + +In this example ``entry_point`` is RPython, ``add`` and ``sub`` are RPython, +however, ``generator`` is not. + +A good introductory level articles are available: + +* Laurence Tratt -- `Fast Enough VMs in Fast Enough Time`_. + +* `How to write interpreters in RPython`_ and `part 2`_ by Andrew Brown. + +.. _`Fast Enough VMs in Fast Enough Time`: http://tratt.net/laurie/tech_articles/articles/fast_enough_vms_in_fast_enough_time + +.. _`How to write interpreters in RPython`: http://morepypy.blogspot.com/2011/04/tutorial-writing-interpreter-with-pypy.html + +.. _`part 2`: http://morepypy.blogspot.com/2011/04/tutorial-part-2-adding-jit.html .. _`try out the translator`: From noreply at buildbot.pypy.org Thu Apr 11 19:43:38 2013 From: noreply at buildbot.pypy.org (fijal) Date: Thu, 11 Apr 2013 19:43:38 +0200 (CEST) Subject: [pypy-commit] pypy improve-docs-2: close to be merged branch Message-ID: <20130411174338.D4D631C016E@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: improve-docs-2 Changeset: r63239:31a216b51485 Date: 2013-04-11 19:42 +0200 http://bitbucket.org/pypy/pypy/changeset/31a216b51485/ Log: close to be merged branch From noreply at buildbot.pypy.org Thu Apr 11 19:43:40 2013 From: noreply at buildbot.pypy.org (fijal) Date: Thu, 11 Apr 2013 19:43:40 +0200 (CEST) Subject: [pypy-commit] pypy default: attack the docs Message-ID: <20130411174340.2942F1C016E@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r63240:41bbdcefb3ac Date: 2013-04-11 19:43 +0200 http://bitbucket.org/pypy/pypy/changeset/41bbdcefb3ac/ Log: attack the docs diff --git a/README.rst b/README.rst --- a/README.rst +++ b/README.rst @@ -13,9 +13,9 @@ http://pypy.org/ -The getting-started document will help guide you: +If you want to help developing PyPy, this document might help you: - http://doc.pypy.org/en/latest/getting-started.html + http://doc.pypy.org/ It will also point you to the rest of the documentation which is generated from files in the pypy/doc directory within the source repositories. Enjoy diff --git a/pypy/doc/dir-reference.rst b/pypy/doc/dir-reference.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/dir-reference.rst @@ -0,0 +1,140 @@ +PyPy directory cross-reference +------------------------------ + +Here is a fully referenced alphabetical two-level deep +directory overview of PyPy: + +================================= ============================================ +Directory explanation/links +================================= ============================================ +`pypy/bin/`_ command-line scripts, mainly + `pypy/bin/pyinteractive.py`_ + +`pypy/config/`_ handles the numerous options for building + and running PyPy + +`pypy/doc/`_ text versions of PyPy developer + documentation + +`pypy/doc/config/`_ documentation for the numerous translation + options + +`pypy/doc/discussion/`_ drafts of ideas and documentation + +``doc/*/`` other specific documentation topics or tools + +`pypy/interpreter/`_ `bytecode interpreter`_ and related objects + (frames, functions, modules,...) + +`pypy/interpreter/pyparser/`_ interpreter-level Python source parser + +`pypy/interpreter/astcompiler/`_ interpreter-level bytecode compiler, + via an AST representation + +`pypy/module/`_ contains `mixed modules`_ + implementing core modules with + both application and interpreter level code. + Not all are finished and working. Use + the ``--withmod-xxx`` + or ``--allworkingmodules`` translation + options. + +`pypy/objspace/`_ `object space`_ implementations + +`pypy/objspace/std/`_ the StdObjSpace_ implementing CPython's + objects and types + +`pypy/tool/`_ various utilities and hacks used + from various places + +`pypy/tool/algo/`_ general-purpose algorithmic and mathematic + tools + +`pypy/tool/pytest/`_ support code for our `testing methods`_ + + +`rpython/annotator/`_ `type inferencing code`_ for + `RPython`_ programs + +`rpython/config/`_ handles the numerous options for RPython + + +`rpython/flowspace/`_ the FlowObjSpace_ implementing + `abstract interpretation`_ + +`rpython/rlib/`_ a `"standard library"`_ for RPython_ + programs + +`rpython/rtyper/`_ the `RPython Typer`_ + +`rpython/rtyper/lltypesystem/`_ the `low-level type system`_ for + C-like backends + +`rpython/rtyper/ootypesystem/`_ the `object-oriented type system`_ + for OO backends + +`rpython/memory/`_ the `garbage collector`_ construction + framework + +`rpython/translator/`_ translation_ backends and support code + +`rpython/translator/backendopt/`_ general optimizations that run before a + backend generates code + +`rpython/translator/c/`_ the `GenC backend`_, producing C code + from an + RPython program (generally via the rtyper_) + +`rpython/translator/cli/`_ the `CLI backend`_ for `.NET`_ + (Microsoft CLR or Mono_) + +`pypy/goal/`_ our `main PyPy-translation scripts`_ + live here + +`rpython/translator/jvm/`_ the Java backend + +`rpython/translator/tool/`_ helper tools for translation + +`dotviewer/`_ `graph viewer`_ + +``*/test/`` many directories have a test subdirectory + containing test + modules (see `Testing in PyPy`_) + +``_cache/`` holds cache files from various purposes +================================= ============================================ + +.. _`bytecode interpreter`: interpreter.html +.. _`Testing in PyPy`: coding-guide.html#testing-in-pypy +.. _`mixed modules`: coding-guide.html#mixed-modules +.. _`modules`: coding-guide.html#modules +.. _`basil`: http://people.cs.uchicago.edu/~jriehl/BasilTalk.pdf +.. _`object space`: objspace.html +.. _FlowObjSpace: objspace.html#the-flow-object-space +.. _`transparent proxies`: objspace-proxies.html#tproxy +.. _`Differences between PyPy and CPython`: cpython_differences.html +.. _`What PyPy can do for your objects`: objspace-proxies.html +.. _`Continulets and greenlets`: stackless.html +.. _StdObjSpace: objspace.html#the-standard-object-space +.. _`abstract interpretation`: http://en.wikipedia.org/wiki/Abstract_interpretation +.. _`rpython`: coding-guide.html#rpython +.. _`type inferencing code`: translation.html#the-annotation-pass +.. _`RPython Typer`: translation.html#rpython-typer +.. _`testing methods`: coding-guide.html#testing-in-pypy +.. _`translation`: translation.html +.. _`GenC backend`: translation.html#genc +.. _`CLI backend`: cli-backend.html +.. _`py.py`: getting-started-python.html#the-py.py-interpreter +.. _`translatorshell.py`: getting-started-dev.html#try-out-the-translator +.. _JIT: jit/index.html +.. _`JIT Generation in PyPy`: jit/index.html +.. _`just-in-time compiler generator`: jit/index.html +.. _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 +.. _`main PyPy-translation scripts`: getting-started-python.html#translating-the-pypy-python-interpreter +.. _`.NET`: http://www.microsoft.com/net/ +.. _Mono: http://www.mono-project.com/ +.. _`"standard library"`: rlib.html +.. _`graph viewer`: getting-started-dev.html#try-out-the-translator diff --git a/pypy/doc/getting-started-dev.rst b/pypy/doc/getting-started-dev.rst --- a/pypy/doc/getting-started-dev.rst +++ b/pypy/doc/getting-started-dev.rst @@ -1,13 +1,58 @@ -=============================================================================== -Getting Started with the Translation Toolchain and Development Process -=============================================================================== +============================ +Getting Started with RPython +============================ .. contents:: +RPython is a subset of Python that can be statically compiled. The PyPy +interpreter is written mostly in RPython (with pieces in Python), while +the RPython compiler is written in Python. The hard to understand part +is that Python is a meta-programming language for RPython, that is, +RPython is considered from live objects **after** the imports are done. +This might require more explanation. You start writing RPython from +``entry_point``, a good starting point is +``rpython/translator/goal/targetnopstandalone.py``. This does not do all that +much, but is a start. Now if code analyzed (in this case ``entry_point``) +calls some functions, those calls will be followed. Those followed calls +have to be RPython themselves (and everything they call etc.), however not +entire module files. To show how you can use metaprogramming, we can do +a silly example (note that closures are not RPython):: + + def generator(operation): + if operation == 'add': + def f(a, b): + return a + b + else: + def f(a, b): + return a - b + return f + + add = generator('add') + sub = generator('sub') + + def entry_point(argv): + print add(sub(int(argv[1]), 3) 4) + return 0 + +In this example ``entry_point`` is RPython, ``add`` and ``sub`` are RPython, +however, ``generator`` is not. + +A good introductory level articles are available: + +* Laurence Tratt -- `Fast Enough VMs in Fast Enough Time`_. + +* `How to write interpreters in RPython`_ and `part 2`_ by Andrew Brown. + +.. _`Fast Enough VMs in Fast Enough Time`: http://tratt.net/laurie/tech_articles/articles/fast_enough_vms_in_fast_enough_time + +.. _`How to write interpreters in RPython`: http://morepypy.blogspot.com/2011/04/tutorial-writing-interpreter-with-pypy.html + +.. _`part 2`: http://morepypy.blogspot.com/2011/04/tutorial-part-2-adding-jit.html + .. _`try out the translator`: Trying out the translator -------------------------- +------------------------- The translator is a tool based on the PyPy interpreter which can translate sufficiently static RPython programs into low-level code (in particular it can @@ -28,7 +73,7 @@ >>> t = Translation(snippet.is_perfect_number, [int]) >>> t.view() - + After that, the graph viewer pops up, that lets you interactively inspect the flow graph. To move around, click on something that you want to inspect. To get help about how to use it, press 'H'. To close it again, press 'Q'. @@ -83,10 +128,10 @@ The object returned by ``compile_cli`` or ``compile_jvm`` is a wrapper around the real executable: the parameters are passed as command line arguments, and -the returned value is read from the standard output. +the returned value is read from the standard output. Once you have compiled the snippet, you can also try to launch the -executable directly from the shell. You will find the +executable directly from the shell. You will find the executable in one of the ``/tmp/usession-*`` directories:: # For CLI: diff --git a/pypy/doc/getting-started-python.rst b/pypy/doc/getting-started-python.rst --- a/pypy/doc/getting-started-python.rst +++ b/pypy/doc/getting-started-python.rst @@ -6,7 +6,7 @@ PyPy's Python interpreter is a very compliant Python -interpreter implemented in Python. When translated to C, it passes most of +interpreter implemented in RPython. When compiled, it passes most of `CPythons core language regression tests`_ and comes with many of the extension modules included in the standard library including ``ctypes``. It can run large libraries such as Django_ and Twisted_. There are some small behavioral @@ -147,6 +147,8 @@ Translating using the CLI backend +++++++++++++++++++++++++++++++++ +**Note: the CLI backend is no longer maintained** + To create a standalone .NET executable using the `CLI backend`_:: ./translate.py --backend=cli targetpypystandalone.py diff --git a/pypy/doc/how-to-contribute.rst b/pypy/doc/how-to-contribute.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/how-to-contribute.rst @@ -0,0 +1,78 @@ +How to contribute to PyPy +------------------------- + +This page describes how to contribute to the PyPy project. The first thing +to remember is that PyPy project is very different than most projects out there. +It's also different from a classic compiler project, so academic courses +about compilers often don't apply or lead in the wrong direction. + +Don't just hack +--------------- + +The first and most important rule how not to contribute to PyPy is +"just hacking". This won't work. There are two major reasons why not +-- build times are large and PyPy has very thick layer separation which +make it harder to "just hack a feature". + +Test driven development +----------------------- + +Instead, we practice a lot of test driven development. This is partly because +of very high quality requirements for compilers and partly because there is +simply no other way to get around such complex project, that will keep you sane. +There are probably people out there who are smart enough not to need it, we're +not one of those. You may consider familiarizing yourself with `pytest`_, +since this is a tool we use for tests. +This leads to the next issue: + +Layers +------ + +PyPy has layers. Those layers help us keep the respective parts separated enough +to be worked on independently and make the complexity manageable. This is, +again, just a sanity requirement for such a complex project. For example writing +a new optimization for the JIT usually does **not** involve touching a Python +interpreter at all or the JIT assembler backend or the garbage collector. +Instead it requires writing small tests in +``rpython/jit/metainterp/optimizeopt/test/test_*`` and fixing files there. +After that, you can just compile PyPy and things should just work. + +The short list of layers for further reading. For each of those layers, a good +entry point is a test subdirectory in respective directories. It usually +describes (better or worse) the interfaces between the submodules. For the +``pypy`` subdirectory, most tests are small snippets of python programs that +check for correctness (calls ``AppTestXxx``) that will call the appropriate +part of the interpreter. For the ``rpython`` directory, most tests are small +RPython interpreters that perform certain tasks. To see how they translate +to low-level graphs, run them with ``--view``. To see small interpreters +with a JIT compiler, use ``--viewloops`` option. + +* **python interpreter** - it's the part implemented in the ``pypy/`` directory. + It's implemented in RPython, which is a high level static language with + classes, garbage collection, just-in-time compiler generation and the ability + to call C. A cool part about it is that it can be run untranslated, so all + the tests are runnable without translating PyPy. + + **interpreter** contains the interpreter core + + **objspace** contains implementations of various objects exported to + the Python layer + + **module** directory contains extension modules written in RPython + +* **rpython compiler** that resides in ``rpython/annotator`` and + ``rpython/rtyper`` directories. Consult `introduction to RPython`_ for + further reading + +* **JIT generator** lives in ``rpython/jit`` directory. optimizations live + in ``rpython/jit/metainterp/optimizeopt``, the main JIT in + ``rpython/jit/metainterp`` (runtime part) and + ``rpython/jit/codewriter`` (translation-time part). Backends live in + ``rpython/jit/backend``. + +* **garbage collection** lives in ``rpython/memory`` + +The rest of directories serve specific niche goal and are unlikely a good +entry point. + +.. _`introduction to RPython`: getting-started-dev.rst diff --git a/pypy/doc/index.rst b/pypy/doc/index.rst --- a/pypy/doc/index.rst +++ b/pypy/doc/index.rst @@ -1,15 +1,39 @@ -Welcome to PyPy Development -============================================= +Welcome to PyPy +=============== -The PyPy project aims at producing a flexible and fast Python_ -implementation. The guiding idea is to translate a Python-level -description of the Python language itself to lower level languages. -Rumors have it that the secret goal is being faster-than-C which is -nonsense, isn't it? `more...`_ +The PyPy project aims to produce a flexible and fast Python_ +implementation. This page documents the development of the PyPy +project itself. If you don't know what PyPy is, consult the `PyPy +website`_. If you just want to use PyPy, consult the `download`_ page +and the `getting started with pypy`_ documents. If you want to help +develop PyPy -- keep reading! -Getting into PyPy ... -============================================= +PyPy is written in a language called `RPython`_, which is suitable for +writing dynamic language interpreters (and not much else). RPython is +a subset of Python and is itself written in Python. If you'd like to +learn more about RPython, `Starting with RPython`_ should provide a +reasonable overview. + +**If you would like to contribute to PyPy**, please read `how to +contribute`_ first. PyPy's development style is somewhat different to +that of many other software projects and it often surprises +newcomers. What is **not** necessary is an academic background from +university in writing compilers -- much of it does not apply to PyPy +any way. + +All of the documentation and source code is available under the MIT license, +unless otherwise specified. Consult `LICENSE`_ + +.. _`download`: http://pypy.org/download.html +.. _`getting started with pypy`: getting-started-python.html +.. _`RPython`: coding-guide.html#RPython +.. _`Starting with RPython`: getting-started-dev.html +.. _`how to contribute`: how-to-contribute.html +.. _`PyPy website`: http://pypy.org + +Index of various topics: +======================== * `Getting started`_: how to install and run the PyPy Python interpreter @@ -25,20 +49,32 @@ * `potential project ideas`_: In case you want to get your feet wet... +* `more stuff`_: this is a collection of documentation that's there, but not + particularly organized + Documentation for the PyPy Python Interpreter -=============================================== +============================================= New features of PyPy's Python Interpreter and Translation Framework: * `Differences between PyPy and CPython`_ - * `What PyPy can do for your objects`_ - * `Continulets and greenlets`_ + * `What PyPy can do for your objects`_ - transparent proxy documentation + * `Continulets and greenlets`_ - documentation about stackless features * `JIT Generation in PyPy`_ + * `JIT hooks`_ * `Sandboxing Python code`_ + * `Garbage collection environment variables`_ Status_ of the project. +.. _`Differences between PyPy and CPython`: cpython_differences.html +.. _`What PyPy can do for your objects`: objspace-proxies.html +.. _`Continulets and greenlets_`: stackless.html +.. _`JIT Generation in PyPy`: jit/index.html +.. _`JIT hooks`: jit-hooks.html +.. _`Sandboxing Python code`: sandbox.html +.. _`Garbage collection environment variables`: gc_info.html Mailing lists, bug tracker, IRC channel ============================================= @@ -79,354 +115,6 @@ .. _`speed.pypy.org`: http://speed.pypy.org .. _`RPython toolchain`: translation.html .. _`potential project ideas`: project-ideas.html - -Project Documentation -===================================== - -PyPy was funded by the EU for several years. See the `web site of the EU -project`_ for more details. - -.. _`web site of the EU project`: http://pypy.org - -architecture_ gives a complete view of PyPy's basic design. - -`coding guide`_ helps you to write code for PyPy (especially also describes -coding in RPython a bit). - -`sprint reports`_ lists reports written at most of our sprints, from -2003 to the present. - -`papers, talks and related projects`_ lists presentations -and related projects as well as our published papers. - -`PyPy video documentation`_ is a page linking to the videos (e.g. of talks and -introductions) that are available. - -`Technical reports`_ is a page that contains links to the -reports that we submitted to the European Union. - -`development methodology`_ describes our sprint-driven approach. - -`LICENSE`_ contains licensing details (basically a straight MIT-license). - -`Glossary`_ of PyPy words to help you align your inner self with -the PyPy universe. - - -Status -=================================== - -PyPy can be used to run Python programs on Linux, OS/X, -Windows, on top of .NET, and on top of Java. -To dig into PyPy it is recommended to try out the current -Mercurial default branch, which is always working or mostly working, -instead of the latest release, which is `2.0 beta1`__. - -.. __: release-2.0.0-beta1.html - -PyPy is mainly developed on Linux and Mac OS X. Windows is supported, -but platform-specific bugs tend to take longer before we notice and fix -them. Linux 64-bit machines are supported (though it may also take some -time before we notice and fix bugs). - -PyPy's own tests `summary`_, daily updated, run through BuildBot infrastructure. -You can also find CPython's compliance tests run with compiled ``pypy-c`` -executables there. - - -Source Code Documentation -=============================================== - -`object spaces`_ discusses the object space interface -and several implementations. - -`bytecode interpreter`_ explains the basic mechanisms -of the bytecode interpreter and virtual machine. - -`interpreter optimizations`_ describes our various strategies for -improving the performance of our interpreter, including alternative -object implementations (for strings, dictionaries and lists) in the -standard object space. - -`translation`_ is a detailed overview of our translation process. The -rtyper_ is the largest component of our translation process. - -`dynamic-language translation`_ is a paper that describes -the translation process, especially the flow object space -and the annotator in detail. (This document is one -of the `EU reports`_.) - -`low-level encapsulation`_ describes how our approach hides -away a lot of low level details. This document is also part -of the `EU reports`_. - -`translation aspects`_ describes how we weave different -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. - -`rlib`_ describes some modules that can be used when implementing programs in -RPython. - -`configuration documentation`_ describes the various configuration options that -allow you to customize PyPy. - -`CLI backend`_ describes the details of the .NET backend. - -`JIT Generation in PyPy`_ describes how we produce the Python Just-in-time Compiler -from our Python interpreter. - - - -.. _`FAQ`: faq.html -.. _Glossary: glossary.html -.. _`PyPy video documentation`: video-index.html -.. _parser: parser.html -.. _`development methodology`: dev_method.html -.. _`sprint reports`: sprint-reports.html -.. _`papers, talks and related projects`: extradoc.html -.. _`object spaces`: objspace.html -.. _`interpreter optimizations`: interpreter-optimizations.html -.. _`translation`: translation.html -.. _`dynamic-language translation`: https://bitbucket.org/pypy/extradoc/raw/tip/eu-report/D05.1_Publish_on_translating_a_very-high-level_description.pdf -.. _`low-level encapsulation`: low-level-encapsulation.html -.. _`translation aspects`: translation-aspects.html -.. _`configuration documentation`: config/ -.. _`coding guide`: coding-guide.html -.. _`architecture`: architecture.html -.. _`getting started`: getting-started.html -.. _`bytecode interpreter`: interpreter.html -.. _`EU reports`: index-report.html -.. _`Technical reports`: index-report.html -.. _`summary`: http://buildbot.pypy.org/summary -.. _`ideas for PyPy related projects`: project-ideas.html -.. _`Nightly builds and benchmarks`: http://tuatara.cs.uni-duesseldorf.de/benchmark.html -.. _`directory reference`: -.. _`rlib`: rlib.html -.. _`Sandboxing Python code`: sandbox.html -.. _`LICENSE`: https://bitbucket.org/pypy/pypy/src/default/LICENSE - -PyPy directory cross-reference ------------------------------- - -Here is a fully referenced alphabetical two-level deep -directory overview of PyPy: - -================================= ============================================ -Directory explanation/links -================================= ============================================ -`pypy/bin/`_ command-line scripts, mainly - `pypy/bin/pyinteractive.py`_ - -`pypy/config/`_ handles the numerous options for building - and running PyPy - -`pypy/doc/`_ text versions of PyPy developer - documentation - -`pypy/doc/config/`_ documentation for the numerous translation - options - -`pypy/doc/discussion/`_ drafts of ideas and documentation - -``doc/*/`` other specific documentation topics or tools - -`pypy/interpreter/`_ `bytecode interpreter`_ and related objects - (frames, functions, modules,...) - -`pypy/interpreter/pyparser/`_ interpreter-level Python source parser - -`pypy/interpreter/astcompiler/`_ interpreter-level bytecode compiler, - via an AST representation - -`pypy/module/`_ contains `mixed modules`_ - implementing core modules with - both application and interpreter level code. - Not all are finished and working. Use - the ``--withmod-xxx`` - or ``--allworkingmodules`` translation - options. - -`pypy/objspace/`_ `object space`_ implementations - -`pypy/objspace/std/`_ the StdObjSpace_ implementing CPython's - objects and types - -`pypy/tool/`_ various utilities and hacks used - from various places - -`pypy/tool/algo/`_ general-purpose algorithmic and mathematic - tools - -`pypy/tool/pytest/`_ support code for our `testing methods`_ - - -`rpython/annotator/`_ `type inferencing code`_ for - `RPython`_ programs - -`rpython/config/`_ handles the numerous options for RPython - - -`rpython/flowspace/`_ the FlowObjSpace_ implementing - `abstract interpretation`_ - -`rpython/rlib/`_ a `"standard library"`_ for RPython_ - programs - -`rpython/rtyper/`_ the `RPython Typer`_ - -`rpython/rtyper/lltypesystem/`_ the `low-level type system`_ for - C-like backends - -`rpython/rtyper/ootypesystem/`_ the `object-oriented type system`_ - for OO backends - -`rpython/memory/`_ the `garbage collector`_ construction - framework - -`rpython/translator/`_ translation_ backends and support code - -`rpython/translator/backendopt/`_ general optimizations that run before a - backend generates code - -`rpython/translator/c/`_ the `GenC backend`_, producing C code - from an - RPython program (generally via the rtyper_) - -`rpython/translator/cli/`_ the `CLI backend`_ for `.NET`_ - (Microsoft CLR or Mono_) - -`pypy/goal/`_ our `main PyPy-translation scripts`_ - live here - -`rpython/translator/jvm/`_ the Java backend - -`rpython/translator/tool/`_ helper tools for translation - -`dotviewer/`_ `graph viewer`_ - -``*/test/`` many directories have a test subdirectory - containing test - modules (see `Testing in PyPy`_) - -``_cache/`` holds cache files from various purposes -================================= ============================================ - -.. _`bytecode interpreter`: interpreter.html -.. _`Testing in PyPy`: coding-guide.html#testing-in-pypy -.. _`mixed modules`: coding-guide.html#mixed-modules -.. _`modules`: coding-guide.html#modules -.. _`basil`: http://people.cs.uchicago.edu/~jriehl/BasilTalk.pdf -.. _`object space`: objspace.html -.. _FlowObjSpace: objspace.html#the-flow-object-space -.. _`transparent proxies`: objspace-proxies.html#tproxy -.. _`Differences between PyPy and CPython`: cpython_differences.html -.. _`What PyPy can do for your objects`: objspace-proxies.html -.. _`Continulets and greenlets`: stackless.html -.. _StdObjSpace: objspace.html#the-standard-object-space -.. _`abstract interpretation`: http://en.wikipedia.org/wiki/Abstract_interpretation -.. _`rpython`: coding-guide.html#rpython -.. _`type inferencing code`: translation.html#the-annotation-pass -.. _`RPython Typer`: translation.html#rpython-typer -.. _`testing methods`: coding-guide.html#testing-in-pypy -.. _`translation`: translation.html -.. _`GenC backend`: translation.html#genc -.. _`CLI backend`: cli-backend.html -.. _`py.py`: getting-started-python.html#the-py.py-interpreter -.. _`translatorshell.py`: getting-started-dev.html#try-out-the-translator -.. _JIT: jit/index.html -.. _`JIT Generation in PyPy`: jit/index.html -.. _`just-in-time compiler generator`: jit/index.html -.. _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 -.. _`main PyPy-translation scripts`: getting-started-python.html#translating-the-pypy-python-interpreter -.. _`.NET`: http://www.microsoft.com/net/ -.. _Mono: http://www.mono-project.com/ -.. _`"standard library"`: rlib.html -.. _`graph viewer`: getting-started-dev.html#try-out-the-translator - - -.. The following documentation is important and reasonably up-to-date: - -.. extradoc: should this be integrated one level up: dcolish? - - -.. toctree:: - :maxdepth: 1 - :hidden: - - getting-started.rst - getting-started-python.rst - getting-started-dev.rst - windows.rst - faq.rst - commandline_ref.rst - architecture.rst - coding-guide.rst - cpython_differences.rst - garbage_collection.rst - gc_info.rst - interpreter.rst - objspace.rst - __pypy__-module.rst - objspace-proxies.rst - config/index.rst - - dev_method.rst - extending.rst - - extradoc.rst - video-index.rst - - glossary.rst - - contributor.rst - - interpreter-optimizations.rst - configuration.rst - parser.rst - rlib.rst - rtyper.rst - rffi.rst - - translation.rst - jit/index.rst - jit/overview.rst - jit/pyjitpl5.rst - - index-of-release-notes.rst - - ctypes-implementation.rst - - how-to-release.rst - - index-report.rst - - stackless.rst - sandbox.rst - - discussions.rst - - cleanup.rst - - sprint-reports.rst - - eventhistory.rst - statistic/index.rst - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`search` -* :ref:`glossary` - +.. _`more stuff`: project-documentation.html .. include:: _ref.txt diff --git a/pypy/doc/needswork.txt b/pypy/doc/needswork.txt deleted file mode 100644 --- a/pypy/doc/needswork.txt +++ /dev/null @@ -1,3 +0,0 @@ -.. warning:: - - This documentation needs work (as discussed during the Gothenburg sprint in 2011) diff --git a/pypy/doc/objspace-proxies.rst b/pypy/doc/objspace-proxies.rst --- a/pypy/doc/objspace-proxies.rst +++ b/pypy/doc/objspace-proxies.rst @@ -5,7 +5,6 @@ .. contents:: - Thanks to the `Object Space`_ architecture, any feature that is based on proxying, extending, changing or otherwise controlling the behavior of all objects in a running program is easy to implement on diff --git a/pypy/doc/project-documentation.rst b/pypy/doc/project-documentation.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/project-documentation.rst @@ -0,0 +1,177 @@ + +Project Documentation +===================================== + +`architecture`_ gives a complete view of PyPy's basic design. + +`coding guide`_ helps you to write code for PyPy (especially also describes +coding in RPython a bit). + +`sprint reports`_ lists reports written at most of our sprints, from +2003 to the present. + +`papers, talks and related projects`_ lists presentations +and related projects as well as our published papers. + +`PyPy video documentation`_ is a page linking to the videos (e.g. of talks and +introductions) that are available. + +`Technical reports`_ is a page that contains links to the +reports that we submitted to the European Union. + +`development methodology`_ describes our sprint-driven approach. + +`LICENSE`_ contains licensing details (basically a straight MIT-license). + +`Glossary`_ of PyPy words to help you align your inner self with +the PyPy universe. + +Source Code Documentation +=============================================== + +`object spaces`_ discusses the object space interface +and several implementations. + +`bytecode interpreter`_ explains the basic mechanisms +of the bytecode interpreter and virtual machine. + +`interpreter optimizations`_ describes our various strategies for +improving the performance of our interpreter, including alternative +object implementations (for strings, dictionaries and lists) in the +standard object space. + +`translation`_ is a detailed overview of our translation process. The +rtyper_ is the largest component of our translation process. + +`dynamic-language translation`_ is a paper that describes +the translation process, especially the flow object space +and the annotator in detail. (This document is one +of the `EU reports`_.) + +`low-level encapsulation`_ describes how our approach hides +away a lot of low level details. This document is also part +of the `EU reports`_. + +`translation aspects`_ describes how we weave different +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. + +`rlib`_ describes some modules that can be used when implementing programs in +RPython. + +`configuration documentation`_ describes the various configuration options that +allow you to customize PyPy. + +`pypy on windows`_ + +`command line reference`_ + +`CLI backend`_ describes the details of the .NET backend. + +`JIT Generation in PyPy`_ describes how we produce the Python Just-in-time Compiler +from our Python interpreter. + +`directory cross-reference`_ + +.. _`garbage collector`: garbage_collection.html +.. _`directory cross-reference`: dir-reference.html +.. _`pypy on windows`: windows.html +.. _`command line reference`: commandline_ref.html +.. _`FAQ`: faq.html +.. _Glossary: glossary.html +.. _`PyPy video documentation`: video-index.html +.. _parser: parser.html +.. _`development methodology`: dev_method.html +.. _`sprint reports`: sprint-reports.html +.. _`papers, talks and related projects`: extradoc.html +.. _`object spaces`: objspace.html +.. _`interpreter optimizations`: interpreter-optimizations.html +.. _`translation`: translation.html +.. _`dynamic-language translation`: https://bitbucket.org/pypy/extradoc/raw/tip/eu-report/D05.1_Publish_on_translating_a_very-high-level_description.pdf +.. _`low-level encapsulation`: low-level-encapsulation.html +.. _`translation aspects`: translation-aspects.html +.. _`configuration documentation`: config/ +.. _`coding guide`: coding-guide.html +.. _`Architecture`: architecture.html +.. _`getting started`: getting-started.html +.. _`bytecode interpreter`: interpreter.html +.. _`EU reports`: index-report.html +.. _`Technical reports`: index-report.html +.. _`summary`: http://buildbot.pypy.org/summary +.. _`ideas for PyPy related projects`: project-ideas.html +.. _`Nightly builds and benchmarks`: http://tuatara.cs.uni-duesseldorf.de/benchmark.html +.. _`directory reference`: +.. _`rlib`: rlib.html +.. _`Sandboxing Python code`: sandbox.html +.. _`LICENSE`: https://bitbucket.org/pypy/pypy/src/default/LICENSE + +.. The following documentation is important and reasonably up-to-date: + +.. extradoc: should this be integrated one level up: dcolish? + +.. toctree:: + :maxdepth: 1 + :hidden: + + interpreter.rst + objspace.rst + __pypy__-module.rst + objspace-proxies.rst + config/index.rst + + dev_method.rst + extending.rst + + extradoc.rst + video-index.rst + + glossary.rst + + contributor.rst + + interpreter-optimizations.rst + configuration.rst + parser.rst + rlib.rst + rtyper.rst + rffi.rst + + translation.rst + jit/index.rst + jit/overview.rst + jit/pyjitpl5.rst + + index-of-release-notes.rst + + ctypes-implementation.rst + + how-to-release.rst + + index-report.rst + + stackless.rst + sandbox.rst + + discussions.rst + + cleanup.rst + + sprint-reports.rst + + eventhistory.rst + statistic/index.rst + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`search` +* :ref:`glossary` + +.. include:: _ref.txt diff --git a/rpython/translator/goal/bpnn.py b/rpython/translator/goal/bpnn.py --- a/rpython/translator/goal/bpnn.py +++ b/rpython/translator/goal/bpnn.py @@ -60,7 +60,7 @@ # create weights self.wi = makeMatrix(self.ni, self.nh) self.wo = makeMatrix(self.nh, self.no) - # set them to random vaules + # set them to random values for i in range(self.ni): for j in range(self.nh): self.wi[i][j] = rand(-2.0, 2.0) @@ -177,7 +177,7 @@ [[1,1], [0]] ] - # create a network with two input, two hidden, and two output nodes + # create a network with two input, three hidden, and one output nodes n = NN(2, 3, 1) # train it with some patterns n.train(pat, 2000) From noreply at buildbot.pypy.org Thu Apr 11 20:04:20 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Thu, 11 Apr 2013 20:04:20 +0200 (CEST) Subject: [pypy-commit] benchmarks default: have runner.py support --niceness option Message-ID: <20130411180420.4FE3C1C3085@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r203:6f149a47d993 Date: 2013-04-11 14:03 -0400 http://bitbucket.org/pypy/benchmarks/changeset/6f149a47d993/ Log: have runner.py support --niceness option diff --git a/benchmarks.py b/benchmarks.py --- a/benchmarks.py +++ b/benchmarks.py @@ -82,6 +82,7 @@ 'raytrace-simple', 'crypto_pyaes', 'bm_mako', 'bm_chameleon', 'json_bench', 'pidigits', 'hexiom2', 'eparse']: _register_new_bm(name, name, globals(), **opts.get(name, {})) + for name in ['names', 'iteration', 'tcp', 'pb', ]:#'web']:#, 'accepts']: if name == 'web': iteration_scaling = 0.2 @@ -90,13 +91,12 @@ _register_new_bm_twisted(name, 'twisted_' + name, globals(), bm_env={'PYTHONPATH': ':'.join(TWISTED)}, iteration_scaling=iteration_scaling) + _register_new_bm('spitfire', 'spitfire', globals(), extra_args=['--benchmark=spitfire_o4']) _register_new_bm('spitfire', 'spitfire_cstringio', globals(), extra_args=['--benchmark=python_cstringio']) - - # ========================================================================= # translate.py benchmark # ========================================================================= diff --git a/runner.py b/runner.py --- a/runner.py +++ b/runner.py @@ -5,6 +5,7 @@ import json import socket import sys +import os import benchmarks from saveresults import save @@ -207,6 +208,8 @@ "--force-host", default=None, action="store", help=("Force the hostname. This option will also be used when " "uploading the baseline result.")) + parser.add_option("--niceness", default=None, type="int", + help="Set absolute niceness for process") # upload baseline group upload_baseline_group = optparse.OptionGroup( @@ -271,6 +274,9 @@ revision = options.upload_revision force_host = options.force_host + if options.niceness: + os.nice(options.niceness - os.nice(0)) + results = run_and_store(benchmarks, output_filename, changed_path, revision, args=args, fast=fast, baseline_path=baseline_path, From noreply at buildbot.pypy.org Thu Apr 11 20:09:55 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Thu, 11 Apr 2013 20:09:55 +0200 (CEST) Subject: [pypy-commit] buildbot default: have benchmark run set niceness Message-ID: <20130411180955.B5E2D1C23C8@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r777:33564e2e9fc7 Date: 2013-04-11 14:09 -0400 http://bitbucket.org/pypy/buildbot/changeset/33564e2e9fc7/ Log: have benchmark run set niceness diff --git a/bot2/pypybuildbot/builds.py b/bot2/pypybuildbot/builds.py --- a/bot2/pypybuildbot/builds.py +++ b/bot2/pypybuildbot/builds.py @@ -118,7 +118,7 @@ 'latest.html') symlink_force(self.masterdest, symname) except OSError: - pass + pass class Translate(ShellCmd): name = "translate" @@ -145,7 +145,6 @@ class PytestCmd(ShellCmd): - def commandComplete(self, cmd): from pypybuildbot.summary import RevisionOutcomeSet if 'pytestLog' not in cmd.logs: @@ -176,7 +175,6 @@ d[key] = summary builder.saveYourself() - # _______________________________________________________________ class UpdateCheckout(ShellCmd): @@ -353,8 +351,8 @@ "pypy/module/pypyjit/test_pypy_c"], logfiles={'pytestLog': 'pypyjit_new.log'})) +# ---- -# ---- class Own(factory.BuildFactory): def __init__(self, platform='linux', cherrypick='', extra_cfgs=[], **kwargs): @@ -523,6 +521,7 @@ if trigger: # if provided trigger schedulers that are depend on this one self.addStep(Trigger(schedulerNames=[trigger])) + class JITBenchmark(factory.BuildFactory): def __init__(self, platform='linux', host='tannit', postfix=''): factory.BuildFactory.__init__(self) @@ -568,6 +567,7 @@ locks=[lock.access('exclusive')], description="run benchmarks on top of pypy-c", command=["python", "runner.py", '--output-filename', 'result.json', + '--niceness', '-10', '--changed', pypy_c_rel, '--baseline', pypy_c_rel, '--args', ',--jit off', From noreply at buildbot.pypy.org Thu Apr 11 20:38:35 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Thu, 11 Apr 2013 20:38:35 +0200 (CEST) Subject: [pypy-commit] buildbot default: settle for niceness 0 Message-ID: <20130411183835.E66DD1C0F12@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r778:c5df804d3d58 Date: 2013-04-11 14:38 -0400 http://bitbucket.org/pypy/buildbot/changeset/c5df804d3d58/ Log: settle for niceness 0 diff --git a/bot2/pypybuildbot/builds.py b/bot2/pypybuildbot/builds.py --- a/bot2/pypybuildbot/builds.py +++ b/bot2/pypybuildbot/builds.py @@ -567,7 +567,7 @@ locks=[lock.access('exclusive')], description="run benchmarks on top of pypy-c", command=["python", "runner.py", '--output-filename', 'result.json', - '--niceness', '-10', + '--niceness', '0', # can't get limits.conf to allow -10 '--changed', pypy_c_rel, '--baseline', pypy_c_rel, '--args', ',--jit off', From noreply at buildbot.pypy.org Thu Apr 11 21:08:27 2013 From: noreply at buildbot.pypy.org (bivab) Date: Thu, 11 Apr 2013 21:08:27 +0200 (CEST) Subject: [pypy-commit] pypy default: Move zrpy_* and ztranslation* tests to llsupport and import them correspondingly in the backends Message-ID: <20130411190827.7949B1C23C8@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63241:d69d9958dc92 Date: 2013-04-11 21:01 +0200 http://bitbucket.org/pypy/pypy/changeset/d69d9958dc92/ Log: Move zrpy_* and ztranslation* tests to llsupport and import them correspondingly in the backends diff too long, truncating to 2000 out of 2756 lines diff --git a/rpython/jit/backend/arm/test/test_zrpy_gc.py b/rpython/jit/backend/arm/test/test_zrpy_gc.py --- a/rpython/jit/backend/arm/test/test_zrpy_gc.py +++ b/rpython/jit/backend/arm/test/test_zrpy_gc.py @@ -1,798 +1,4 @@ -""" -This is a test that translates a complete JIT together with a GC and runs it. -It is testing that the GC-dependent aspects basically work, mostly the mallocs -and the various cases of write barrier. -""" - -import weakref -import py, os -from rpython.annotator import policy as annpolicy -from rpython.rlib import rgc -from rpython.rtyper.lltypesystem import lltype, llmemory, rffi -from rpython.rlib.jit import JitDriver, dont_look_inside -from rpython.rlib.jit import elidable, unroll_safe -from rpython.jit.backend.llsupport.gc import GcLLDescr_framework -from rpython.tool.udir import udir -from rpython.config.translationoption import DEFL_GC from rpython.jit.backend.arm.test.support import skip_unless_run_slow_tests skip_unless_run_slow_tests() - -class X(object): - def __init__(self, x=0): - self.x = x - - next = None - -class CheckError(Exception): - pass - -def check(flag): - if not flag: - raise CheckError - -def get_g(main): - main._dont_inline_ = True - def g(name, n): - x = X() - x.foo = 2 - main(n, x) - x.foo = 5 - return weakref.ref(x) - g._dont_inline_ = True - return g - - -def get_entry(g): - - def entrypoint(args): - name = '' - n = 2000 - argc = len(args) - if argc > 1: - name = args[1] - if argc > 2: - n = int(args[2]) - r_list = [] - for i in range(20): - r = g(name, n) - r_list.append(r) - rgc.collect() - rgc.collect(); rgc.collect() - freed = 0 - for r in r_list: - if r() is None: - freed += 1 - print freed - return 0 - - return entrypoint - - -def get_functions_to_patch(): - from rpython.jit.backend.llsupport import gc - # - can_use_nursery_malloc1 = gc.GcLLDescr_framework.can_use_nursery_malloc - def can_use_nursery_malloc2(*args): - try: - if os.environ['PYPY_NO_INLINE_MALLOC']: - return False - except KeyError: - pass - return can_use_nursery_malloc1(*args) - # - return {(gc.GcLLDescr_framework, 'can_use_nursery_malloc'): - can_use_nursery_malloc2} - -def compile(f, gc, enable_opts='', **kwds): - from rpython.annotator.listdef import s_list_of_strings - from rpython.translator.translator import TranslationContext - from rpython.jit.metainterp.warmspot import apply_jit - from rpython.translator.c import genc - # - t = TranslationContext() - t.config.translation.gc = gc - if gc != 'boehm': - t.config.translation.gcremovetypeptr = True - for name, value in kwds.items(): - setattr(t.config.translation, name, value) - ann = t.buildannotator() - ann.build_types(f, [s_list_of_strings], main_entry_point=True) - t.buildrtyper().specialize() - - if kwds['jit']: - patch = get_functions_to_patch() - old_value = {} - try: - for (obj, attr), value in patch.items(): - old_value[obj, attr] = getattr(obj, attr) - setattr(obj, attr, value) - # - apply_jit(t, enable_opts=enable_opts) - # - finally: - for (obj, attr), oldvalue in old_value.items(): - setattr(obj, attr, oldvalue) - - cbuilder = genc.CStandaloneBuilder(t, f, t.config) - cbuilder.generate_source(defines=cbuilder.DEBUG_DEFINES) - cbuilder.compile() - return cbuilder - -def run(cbuilder, args=''): - # - pypylog = udir.join('test_zrpy_gc.log') - data = cbuilder.cmdexec(args, env={'PYPYLOG': ':%s' % pypylog}) - return data.strip() - -def compile_and_run(f, gc, **kwds): - cbuilder = compile(f, gc, **kwds) - return run(cbuilder) - - - -def test_compile_boehm(): - myjitdriver = JitDriver(greens = [], reds = ['n', 'x']) - @dont_look_inside - def see(lst, n): - assert len(lst) == 3 - assert lst[0] == n+10 - assert lst[1] == n+20 - assert lst[2] == n+30 - def main(n, x): - while n > 0: - myjitdriver.can_enter_jit(n=n, x=x) - myjitdriver.jit_merge_point(n=n, x=x) - y = X() - y.foo = x.foo - n -= y.foo - see([n+10, n+20, n+30], n) - res = compile_and_run(get_entry(get_g(main)), "boehm", jit=True) - assert int(res) >= 16 - -# ______________________________________________________________________ - - -class BaseFrameworkTests(object): - compile_kwds = {} - - def setup_class(cls): - funcs = [] - name_to_func = {} - for fullname in dir(cls): - if not fullname.startswith('define'): - continue - definefunc = getattr(cls, fullname) - _, name = fullname.split('_', 1) - beforefunc, loopfunc, afterfunc = definefunc.im_func(cls) - if beforefunc is None: - def beforefunc(n, x): - return n, x, None, None, None, None, None, None, None, None, None, '' - if afterfunc is None: - def afterfunc(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - pass - beforefunc.func_name = 'before_'+name - loopfunc.func_name = 'loop_'+name - afterfunc.func_name = 'after_'+name - funcs.append((beforefunc, loopfunc, afterfunc)) - assert name not in name_to_func - name_to_func[name] = len(name_to_func) - print name_to_func - def allfuncs(name, n): - x = X() - x.foo = 2 - main_allfuncs(name, n, x) - x.foo = 5 - return weakref.ref(x) - def main_allfuncs(name, n, x): - num = name_to_func[name] - n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s = funcs[num][0](n, x) - while n > 0: - myjitdriver.can_enter_jit(num=num, n=n, x=x, x0=x0, x1=x1, - x2=x2, x3=x3, x4=x4, x5=x5, x6=x6, x7=x7, l=l, s=s) - myjitdriver.jit_merge_point(num=num, n=n, x=x, x0=x0, x1=x1, - x2=x2, x3=x3, x4=x4, x5=x5, x6=x6, x7=x7, l=l, s=s) - - n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s = funcs[num][1]( - n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s) - funcs[num][2](n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s) - myjitdriver = JitDriver(greens = ['num'], - reds = ['n', 'x', 'x0', 'x1', 'x2', 'x3', 'x4', - 'x5', 'x6', 'x7', 'l', 's']) - cls.main_allfuncs = staticmethod(main_allfuncs) - cls.name_to_func = name_to_func - OLD_DEBUG = GcLLDescr_framework.DEBUG - try: - GcLLDescr_framework.DEBUG = True - cls.cbuilder = compile(get_entry(allfuncs), DEFL_GC, - gcrootfinder=cls.gcrootfinder, jit=True, - **cls.compile_kwds) - finally: - GcLLDescr_framework.DEBUG = OLD_DEBUG - - def _run(self, name, n, env): - res = self.cbuilder.cmdexec("%s %d" %(name, n), env=env) - assert int(res) == 20 - - def run(self, name, n=2000): - pypylog = udir.join('TestCompileFramework.log') - env = {'PYPYLOG': ':%s' % pypylog, - 'PYPY_NO_INLINE_MALLOC': '1'} - self._run(name, n, env) - env['PYPY_NO_INLINE_MALLOC'] = '' - self._run(name, n, env) - - def run_orig(self, name, n, x): - self.main_allfuncs(name, n, x) - - -class CompileFrameworkTests(BaseFrameworkTests): - # Test suite using (so far) the minimark GC. - -## def define_libffi_workaround(cls): -## # XXX: this is a workaround for a bug in database.py. It seems that -## # the problem is triggered by optimizeopt/fficall.py, and in -## # particular by the ``cast_base_ptr_to_instance(Func, llfunc)``: in -## # these tests, that line is the only place where libffi.Func is -## # referenced. -## # -## # The problem occurs because the gctransformer tries to annotate a -## # low-level helper to call the __del__ of libffi.Func when it's too -## # late. -## # -## # This workaround works by forcing the annotator (and all the rest of -## # the toolchain) to see libffi.Func in a "proper" context, not just as -## # the target of cast_base_ptr_to_instance. Note that the function -## # below is *never* called by any actual test, it's just annotated. -## # -## from rpython.rlib.libffi import get_libc_name, CDLL, types, ArgChain -## libc_name = get_libc_name() -## def f(n, x, *args): -## libc = CDLL(libc_name) -## ptr = libc.getpointer('labs', [types.slong], types.slong) -## chain = ArgChain() -## chain.arg(n) -## n = ptr.call(chain, lltype.Signed) -## return (n, x) + args -## return None, f, None - - def define_compile_framework_1(cls): - # a moving GC. Supports malloc_varsize_nonmovable. Simple test, works - # without write_barriers and root stack enumeration. - def f(n, x, *args): - y = X() - y.foo = x.foo - n -= y.foo - return (n, x) + args - return None, f, None - - def test_compile_framework_1(self): - self.run('compile_framework_1') - - def define_compile_framework_2(cls): - # More complex test, requires root stack enumeration but - # not write_barriers. - def f(n, x, *args): - prev = x - for j in range(101): # f() runs 20'000 times, thus allocates - y = X() # a total of 2'020'000 objects - y.foo = prev.foo - prev = y - n -= prev.foo - return (n, x) + args - return None, f, None - - def test_compile_framework_2(self): - self.run('compile_framework_2') - - def define_compile_framework_3(cls): - # Third version of the test. Really requires write_barriers. - def f(n, x, *args): - x.next = None - for j in range(101): # f() runs 20'000 times, thus allocates - y = X() # a total of 2'020'000 objects - y.foo = j+1 - y.next = x.next - x.next = y - check(x.next.foo == 101) - total = 0 - y = x - for j in range(101): - y = y.next - total += y.foo - check(not y.next) - check(total == 101*102/2) - n -= x.foo - return (n, x) + args - return None, f, None - - - - def test_compile_framework_3(self): - x_test = X() - x_test.foo = 5 - self.run_orig('compile_framework_3', 6, x_test) # check that it does not raise CheckError - self.run('compile_framework_3') - - def define_compile_framework_3_extra(cls): - # Extra version of the test, with tons of live vars around the residual - # call that all contain a GC pointer. - @dont_look_inside - def residual(n=26): - x = X() - x.next = X() - x.next.foo = n - return x - # - def before(n, x): - residual(5) - x0 = residual() - x1 = residual() - x2 = residual() - x3 = residual() - x4 = residual() - x5 = residual() - x6 = residual() - x7 = residual() - n *= 19 - return n, None, x0, x1, x2, x3, x4, x5, x6, x7, None, None - def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - x8 = residual() - x9 = residual() - check(x0.next.foo == 26) - check(x1.next.foo == 26) - check(x2.next.foo == 26) - check(x3.next.foo == 26) - check(x4.next.foo == 26) - check(x5.next.foo == 26) - check(x6.next.foo == 26) - check(x7.next.foo == 26) - check(x8.next.foo == 26) - check(x9.next.foo == 26) - x0, x1, x2, x3, x4, x5, x6, x7 = x7, x4, x6, x5, x3, x2, x9, x8 - n -= 1 - return n, None, x0, x1, x2, x3, x4, x5, x6, x7, None, None - return before, f, None - - def test_compile_framework_3_extra(self): - self.run_orig('compile_framework_3_extra', 6, None) # check that it does not raise CheckError - self.run('compile_framework_3_extra') - - def define_compile_framework_4(cls): - # Fourth version of the test, with __del__. - from rpython.rlib.debug import debug_print - class Counter: - cnt = 0 - counter = Counter() - class Z: - def __del__(self): - counter.cnt -= 1 - def before(n, x): - debug_print('counter.cnt =', counter.cnt) - check(counter.cnt < 5) - counter.cnt = n // x.foo - return n, x, None, None, None, None, None, None, None, None, None, None - def f(n, x, *args): - Z() - n -= x.foo - return (n, x) + args - return before, f, None - - def test_compile_framework_4(self): - self.run('compile_framework_4') - - def define_compile_framework_5(cls): - # Test string manipulation. - def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - n -= x.foo - s += str(n) - return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s - def after(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - check(len(s) == 1*5 + 2*45 + 3*450 + 4*500) - return None, f, after - - def test_compile_framework_5(self): - self.run('compile_framework_5') - - def define_compile_framework_7(cls): - # Array of pointers (test the write barrier for setarrayitem_gc) - def before(n, x): - return n, x, None, None, None, None, None, None, None, None, [X(123)], None - def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - if n < 1900: - check(l[0].x == 123) - l = [None] * 16 - l[0] = X(123) - l[1] = X(n) - l[2] = X(n+10) - l[3] = X(n+20) - l[4] = X(n+30) - l[5] = X(n+40) - l[6] = X(n+50) - l[7] = X(n+60) - l[8] = X(n+70) - l[9] = X(n+80) - l[10] = X(n+90) - l[11] = X(n+100) - l[12] = X(n+110) - l[13] = X(n+120) - l[14] = X(n+130) - l[15] = X(n+140) - if n < 1800: - check(len(l) == 16) - check(l[0].x == 123) - check(l[1].x == n) - check(l[2].x == n+10) - check(l[3].x == n+20) - check(l[4].x == n+30) - check(l[5].x == n+40) - check(l[6].x == n+50) - check(l[7].x == n+60) - check(l[8].x == n+70) - check(l[9].x == n+80) - check(l[10].x == n+90) - check(l[11].x == n+100) - check(l[12].x == n+110) - check(l[13].x == n+120) - check(l[14].x == n+130) - check(l[15].x == n+140) - n -= x.foo - return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s - def after(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - check(len(l) == 16) - check(l[0].x == 123) - check(l[1].x == 2) - check(l[2].x == 12) - check(l[3].x == 22) - check(l[4].x == 32) - check(l[5].x == 42) - check(l[6].x == 52) - check(l[7].x == 62) - check(l[8].x == 72) - check(l[9].x == 82) - check(l[10].x == 92) - check(l[11].x == 102) - check(l[12].x == 112) - check(l[13].x == 122) - check(l[14].x == 132) - check(l[15].x == 142) - return before, f, after - - def test_compile_framework_7(self): - self.run('compile_framework_7') - - def define_compile_framework_7_interior(cls): - # Array of structs containing pointers (test the write barrier - # for setinteriorfield_gc) - S = lltype.GcStruct('S', ('i', lltype.Signed)) - A = lltype.GcArray(lltype.Struct('entry', ('x', lltype.Ptr(S)), - ('y', lltype.Ptr(S)), - ('z', lltype.Ptr(S)))) - class Glob: - a = lltype.nullptr(A) - glob = Glob() - # - def make_s(i): - s = lltype.malloc(S) - s.i = i - return s - # - @unroll_safe - def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - a = glob.a - if not a: - a = glob.a = lltype.malloc(A, 10) - i = 0 - while i < 10: - a[i].x = make_s(n + i * 100 + 1) - a[i].y = make_s(n + i * 100 + 2) - a[i].z = make_s(n + i * 100 + 3) - i += 1 - i = 0 - while i < 10: - check(a[i].x.i == n + i * 100 + 1) - check(a[i].y.i == n + i * 100 + 2) - check(a[i].z.i == n + i * 100 + 3) - i += 1 - n -= x.foo - return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s - return None, f, None - - def test_compile_framework_7_interior(self): - self.run('compile_framework_7_interior') - - def define_compile_framework_8(cls): - # Array of pointers, of unknown length (test write_barrier_from_array) - def before(n, x): - return n, x, None, None, None, None, None, None, None, None, [X(123)], None - def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - if n < 1900: - check(l[0].x == 123) - l = [None] * (16 + (n & 7)) - l[0] = X(123) - l[1] = X(n) - l[2] = X(n+10) - l[3] = X(n+20) - l[4] = X(n+30) - l[5] = X(n+40) - l[6] = X(n+50) - l[7] = X(n+60) - l[8] = X(n+70) - l[9] = X(n+80) - l[10] = X(n+90) - l[11] = X(n+100) - l[12] = X(n+110) - l[13] = X(n+120) - l[14] = X(n+130) - l[15] = X(n+140) - if n < 1800: - check(len(l) == 16 + (n & 7)) - check(l[0].x == 123) - check(l[1].x == n) - check(l[2].x == n+10) - check(l[3].x == n+20) - check(l[4].x == n+30) - check(l[5].x == n+40) - check(l[6].x == n+50) - check(l[7].x == n+60) - check(l[8].x == n+70) - check(l[9].x == n+80) - check(l[10].x == n+90) - check(l[11].x == n+100) - check(l[12].x == n+110) - check(l[13].x == n+120) - check(l[14].x == n+130) - check(l[15].x == n+140) - n -= x.foo - return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s - def after(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - check(len(l) >= 16) - check(l[0].x == 123) - check(l[1].x == 2) - check(l[2].x == 12) - check(l[3].x == 22) - check(l[4].x == 32) - check(l[5].x == 42) - check(l[6].x == 52) - check(l[7].x == 62) - check(l[8].x == 72) - check(l[9].x == 82) - check(l[10].x == 92) - check(l[11].x == 102) - check(l[12].x == 112) - check(l[13].x == 122) - check(l[14].x == 132) - check(l[15].x == 142) - return before, f, after - - def test_compile_framework_8(self): - self.run('compile_framework_8') - - def define_compile_framework_9(cls): - # Like compile_framework_8, but with variable indexes and large - # arrays, testing the card_marking case - def before(n, x): - return n, x, None, None, None, None, None, None, None, None, [X(123)], None - def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - if n < 1900: - check(l[0].x == 123) - num = 512 + (n & 7) - l = [None] * num - l[0] = X(123) - l[1] = X(n) - l[2] = X(n+10) - l[3] = X(n+20) - l[4] = X(n+30) - l[5] = X(n+40) - l[6] = X(n+50) - l[7] = X(n+60) - l[num-8] = X(n+70) - l[num-9] = X(n+80) - l[num-10] = X(n+90) - l[num-11] = X(n+100) - l[-12] = X(n+110) - l[-13] = X(n+120) - l[-14] = X(n+130) - l[-15] = X(n+140) - if n < 1800: - num = 512 + (n & 7) - check(len(l) == num) - check(l[0].x == 123) - check(l[1].x == n) - check(l[2].x == n+10) - check(l[3].x == n+20) - check(l[4].x == n+30) - check(l[5].x == n+40) - check(l[6].x == n+50) - check(l[7].x == n+60) - check(l[num-8].x == n+70) - check(l[num-9].x == n+80) - check(l[num-10].x == n+90) - check(l[num-11].x == n+100) - check(l[-12].x == n+110) - check(l[-13].x == n+120) - check(l[-14].x == n+130) - check(l[-15].x == n+140) - n -= x.foo - return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s - def after(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - check(len(l) >= 512) - check(l[0].x == 123) - check(l[1].x == 2) - check(l[2].x == 12) - check(l[3].x == 22) - check(l[4].x == 32) - check(l[5].x == 42) - check(l[6].x == 52) - check(l[7].x == 62) - check(l[-8].x == 72) - check(l[-9].x == 82) - check(l[-10].x == 92) - check(l[-11].x == 102) - check(l[-12].x == 112) - check(l[-13].x == 122) - check(l[-14].x == 132) - check(l[-15].x == 142) - return before, f, after - - def test_compile_framework_9(self): - self.run('compile_framework_9') - - def define_compile_framework_external_exception_handling(cls): - def before(n, x): - x = X(0) - return n, x, None, None, None, None, None, None, None, None, None, None - - @dont_look_inside - def g(x): - if x > 200: - return 2 - raise ValueError - @dont_look_inside - def h(x): - if x > 150: - raise ValueError - return 2 - - def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - try: - x.x += g(n) - except ValueError: - x.x += 1 - try: - x.x += h(n) - except ValueError: - x.x -= 1 - n -= 1 - return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s - - def after(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - check(x.x == 1800 * 2 + 1850 * 2 + 200 - 150) - - return before, f, None - - def test_compile_framework_external_exception_handling(self): - self.run('compile_framework_external_exception_handling') - - def define_compile_framework_bug1(self): - @elidable - def nonmoving(): - x = X(1) - for i in range(7): - rgc.collect() - return x - - @dont_look_inside - def do_more_stuff(): - x = X(5) - for i in range(7): - rgc.collect() - return x - - def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - x0 = do_more_stuff() - check(nonmoving().x == 1) - n -= 1 - return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s - - return None, f, None - - def test_compile_framework_bug1(self): - self.run('compile_framework_bug1', 200) - - def define_compile_framework_vref(self): - from rpython.rlib.jit import virtual_ref, virtual_ref_finish - class A: - pass - glob = A() - def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - a = A() - glob.v = vref = virtual_ref(a) - virtual_ref_finish(vref, a) - n -= 1 - return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s - return None, f, None - - def test_compile_framework_vref(self): - self.run('compile_framework_vref', 200) - - def define_compile_framework_float(self): - # test for a bug: the fastpath_malloc does not save and restore - # xmm registers around the actual call to the slow path - class A: - x0 = x1 = x2 = x3 = x4 = x5 = x6 = x7 = 0 - @dont_look_inside - def escape1(a): - a.x0 += 0 - a.x1 += 6 - a.x2 += 12 - a.x3 += 18 - a.x4 += 24 - a.x5 += 30 - a.x6 += 36 - a.x7 += 42 - @dont_look_inside - def escape2(n, f0, f1, f2, f3, f4, f5, f6, f7): - check(f0 == n + 0.0) - check(f1 == n + 0.125) - check(f2 == n + 0.25) - check(f3 == n + 0.375) - check(f4 == n + 0.5) - check(f5 == n + 0.625) - check(f6 == n + 0.75) - check(f7 == n + 0.875) - @unroll_safe - def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - i = 0 - while i < 42: - m = n + i - f0 = m + 0.0 - f1 = m + 0.125 - f2 = m + 0.25 - f3 = m + 0.375 - f4 = m + 0.5 - f5 = m + 0.625 - f6 = m + 0.75 - f7 = m + 0.875 - a1 = A() - # at this point, all or most f's are still in xmm registers - escape1(a1) - escape2(m, f0, f1, f2, f3, f4, f5, f6, f7) - i += 1 - n -= 1 - return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s - return None, f, None - - def test_compile_framework_float(self): - self.run('compile_framework_float') - - def define_compile_framework_minimal_size_in_nursery(self): - S = lltype.GcStruct('S') # no fields! - T = lltype.GcStruct('T', ('i', lltype.Signed)) - @unroll_safe - def f42(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - lst1 = [] - lst2 = [] - i = 0 - while i < 42: - s1 = lltype.malloc(S) - t1 = lltype.malloc(T) - t1.i = 10000 + i + n - lst1.append(s1) - lst2.append(t1) - i += 1 - i = 0 - while i < 42: - check(lst2[i].i == 10000 + i + n) - i += 1 - n -= 1 - return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s - return None, f42, None - - def test_compile_framework_minimal_size_in_nursery(self): - self.run('compile_framework_minimal_size_in_nursery') - - -class TestShadowStack(CompileFrameworkTests): - gcrootfinder = "shadowstack" - +from rpython.jit.backend.llsupport.test.zrpy_gc_test import TestShadowStack diff --git a/rpython/jit/backend/x86/test/test_zrpy_gc_boehm.py b/rpython/jit/backend/arm/test/test_zrpy_gc_boehm.py copy from rpython/jit/backend/x86/test/test_zrpy_gc_boehm.py copy to rpython/jit/backend/arm/test/test_zrpy_gc_boehm.py --- a/rpython/jit/backend/x86/test/test_zrpy_gc_boehm.py +++ b/rpython/jit/backend/arm/test/test_zrpy_gc_boehm.py @@ -1,53 +1,3 @@ - -import weakref -from rpython.rlib.jit import JitDriver, dont_look_inside -from rpython.jit.backend.x86.test.test_zrpy_gc import run, get_entry, compile -from rpython.jit.backend.x86.test.test_ztranslation import fix_annotator_for_vrawbuffer - -class X(object): - def __init__(self, x=0): - self.x = x - - next = None - -class CheckError(Exception): - pass - -def check(flag): - if not flag: - raise CheckError - -def compile_and_run(f, gc, **kwds): - cbuilder = compile(f, gc, **kwds) - return run(cbuilder) - -def get_g(main): - main._dont_inline_ = True - def g(name, n): - x = X() - x.foo = 2 - main(n, x) - x.foo = 5 - return weakref.ref(x) - g._dont_inline_ = True - return g - -def test_compile_boehm(monkeypatch): - fix_annotator_for_vrawbuffer(monkeypatch) - myjitdriver = JitDriver(greens = [], reds = ['n', 'x']) - @dont_look_inside - def see(lst, n): - assert len(lst) == 3 - assert lst[0] == n+10 - assert lst[1] == n+20 - assert lst[2] == n+30 - def main(n, x): - while n > 0: - myjitdriver.can_enter_jit(n=n, x=x) - myjitdriver.jit_merge_point(n=n, x=x) - y = X() - y.foo = x.foo - n -= y.foo - see([n+10, n+20, n+30], n) - res = compile_and_run(get_entry(get_g(main)), "boehm", jit=True) - assert int(res) >= 16 +from rpython.jit.backend.arm.test.support import skip_unless_run_slow_tests +skip_unless_run_slow_tests() +from rpython.jit.backend.llsupport.test.zrpy_gc_boehm_test import test_compile_boehm diff --git a/rpython/jit/backend/x86/test/test_zrpy_releasegil.py b/rpython/jit/backend/arm/test/test_zrpy_releasegil.py copy from rpython/jit/backend/x86/test/test_zrpy_releasegil.py copy to rpython/jit/backend/arm/test/test_zrpy_releasegil.py --- a/rpython/jit/backend/x86/test/test_zrpy_releasegil.py +++ b/rpython/jit/backend/arm/test/test_zrpy_releasegil.py @@ -1,104 +1,4 @@ -from rpython.rtyper.lltypesystem import lltype, llmemory, rffi -from rpython.rlib.jit import dont_look_inside -from rpython.rlib.objectmodel import invoke_around_extcall -from rpython.jit.metainterp.optimizeopt import ALL_OPTS_NAMES +from rpython.jit.backend.arm.test.support import skip_unless_run_slow_tests +skip_unless_run_slow_tests() -from rpython.rtyper.annlowlevel import llhelper - -from rpython.jit.backend.x86.test.test_zrpy_gc import BaseFrameworkTests -from rpython.jit.backend.x86.test.test_zrpy_gc import check -from rpython.tool.udir import udir - - -class ReleaseGILTests(BaseFrameworkTests): - compile_kwds = dict(enable_opts=ALL_OPTS_NAMES, thread=True) - - def define_simple(self): - class Glob: - def __init__(self): - self.event = 0 - glob = Glob() - # - - c_strchr = rffi.llexternal('strchr', [rffi.CCHARP, lltype.Signed], - rffi.CCHARP) - - def func(): - glob.event += 1 - - def before(n, x): - invoke_around_extcall(func, func) - return (n, None, None, None, None, None, - None, None, None, None, None, None) - # - def f(n, x, *args): - a = rffi.str2charp(str(n)) - c_strchr(a, ord('0')) - lltype.free(a, flavor='raw') - n -= 1 - return (n, x) + args - return before, f, None - - def test_simple(self): - self.run('simple') - assert 'call_release_gil' in udir.join('TestCompileFramework.log').read() - - def define_close_stack(self): - # - class Glob(object): - pass - glob = Glob() - class X(object): - pass - # - def callback(p1, p2): - for i in range(100): - glob.lst.append(X()) - return rffi.cast(rffi.INT, 1) - CALLBACK = lltype.Ptr(lltype.FuncType([lltype.Signed, - lltype.Signed], rffi.INT)) - # - @dont_look_inside - def alloc1(): - return llmemory.raw_malloc(16) - @dont_look_inside - def free1(p): - llmemory.raw_free(p) - - c_qsort = rffi.llexternal('qsort', [rffi.VOIDP, rffi.SIZE_T, - rffi.SIZE_T, CALLBACK], lltype.Void) - # - def f42(n): - length = len(glob.lst) - raw = alloc1() - fn = llhelper(CALLBACK, rffi._make_wrapper_for(CALLBACK, callback)) - if n & 1: # to create a loop and a bridge, and also - pass # to run the qsort() call in the blackhole interp - c_qsort(rffi.cast(rffi.VOIDP, raw), rffi.cast(rffi.SIZE_T, 2), - rffi.cast(rffi.SIZE_T, 8), fn) - free1(raw) - check(len(glob.lst) > length) - del glob.lst[:] - # - def before(n, x): - glob.lst = [] - - return (n, None, None, None, None, None, - None, None, None, None, None, None) - # - def f(n, x, *args): - f42(n) - n -= 1 - return (n, x) + args - return before, f, None - - def test_close_stack(self): - self.run('close_stack') - assert 'call_release_gil' in udir.join('TestCompileFramework.log').read() - - -class TestShadowStack(ReleaseGILTests): - gcrootfinder = "shadowstack" - -class TestAsmGcc(ReleaseGILTests): - gcrootfinder = "asmgcc" +from rpython.jit.backend.llsupport.test.zrpy_releasegil_test import TestShadowStack, TestAsmGcc diff --git a/rpython/jit/backend/arm/test/test_ztranslation.py b/rpython/jit/backend/arm/test/test_ztranslation.py deleted file mode 100644 --- a/rpython/jit/backend/arm/test/test_ztranslation.py +++ /dev/null @@ -1,279 +0,0 @@ -import py, os, sys -from rpython.tool.udir import udir -from rpython.rlib.jit import JitDriver, unroll_parameters, set_param -from rpython.rlib.jit import PARAMETERS, dont_look_inside -from rpython.rlib.jit import promote -from rpython.rlib import jit_hooks -from rpython.jit.metainterp.jitprof import Profiler -from rpython.jit.backend.detect_cpu import getcpuclass -from rpython.jit.backend.test.support import CCompiledMixin -from rpython.jit.codewriter.policy import StopAtXPolicy -from rpython.translator.translator import TranslationContext -from rpython.config.translationoption import DEFL_GC -from rpython.rlib import rgc -from rpython.jit.backend.arm.test.support import skip_unless_run_slow_tests -skip_unless_run_slow_tests() - -class TestTranslationARM(CCompiledMixin): - CPUClass = getcpuclass() - - def _get_TranslationContext(self): - t = TranslationContext() - t.config.translation.gc = DEFL_GC # 'hybrid' or 'minimark' - t.config.translation.gcrootfinder = 'shadowstack' - return t - - def _check_cbuilder(self, cbuilder): - pass - - def test_stuff_translates(self): - # this is a basic test that tries to hit a number of features and their - # translation: - # - jitting of loops and bridges - # - virtualizables - # - set_param interface - # - profiler - # - full optimizer - # - floats neg and abs - - class Frame(object): - _virtualizable2_ = ['i'] - - def __init__(self, i): - self.i = i - - @dont_look_inside - def myabs(x): - return abs(x) - - jitdriver = JitDriver(greens = [], - reds = ['total', 'frame', 'j'], - virtualizables = ['frame']) - def f(i, j): - for param, _ in unroll_parameters: - defl = PARAMETERS[param] - set_param(jitdriver, param, defl) - set_param(jitdriver, "threshold", 3) - set_param(jitdriver, "trace_eagerness", 2) - total = 0 - frame = Frame(i) - j = float(j) - while frame.i > 3: - jitdriver.can_enter_jit(frame=frame, total=total, j=j) - jitdriver.jit_merge_point(frame=frame, total=total, j=j) - total += frame.i - if frame.i >= 20: - frame.i -= 2 - frame.i -= 1 - j *= -0.712 - if j + (-j): raise ValueError - k = myabs(j) - if k - abs(j): raise ValueError - if k - abs(-j): raise ValueError - return chr(total % 253) - # - from rpython.rtyper.lltypesystem import lltype, rffi - from rpython.rlib.libffi import types, CDLL, ArgChain - from rpython.rlib.test.test_clibffi import get_libm_name - libm_name = get_libm_name(sys.platform) - jitdriver2 = JitDriver(greens=[], reds = ['i', 'func', 'res', 'x']) - def libffi_stuff(i, j): - lib = CDLL(libm_name) - func = lib.getpointer('fabs', [types.double], types.double) - res = 0.0 - x = float(j) - while i > 0: - jitdriver2.jit_merge_point(i=i, res=res, func=func, x=x) - promote(func) - argchain = ArgChain() - argchain.arg(x) - res = func.call(argchain, rffi.DOUBLE) - i -= 1 - return res - # - def main(i, j): - a_char = f(i, j) - a_float = libffi_stuff(i, j) - return ord(a_char) * 10 + int(a_float) - expected = main(40, -49) - res = self.meta_interp(main, [40, -49]) - assert res == expected - - def test_direct_assembler_call_translates(self): - """Test CALL_ASSEMBLER and the recursion limit""" - from rpython.rlib.rstackovf import StackOverflow - - class Thing(object): - def __init__(self, val): - self.val = val - - class Frame(object): - _virtualizable2_ = ['thing'] - - driver = JitDriver(greens = ['codeno'], reds = ['i', 'frame'], - virtualizables = ['frame'], - get_printable_location = lambda codeno: str(codeno)) - class SomewhereElse(object): - pass - - somewhere_else = SomewhereElse() - - def change(newthing): - somewhere_else.frame.thing = newthing - - def main(codeno): - frame = Frame() - somewhere_else.frame = frame - frame.thing = Thing(0) - portal(codeno, frame) - return frame.thing.val - - def portal(codeno, frame): - i = 0 - while i < 10: - driver.can_enter_jit(frame=frame, codeno=codeno, i=i) - driver.jit_merge_point(frame=frame, codeno=codeno, i=i) - nextval = frame.thing.val - if codeno == 0: - subframe = Frame() - subframe.thing = Thing(nextval) - nextval = portal(1, subframe) - elif frame.thing.val > 40: - change(Thing(13)) - nextval = 13 - frame.thing = Thing(nextval + 1) - i += 1 - return frame.thing.val - - driver2 = JitDriver(greens = [], reds = ['n']) - - def main2(bound): - try: - while portal2(bound) == -bound+1: - bound *= 2 - except StackOverflow: - pass - return bound - - def portal2(n): - while True: - driver2.jit_merge_point(n=n) - n -= 1 - if n <= 0: - return n - n = portal2(n) - assert portal2(10) == -9 - - def mainall(codeno, bound): - return main(codeno) + main2(bound) - - res = self.meta_interp(mainall, [0, 1], inline=True, - policy=StopAtXPolicy(change)) - print hex(res) - assert res & 255 == main(0) - bound = res & ~255 - assert 1024 <= bound <= 131072 - assert bound & (bound-1) == 0 # a power of two - - def test_jit_get_stats(self): - driver = JitDriver(greens = [], reds = ['i']) - - def f(): - i = 0 - while i < 100000: - driver.jit_merge_point(i=i) - i += 1 - - def main(): - jit_hooks.stats_set_debug(None, True) - f() - ll_times = jit_hooks.stats_get_loop_run_times(None) - return len(ll_times) - - res = self.meta_interp(main, []) - assert res == 3 - # one for loop, one for entry point and one for the prologue - -class TestTranslationRemoveTypePtrARM(CCompiledMixin): - CPUClass = getcpuclass() - - def _get_TranslationContext(self): - t = TranslationContext() - t.config.translation.gc = DEFL_GC # 'hybrid' or 'minimark' - t.config.translation.gcrootfinder = 'shadowstack' - t.config.translation.list_comprehension_operations = True - t.config.translation.gcremovetypeptr = True - return t - - def test_external_exception_handling_translates(self): - jitdriver = JitDriver(greens = [], reds = ['n', 'total']) - - class ImDone(Exception): - def __init__(self, resvalue): - self.resvalue = resvalue - - @dont_look_inside - def f(x, total): - if x <= 30: - raise ImDone(total * 10) - if x > 200: - return 2 - raise ValueError - @dont_look_inside - def g(x): - if x > 150: - raise ValueError - return 2 - class Base: - def meth(self): - return 2 - class Sub(Base): - def meth(self): - return 1 - @dont_look_inside - def h(x): - if x < 20000: - return Sub() - else: - return Base() - def myportal(i): - set_param(jitdriver, "threshold", 3) - set_param(jitdriver, "trace_eagerness", 2) - total = 0 - n = i - while True: - jitdriver.can_enter_jit(n=n, total=total) - jitdriver.jit_merge_point(n=n, total=total) - try: - total += f(n, total) - except ValueError: - total += 1 - try: - total += g(n) - except ValueError: - total -= 1 - n -= h(n).meth() # this is to force a GUARD_CLASS - def main(i): - try: - myportal(i) - except ImDone, e: - return e.resvalue - - # XXX custom fishing, depends on the exact env var and format - logfile = udir.join('test_ztranslation.log') - os.environ['PYPYLOG'] = 'jit-log-opt:%s' % (logfile,) - try: - res = self.meta_interp(main, [400]) - assert res == main(400) - finally: - del os.environ['PYPYLOG'] - - guard_class = 0 - for line in open(str(logfile)): - if 'guard_class' in line: - guard_class += 1 - # if we get many more guard_classes, it means that we generate - # guards that always fail (the following assert's original purpose - # is to catch the following case: each GUARD_CLASS is misgenerated - # and always fails with "gcremovetypeptr") - assert 0 < guard_class < 10 diff --git a/rpython/jit/backend/arm/test/test_ztranslation_basic.py b/rpython/jit/backend/arm/test/test_ztranslation_basic.py new file mode 100644 --- /dev/null +++ b/rpython/jit/backend/arm/test/test_ztranslation_basic.py @@ -0,0 +1,13 @@ +from rpython.jit.backend.llsupport.test.ztranslation_test import TranslationTest +from rpython.translator.translator import TranslationContext +from rpython.config.translationoption import DEFL_GC +from rpython.jit.backend.arm.test.support import skip_unless_run_slow_tests +skip_unless_run_slow_tests() + + +class TestTranslationX86(TranslationTest): + def _check_cbuilder(self, cbuilder): + # We assume here that we have sse2. If not, the CPUClass + # needs to be changed to CPU386_NO_SSE2, but well. + assert '-msse2' in cbuilder.eci.compile_extra + assert '-mfpmath=sse' in cbuilder.eci.compile_extra diff --git a/rpython/jit/backend/arm/test/test_ztranslation_call_assembler.py b/rpython/jit/backend/arm/test/test_ztranslation_call_assembler.py new file mode 100644 --- /dev/null +++ b/rpython/jit/backend/arm/test/test_ztranslation_call_assembler.py @@ -0,0 +1,13 @@ +from rpython.jit.backend.llsupport.test.ztranslation_test import TranslationTestCallAssembler +from rpython.translator.translator import TranslationContext +from rpython.config.translationoption import DEFL_GC +from rpython.jit.backend.arm.test.support import skip_unless_run_slow_tests +skip_unless_run_slow_tests() + + +class TestTranslationCallAssemblerX86(TranslationTestCallAssembler): + def _check_cbuilder(self, cbuilder): + # We assume here that we have sse2. If not, the CPUClass + # needs to be changed to CPU386_NO_SSE2, but well. + assert '-msse2' in cbuilder.eci.compile_extra + assert '-mfpmath=sse' in cbuilder.eci.compile_extra \ No newline at end of file diff --git a/rpython/jit/backend/arm/test/test_ztranslation_external_exception.py b/rpython/jit/backend/arm/test/test_ztranslation_external_exception.py new file mode 100644 --- /dev/null +++ b/rpython/jit/backend/arm/test/test_ztranslation_external_exception.py @@ -0,0 +1,15 @@ +from rpython.jit.backend.llsupport.test.ztranslation_test import TranslationRemoveTypePtrTest +from rpython.translator.translator import TranslationContext +from rpython.config.translationoption import DEFL_GC +from rpython.jit.backend.arm.test.support import skip_unless_run_slow_tests +skip_unless_run_slow_tests() + + +class TestTranslationRemoveTypePtrX86(TranslationRemoveTypePtrTest): + def _get_TranslationContext(self): + t = TranslationContext() + t.config.translation.gc = DEFL_GC # 'hybrid' or 'minimark' + t.config.translation.gcrootfinder = 'asmgcc' + t.config.translation.list_comprehension_operations = True + t.config.translation.gcremovetypeptr = True + return t diff --git a/rpython/jit/backend/arm/test/test_ztranslation_jit_stats.py b/rpython/jit/backend/arm/test/test_ztranslation_jit_stats.py new file mode 100644 --- /dev/null +++ b/rpython/jit/backend/arm/test/test_ztranslation_jit_stats.py @@ -0,0 +1,13 @@ +from rpython.jit.backend.llsupport.test.ztranslation_test import TranslationTestJITStats +from rpython.translator.translator import TranslationContext +from rpython.config.translationoption import DEFL_GC +from rpython.jit.backend.arm.test.support import skip_unless_run_slow_tests +skip_unless_run_slow_tests() + + +class TestTranslationJITStatsX86(TranslationTestJITStats): + def _check_cbuilder(self, cbuilder): + # We assume here that we have sse2. If not, the CPUClass + # needs to be changed to CPU386_NO_SSE2, but well. + assert '-msse2' in cbuilder.eci.compile_extra + assert '-mfpmath=sse' in cbuilder.eci.compile_extra \ No newline at end of file diff --git a/rpython/jit/backend/x86/test/test_zrpy_gc_boehm.py b/rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py copy from rpython/jit/backend/x86/test/test_zrpy_gc_boehm.py copy to rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py --- a/rpython/jit/backend/x86/test/test_zrpy_gc_boehm.py +++ b/rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py @@ -1,8 +1,8 @@ import weakref from rpython.rlib.jit import JitDriver, dont_look_inside -from rpython.jit.backend.x86.test.test_zrpy_gc import run, get_entry, compile -from rpython.jit.backend.x86.test.test_ztranslation import fix_annotator_for_vrawbuffer +from rpython.jit.backend.llsupport.test.zrpy_gc_test import run, get_entry, compile +from rpython.jit.backend.llsupport.test.ztranslation_test import fix_annotator_for_vrawbuffer class X(object): def __init__(self, x=0): diff --git a/rpython/jit/backend/x86/test/test_zrpy_gc.py b/rpython/jit/backend/llsupport/test/zrpy_gc_test.py copy from rpython/jit/backend/x86/test/test_zrpy_gc.py copy to rpython/jit/backend/llsupport/test/zrpy_gc_test.py diff --git a/rpython/jit/backend/x86/test/test_zrpy_releasegil.py b/rpython/jit/backend/llsupport/test/zrpy_releasegil_test.py copy from rpython/jit/backend/x86/test/test_zrpy_releasegil.py copy to rpython/jit/backend/llsupport/test/zrpy_releasegil_test.py --- a/rpython/jit/backend/x86/test/test_zrpy_releasegil.py +++ b/rpython/jit/backend/llsupport/test/zrpy_releasegil_test.py @@ -5,8 +5,8 @@ from rpython.rtyper.annlowlevel import llhelper -from rpython.jit.backend.x86.test.test_zrpy_gc import BaseFrameworkTests -from rpython.jit.backend.x86.test.test_zrpy_gc import check +from rpython.jit.backend.llsupport.test.zrpy_gc_test import BaseFrameworkTests +from rpython.jit.backend.llsupport.test.zrpy_gc_test import check from rpython.tool.udir import udir diff --git a/rpython/jit/backend/x86/test/test_ztranslation.py b/rpython/jit/backend/llsupport/test/ztranslation_test.py rename from rpython/jit/backend/x86/test/test_ztranslation.py rename to rpython/jit/backend/llsupport/test/ztranslation_test.py --- a/rpython/jit/backend/x86/test/test_ztranslation.py +++ b/rpython/jit/backend/llsupport/test/ztranslation_test.py @@ -1,17 +1,13 @@ -import py, os, sys +import os, sys from rpython.tool.udir import udir from rpython.rlib.jit import JitDriver, unroll_parameters, set_param from rpython.rlib.jit import PARAMETERS, dont_look_inside from rpython.rlib.jit import promote from rpython.rlib import jit_hooks -from rpython.jit.metainterp.jitprof import Profiler from rpython.jit.backend.detect_cpu import getcpuclass from rpython.jit.backend.test.support import CCompiledMixin from rpython.jit.codewriter.policy import StopAtXPolicy -from rpython.translator.translator import TranslationContext -from rpython.jit.backend.x86.arch import IS_X86_32, IS_X86_64 -from rpython.config.translationoption import DEFL_GC -from rpython.rlib import rgc + def fix_annotator_for_vrawbuffer(monkeypatch): from rpython.rlib.nonconst import NonConstant @@ -25,15 +21,9 @@ monkeypatch.setattr(warmspot, 'hook_for_tests', my_hook_for_tests) -class TestTranslationX86(CCompiledMixin): +class TranslationTest(CCompiledMixin): CPUClass = getcpuclass() - def _check_cbuilder(self, cbuilder): - # We assume here that we have sse2. If not, the CPUClass - # needs to be changed to CPU386_NO_SSE2, but well. - assert '-msse2' in cbuilder.eci.compile_extra - assert '-mfpmath=sse' in cbuilder.eci.compile_extra - def test_stuff_translates(self, monkeypatch): fix_annotator_for_vrawbuffer(monkeypatch) # this is a basic test that tries to hit a number of features and their @@ -108,6 +98,10 @@ res = self.meta_interp(main, [40, -49]) assert res == expected + +class TranslationTestCallAssembler(CCompiledMixin): + CPUClass = getcpuclass() + def test_direct_assembler_call_translates(self, monkeypatch): """Test CALL_ASSEMBLER and the recursion limit""" from rpython.rlib.rstackovf import StackOverflow @@ -185,10 +179,14 @@ assert 1024 <= bound <= 131072 assert bound & (bound-1) == 0 # a power of two + +class TranslationTestJITStats(CCompiledMixin): + CPUClass = getcpuclass() + def test_jit_get_stats(self, monkeypatch): fix_annotator_for_vrawbuffer(monkeypatch) driver = JitDriver(greens = [], reds = ['i']) - + def f(): i = 0 while i < 100000: @@ -205,17 +203,10 @@ assert res == 3 # one for loop, one for entry point and one for the prologue -class TestTranslationRemoveTypePtrX86(CCompiledMixin): + +class TranslationRemoveTypePtrTest(CCompiledMixin): CPUClass = getcpuclass() - def _get_TranslationContext(self): - t = TranslationContext() - t.config.translation.gc = DEFL_GC # 'hybrid' or 'minimark' - t.config.translation.gcrootfinder = 'asmgcc' - t.config.translation.list_comprehension_operations = True - t.config.translation.gcremovetypeptr = True - return t - def test_external_exception_handling_translates(self, monkeypatch): fix_annotator_for_vrawbuffer(monkeypatch) jitdriver = JitDriver(greens = [], reds = ['n', 'total']) diff --git a/rpython/jit/backend/x86/test/test_zrpy_gc.py b/rpython/jit/backend/x86/test/test_zrpy_gc.py --- a/rpython/jit/backend/x86/test/test_zrpy_gc.py +++ b/rpython/jit/backend/x86/test/test_zrpy_gc.py @@ -1,775 +1,1 @@ -""" -This is a test that translates a complete JIT together with a GC and runs it. -It is testing that the GC-dependent aspects basically work, mostly the mallocs -and the various cases of write barrier. -""" - -import weakref -import os -from rpython.rlib import rgc -from rpython.rtyper.lltypesystem import lltype -from rpython.rlib.jit import JitDriver, dont_look_inside -from rpython.rlib.jit import elidable, unroll_safe -from rpython.jit.backend.llsupport.gc import GcLLDescr_framework -from rpython.tool.udir import udir -from rpython.config.translationoption import DEFL_GC - - -class X(object): - def __init__(self, x=0): - self.x = x - - next = None - -class CheckError(Exception): - pass - -def check(flag): - if not flag: - raise CheckError - -def get_entry(g): - - def entrypoint(args): - name = '' - n = 2000 - argc = len(args) - if argc > 1: - name = args[1] - if argc > 2: - n = int(args[2]) - r_list = [] - for i in range(20): - r = g(name, n) - r_list.append(r) - rgc.collect() - rgc.collect(); rgc.collect() - freed = 0 - for r in r_list: - if r() is None: - freed += 1 - print freed - return 0 - - return entrypoint - -def get_functions_to_patch(): - from rpython.jit.backend.llsupport import gc - # - can_use_nursery_malloc1 = gc.GcLLDescr_framework.can_use_nursery_malloc - def can_use_nursery_malloc2(*args): - try: - if os.environ['PYPY_NO_INLINE_MALLOC']: - return False - except KeyError: - pass - return can_use_nursery_malloc1(*args) - # - return {(gc.GcLLDescr_framework, 'can_use_nursery_malloc'): - can_use_nursery_malloc2} - -def compile(f, gc, **kwds): - from rpython.annotator.listdef import s_list_of_strings - from rpython.translator.translator import TranslationContext - from rpython.jit.metainterp.warmspot import apply_jit - from rpython.translator.c import genc - # - t = TranslationContext() - t.config.translation.gc = gc - if gc != 'boehm': - t.config.translation.gcremovetypeptr = True - for name, value in kwds.items(): - setattr(t.config.translation, name, value) - ann = t.buildannotator() - ann.build_types(f, [s_list_of_strings], main_entry_point=True) - t.buildrtyper().specialize() - - if kwds['jit']: - patch = get_functions_to_patch() - old_value = {} - try: - for (obj, attr), value in patch.items(): - old_value[obj, attr] = getattr(obj, attr) - setattr(obj, attr, value) - # - apply_jit(t) - # - finally: - for (obj, attr), oldvalue in old_value.items(): - setattr(obj, attr, oldvalue) - - cbuilder = genc.CStandaloneBuilder(t, f, t.config) - cbuilder.generate_source(defines=cbuilder.DEBUG_DEFINES) - cbuilder.compile() - return cbuilder - -def run(cbuilder, args=''): - # - pypylog = udir.join('test_zrpy_gc.log') - data = cbuilder.cmdexec(args, env={'PYPYLOG': ':%s' % pypylog}) - return data.strip() - -# ______________________________________________________________________ - - -class BaseFrameworkTests(object): - - def setup_class(cls): - funcs = [] - name_to_func = {} - for fullname in dir(cls): - if not fullname.startswith('define'): - continue - definefunc = getattr(cls, fullname) - _, name = fullname.split('_', 1) - beforefunc, loopfunc, afterfunc = definefunc.im_func(cls) - if beforefunc is None: - def beforefunc(n, x): - return n, x, None, None, None, None, None, None, None, None, None, '' - if afterfunc is None: - def afterfunc(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - pass - beforefunc.func_name = 'before_'+name - loopfunc.func_name = 'loop_'+name - afterfunc.func_name = 'after_'+name - funcs.append((beforefunc, loopfunc, afterfunc)) - assert name not in name_to_func - name_to_func[name] = len(name_to_func) - print name_to_func - def allfuncs(name, n): - x = X() - x.foo = 2 - main_allfuncs(name, n, x) - x.foo = 5 - return weakref.ref(x) - def main_allfuncs(name, n, x): - num = name_to_func[name] - n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s = funcs[num][0](n, x) - while n > 0: - myjitdriver.can_enter_jit(num=num, n=n, x=x, x0=x0, x1=x1, - x2=x2, x3=x3, x4=x4, x5=x5, x6=x6, x7=x7, l=l, s=s) - myjitdriver.jit_merge_point(num=num, n=n, x=x, x0=x0, x1=x1, - x2=x2, x3=x3, x4=x4, x5=x5, x6=x6, x7=x7, l=l, s=s) - - n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s = funcs[num][1]( - n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s) - funcs[num][2](n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s) - myjitdriver = JitDriver(greens = ['num'], - reds = ['n', 'x', 'x0', 'x1', 'x2', 'x3', 'x4', - 'x5', 'x6', 'x7', 'l', 's']) - cls.main_allfuncs = staticmethod(main_allfuncs) - cls.name_to_func = name_to_func - OLD_DEBUG = GcLLDescr_framework.DEBUG - try: - GcLLDescr_framework.DEBUG = True - cls.cbuilder = compile(get_entry(allfuncs), DEFL_GC, - gcrootfinder=cls.gcrootfinder, jit=True, - thread=True) - finally: - GcLLDescr_framework.DEBUG = OLD_DEBUG - - def _run(self, name, n, env): - res = self.cbuilder.cmdexec("%s %d" %(name, n), env=env) - assert int(res) == 20 - - def run(self, name, n=2000): - pypylog = udir.join('TestCompileFramework.log') - env = {'PYPYLOG': ':%s' % pypylog, - 'PYPY_NO_INLINE_MALLOC': '1'} - self._run(name, n, env) - env['PYPY_NO_INLINE_MALLOC'] = '' - self._run(name, n, env) - - def run_orig(self, name, n, x): - self.main_allfuncs(name, n, x) - - -class CompileFrameworkTests(BaseFrameworkTests): - # Test suite using (so far) the minimark GC. - -## def define_libffi_workaround(cls): -## # XXX: this is a workaround for a bug in database.py. It seems that -## # the problem is triggered by optimizeopt/fficall.py, and in -## # particular by the ``cast_base_ptr_to_instance(Func, llfunc)``: in -## # these tests, that line is the only place where libffi.Func is -## # referenced. -## # -## # The problem occurs because the gctransformer tries to annotate a -## # low-level helper to call the __del__ of libffi.Func when it's too -## # late. -## # -## # This workaround works by forcing the annotator (and all the rest of -## # the toolchain) to see libffi.Func in a "proper" context, not just as -## # the target of cast_base_ptr_to_instance. Note that the function -## # below is *never* called by any actual test, it's just annotated. -## # -## from rpython.rlib.libffi import get_libc_name, CDLL, types, ArgChain -## libc_name = get_libc_name() -## def f(n, x, *args): -## libc = CDLL(libc_name) -## ptr = libc.getpointer('labs', [types.slong], types.slong) -## chain = ArgChain() -## chain.arg(n) -## n = ptr.call(chain, lltype.Signed) -## return (n, x) + args -## return None, f, None - - def define_compile_framework_1(cls): - # a moving GC. Supports malloc_varsize_nonmovable. Simple test, works - # without write_barriers and root stack enumeration. - def f(n, x, *args): - y = X() - y.foo = x.foo - n -= y.foo - return (n, x) + args - return None, f, None - - def test_compile_framework_1(self): - self.run('compile_framework_1') - - def define_compile_framework_2(cls): - # More complex test, requires root stack enumeration but - # not write_barriers. - def f(n, x, *args): - prev = x - for j in range(101): # f() runs 20'000 times, thus allocates - y = X() # a total of 2'020'000 objects - y.foo = prev.foo - prev = y - n -= prev.foo - return (n, x) + args - return None, f, None - - def test_compile_framework_2(self): - self.run('compile_framework_2') - - def define_compile_framework_3(cls): - # Third version of the test. Really requires write_barriers. - def f(n, x, *args): - x.next = None - for j in range(101): # f() runs 20'000 times, thus allocates - y = X() # a total of 2'020'000 objects - y.foo = j+1 - y.next = x.next - x.next = y - check(x.next.foo == 101) - total = 0 - y = x - for j in range(101): - y = y.next - total += y.foo - check(not y.next) - check(total == 101*102/2) - n -= x.foo - return (n, x) + args - return None, f, None - - - - def test_compile_framework_3(self): - x_test = X() - x_test.foo = 5 - self.run_orig('compile_framework_3', 6, x_test) # check that it does not raise CheckError - self.run('compile_framework_3') - - def define_compile_framework_3_extra(cls): - # Extra version of the test, with tons of live vars around the residual - # call that all contain a GC pointer. - @dont_look_inside - def residual(n=26): - x = X() - x.next = X() - x.next.foo = n - return x - # - def before(n, x): - residual(5) - x0 = residual() - x1 = residual() - x2 = residual() - x3 = residual() - x4 = residual() - x5 = residual() - x6 = residual() - x7 = residual() - n *= 19 - return n, None, x0, x1, x2, x3, x4, x5, x6, x7, None, None - def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - x8 = residual() - x9 = residual() - check(x0.next.foo == 26) - check(x1.next.foo == 26) - check(x2.next.foo == 26) - check(x3.next.foo == 26) - check(x4.next.foo == 26) - check(x5.next.foo == 26) - check(x6.next.foo == 26) - check(x7.next.foo == 26) - check(x8.next.foo == 26) - check(x9.next.foo == 26) - x0, x1, x2, x3, x4, x5, x6, x7 = x7, x4, x6, x5, x3, x2, x9, x8 - n -= 1 - return n, None, x0, x1, x2, x3, x4, x5, x6, x7, None, None - return before, f, None - - def test_compile_framework_3_extra(self): - self.run_orig('compile_framework_3_extra', 6, None) # check that it does not raise CheckError - self.run('compile_framework_3_extra') - - def define_compile_framework_4(cls): - # Fourth version of the test, with __del__. - from rpython.rlib.debug import debug_print - class Counter: - cnt = 0 - counter = Counter() - class Z: - def __del__(self): - counter.cnt -= 1 - def before(n, x): - debug_print('counter.cnt =', counter.cnt) - check(counter.cnt < 5) - counter.cnt = n // x.foo - return n, x, None, None, None, None, None, None, None, None, None, None - def f(n, x, *args): - Z() - n -= x.foo - return (n, x) + args - return before, f, None - - def test_compile_framework_4(self): - self.run('compile_framework_4') - - def define_compile_framework_5(cls): - # Test string manipulation. - def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - n -= x.foo - s += str(n) - return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s - def after(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - check(len(s) == 1*5 + 2*45 + 3*450 + 4*500) - return None, f, after - - def test_compile_framework_5(self): - self.run('compile_framework_5') - - def define_compile_framework_7(cls): - # Array of pointers (test the write barrier for setarrayitem_gc) - def before(n, x): - return n, x, None, None, None, None, None, None, None, None, [X(123)], None - def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - if n < 1900: - check(l[0].x == 123) - l = [None] * 16 - l[0] = X(123) - l[1] = X(n) - l[2] = X(n+10) - l[3] = X(n+20) - l[4] = X(n+30) - l[5] = X(n+40) - l[6] = X(n+50) - l[7] = X(n+60) - l[8] = X(n+70) - l[9] = X(n+80) - l[10] = X(n+90) - l[11] = X(n+100) - l[12] = X(n+110) - l[13] = X(n+120) - l[14] = X(n+130) - l[15] = X(n+140) - if n < 1800: - check(len(l) == 16) - check(l[0].x == 123) - check(l[1].x == n) - check(l[2].x == n+10) - check(l[3].x == n+20) - check(l[4].x == n+30) - check(l[5].x == n+40) - check(l[6].x == n+50) - check(l[7].x == n+60) - check(l[8].x == n+70) - check(l[9].x == n+80) - check(l[10].x == n+90) - check(l[11].x == n+100) - check(l[12].x == n+110) - check(l[13].x == n+120) - check(l[14].x == n+130) - check(l[15].x == n+140) - n -= x.foo - return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s - def after(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - check(len(l) == 16) - check(l[0].x == 123) - check(l[1].x == 2) - check(l[2].x == 12) - check(l[3].x == 22) - check(l[4].x == 32) - check(l[5].x == 42) - check(l[6].x == 52) - check(l[7].x == 62) - check(l[8].x == 72) - check(l[9].x == 82) - check(l[10].x == 92) - check(l[11].x == 102) - check(l[12].x == 112) - check(l[13].x == 122) - check(l[14].x == 132) - check(l[15].x == 142) - return before, f, after - - def test_compile_framework_7(self): - self.run('compile_framework_7') - - def define_compile_framework_7_interior(cls): - # Array of structs containing pointers (test the write barrier - # for setinteriorfield_gc) - S = lltype.GcStruct('S', ('i', lltype.Signed)) - A = lltype.GcArray(lltype.Struct('entry', ('x', lltype.Ptr(S)), - ('y', lltype.Ptr(S)), - ('z', lltype.Ptr(S)))) - class Glob: - a = lltype.nullptr(A) - glob = Glob() - # - def make_s(i): - s = lltype.malloc(S) - s.i = i - return s - # - @unroll_safe - def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - a = glob.a - if not a: - a = glob.a = lltype.malloc(A, 10) - i = 0 - while i < 10: - a[i].x = make_s(n + i * 100 + 1) - a[i].y = make_s(n + i * 100 + 2) - a[i].z = make_s(n + i * 100 + 3) - i += 1 - i = 0 - while i < 10: - check(a[i].x.i == n + i * 100 + 1) - check(a[i].y.i == n + i * 100 + 2) - check(a[i].z.i == n + i * 100 + 3) - i += 1 - n -= x.foo - return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s - return None, f, None - - def test_compile_framework_7_interior(self): - self.run('compile_framework_7_interior') - - def define_compile_framework_8(cls): - # Array of pointers, of unknown length (test write_barrier_from_array) - def before(n, x): - return n, x, None, None, None, None, None, None, None, None, [X(123)], None - def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - if n < 1900: - check(l[0].x == 123) - l = [None] * (16 + (n & 7)) - l[0] = X(123) - l[1] = X(n) - l[2] = X(n+10) - l[3] = X(n+20) - l[4] = X(n+30) - l[5] = X(n+40) - l[6] = X(n+50) - l[7] = X(n+60) - l[8] = X(n+70) - l[9] = X(n+80) - l[10] = X(n+90) - l[11] = X(n+100) - l[12] = X(n+110) - l[13] = X(n+120) - l[14] = X(n+130) - l[15] = X(n+140) - if n < 1800: - check(len(l) == 16 + (n & 7)) - check(l[0].x == 123) - check(l[1].x == n) - check(l[2].x == n+10) - check(l[3].x == n+20) - check(l[4].x == n+30) - check(l[5].x == n+40) - check(l[6].x == n+50) - check(l[7].x == n+60) - check(l[8].x == n+70) - check(l[9].x == n+80) - check(l[10].x == n+90) - check(l[11].x == n+100) - check(l[12].x == n+110) - check(l[13].x == n+120) - check(l[14].x == n+130) - check(l[15].x == n+140) - n -= x.foo - return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s - def after(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - check(len(l) >= 16) - check(l[0].x == 123) - check(l[1].x == 2) - check(l[2].x == 12) - check(l[3].x == 22) - check(l[4].x == 32) - check(l[5].x == 42) - check(l[6].x == 52) - check(l[7].x == 62) - check(l[8].x == 72) - check(l[9].x == 82) - check(l[10].x == 92) - check(l[11].x == 102) - check(l[12].x == 112) - check(l[13].x == 122) - check(l[14].x == 132) - check(l[15].x == 142) - return before, f, after - - def test_compile_framework_8(self): - self.run('compile_framework_8') - - def define_compile_framework_9(cls): - # Like compile_framework_8, but with variable indexes and large - # arrays, testing the card_marking case - def before(n, x): - return n, x, None, None, None, None, None, None, None, None, [X(123)], None - def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): From noreply at buildbot.pypy.org Thu Apr 11 21:08:28 2013 From: noreply at buildbot.pypy.org (bivab) Date: Thu, 11 Apr 2013 21:08:28 +0200 (CEST) Subject: [pypy-commit] pypy default: merge heads Message-ID: <20130411190828.C55701C23C8@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63242:fec8fb85c22d Date: 2013-04-11 21:08 +0200 http://bitbucket.org/pypy/pypy/changeset/fec8fb85c22d/ Log: merge heads diff --git a/README.rst b/README.rst --- a/README.rst +++ b/README.rst @@ -13,9 +13,9 @@ http://pypy.org/ -The getting-started document will help guide you: +If you want to help developing PyPy, this document might help you: - http://doc.pypy.org/en/latest/getting-started.html + http://doc.pypy.org/ It will also point you to the rest of the documentation which is generated from files in the pypy/doc directory within the source repositories. Enjoy diff --git a/pypy/doc/dir-reference.rst b/pypy/doc/dir-reference.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/dir-reference.rst @@ -0,0 +1,140 @@ +PyPy directory cross-reference +------------------------------ + +Here is a fully referenced alphabetical two-level deep +directory overview of PyPy: + +================================= ============================================ +Directory explanation/links +================================= ============================================ +`pypy/bin/`_ command-line scripts, mainly + `pypy/bin/pyinteractive.py`_ + +`pypy/config/`_ handles the numerous options for building + and running PyPy + +`pypy/doc/`_ text versions of PyPy developer + documentation + +`pypy/doc/config/`_ documentation for the numerous translation + options + +`pypy/doc/discussion/`_ drafts of ideas and documentation + +``doc/*/`` other specific documentation topics or tools + +`pypy/interpreter/`_ `bytecode interpreter`_ and related objects + (frames, functions, modules,...) + +`pypy/interpreter/pyparser/`_ interpreter-level Python source parser + +`pypy/interpreter/astcompiler/`_ interpreter-level bytecode compiler, + via an AST representation + +`pypy/module/`_ contains `mixed modules`_ + implementing core modules with + both application and interpreter level code. + Not all are finished and working. Use + the ``--withmod-xxx`` + or ``--allworkingmodules`` translation + options. + +`pypy/objspace/`_ `object space`_ implementations + +`pypy/objspace/std/`_ the StdObjSpace_ implementing CPython's + objects and types + +`pypy/tool/`_ various utilities and hacks used + from various places + +`pypy/tool/algo/`_ general-purpose algorithmic and mathematic + tools + +`pypy/tool/pytest/`_ support code for our `testing methods`_ + + +`rpython/annotator/`_ `type inferencing code`_ for + `RPython`_ programs + +`rpython/config/`_ handles the numerous options for RPython + + +`rpython/flowspace/`_ the FlowObjSpace_ implementing + `abstract interpretation`_ + +`rpython/rlib/`_ a `"standard library"`_ for RPython_ + programs + +`rpython/rtyper/`_ the `RPython Typer`_ + +`rpython/rtyper/lltypesystem/`_ the `low-level type system`_ for + C-like backends + +`rpython/rtyper/ootypesystem/`_ the `object-oriented type system`_ + for OO backends + +`rpython/memory/`_ the `garbage collector`_ construction + framework + +`rpython/translator/`_ translation_ backends and support code + +`rpython/translator/backendopt/`_ general optimizations that run before a + backend generates code + +`rpython/translator/c/`_ the `GenC backend`_, producing C code + from an + RPython program (generally via the rtyper_) + +`rpython/translator/cli/`_ the `CLI backend`_ for `.NET`_ + (Microsoft CLR or Mono_) + +`pypy/goal/`_ our `main PyPy-translation scripts`_ + live here + +`rpython/translator/jvm/`_ the Java backend + +`rpython/translator/tool/`_ helper tools for translation + +`dotviewer/`_ `graph viewer`_ + +``*/test/`` many directories have a test subdirectory + containing test + modules (see `Testing in PyPy`_) + +``_cache/`` holds cache files from various purposes +================================= ============================================ + +.. _`bytecode interpreter`: interpreter.html +.. _`Testing in PyPy`: coding-guide.html#testing-in-pypy +.. _`mixed modules`: coding-guide.html#mixed-modules +.. _`modules`: coding-guide.html#modules +.. _`basil`: http://people.cs.uchicago.edu/~jriehl/BasilTalk.pdf +.. _`object space`: objspace.html +.. _FlowObjSpace: objspace.html#the-flow-object-space +.. _`transparent proxies`: objspace-proxies.html#tproxy +.. _`Differences between PyPy and CPython`: cpython_differences.html +.. _`What PyPy can do for your objects`: objspace-proxies.html +.. _`Continulets and greenlets`: stackless.html +.. _StdObjSpace: objspace.html#the-standard-object-space +.. _`abstract interpretation`: http://en.wikipedia.org/wiki/Abstract_interpretation +.. _`rpython`: coding-guide.html#rpython +.. _`type inferencing code`: translation.html#the-annotation-pass +.. _`RPython Typer`: translation.html#rpython-typer +.. _`testing methods`: coding-guide.html#testing-in-pypy +.. _`translation`: translation.html +.. _`GenC backend`: translation.html#genc +.. _`CLI backend`: cli-backend.html +.. _`py.py`: getting-started-python.html#the-py.py-interpreter +.. _`translatorshell.py`: getting-started-dev.html#try-out-the-translator +.. _JIT: jit/index.html +.. _`JIT Generation in PyPy`: jit/index.html +.. _`just-in-time compiler generator`: jit/index.html +.. _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 +.. _`main PyPy-translation scripts`: getting-started-python.html#translating-the-pypy-python-interpreter +.. _`.NET`: http://www.microsoft.com/net/ +.. _Mono: http://www.mono-project.com/ +.. _`"standard library"`: rlib.html +.. _`graph viewer`: getting-started-dev.html#try-out-the-translator diff --git a/pypy/doc/getting-started-dev.rst b/pypy/doc/getting-started-dev.rst --- a/pypy/doc/getting-started-dev.rst +++ b/pypy/doc/getting-started-dev.rst @@ -1,13 +1,58 @@ -=============================================================================== -Getting Started with the Translation Toolchain and Development Process -=============================================================================== +============================ +Getting Started with RPython +============================ .. contents:: +RPython is a subset of Python that can be statically compiled. The PyPy +interpreter is written mostly in RPython (with pieces in Python), while +the RPython compiler is written in Python. The hard to understand part +is that Python is a meta-programming language for RPython, that is, +RPython is considered from live objects **after** the imports are done. +This might require more explanation. You start writing RPython from +``entry_point``, a good starting point is +``rpython/translator/goal/targetnopstandalone.py``. This does not do all that +much, but is a start. Now if code analyzed (in this case ``entry_point``) +calls some functions, those calls will be followed. Those followed calls +have to be RPython themselves (and everything they call etc.), however not +entire module files. To show how you can use metaprogramming, we can do +a silly example (note that closures are not RPython):: + + def generator(operation): + if operation == 'add': + def f(a, b): + return a + b + else: + def f(a, b): + return a - b + return f + + add = generator('add') + sub = generator('sub') + + def entry_point(argv): + print add(sub(int(argv[1]), 3) 4) + return 0 + +In this example ``entry_point`` is RPython, ``add`` and ``sub`` are RPython, +however, ``generator`` is not. + +A good introductory level articles are available: + +* Laurence Tratt -- `Fast Enough VMs in Fast Enough Time`_. + +* `How to write interpreters in RPython`_ and `part 2`_ by Andrew Brown. + +.. _`Fast Enough VMs in Fast Enough Time`: http://tratt.net/laurie/tech_articles/articles/fast_enough_vms_in_fast_enough_time + +.. _`How to write interpreters in RPython`: http://morepypy.blogspot.com/2011/04/tutorial-writing-interpreter-with-pypy.html + +.. _`part 2`: http://morepypy.blogspot.com/2011/04/tutorial-part-2-adding-jit.html + .. _`try out the translator`: Trying out the translator -------------------------- +------------------------- The translator is a tool based on the PyPy interpreter which can translate sufficiently static RPython programs into low-level code (in particular it can @@ -28,7 +73,7 @@ >>> t = Translation(snippet.is_perfect_number, [int]) >>> t.view() - + After that, the graph viewer pops up, that lets you interactively inspect the flow graph. To move around, click on something that you want to inspect. To get help about how to use it, press 'H'. To close it again, press 'Q'. @@ -83,10 +128,10 @@ The object returned by ``compile_cli`` or ``compile_jvm`` is a wrapper around the real executable: the parameters are passed as command line arguments, and -the returned value is read from the standard output. +the returned value is read from the standard output. Once you have compiled the snippet, you can also try to launch the -executable directly from the shell. You will find the +executable directly from the shell. You will find the executable in one of the ``/tmp/usession-*`` directories:: # For CLI: diff --git a/pypy/doc/getting-started-python.rst b/pypy/doc/getting-started-python.rst --- a/pypy/doc/getting-started-python.rst +++ b/pypy/doc/getting-started-python.rst @@ -6,7 +6,7 @@ PyPy's Python interpreter is a very compliant Python -interpreter implemented in Python. When translated to C, it passes most of +interpreter implemented in RPython. When compiled, it passes most of `CPythons core language regression tests`_ and comes with many of the extension modules included in the standard library including ``ctypes``. It can run large libraries such as Django_ and Twisted_. There are some small behavioral @@ -147,6 +147,8 @@ Translating using the CLI backend +++++++++++++++++++++++++++++++++ +**Note: the CLI backend is no longer maintained** + To create a standalone .NET executable using the `CLI backend`_:: ./translate.py --backend=cli targetpypystandalone.py diff --git a/pypy/doc/how-to-contribute.rst b/pypy/doc/how-to-contribute.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/how-to-contribute.rst @@ -0,0 +1,78 @@ +How to contribute to PyPy +------------------------- + +This page describes how to contribute to the PyPy project. The first thing +to remember is that PyPy project is very different than most projects out there. +It's also different from a classic compiler project, so academic courses +about compilers often don't apply or lead in the wrong direction. + +Don't just hack +--------------- + +The first and most important rule how not to contribute to PyPy is +"just hacking". This won't work. There are two major reasons why not +-- build times are large and PyPy has very thick layer separation which +make it harder to "just hack a feature". + +Test driven development +----------------------- + +Instead, we practice a lot of test driven development. This is partly because +of very high quality requirements for compilers and partly because there is +simply no other way to get around such complex project, that will keep you sane. +There are probably people out there who are smart enough not to need it, we're +not one of those. You may consider familiarizing yourself with `pytest`_, +since this is a tool we use for tests. +This leads to the next issue: + +Layers +------ + +PyPy has layers. Those layers help us keep the respective parts separated enough +to be worked on independently and make the complexity manageable. This is, +again, just a sanity requirement for such a complex project. For example writing +a new optimization for the JIT usually does **not** involve touching a Python +interpreter at all or the JIT assembler backend or the garbage collector. +Instead it requires writing small tests in +``rpython/jit/metainterp/optimizeopt/test/test_*`` and fixing files there. +After that, you can just compile PyPy and things should just work. + +The short list of layers for further reading. For each of those layers, a good +entry point is a test subdirectory in respective directories. It usually +describes (better or worse) the interfaces between the submodules. For the +``pypy`` subdirectory, most tests are small snippets of python programs that +check for correctness (calls ``AppTestXxx``) that will call the appropriate +part of the interpreter. For the ``rpython`` directory, most tests are small +RPython interpreters that perform certain tasks. To see how they translate +to low-level graphs, run them with ``--view``. To see small interpreters +with a JIT compiler, use ``--viewloops`` option. + +* **python interpreter** - it's the part implemented in the ``pypy/`` directory. + It's implemented in RPython, which is a high level static language with + classes, garbage collection, just-in-time compiler generation and the ability + to call C. A cool part about it is that it can be run untranslated, so all + the tests are runnable without translating PyPy. + + **interpreter** contains the interpreter core + + **objspace** contains implementations of various objects exported to + the Python layer + + **module** directory contains extension modules written in RPython + +* **rpython compiler** that resides in ``rpython/annotator`` and + ``rpython/rtyper`` directories. Consult `introduction to RPython`_ for + further reading + +* **JIT generator** lives in ``rpython/jit`` directory. optimizations live + in ``rpython/jit/metainterp/optimizeopt``, the main JIT in + ``rpython/jit/metainterp`` (runtime part) and + ``rpython/jit/codewriter`` (translation-time part). Backends live in + ``rpython/jit/backend``. + +* **garbage collection** lives in ``rpython/memory`` + +The rest of directories serve specific niche goal and are unlikely a good +entry point. + +.. _`introduction to RPython`: getting-started-dev.rst diff --git a/pypy/doc/index.rst b/pypy/doc/index.rst --- a/pypy/doc/index.rst +++ b/pypy/doc/index.rst @@ -1,15 +1,39 @@ -Welcome to PyPy Development -============================================= +Welcome to PyPy +=============== -The PyPy project aims at producing a flexible and fast Python_ -implementation. The guiding idea is to translate a Python-level -description of the Python language itself to lower level languages. -Rumors have it that the secret goal is being faster-than-C which is -nonsense, isn't it? `more...`_ +The PyPy project aims to produce a flexible and fast Python_ +implementation. This page documents the development of the PyPy +project itself. If you don't know what PyPy is, consult the `PyPy +website`_. If you just want to use PyPy, consult the `download`_ page +and the `getting started with pypy`_ documents. If you want to help +develop PyPy -- keep reading! -Getting into PyPy ... -============================================= +PyPy is written in a language called `RPython`_, which is suitable for +writing dynamic language interpreters (and not much else). RPython is +a subset of Python and is itself written in Python. If you'd like to +learn more about RPython, `Starting with RPython`_ should provide a +reasonable overview. + +**If you would like to contribute to PyPy**, please read `how to +contribute`_ first. PyPy's development style is somewhat different to +that of many other software projects and it often surprises +newcomers. What is **not** necessary is an academic background from +university in writing compilers -- much of it does not apply to PyPy +any way. + +All of the documentation and source code is available under the MIT license, +unless otherwise specified. Consult `LICENSE`_ + +.. _`download`: http://pypy.org/download.html +.. _`getting started with pypy`: getting-started-python.html +.. _`RPython`: coding-guide.html#RPython +.. _`Starting with RPython`: getting-started-dev.html +.. _`how to contribute`: how-to-contribute.html +.. _`PyPy website`: http://pypy.org + +Index of various topics: +======================== * `Getting started`_: how to install and run the PyPy Python interpreter @@ -25,20 +49,32 @@ * `potential project ideas`_: In case you want to get your feet wet... +* `more stuff`_: this is a collection of documentation that's there, but not + particularly organized + Documentation for the PyPy Python Interpreter -=============================================== +============================================= New features of PyPy's Python Interpreter and Translation Framework: * `Differences between PyPy and CPython`_ - * `What PyPy can do for your objects`_ - * `Continulets and greenlets`_ + * `What PyPy can do for your objects`_ - transparent proxy documentation + * `Continulets and greenlets`_ - documentation about stackless features * `JIT Generation in PyPy`_ + * `JIT hooks`_ * `Sandboxing Python code`_ + * `Garbage collection environment variables`_ Status_ of the project. +.. _`Differences between PyPy and CPython`: cpython_differences.html +.. _`What PyPy can do for your objects`: objspace-proxies.html +.. _`Continulets and greenlets_`: stackless.html +.. _`JIT Generation in PyPy`: jit/index.html +.. _`JIT hooks`: jit-hooks.html +.. _`Sandboxing Python code`: sandbox.html +.. _`Garbage collection environment variables`: gc_info.html Mailing lists, bug tracker, IRC channel ============================================= @@ -79,354 +115,6 @@ .. _`speed.pypy.org`: http://speed.pypy.org .. _`RPython toolchain`: translation.html .. _`potential project ideas`: project-ideas.html - -Project Documentation -===================================== - -PyPy was funded by the EU for several years. See the `web site of the EU -project`_ for more details. - -.. _`web site of the EU project`: http://pypy.org - -architecture_ gives a complete view of PyPy's basic design. - -`coding guide`_ helps you to write code for PyPy (especially also describes -coding in RPython a bit). - -`sprint reports`_ lists reports written at most of our sprints, from -2003 to the present. - -`papers, talks and related projects`_ lists presentations -and related projects as well as our published papers. - -`PyPy video documentation`_ is a page linking to the videos (e.g. of talks and -introductions) that are available. - -`Technical reports`_ is a page that contains links to the -reports that we submitted to the European Union. - -`development methodology`_ describes our sprint-driven approach. - -`LICENSE`_ contains licensing details (basically a straight MIT-license). - -`Glossary`_ of PyPy words to help you align your inner self with -the PyPy universe. - - -Status -=================================== - -PyPy can be used to run Python programs on Linux, OS/X, -Windows, on top of .NET, and on top of Java. -To dig into PyPy it is recommended to try out the current -Mercurial default branch, which is always working or mostly working, -instead of the latest release, which is `2.0 beta1`__. - -.. __: release-2.0.0-beta1.html - -PyPy is mainly developed on Linux and Mac OS X. Windows is supported, -but platform-specific bugs tend to take longer before we notice and fix -them. Linux 64-bit machines are supported (though it may also take some -time before we notice and fix bugs). - -PyPy's own tests `summary`_, daily updated, run through BuildBot infrastructure. -You can also find CPython's compliance tests run with compiled ``pypy-c`` -executables there. - - -Source Code Documentation -=============================================== - -`object spaces`_ discusses the object space interface -and several implementations. - -`bytecode interpreter`_ explains the basic mechanisms -of the bytecode interpreter and virtual machine. - -`interpreter optimizations`_ describes our various strategies for -improving the performance of our interpreter, including alternative -object implementations (for strings, dictionaries and lists) in the -standard object space. - -`translation`_ is a detailed overview of our translation process. The -rtyper_ is the largest component of our translation process. - -`dynamic-language translation`_ is a paper that describes -the translation process, especially the flow object space -and the annotator in detail. (This document is one -of the `EU reports`_.) - -`low-level encapsulation`_ describes how our approach hides -away a lot of low level details. This document is also part -of the `EU reports`_. - -`translation aspects`_ describes how we weave different -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. - -`rlib`_ describes some modules that can be used when implementing programs in -RPython. - -`configuration documentation`_ describes the various configuration options that -allow you to customize PyPy. - -`CLI backend`_ describes the details of the .NET backend. - -`JIT Generation in PyPy`_ describes how we produce the Python Just-in-time Compiler -from our Python interpreter. - - - -.. _`FAQ`: faq.html -.. _Glossary: glossary.html -.. _`PyPy video documentation`: video-index.html -.. _parser: parser.html -.. _`development methodology`: dev_method.html -.. _`sprint reports`: sprint-reports.html -.. _`papers, talks and related projects`: extradoc.html -.. _`object spaces`: objspace.html -.. _`interpreter optimizations`: interpreter-optimizations.html -.. _`translation`: translation.html -.. _`dynamic-language translation`: https://bitbucket.org/pypy/extradoc/raw/tip/eu-report/D05.1_Publish_on_translating_a_very-high-level_description.pdf -.. _`low-level encapsulation`: low-level-encapsulation.html -.. _`translation aspects`: translation-aspects.html -.. _`configuration documentation`: config/ -.. _`coding guide`: coding-guide.html -.. _`architecture`: architecture.html -.. _`getting started`: getting-started.html -.. _`bytecode interpreter`: interpreter.html -.. _`EU reports`: index-report.html -.. _`Technical reports`: index-report.html -.. _`summary`: http://buildbot.pypy.org/summary -.. _`ideas for PyPy related projects`: project-ideas.html -.. _`Nightly builds and benchmarks`: http://tuatara.cs.uni-duesseldorf.de/benchmark.html -.. _`directory reference`: -.. _`rlib`: rlib.html -.. _`Sandboxing Python code`: sandbox.html -.. _`LICENSE`: https://bitbucket.org/pypy/pypy/src/default/LICENSE - -PyPy directory cross-reference ------------------------------- - -Here is a fully referenced alphabetical two-level deep -directory overview of PyPy: - -================================= ============================================ -Directory explanation/links -================================= ============================================ -`pypy/bin/`_ command-line scripts, mainly - `pypy/bin/pyinteractive.py`_ - -`pypy/config/`_ handles the numerous options for building - and running PyPy - -`pypy/doc/`_ text versions of PyPy developer - documentation - -`pypy/doc/config/`_ documentation for the numerous translation - options - -`pypy/doc/discussion/`_ drafts of ideas and documentation - -``doc/*/`` other specific documentation topics or tools - -`pypy/interpreter/`_ `bytecode interpreter`_ and related objects - (frames, functions, modules,...) - -`pypy/interpreter/pyparser/`_ interpreter-level Python source parser - -`pypy/interpreter/astcompiler/`_ interpreter-level bytecode compiler, - via an AST representation - -`pypy/module/`_ contains `mixed modules`_ - implementing core modules with - both application and interpreter level code. - Not all are finished and working. Use - the ``--withmod-xxx`` - or ``--allworkingmodules`` translation - options. - -`pypy/objspace/`_ `object space`_ implementations - -`pypy/objspace/std/`_ the StdObjSpace_ implementing CPython's - objects and types - -`pypy/tool/`_ various utilities and hacks used - from various places - -`pypy/tool/algo/`_ general-purpose algorithmic and mathematic - tools - -`pypy/tool/pytest/`_ support code for our `testing methods`_ - - -`rpython/annotator/`_ `type inferencing code`_ for - `RPython`_ programs - -`rpython/config/`_ handles the numerous options for RPython - - -`rpython/flowspace/`_ the FlowObjSpace_ implementing - `abstract interpretation`_ - -`rpython/rlib/`_ a `"standard library"`_ for RPython_ - programs - -`rpython/rtyper/`_ the `RPython Typer`_ - -`rpython/rtyper/lltypesystem/`_ the `low-level type system`_ for - C-like backends - -`rpython/rtyper/ootypesystem/`_ the `object-oriented type system`_ - for OO backends - -`rpython/memory/`_ the `garbage collector`_ construction - framework - -`rpython/translator/`_ translation_ backends and support code - -`rpython/translator/backendopt/`_ general optimizations that run before a - backend generates code - -`rpython/translator/c/`_ the `GenC backend`_, producing C code - from an - RPython program (generally via the rtyper_) - -`rpython/translator/cli/`_ the `CLI backend`_ for `.NET`_ - (Microsoft CLR or Mono_) - -`pypy/goal/`_ our `main PyPy-translation scripts`_ - live here - -`rpython/translator/jvm/`_ the Java backend - -`rpython/translator/tool/`_ helper tools for translation - -`dotviewer/`_ `graph viewer`_ - -``*/test/`` many directories have a test subdirectory - containing test - modules (see `Testing in PyPy`_) - -``_cache/`` holds cache files from various purposes -================================= ============================================ - -.. _`bytecode interpreter`: interpreter.html -.. _`Testing in PyPy`: coding-guide.html#testing-in-pypy -.. _`mixed modules`: coding-guide.html#mixed-modules -.. _`modules`: coding-guide.html#modules -.. _`basil`: http://people.cs.uchicago.edu/~jriehl/BasilTalk.pdf -.. _`object space`: objspace.html -.. _FlowObjSpace: objspace.html#the-flow-object-space -.. _`transparent proxies`: objspace-proxies.html#tproxy -.. _`Differences between PyPy and CPython`: cpython_differences.html -.. _`What PyPy can do for your objects`: objspace-proxies.html -.. _`Continulets and greenlets`: stackless.html -.. _StdObjSpace: objspace.html#the-standard-object-space -.. _`abstract interpretation`: http://en.wikipedia.org/wiki/Abstract_interpretation -.. _`rpython`: coding-guide.html#rpython -.. _`type inferencing code`: translation.html#the-annotation-pass -.. _`RPython Typer`: translation.html#rpython-typer -.. _`testing methods`: coding-guide.html#testing-in-pypy -.. _`translation`: translation.html -.. _`GenC backend`: translation.html#genc -.. _`CLI backend`: cli-backend.html -.. _`py.py`: getting-started-python.html#the-py.py-interpreter -.. _`translatorshell.py`: getting-started-dev.html#try-out-the-translator -.. _JIT: jit/index.html -.. _`JIT Generation in PyPy`: jit/index.html -.. _`just-in-time compiler generator`: jit/index.html -.. _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 -.. _`main PyPy-translation scripts`: getting-started-python.html#translating-the-pypy-python-interpreter -.. _`.NET`: http://www.microsoft.com/net/ -.. _Mono: http://www.mono-project.com/ -.. _`"standard library"`: rlib.html -.. _`graph viewer`: getting-started-dev.html#try-out-the-translator - - -.. The following documentation is important and reasonably up-to-date: - -.. extradoc: should this be integrated one level up: dcolish? - - -.. toctree:: - :maxdepth: 1 - :hidden: - - getting-started.rst - getting-started-python.rst - getting-started-dev.rst - windows.rst - faq.rst - commandline_ref.rst - architecture.rst - coding-guide.rst - cpython_differences.rst - garbage_collection.rst - gc_info.rst - interpreter.rst - objspace.rst - __pypy__-module.rst - objspace-proxies.rst - config/index.rst - - dev_method.rst - extending.rst - - extradoc.rst - video-index.rst - - glossary.rst - - contributor.rst - - interpreter-optimizations.rst - configuration.rst - parser.rst - rlib.rst - rtyper.rst - rffi.rst - - translation.rst - jit/index.rst - jit/overview.rst - jit/pyjitpl5.rst - - index-of-release-notes.rst - - ctypes-implementation.rst - - how-to-release.rst - - index-report.rst - - stackless.rst - sandbox.rst - - discussions.rst - - cleanup.rst - - sprint-reports.rst - - eventhistory.rst - statistic/index.rst - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`search` -* :ref:`glossary` - +.. _`more stuff`: project-documentation.html .. include:: _ref.txt diff --git a/pypy/doc/needswork.txt b/pypy/doc/needswork.txt deleted file mode 100644 --- a/pypy/doc/needswork.txt +++ /dev/null @@ -1,3 +0,0 @@ -.. warning:: - - This documentation needs work (as discussed during the Gothenburg sprint in 2011) diff --git a/pypy/doc/objspace-proxies.rst b/pypy/doc/objspace-proxies.rst --- a/pypy/doc/objspace-proxies.rst +++ b/pypy/doc/objspace-proxies.rst @@ -5,7 +5,6 @@ .. contents:: - Thanks to the `Object Space`_ architecture, any feature that is based on proxying, extending, changing or otherwise controlling the behavior of all objects in a running program is easy to implement on diff --git a/pypy/doc/project-documentation.rst b/pypy/doc/project-documentation.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/project-documentation.rst @@ -0,0 +1,177 @@ + +Project Documentation +===================================== + +`architecture`_ gives a complete view of PyPy's basic design. + +`coding guide`_ helps you to write code for PyPy (especially also describes +coding in RPython a bit). + +`sprint reports`_ lists reports written at most of our sprints, from +2003 to the present. + +`papers, talks and related projects`_ lists presentations +and related projects as well as our published papers. + +`PyPy video documentation`_ is a page linking to the videos (e.g. of talks and +introductions) that are available. + +`Technical reports`_ is a page that contains links to the +reports that we submitted to the European Union. + +`development methodology`_ describes our sprint-driven approach. + +`LICENSE`_ contains licensing details (basically a straight MIT-license). + +`Glossary`_ of PyPy words to help you align your inner self with +the PyPy universe. + +Source Code Documentation +=============================================== + +`object spaces`_ discusses the object space interface +and several implementations. + +`bytecode interpreter`_ explains the basic mechanisms +of the bytecode interpreter and virtual machine. + +`interpreter optimizations`_ describes our various strategies for +improving the performance of our interpreter, including alternative +object implementations (for strings, dictionaries and lists) in the +standard object space. + +`translation`_ is a detailed overview of our translation process. The +rtyper_ is the largest component of our translation process. + +`dynamic-language translation`_ is a paper that describes +the translation process, especially the flow object space +and the annotator in detail. (This document is one +of the `EU reports`_.) + +`low-level encapsulation`_ describes how our approach hides +away a lot of low level details. This document is also part +of the `EU reports`_. + +`translation aspects`_ describes how we weave different +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. + +`rlib`_ describes some modules that can be used when implementing programs in +RPython. + +`configuration documentation`_ describes the various configuration options that +allow you to customize PyPy. + +`pypy on windows`_ + +`command line reference`_ + +`CLI backend`_ describes the details of the .NET backend. + +`JIT Generation in PyPy`_ describes how we produce the Python Just-in-time Compiler +from our Python interpreter. + +`directory cross-reference`_ + +.. _`garbage collector`: garbage_collection.html +.. _`directory cross-reference`: dir-reference.html +.. _`pypy on windows`: windows.html +.. _`command line reference`: commandline_ref.html +.. _`FAQ`: faq.html +.. _Glossary: glossary.html +.. _`PyPy video documentation`: video-index.html +.. _parser: parser.html +.. _`development methodology`: dev_method.html +.. _`sprint reports`: sprint-reports.html +.. _`papers, talks and related projects`: extradoc.html +.. _`object spaces`: objspace.html +.. _`interpreter optimizations`: interpreter-optimizations.html +.. _`translation`: translation.html +.. _`dynamic-language translation`: https://bitbucket.org/pypy/extradoc/raw/tip/eu-report/D05.1_Publish_on_translating_a_very-high-level_description.pdf +.. _`low-level encapsulation`: low-level-encapsulation.html +.. _`translation aspects`: translation-aspects.html +.. _`configuration documentation`: config/ +.. _`coding guide`: coding-guide.html +.. _`Architecture`: architecture.html +.. _`getting started`: getting-started.html +.. _`bytecode interpreter`: interpreter.html +.. _`EU reports`: index-report.html +.. _`Technical reports`: index-report.html +.. _`summary`: http://buildbot.pypy.org/summary +.. _`ideas for PyPy related projects`: project-ideas.html +.. _`Nightly builds and benchmarks`: http://tuatara.cs.uni-duesseldorf.de/benchmark.html +.. _`directory reference`: +.. _`rlib`: rlib.html +.. _`Sandboxing Python code`: sandbox.html +.. _`LICENSE`: https://bitbucket.org/pypy/pypy/src/default/LICENSE + +.. The following documentation is important and reasonably up-to-date: + +.. extradoc: should this be integrated one level up: dcolish? + +.. toctree:: + :maxdepth: 1 + :hidden: + + interpreter.rst + objspace.rst + __pypy__-module.rst + objspace-proxies.rst + config/index.rst + + dev_method.rst + extending.rst + + extradoc.rst + video-index.rst + + glossary.rst + + contributor.rst + + interpreter-optimizations.rst + configuration.rst + parser.rst + rlib.rst + rtyper.rst + rffi.rst + + translation.rst + jit/index.rst + jit/overview.rst + jit/pyjitpl5.rst + + index-of-release-notes.rst + + ctypes-implementation.rst + + how-to-release.rst + + index-report.rst + + stackless.rst + sandbox.rst + + discussions.rst + + cleanup.rst + + sprint-reports.rst + + eventhistory.rst + statistic/index.rst + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`search` +* :ref:`glossary` + +.. include:: _ref.txt diff --git a/rpython/translator/goal/bpnn.py b/rpython/translator/goal/bpnn.py --- a/rpython/translator/goal/bpnn.py +++ b/rpython/translator/goal/bpnn.py @@ -60,7 +60,7 @@ # create weights self.wi = makeMatrix(self.ni, self.nh) self.wo = makeMatrix(self.nh, self.no) - # set them to random vaules + # set them to random values for i in range(self.ni): for j in range(self.nh): self.wi[i][j] = rand(-2.0, 2.0) @@ -177,7 +177,7 @@ [[1,1], [0]] ] - # create a network with two input, two hidden, and two output nodes + # create a network with two input, three hidden, and one output nodes n = NN(2, 3, 1) # train it with some patterns n.train(pat, 2000) From noreply at buildbot.pypy.org Thu Apr 11 21:28:14 2013 From: noreply at buildbot.pypy.org (bivab) Date: Thu, 11 Apr 2013 21:28:14 +0200 (CEST) Subject: [pypy-commit] pypy default: update arm tests Message-ID: <20130411192814.B04901C23C8@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63243:5dd20a9b2d3a Date: 2013-04-11 21:27 +0200 http://bitbucket.org/pypy/pypy/changeset/5dd20a9b2d3a/ Log: update arm tests diff --git a/rpython/jit/backend/arm/test/test_zrpy_releasegil.py b/rpython/jit/backend/arm/test/test_zrpy_releasegil.py --- a/rpython/jit/backend/arm/test/test_zrpy_releasegil.py +++ b/rpython/jit/backend/arm/test/test_zrpy_releasegil.py @@ -1,4 +1,4 @@ from rpython.jit.backend.arm.test.support import skip_unless_run_slow_tests skip_unless_run_slow_tests() -from rpython.jit.backend.llsupport.test.zrpy_releasegil_test import TestShadowStack, TestAsmGcc +from rpython.jit.backend.llsupport.test.zrpy_releasegil_test import TestShadowStack diff --git a/rpython/jit/backend/arm/test/test_ztranslation_basic.py b/rpython/jit/backend/arm/test/test_ztranslation_basic.py --- a/rpython/jit/backend/arm/test/test_ztranslation_basic.py +++ b/rpython/jit/backend/arm/test/test_ztranslation_basic.py @@ -5,9 +5,9 @@ skip_unless_run_slow_tests() -class TestTranslationX86(TranslationTest): - def _check_cbuilder(self, cbuilder): - # We assume here that we have sse2. If not, the CPUClass - # needs to be changed to CPU386_NO_SSE2, but well. - assert '-msse2' in cbuilder.eci.compile_extra - assert '-mfpmath=sse' in cbuilder.eci.compile_extra +class TestTranslationARM(TranslationTest): + def _get_TranslationContext(self): + t = TranslationContext() + t.config.translation.gc = DEFL_GC # 'hybrid' or 'minimark' + t.config.translation.gcrootfinder = 'shadowstack' + return t diff --git a/rpython/jit/backend/arm/test/test_ztranslation_call_assembler.py b/rpython/jit/backend/arm/test/test_ztranslation_call_assembler.py --- a/rpython/jit/backend/arm/test/test_ztranslation_call_assembler.py +++ b/rpython/jit/backend/arm/test/test_ztranslation_call_assembler.py @@ -5,9 +5,9 @@ skip_unless_run_slow_tests() -class TestTranslationCallAssemblerX86(TranslationTestCallAssembler): - def _check_cbuilder(self, cbuilder): - # We assume here that we have sse2. If not, the CPUClass - # needs to be changed to CPU386_NO_SSE2, but well. - assert '-msse2' in cbuilder.eci.compile_extra - assert '-mfpmath=sse' in cbuilder.eci.compile_extra \ No newline at end of file +class TestTranslationCallAssemblerARM(TranslationTestCallAssembler): + def _get_TranslationContext(self): + t = TranslationContext() + t.config.translation.gc = DEFL_GC # 'hybrid' or 'minimark' + t.config.translation.gcrootfinder = 'shadowstack' + return t diff --git a/rpython/jit/backend/arm/test/test_ztranslation_external_exception.py b/rpython/jit/backend/arm/test/test_ztranslation_external_exception.py --- a/rpython/jit/backend/arm/test/test_ztranslation_external_exception.py +++ b/rpython/jit/backend/arm/test/test_ztranslation_external_exception.py @@ -5,11 +5,11 @@ skip_unless_run_slow_tests() -class TestTranslationRemoveTypePtrX86(TranslationRemoveTypePtrTest): +class TestTranslationRemoveTypePtrARM(TranslationRemoveTypePtrTest): def _get_TranslationContext(self): t = TranslationContext() t.config.translation.gc = DEFL_GC # 'hybrid' or 'minimark' - t.config.translation.gcrootfinder = 'asmgcc' + t.config.translation.gcrootfinder = 'shadowstack' t.config.translation.list_comprehension_operations = True t.config.translation.gcremovetypeptr = True - return t + return t \ No newline at end of file diff --git a/rpython/jit/backend/arm/test/test_ztranslation_jit_stats.py b/rpython/jit/backend/arm/test/test_ztranslation_jit_stats.py --- a/rpython/jit/backend/arm/test/test_ztranslation_jit_stats.py +++ b/rpython/jit/backend/arm/test/test_ztranslation_jit_stats.py @@ -5,9 +5,9 @@ skip_unless_run_slow_tests() -class TestTranslationJITStatsX86(TranslationTestJITStats): - def _check_cbuilder(self, cbuilder): - # We assume here that we have sse2. If not, the CPUClass - # needs to be changed to CPU386_NO_SSE2, but well. - assert '-msse2' in cbuilder.eci.compile_extra - assert '-mfpmath=sse' in cbuilder.eci.compile_extra \ No newline at end of file +class TestTranslationJITStatsARM(TranslationTestJITStats): + def _get_TranslationContext(self): + t = TranslationContext() + t.config.translation.gc = DEFL_GC # 'hybrid' or 'minimark' + t.config.translation.gcrootfinder = 'shadowstack' + return t From noreply at buildbot.pypy.org Thu Apr 11 21:56:24 2013 From: noreply at buildbot.pypy.org (rlamy) Date: Thu, 11 Apr 2013 21:56:24 +0200 (CEST) Subject: [pypy-commit] pypy longdouble2: move ENABLED_LONG_DOUBLE def to typespec.py Message-ID: <20130411195624.9FD911C0149@cobra.cs.uni-duesseldorf.de> Author: Ronan Lamy Branch: longdouble2 Changeset: r63244:d6af37df55fe Date: 2013-04-11 20:42 +0100 http://bitbucket.org/pypy/pypy/changeset/d6af37df55fe/ Log: move ENABLED_LONG_DOUBLE def to typespec.py diff --git a/pypy/module/micronumpy/interp_boxes.py b/pypy/module/micronumpy/interp_boxes.py --- a/pypy/module/micronumpy/interp_boxes.py +++ b/pypy/module/micronumpy/interp_boxes.py @@ -12,20 +12,12 @@ from rpython.rlib.objectmodel import specialize from rpython.tool.sourcetools import func_with_new_name from pypy.module.micronumpy.arrayimpl.voidbox import VoidBoxStorage +from pypy.module.micronumpy.typespec import (ENABLED_LONG_DOUBLE, + long_double_size) MIXIN_32 = (int_typedef,) if LONG_BIT == 32 else () MIXIN_64 = (int_typedef,) if LONG_BIT == 64 else () -# Is this the proper place for this? -ENABLED_LONG_DOUBLE = False -long_double_size = rffi.sizeof_c_type('long double', ignore_errors=True) - -import os -if long_double_size == 8 and os.name == 'nt': - # this is a lie, or maybe a wish, MS fakes longdouble math with double - long_double_size = 12 - - def new_dtype_getter(name): def _get_dtype(space): from pypy.module.micronumpy.interp_dtype import get_dtype_cache diff --git a/pypy/module/micronumpy/interp_dtype.py b/pypy/module/micronumpy/interp_dtype.py --- a/pypy/module/micronumpy/interp_dtype.py +++ b/pypy/module/micronumpy/interp_dtype.py @@ -12,6 +12,8 @@ from rpython.rlib import jit from pypy.module.micronumpy.arrayimpl.concrete import SliceArray +from pypy.module.micronumpy.typespec import (ENABLED_LONG_DOUBLE, + long_double_size) UNSIGNEDLTR = "u" @@ -517,7 +519,7 @@ aliases=["complex"], float_type = self.w_float64dtype, ) - if interp_boxes.ENABLED_LONG_DOUBLE and interp_boxes.long_double_size > 8: + if ENABLED_LONG_DOUBLE and long_double_size > 8: self.w_longdouble = W_Dtype( types.Float80_instance, num=13, @@ -538,17 +540,17 @@ aliases=["clongdouble", "clongfloat"], float_type = self.w_longdouble, ) - if interp_boxes.long_double_size == 12: + if long_double_size == 12: self.w_longdouble.name = "float96" self.w_float96dtype = self.w_longdouble self.w_clongdouble.name = "complex192" self.w_complex192dtype = self.w_clongdouble - elif interp_boxes.long_double_size == 16: + elif long_double_size == 16: self.w_longdouble.name = "float128" self.w_float128dtype = self.w_longdouble self.w_clongdouble.name = "complex256" self.w_complex256dtype = self.w_clongdouble - elif interp_boxes.ENABLED_LONG_DOUBLE: + elif ENABLED_LONG_DOUBLE: self.w_float64dtype.aliases += ["longdouble", "longfloat"] self.w_complex128dtype.aliases += ["clongdouble", "clongfloat"] self.w_longdouble = self.w_float64dtype @@ -628,7 +630,7 @@ self.w_float32dtype, self.w_float64dtype, ] complex_dtypes = [self.w_complex64dtype, self.w_complex128dtype] - if interp_boxes.ENABLED_LONG_DOUBLE: + if ENABLED_LONG_DOUBLE: float_dtypes.append(self.w_longdouble) complex_dtypes.append(self.w_clongdouble) self.builtin_dtypes = [ @@ -702,7 +704,7 @@ 'FLOAT': self.w_float32dtype, 'BOOL': self.w_booldtype, } - if interp_boxes.ENABLED_LONG_DOUBLE: + if ENABLED_LONG_DOUBLE: typeinfo_full['LONGDOUBLE'] = self.w_longdouble typeinfo_full['CLONGDOUBLE'] = self.w_clongdouble diff --git a/pypy/module/micronumpy/types.py b/pypy/module/micronumpy/types.py --- a/pypy/module/micronumpy/types.py +++ b/pypy/module/micronumpy/types.py @@ -23,6 +23,8 @@ int16_spec, uint16_spec, int32_spec, uint32_spec, long_spec, ulong_spec, int64_spec, uint64_spec, float32_spec, float64_spec, float16_spec) +from pypy.module.micronumpy.typespec import (ENABLED_LONG_DOUBLE, + long_double_size) degToRad = math.pi / 180.0 log2 = math.log(2) @@ -1461,7 +1463,7 @@ BoxType = interp_boxes.W_Complex128Box FloatType = Float64_instance -if interp_boxes.ENABLED_LONG_DOUBLE and interp_boxes.long_double_size > 8: +if ENABLED_LONG_DOUBLE and long_double_size > 8: class Float80(BaseType, Float): _attrs_ = () spec = longdouble_spec @@ -1485,8 +1487,8 @@ BoxType = interp_boxes.W_CLongDoubleBox FloatType = Float80_instance - if interp_boxes.long_double_size in (12, 16): - Float80.storage_bytes = interp_boxes.long_double_size + if long_double_size in (12, 16): + Float80.storage_bytes = long_double_size else: raise ImportError("Unsupported size for long double") diff --git a/pypy/module/micronumpy/typespec.py b/pypy/module/micronumpy/typespec.py --- a/pypy/module/micronumpy/typespec.py +++ b/pypy/module/micronumpy/typespec.py @@ -1,4 +1,5 @@ """ Meta-data for the low-level types """ +import os from rpython.rtyper.lltypesystem import rffi, lltype from rpython.rlib.objectmodel import specialize @@ -26,3 +27,11 @@ float32_spec = TypeSpec("float32", rffi.FLOAT) float64_spec = TypeSpec("float64", rffi.DOUBLE) float16_spec = TypeSpec("float16", rffi.SHORT) + +ENABLED_LONG_DOUBLE = False +long_double_size = rffi.sizeof_c_type('long double', ignore_errors=True) +if long_double_size == 8 and os.name == 'nt': + # this is a lie, or maybe a wish, MS fakes longdouble math with double + long_double_size = 12 + + From noreply at buildbot.pypy.org Thu Apr 11 21:56:26 2013 From: noreply at buildbot.pypy.org (rlamy) Date: Thu, 11 Apr 2013 21:56:26 +0200 (CEST) Subject: [pypy-commit] pypy longdouble2: add missing longdouble_spec Message-ID: <20130411195626.242D31C0149@cobra.cs.uni-duesseldorf.de> Author: Ronan Lamy Branch: longdouble2 Changeset: r63245:246f17c620ac Date: 2013-04-11 20:55 +0100 http://bitbucket.org/pypy/pypy/changeset/246f17c620ac/ Log: add missing longdouble_spec diff --git a/pypy/module/micronumpy/types.py b/pypy/module/micronumpy/types.py --- a/pypy/module/micronumpy/types.py +++ b/pypy/module/micronumpy/types.py @@ -22,7 +22,7 @@ from pypy.module.micronumpy.typespec import (bool_spec, int8_spec, uint8_spec, int16_spec, uint16_spec, int32_spec, uint32_spec, long_spec, ulong_spec, int64_spec, uint64_spec, float32_spec, float64_spec, - float16_spec) + float16_spec, longdouble_spec) from pypy.module.micronumpy.typespec import (ENABLED_LONG_DOUBLE, long_double_size) diff --git a/pypy/module/micronumpy/typespec.py b/pypy/module/micronumpy/typespec.py --- a/pypy/module/micronumpy/typespec.py +++ b/pypy/module/micronumpy/typespec.py @@ -33,5 +33,6 @@ if long_double_size == 8 and os.name == 'nt': # this is a lie, or maybe a wish, MS fakes longdouble math with double long_double_size = 12 +longdouble_spec = TypeSpec("float80", rffi.LONGDOUBLE) From noreply at buildbot.pypy.org Thu Apr 11 22:37:20 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Thu, 11 Apr 2013 22:37:20 +0200 (CEST) Subject: [pypy-commit] pypy py3k: PyInt_ apis -> PyLong_ Message-ID: <20130411203720.919E81C0149@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63246:8bc3fa4eca19 Date: 2013-04-11 13:35 -0700 http://bitbucket.org/pypy/pypy/changeset/8bc3fa4eca19/ Log: PyInt_ apis -> PyLong_ diff --git a/pypy/module/cpyext/dictobject.py b/pypy/module/cpyext/dictobject.py --- a/pypy/module/cpyext/dictobject.py +++ b/pypy/module/cpyext/dictobject.py @@ -157,8 +157,8 @@ Py_ssize_t pos = 0; while (PyDict_Next(self->dict, &pos, &key, &value)) { - int i = PyInt_AS_LONG(value) + 1; - PyObject *o = PyInt_FromLong(i); + int i = PyLong_AS_LONG(value) + 1; + PyObject *o = PyLong_FromLong(i); if (o == NULL) return -1; if (PyDict_SetItem(self->dict, key, o) < 0) { diff --git a/pypy/module/cpyext/test/comparisons.c b/pypy/module/cpyext/test/comparisons.c --- a/pypy/module/cpyext/test/comparisons.c +++ b/pypy/module/cpyext/test/comparisons.c @@ -1,5 +1,9 @@ #include "Python.h" +#if PY_MAJOR_VERSION >= 3 + #define PyInt_CheckExact PyLong_CheckExact +#endif + typedef struct CmpObject { PyObject_HEAD } CmpObject; diff --git a/pypy/module/cpyext/test/foo.c b/pypy/module/cpyext/test/foo.c --- a/pypy/module/cpyext/test/foo.c +++ b/pypy/module/cpyext/test/foo.c @@ -1,6 +1,11 @@ #include "Python.h" #include "structmember.h" +#if PY_MAJOR_VERSION >= 3 + #define PyInt_FromLong PyLong_FromLong + #define PyInt_AsLong PyLong_AsLong +#endif + typedef struct { PyObject_HEAD int foo; /* the context holder */ diff --git a/pypy/module/cpyext/test/test_borrow.py b/pypy/module/cpyext/test/test_borrow.py --- a/pypy/module/cpyext/test/test_borrow.py +++ b/pypy/module/cpyext/test/test_borrow.py @@ -42,7 +42,7 @@ module = self.import_extension('foo', [ ("test_borrow_destroy", "METH_NOARGS", """ - PyObject *i = PyInt_FromLong(42); + PyObject *i = PyLong_FromLong(42); PyObject *j; PyObject *t1 = PyTuple_Pack(1, i); PyObject *t2 = PyTuple_Pack(1, i); @@ -52,7 +52,7 @@ PyTuple_GetItem(t2, 0); Py_DECREF(t2); - j = PyInt_FromLong(PyInt_AsLong(i)); + j = PyLong_FromLong(PyLong_AsLong(i)); Py_DECREF(t1); return j; """), diff --git a/pypy/module/cpyext/test/test_cpyext.py b/pypy/module/cpyext/test/test_cpyext.py --- a/pypy/module/cpyext/test/test_cpyext.py +++ b/pypy/module/cpyext/test/test_cpyext.py @@ -738,7 +738,7 @@ mod = self.import_extension('foo', [ ('get_hash', 'METH_NOARGS', ''' - return PyInt_FromLong(_Py_HashPointer(Py_None)); + return PyLong_FromLong(_Py_HashPointer(Py_None)); ''' ), ]) diff --git a/pypy/module/cpyext/test/test_getargs.py b/pypy/module/cpyext/test/test_getargs.py --- a/pypy/module/cpyext/test/test_getargs.py +++ b/pypy/module/cpyext/test/test_getargs.py @@ -18,7 +18,7 @@ if (!PyArg_ParseTuple(args, "i", &l)) { return NULL; } - return PyInt_FromLong(l); + return PyLong_FromLong(l); ''') assert oneargint(1) == 1 raises(TypeError, oneargint, None) @@ -36,7 +36,7 @@ if (!PyArg_ParseTuple(args, "i:oneargandstuff", &l)) { return NULL; } - return PyInt_FromLong(l); + return PyLong_FromLong(l); ''') assert oneargandform(1) == 1 @@ -94,7 +94,7 @@ if (b) Py_INCREF(b); else - b = PyInt_FromLong(42); + b = PyLong_FromLong(42); /* return an owned reference */ return b; ''') diff --git a/pypy/module/cpyext/test/test_listobject.py b/pypy/module/cpyext/test/test_listobject.py --- a/pypy/module/cpyext/test/test_listobject.py +++ b/pypy/module/cpyext/test/test_listobject.py @@ -70,16 +70,16 @@ ("newlist", "METH_NOARGS", """ PyObject *lst = PyList_New(3); - PyList_SetItem(lst, 0, PyInt_FromLong(3)); - PyList_SetItem(lst, 2, PyInt_FromLong(1000)); - PyList_SetItem(lst, 1, PyInt_FromLong(-5)); + PyList_SetItem(lst, 0, PyLong_FromLong(3)); + PyList_SetItem(lst, 2, PyLong_FromLong(1000)); + PyList_SetItem(lst, 1, PyLong_FromLong(-5)); return lst; """ ), ("setlistitem", "METH_VARARGS", """ PyObject *l = PyTuple_GetItem(args, 0); - int index = PyInt_AsLong(PyTuple_GetItem(args, 1)); + int index = PyLong_AsLong(PyTuple_GetItem(args, 1)); Py_INCREF(Py_None); if (PyList_SetItem(l, index, Py_None) < 0) return NULL; diff --git a/pypy/module/cpyext/test/test_number.py b/pypy/module/cpyext/test/test_number.py --- a/pypy/module/cpyext/test/test_number.py +++ b/pypy/module/cpyext/test/test_number.py @@ -22,11 +22,11 @@ def test_number_int(self, space, api): w_l = api.PyNumber_Int(space.wraplong(123L)) - assert api.PyInt_CheckExact(w_l) + assert api.PyLong_CheckExact(w_l) w_l = api.PyNumber_Int(space.wrap(2 << 65)) assert api.PyLong_CheckExact(w_l) w_l = api.PyNumber_Int(space.wrap(42.3)) - assert api.PyInt_CheckExact(w_l) + assert api.PyLong_CheckExact(w_l) def test_number_index(self, space, api): w_l = api.PyNumber_Index(space.wraplong(123L)) diff --git a/pypy/module/cpyext/test/test_pysignals.py b/pypy/module/cpyext/test/test_pysignals.py --- a/pypy/module/cpyext/test/test_pysignals.py +++ b/pypy/module/cpyext/test/test_pysignals.py @@ -21,7 +21,7 @@ if( handler != SIG_IGN ) result += 2; - return PyInt_FromLong(result); + return PyLong_FromLong(result); """), ], prologue = """ #include diff --git a/pypy/module/cpyext/test/test_structseq.py b/pypy/module/cpyext/test/test_structseq.py --- a/pypy/module/cpyext/test/test_structseq.py +++ b/pypy/module/cpyext/test/test_structseq.py @@ -33,8 +33,8 @@ if (PyErr_Occurred()) return NULL; seq = PyStructSequence_New(&PyDatatype); if (!seq) return NULL; - PyStructSequence_SET_ITEM(seq, 0, PyInt_FromLong(42)); - PyStructSequence_SET_ITEM(seq, 1, PyInt_FromLong(43)); + PyStructSequence_SET_ITEM(seq, 0, PyLong_FromLong(42)); + PyStructSequence_SET_ITEM(seq, 1, PyLong_FromLong(43)); PyStructSequence_SET_ITEM(seq, 2, PyUnicode_FromString("hello")); PyStructSequence_SET_ITEM(seq, 3, PyUnicode_FromString("other")); Py_DECREF(&PyDatatype); diff --git a/pypy/module/cpyext/test/test_thread.py b/pypy/module/cpyext/test/test_thread.py --- a/pypy/module/cpyext/test/test_thread.py +++ b/pypy/module/cpyext/test/test_thread.py @@ -9,7 +9,7 @@ ("get_thread_ident", "METH_NOARGS", """ /* Use the 'PyPy' prefix to ensure we access our functions */ - return PyInt_FromLong(PyPyThread_get_thread_ident()); + return PyLong_FromLong(PyPyThread_get_thread_ident()); """), ]) import threading @@ -72,11 +72,11 @@ module = self.import_extension('foo', [ ("create_key", "METH_NOARGS", """ - return PyInt_FromLong(PyThread_create_key()); + return PyLong_FromLong(PyThread_create_key()); """), ("test_key", "METH_O", """ - int key = PyInt_AsLong(args); + int key = PyLong_AsLong(args); if (PyThread_get_key_value(key) != NULL) { PyErr_SetNone(PyExc_ValueError); return NULL; diff --git a/pypy/module/cpyext/test/test_typeobject.py b/pypy/module/cpyext/test/test_typeobject.py --- a/pypy/module/cpyext/test/test_typeobject.py +++ b/pypy/module/cpyext/test/test_typeobject.py @@ -449,7 +449,7 @@ static int mp_ass_subscript(PyObject *self, PyObject *key, PyObject *value) { - if (PyInt_Check(key)) { + if (PyLong_Check(key)) { PyErr_SetNone(PyExc_ZeroDivisionError); return -1; } diff --git a/pypy/module/cpyext/test/test_unicodeobject.py b/pypy/module/cpyext/test/test_unicodeobject.py --- a/pypy/module/cpyext/test/test_unicodeobject.py +++ b/pypy/module/cpyext/test/test_unicodeobject.py @@ -79,7 +79,7 @@ ("test_unicode_format_v", "METH_VARARGS", ''' return helper("bla %d ble %s\\n", - PyInt_AsLong(PyTuple_GetItem(args, 0)), + PyLong_AsLong(PyTuple_GetItem(args, 0)), _PyUnicode_AsString(PyTuple_GetItem(args, 1))); ''' ) @@ -102,7 +102,7 @@ ("test_unicode_format", "METH_VARARGS", ''' return PyUnicode_FromFormat("bla %d ble %s\\n", - PyInt_AsLong(PyTuple_GetItem(args, 0)), + PyLong_AsLong(PyTuple_GetItem(args, 0)), _PyUnicode_AsString(PyTuple_GetItem(args, 1))); ''' ) From noreply at buildbot.pypy.org Thu Apr 11 22:37:22 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Thu, 11 Apr 2013 22:37:22 +0200 (CEST) Subject: [pypy-commit] pypy py3k: add a null check to PyMemoryView_FromBuffer. test_FillWithObject seems to Message-ID: <20130411203722.09C941C0149@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63247:ea6d963fbdba Date: 2013-04-11 13:36 -0700 http://bitbucket.org/pypy/pypy/changeset/ea6d963fbdba/ Log: add a null check to PyMemoryView_FromBuffer. test_FillWithObject seems to require an extra del for correct cleanup diff --git a/pypy/module/cpyext/memoryobject.py b/pypy/module/cpyext/memoryobject.py --- a/pypy/module/cpyext/memoryobject.py +++ b/pypy/module/cpyext/memoryobject.py @@ -1,3 +1,4 @@ +from pypy.interpreter.error import OperationError from pypy.module.cpyext.api import cpython_api, Py_buffer from pypy.module.cpyext.pyobject import PyObject, from_ref from pypy.module.cpyext.buffer import CBuffer @@ -14,6 +15,9 @@ The memoryview object then owns the buffer represented by view, which means you shouldn't try to call PyBuffer_Release() yourself: it will be done on deallocation of the memoryview object.""" + if not view.c_buf: + msg = "cannot make memory view from a buffer with a NULL data pointer" + raise OperationError(space.w_ValueError, space.wrap(msg)) w_obj = from_ref(space, view.c_obj) buf = CBuffer(space, view.c_buf, view.c_len, w_obj) return space.wrap(W_MemoryView(space.wrap(buf))) diff --git a/pypy/module/cpyext/test/test_memoryobject.py b/pypy/module/cpyext/test/test_memoryobject.py --- a/pypy/module/cpyext/test/test_memoryobject.py +++ b/pypy/module/cpyext/test/test_memoryobject.py @@ -36,5 +36,20 @@ """)]) result = module.fillinfo() assert b"hello, world." == result + del result - + def test_fill_from_NULL_pointer(self): + module = self.import_extension('foo', [ + ("fillinfo_NULL", "METH_VARARGS", + """ + Py_buffer info; + if (PyBuffer_FillInfo(&info, NULL, NULL, 1, 1, + PyBUF_FULL_RO) < 0) { + return NULL; + } + return PyMemoryView_FromBuffer(&info); + """)]) + exc = raises(ValueError, module.fillinfo_NULL) + expected = ("cannot make memory view from a buffer with a NULL data " + "pointer") + assert str(exc.value) == expected From noreply at buildbot.pypy.org Thu Apr 11 23:48:38 2013 From: noreply at buildbot.pypy.org (fijal) Date: Thu, 11 Apr 2013 23:48:38 +0200 (CEST) Subject: [pypy-commit] pypy default: add one extra assert here Message-ID: <20130411214838.2F2D61C030D@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r63249:fa879c4fc72f Date: 2013-04-11 23:47 +0200 http://bitbucket.org/pypy/pypy/changeset/fa879c4fc72f/ Log: add one extra assert here diff --git a/rpython/rtyper/rlist.py b/rpython/rtyper/rlist.py --- a/rpython/rtyper/rlist.py +++ b/rpython/rtyper/rlist.py @@ -952,6 +952,7 @@ ll_assert(start <= l1.ll_length(), "l[start:x] = l with start > len(l)") ll_assert(count == stop - start, "setslice cannot resize lists in RPython") + ll_assert(stop <= l1.ll_length(), "stop cannot be past the end of l1") # XXX ...but it would be easy enough to support if really needed ll_arraycopy(l2, l1, 0, start, count) ll_listsetslice.oopspec = 'list.setslice(l1, start, stop, l2)' From noreply at buildbot.pypy.org Thu Apr 11 23:48:39 2013 From: noreply at buildbot.pypy.org (fijal) Date: Thu, 11 Apr 2013 23:48:39 +0200 (CEST) Subject: [pypy-commit] pypy default: merge Message-ID: <20130411214839.A35CC1C030D@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r63250:9fb9c1170e25 Date: 2013-04-11 23:48 +0200 http://bitbucket.org/pypy/pypy/changeset/9fb9c1170e25/ Log: merge diff too long, truncating to 2000 out of 2651 lines diff --git a/rpython/jit/backend/arm/test/test_zrpy_gc.py b/rpython/jit/backend/arm/test/test_zrpy_gc.py --- a/rpython/jit/backend/arm/test/test_zrpy_gc.py +++ b/rpython/jit/backend/arm/test/test_zrpy_gc.py @@ -1,798 +1,4 @@ -""" -This is a test that translates a complete JIT together with a GC and runs it. -It is testing that the GC-dependent aspects basically work, mostly the mallocs -and the various cases of write barrier. -""" - -import weakref -import py, os -from rpython.annotator import policy as annpolicy -from rpython.rlib import rgc -from rpython.rtyper.lltypesystem import lltype, llmemory, rffi -from rpython.rlib.jit import JitDriver, dont_look_inside -from rpython.rlib.jit import elidable, unroll_safe -from rpython.jit.backend.llsupport.gc import GcLLDescr_framework -from rpython.tool.udir import udir -from rpython.config.translationoption import DEFL_GC from rpython.jit.backend.arm.test.support import skip_unless_run_slow_tests skip_unless_run_slow_tests() - -class X(object): - def __init__(self, x=0): - self.x = x - - next = None - -class CheckError(Exception): - pass - -def check(flag): - if not flag: - raise CheckError - -def get_g(main): - main._dont_inline_ = True - def g(name, n): - x = X() - x.foo = 2 - main(n, x) - x.foo = 5 - return weakref.ref(x) - g._dont_inline_ = True - return g - - -def get_entry(g): - - def entrypoint(args): - name = '' - n = 2000 - argc = len(args) - if argc > 1: - name = args[1] - if argc > 2: - n = int(args[2]) - r_list = [] - for i in range(20): - r = g(name, n) - r_list.append(r) - rgc.collect() - rgc.collect(); rgc.collect() - freed = 0 - for r in r_list: - if r() is None: - freed += 1 - print freed - return 0 - - return entrypoint - - -def get_functions_to_patch(): - from rpython.jit.backend.llsupport import gc - # - can_use_nursery_malloc1 = gc.GcLLDescr_framework.can_use_nursery_malloc - def can_use_nursery_malloc2(*args): - try: - if os.environ['PYPY_NO_INLINE_MALLOC']: - return False - except KeyError: - pass - return can_use_nursery_malloc1(*args) - # - return {(gc.GcLLDescr_framework, 'can_use_nursery_malloc'): - can_use_nursery_malloc2} - -def compile(f, gc, enable_opts='', **kwds): - from rpython.annotator.listdef import s_list_of_strings - from rpython.translator.translator import TranslationContext - from rpython.jit.metainterp.warmspot import apply_jit - from rpython.translator.c import genc - # - t = TranslationContext() - t.config.translation.gc = gc - if gc != 'boehm': - t.config.translation.gcremovetypeptr = True - for name, value in kwds.items(): - setattr(t.config.translation, name, value) - ann = t.buildannotator() - ann.build_types(f, [s_list_of_strings], main_entry_point=True) - t.buildrtyper().specialize() - - if kwds['jit']: - patch = get_functions_to_patch() - old_value = {} - try: - for (obj, attr), value in patch.items(): - old_value[obj, attr] = getattr(obj, attr) - setattr(obj, attr, value) - # - apply_jit(t, enable_opts=enable_opts) - # - finally: - for (obj, attr), oldvalue in old_value.items(): - setattr(obj, attr, oldvalue) - - cbuilder = genc.CStandaloneBuilder(t, f, t.config) - cbuilder.generate_source(defines=cbuilder.DEBUG_DEFINES) - cbuilder.compile() - return cbuilder - -def run(cbuilder, args=''): - # - pypylog = udir.join('test_zrpy_gc.log') - data = cbuilder.cmdexec(args, env={'PYPYLOG': ':%s' % pypylog}) - return data.strip() - -def compile_and_run(f, gc, **kwds): - cbuilder = compile(f, gc, **kwds) - return run(cbuilder) - - - -def test_compile_boehm(): - myjitdriver = JitDriver(greens = [], reds = ['n', 'x']) - @dont_look_inside - def see(lst, n): - assert len(lst) == 3 - assert lst[0] == n+10 - assert lst[1] == n+20 - assert lst[2] == n+30 - def main(n, x): - while n > 0: - myjitdriver.can_enter_jit(n=n, x=x) - myjitdriver.jit_merge_point(n=n, x=x) - y = X() - y.foo = x.foo - n -= y.foo - see([n+10, n+20, n+30], n) - res = compile_and_run(get_entry(get_g(main)), "boehm", jit=True) - assert int(res) >= 16 - -# ______________________________________________________________________ - - -class BaseFrameworkTests(object): - compile_kwds = {} - - def setup_class(cls): - funcs = [] - name_to_func = {} - for fullname in dir(cls): - if not fullname.startswith('define'): - continue - definefunc = getattr(cls, fullname) - _, name = fullname.split('_', 1) - beforefunc, loopfunc, afterfunc = definefunc.im_func(cls) - if beforefunc is None: - def beforefunc(n, x): - return n, x, None, None, None, None, None, None, None, None, None, '' - if afterfunc is None: - def afterfunc(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - pass - beforefunc.func_name = 'before_'+name - loopfunc.func_name = 'loop_'+name - afterfunc.func_name = 'after_'+name - funcs.append((beforefunc, loopfunc, afterfunc)) - assert name not in name_to_func - name_to_func[name] = len(name_to_func) - print name_to_func - def allfuncs(name, n): - x = X() - x.foo = 2 - main_allfuncs(name, n, x) - x.foo = 5 - return weakref.ref(x) - def main_allfuncs(name, n, x): - num = name_to_func[name] - n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s = funcs[num][0](n, x) - while n > 0: - myjitdriver.can_enter_jit(num=num, n=n, x=x, x0=x0, x1=x1, - x2=x2, x3=x3, x4=x4, x5=x5, x6=x6, x7=x7, l=l, s=s) - myjitdriver.jit_merge_point(num=num, n=n, x=x, x0=x0, x1=x1, - x2=x2, x3=x3, x4=x4, x5=x5, x6=x6, x7=x7, l=l, s=s) - - n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s = funcs[num][1]( - n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s) - funcs[num][2](n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s) - myjitdriver = JitDriver(greens = ['num'], - reds = ['n', 'x', 'x0', 'x1', 'x2', 'x3', 'x4', - 'x5', 'x6', 'x7', 'l', 's']) - cls.main_allfuncs = staticmethod(main_allfuncs) - cls.name_to_func = name_to_func - OLD_DEBUG = GcLLDescr_framework.DEBUG - try: - GcLLDescr_framework.DEBUG = True - cls.cbuilder = compile(get_entry(allfuncs), DEFL_GC, - gcrootfinder=cls.gcrootfinder, jit=True, - **cls.compile_kwds) - finally: - GcLLDescr_framework.DEBUG = OLD_DEBUG - - def _run(self, name, n, env): - res = self.cbuilder.cmdexec("%s %d" %(name, n), env=env) - assert int(res) == 20 - - def run(self, name, n=2000): - pypylog = udir.join('TestCompileFramework.log') - env = {'PYPYLOG': ':%s' % pypylog, - 'PYPY_NO_INLINE_MALLOC': '1'} - self._run(name, n, env) - env['PYPY_NO_INLINE_MALLOC'] = '' - self._run(name, n, env) - - def run_orig(self, name, n, x): - self.main_allfuncs(name, n, x) - - -class CompileFrameworkTests(BaseFrameworkTests): - # Test suite using (so far) the minimark GC. - -## def define_libffi_workaround(cls): -## # XXX: this is a workaround for a bug in database.py. It seems that -## # the problem is triggered by optimizeopt/fficall.py, and in -## # particular by the ``cast_base_ptr_to_instance(Func, llfunc)``: in -## # these tests, that line is the only place where libffi.Func is -## # referenced. -## # -## # The problem occurs because the gctransformer tries to annotate a -## # low-level helper to call the __del__ of libffi.Func when it's too -## # late. -## # -## # This workaround works by forcing the annotator (and all the rest of -## # the toolchain) to see libffi.Func in a "proper" context, not just as -## # the target of cast_base_ptr_to_instance. Note that the function -## # below is *never* called by any actual test, it's just annotated. -## # -## from rpython.rlib.libffi import get_libc_name, CDLL, types, ArgChain -## libc_name = get_libc_name() -## def f(n, x, *args): -## libc = CDLL(libc_name) -## ptr = libc.getpointer('labs', [types.slong], types.slong) -## chain = ArgChain() -## chain.arg(n) -## n = ptr.call(chain, lltype.Signed) -## return (n, x) + args -## return None, f, None - - def define_compile_framework_1(cls): - # a moving GC. Supports malloc_varsize_nonmovable. Simple test, works - # without write_barriers and root stack enumeration. - def f(n, x, *args): - y = X() - y.foo = x.foo - n -= y.foo - return (n, x) + args - return None, f, None - - def test_compile_framework_1(self): - self.run('compile_framework_1') - - def define_compile_framework_2(cls): - # More complex test, requires root stack enumeration but - # not write_barriers. - def f(n, x, *args): - prev = x - for j in range(101): # f() runs 20'000 times, thus allocates - y = X() # a total of 2'020'000 objects - y.foo = prev.foo - prev = y - n -= prev.foo - return (n, x) + args - return None, f, None - - def test_compile_framework_2(self): - self.run('compile_framework_2') - - def define_compile_framework_3(cls): - # Third version of the test. Really requires write_barriers. - def f(n, x, *args): - x.next = None - for j in range(101): # f() runs 20'000 times, thus allocates - y = X() # a total of 2'020'000 objects - y.foo = j+1 - y.next = x.next - x.next = y - check(x.next.foo == 101) - total = 0 - y = x - for j in range(101): - y = y.next - total += y.foo - check(not y.next) - check(total == 101*102/2) - n -= x.foo - return (n, x) + args - return None, f, None - - - - def test_compile_framework_3(self): - x_test = X() - x_test.foo = 5 - self.run_orig('compile_framework_3', 6, x_test) # check that it does not raise CheckError - self.run('compile_framework_3') - - def define_compile_framework_3_extra(cls): - # Extra version of the test, with tons of live vars around the residual - # call that all contain a GC pointer. - @dont_look_inside - def residual(n=26): - x = X() - x.next = X() - x.next.foo = n - return x - # - def before(n, x): - residual(5) - x0 = residual() - x1 = residual() - x2 = residual() - x3 = residual() - x4 = residual() - x5 = residual() - x6 = residual() - x7 = residual() - n *= 19 - return n, None, x0, x1, x2, x3, x4, x5, x6, x7, None, None - def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - x8 = residual() - x9 = residual() - check(x0.next.foo == 26) - check(x1.next.foo == 26) - check(x2.next.foo == 26) - check(x3.next.foo == 26) - check(x4.next.foo == 26) - check(x5.next.foo == 26) - check(x6.next.foo == 26) - check(x7.next.foo == 26) - check(x8.next.foo == 26) - check(x9.next.foo == 26) - x0, x1, x2, x3, x4, x5, x6, x7 = x7, x4, x6, x5, x3, x2, x9, x8 - n -= 1 - return n, None, x0, x1, x2, x3, x4, x5, x6, x7, None, None - return before, f, None - - def test_compile_framework_3_extra(self): - self.run_orig('compile_framework_3_extra', 6, None) # check that it does not raise CheckError - self.run('compile_framework_3_extra') - - def define_compile_framework_4(cls): - # Fourth version of the test, with __del__. - from rpython.rlib.debug import debug_print - class Counter: - cnt = 0 - counter = Counter() - class Z: - def __del__(self): - counter.cnt -= 1 - def before(n, x): - debug_print('counter.cnt =', counter.cnt) - check(counter.cnt < 5) - counter.cnt = n // x.foo - return n, x, None, None, None, None, None, None, None, None, None, None - def f(n, x, *args): - Z() - n -= x.foo - return (n, x) + args - return before, f, None - - def test_compile_framework_4(self): - self.run('compile_framework_4') - - def define_compile_framework_5(cls): - # Test string manipulation. - def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - n -= x.foo - s += str(n) - return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s - def after(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - check(len(s) == 1*5 + 2*45 + 3*450 + 4*500) - return None, f, after - - def test_compile_framework_5(self): - self.run('compile_framework_5') - - def define_compile_framework_7(cls): - # Array of pointers (test the write barrier for setarrayitem_gc) - def before(n, x): - return n, x, None, None, None, None, None, None, None, None, [X(123)], None - def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - if n < 1900: - check(l[0].x == 123) - l = [None] * 16 - l[0] = X(123) - l[1] = X(n) - l[2] = X(n+10) - l[3] = X(n+20) - l[4] = X(n+30) - l[5] = X(n+40) - l[6] = X(n+50) - l[7] = X(n+60) - l[8] = X(n+70) - l[9] = X(n+80) - l[10] = X(n+90) - l[11] = X(n+100) - l[12] = X(n+110) - l[13] = X(n+120) - l[14] = X(n+130) - l[15] = X(n+140) - if n < 1800: - check(len(l) == 16) - check(l[0].x == 123) - check(l[1].x == n) - check(l[2].x == n+10) - check(l[3].x == n+20) - check(l[4].x == n+30) - check(l[5].x == n+40) - check(l[6].x == n+50) - check(l[7].x == n+60) - check(l[8].x == n+70) - check(l[9].x == n+80) - check(l[10].x == n+90) - check(l[11].x == n+100) - check(l[12].x == n+110) - check(l[13].x == n+120) - check(l[14].x == n+130) - check(l[15].x == n+140) - n -= x.foo - return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s - def after(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - check(len(l) == 16) - check(l[0].x == 123) - check(l[1].x == 2) - check(l[2].x == 12) - check(l[3].x == 22) - check(l[4].x == 32) - check(l[5].x == 42) - check(l[6].x == 52) - check(l[7].x == 62) - check(l[8].x == 72) - check(l[9].x == 82) - check(l[10].x == 92) - check(l[11].x == 102) - check(l[12].x == 112) - check(l[13].x == 122) - check(l[14].x == 132) - check(l[15].x == 142) - return before, f, after - - def test_compile_framework_7(self): - self.run('compile_framework_7') - - def define_compile_framework_7_interior(cls): - # Array of structs containing pointers (test the write barrier - # for setinteriorfield_gc) - S = lltype.GcStruct('S', ('i', lltype.Signed)) - A = lltype.GcArray(lltype.Struct('entry', ('x', lltype.Ptr(S)), - ('y', lltype.Ptr(S)), - ('z', lltype.Ptr(S)))) - class Glob: - a = lltype.nullptr(A) - glob = Glob() - # - def make_s(i): - s = lltype.malloc(S) - s.i = i - return s - # - @unroll_safe - def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - a = glob.a - if not a: - a = glob.a = lltype.malloc(A, 10) - i = 0 - while i < 10: - a[i].x = make_s(n + i * 100 + 1) - a[i].y = make_s(n + i * 100 + 2) - a[i].z = make_s(n + i * 100 + 3) - i += 1 - i = 0 - while i < 10: - check(a[i].x.i == n + i * 100 + 1) - check(a[i].y.i == n + i * 100 + 2) - check(a[i].z.i == n + i * 100 + 3) - i += 1 - n -= x.foo - return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s - return None, f, None - - def test_compile_framework_7_interior(self): - self.run('compile_framework_7_interior') - - def define_compile_framework_8(cls): - # Array of pointers, of unknown length (test write_barrier_from_array) - def before(n, x): - return n, x, None, None, None, None, None, None, None, None, [X(123)], None - def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - if n < 1900: - check(l[0].x == 123) - l = [None] * (16 + (n & 7)) - l[0] = X(123) - l[1] = X(n) - l[2] = X(n+10) - l[3] = X(n+20) - l[4] = X(n+30) - l[5] = X(n+40) - l[6] = X(n+50) - l[7] = X(n+60) - l[8] = X(n+70) - l[9] = X(n+80) - l[10] = X(n+90) - l[11] = X(n+100) - l[12] = X(n+110) - l[13] = X(n+120) - l[14] = X(n+130) - l[15] = X(n+140) - if n < 1800: - check(len(l) == 16 + (n & 7)) - check(l[0].x == 123) - check(l[1].x == n) - check(l[2].x == n+10) - check(l[3].x == n+20) - check(l[4].x == n+30) - check(l[5].x == n+40) - check(l[6].x == n+50) - check(l[7].x == n+60) - check(l[8].x == n+70) - check(l[9].x == n+80) - check(l[10].x == n+90) - check(l[11].x == n+100) - check(l[12].x == n+110) - check(l[13].x == n+120) - check(l[14].x == n+130) - check(l[15].x == n+140) - n -= x.foo - return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s - def after(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - check(len(l) >= 16) - check(l[0].x == 123) - check(l[1].x == 2) - check(l[2].x == 12) - check(l[3].x == 22) - check(l[4].x == 32) - check(l[5].x == 42) - check(l[6].x == 52) - check(l[7].x == 62) - check(l[8].x == 72) - check(l[9].x == 82) - check(l[10].x == 92) - check(l[11].x == 102) - check(l[12].x == 112) - check(l[13].x == 122) - check(l[14].x == 132) - check(l[15].x == 142) - return before, f, after - - def test_compile_framework_8(self): - self.run('compile_framework_8') - - def define_compile_framework_9(cls): - # Like compile_framework_8, but with variable indexes and large - # arrays, testing the card_marking case - def before(n, x): - return n, x, None, None, None, None, None, None, None, None, [X(123)], None - def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - if n < 1900: - check(l[0].x == 123) - num = 512 + (n & 7) - l = [None] * num - l[0] = X(123) - l[1] = X(n) - l[2] = X(n+10) - l[3] = X(n+20) - l[4] = X(n+30) - l[5] = X(n+40) - l[6] = X(n+50) - l[7] = X(n+60) - l[num-8] = X(n+70) - l[num-9] = X(n+80) - l[num-10] = X(n+90) - l[num-11] = X(n+100) - l[-12] = X(n+110) - l[-13] = X(n+120) - l[-14] = X(n+130) - l[-15] = X(n+140) - if n < 1800: - num = 512 + (n & 7) - check(len(l) == num) - check(l[0].x == 123) - check(l[1].x == n) - check(l[2].x == n+10) - check(l[3].x == n+20) - check(l[4].x == n+30) - check(l[5].x == n+40) - check(l[6].x == n+50) - check(l[7].x == n+60) - check(l[num-8].x == n+70) - check(l[num-9].x == n+80) - check(l[num-10].x == n+90) - check(l[num-11].x == n+100) - check(l[-12].x == n+110) - check(l[-13].x == n+120) - check(l[-14].x == n+130) - check(l[-15].x == n+140) - n -= x.foo - return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s - def after(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - check(len(l) >= 512) - check(l[0].x == 123) - check(l[1].x == 2) - check(l[2].x == 12) - check(l[3].x == 22) - check(l[4].x == 32) - check(l[5].x == 42) - check(l[6].x == 52) - check(l[7].x == 62) - check(l[-8].x == 72) - check(l[-9].x == 82) - check(l[-10].x == 92) - check(l[-11].x == 102) - check(l[-12].x == 112) - check(l[-13].x == 122) - check(l[-14].x == 132) - check(l[-15].x == 142) - return before, f, after - - def test_compile_framework_9(self): - self.run('compile_framework_9') - - def define_compile_framework_external_exception_handling(cls): - def before(n, x): - x = X(0) - return n, x, None, None, None, None, None, None, None, None, None, None - - @dont_look_inside - def g(x): - if x > 200: - return 2 - raise ValueError - @dont_look_inside - def h(x): - if x > 150: - raise ValueError - return 2 - - def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - try: - x.x += g(n) - except ValueError: - x.x += 1 - try: - x.x += h(n) - except ValueError: - x.x -= 1 - n -= 1 - return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s - - def after(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - check(x.x == 1800 * 2 + 1850 * 2 + 200 - 150) - - return before, f, None - - def test_compile_framework_external_exception_handling(self): - self.run('compile_framework_external_exception_handling') - - def define_compile_framework_bug1(self): - @elidable - def nonmoving(): - x = X(1) - for i in range(7): - rgc.collect() - return x - - @dont_look_inside - def do_more_stuff(): - x = X(5) - for i in range(7): - rgc.collect() - return x - - def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - x0 = do_more_stuff() - check(nonmoving().x == 1) - n -= 1 - return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s - - return None, f, None - - def test_compile_framework_bug1(self): - self.run('compile_framework_bug1', 200) - - def define_compile_framework_vref(self): - from rpython.rlib.jit import virtual_ref, virtual_ref_finish - class A: - pass - glob = A() - def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - a = A() - glob.v = vref = virtual_ref(a) - virtual_ref_finish(vref, a) - n -= 1 - return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s - return None, f, None - - def test_compile_framework_vref(self): - self.run('compile_framework_vref', 200) - - def define_compile_framework_float(self): - # test for a bug: the fastpath_malloc does not save and restore - # xmm registers around the actual call to the slow path - class A: - x0 = x1 = x2 = x3 = x4 = x5 = x6 = x7 = 0 - @dont_look_inside - def escape1(a): - a.x0 += 0 - a.x1 += 6 - a.x2 += 12 - a.x3 += 18 - a.x4 += 24 - a.x5 += 30 - a.x6 += 36 - a.x7 += 42 - @dont_look_inside - def escape2(n, f0, f1, f2, f3, f4, f5, f6, f7): - check(f0 == n + 0.0) - check(f1 == n + 0.125) - check(f2 == n + 0.25) - check(f3 == n + 0.375) - check(f4 == n + 0.5) - check(f5 == n + 0.625) - check(f6 == n + 0.75) - check(f7 == n + 0.875) - @unroll_safe - def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - i = 0 - while i < 42: - m = n + i - f0 = m + 0.0 - f1 = m + 0.125 - f2 = m + 0.25 - f3 = m + 0.375 - f4 = m + 0.5 - f5 = m + 0.625 - f6 = m + 0.75 - f7 = m + 0.875 - a1 = A() - # at this point, all or most f's are still in xmm registers - escape1(a1) - escape2(m, f0, f1, f2, f3, f4, f5, f6, f7) - i += 1 - n -= 1 - return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s - return None, f, None - - def test_compile_framework_float(self): - self.run('compile_framework_float') - - def define_compile_framework_minimal_size_in_nursery(self): - S = lltype.GcStruct('S') # no fields! - T = lltype.GcStruct('T', ('i', lltype.Signed)) - @unroll_safe - def f42(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - lst1 = [] - lst2 = [] - i = 0 - while i < 42: - s1 = lltype.malloc(S) - t1 = lltype.malloc(T) - t1.i = 10000 + i + n - lst1.append(s1) - lst2.append(t1) - i += 1 - i = 0 - while i < 42: - check(lst2[i].i == 10000 + i + n) - i += 1 - n -= 1 - return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s - return None, f42, None - - def test_compile_framework_minimal_size_in_nursery(self): - self.run('compile_framework_minimal_size_in_nursery') - - -class TestShadowStack(CompileFrameworkTests): - gcrootfinder = "shadowstack" - +from rpython.jit.backend.llsupport.test.zrpy_gc_test import TestShadowStack diff --git a/rpython/jit/backend/x86/test/test_zrpy_gc_boehm.py b/rpython/jit/backend/arm/test/test_zrpy_gc_boehm.py copy from rpython/jit/backend/x86/test/test_zrpy_gc_boehm.py copy to rpython/jit/backend/arm/test/test_zrpy_gc_boehm.py --- a/rpython/jit/backend/x86/test/test_zrpy_gc_boehm.py +++ b/rpython/jit/backend/arm/test/test_zrpy_gc_boehm.py @@ -1,53 +1,3 @@ - -import weakref -from rpython.rlib.jit import JitDriver, dont_look_inside -from rpython.jit.backend.x86.test.test_zrpy_gc import run, get_entry, compile -from rpython.jit.backend.x86.test.test_ztranslation import fix_annotator_for_vrawbuffer - -class X(object): - def __init__(self, x=0): - self.x = x - - next = None - -class CheckError(Exception): - pass - -def check(flag): - if not flag: - raise CheckError - -def compile_and_run(f, gc, **kwds): - cbuilder = compile(f, gc, **kwds) - return run(cbuilder) - -def get_g(main): - main._dont_inline_ = True - def g(name, n): - x = X() - x.foo = 2 - main(n, x) - x.foo = 5 - return weakref.ref(x) - g._dont_inline_ = True - return g - -def test_compile_boehm(monkeypatch): - fix_annotator_for_vrawbuffer(monkeypatch) - myjitdriver = JitDriver(greens = [], reds = ['n', 'x']) - @dont_look_inside - def see(lst, n): - assert len(lst) == 3 - assert lst[0] == n+10 - assert lst[1] == n+20 - assert lst[2] == n+30 - def main(n, x): - while n > 0: - myjitdriver.can_enter_jit(n=n, x=x) - myjitdriver.jit_merge_point(n=n, x=x) - y = X() - y.foo = x.foo - n -= y.foo - see([n+10, n+20, n+30], n) - res = compile_and_run(get_entry(get_g(main)), "boehm", jit=True) - assert int(res) >= 16 +from rpython.jit.backend.arm.test.support import skip_unless_run_slow_tests +skip_unless_run_slow_tests() +from rpython.jit.backend.llsupport.test.zrpy_gc_boehm_test import test_compile_boehm diff --git a/rpython/jit/backend/arm/test/test_zrpy_releasegil.py b/rpython/jit/backend/arm/test/test_zrpy_releasegil.py new file mode 100644 --- /dev/null +++ b/rpython/jit/backend/arm/test/test_zrpy_releasegil.py @@ -0,0 +1,4 @@ +from rpython.jit.backend.arm.test.support import skip_unless_run_slow_tests +skip_unless_run_slow_tests() + +from rpython.jit.backend.llsupport.test.zrpy_releasegil_test import TestShadowStack diff --git a/rpython/jit/backend/arm/test/test_ztranslation.py b/rpython/jit/backend/arm/test/test_ztranslation.py deleted file mode 100644 --- a/rpython/jit/backend/arm/test/test_ztranslation.py +++ /dev/null @@ -1,279 +0,0 @@ -import py, os, sys -from rpython.tool.udir import udir -from rpython.rlib.jit import JitDriver, unroll_parameters, set_param -from rpython.rlib.jit import PARAMETERS, dont_look_inside -from rpython.rlib.jit import promote -from rpython.rlib import jit_hooks -from rpython.jit.metainterp.jitprof import Profiler -from rpython.jit.backend.detect_cpu import getcpuclass -from rpython.jit.backend.test.support import CCompiledMixin -from rpython.jit.codewriter.policy import StopAtXPolicy -from rpython.translator.translator import TranslationContext -from rpython.config.translationoption import DEFL_GC -from rpython.rlib import rgc -from rpython.jit.backend.arm.test.support import skip_unless_run_slow_tests -skip_unless_run_slow_tests() - -class TestTranslationARM(CCompiledMixin): - CPUClass = getcpuclass() - - def _get_TranslationContext(self): - t = TranslationContext() - t.config.translation.gc = DEFL_GC # 'hybrid' or 'minimark' - t.config.translation.gcrootfinder = 'shadowstack' - return t - - def _check_cbuilder(self, cbuilder): - pass - - def test_stuff_translates(self): - # this is a basic test that tries to hit a number of features and their - # translation: - # - jitting of loops and bridges - # - virtualizables - # - set_param interface - # - profiler - # - full optimizer - # - floats neg and abs - - class Frame(object): - _virtualizable2_ = ['i'] - - def __init__(self, i): - self.i = i - - @dont_look_inside - def myabs(x): - return abs(x) - - jitdriver = JitDriver(greens = [], - reds = ['total', 'frame', 'j'], - virtualizables = ['frame']) - def f(i, j): - for param, _ in unroll_parameters: - defl = PARAMETERS[param] - set_param(jitdriver, param, defl) - set_param(jitdriver, "threshold", 3) - set_param(jitdriver, "trace_eagerness", 2) - total = 0 - frame = Frame(i) - j = float(j) - while frame.i > 3: - jitdriver.can_enter_jit(frame=frame, total=total, j=j) - jitdriver.jit_merge_point(frame=frame, total=total, j=j) - total += frame.i - if frame.i >= 20: - frame.i -= 2 - frame.i -= 1 - j *= -0.712 - if j + (-j): raise ValueError - k = myabs(j) - if k - abs(j): raise ValueError - if k - abs(-j): raise ValueError - return chr(total % 253) - # - from rpython.rtyper.lltypesystem import lltype, rffi - from rpython.rlib.libffi import types, CDLL, ArgChain - from rpython.rlib.test.test_clibffi import get_libm_name - libm_name = get_libm_name(sys.platform) - jitdriver2 = JitDriver(greens=[], reds = ['i', 'func', 'res', 'x']) - def libffi_stuff(i, j): - lib = CDLL(libm_name) - func = lib.getpointer('fabs', [types.double], types.double) - res = 0.0 - x = float(j) - while i > 0: - jitdriver2.jit_merge_point(i=i, res=res, func=func, x=x) - promote(func) - argchain = ArgChain() - argchain.arg(x) - res = func.call(argchain, rffi.DOUBLE) - i -= 1 - return res - # - def main(i, j): - a_char = f(i, j) - a_float = libffi_stuff(i, j) - return ord(a_char) * 10 + int(a_float) - expected = main(40, -49) - res = self.meta_interp(main, [40, -49]) - assert res == expected - - def test_direct_assembler_call_translates(self): - """Test CALL_ASSEMBLER and the recursion limit""" - from rpython.rlib.rstackovf import StackOverflow - - class Thing(object): - def __init__(self, val): - self.val = val - - class Frame(object): - _virtualizable2_ = ['thing'] - - driver = JitDriver(greens = ['codeno'], reds = ['i', 'frame'], - virtualizables = ['frame'], - get_printable_location = lambda codeno: str(codeno)) - class SomewhereElse(object): - pass - - somewhere_else = SomewhereElse() - - def change(newthing): - somewhere_else.frame.thing = newthing - - def main(codeno): - frame = Frame() - somewhere_else.frame = frame - frame.thing = Thing(0) - portal(codeno, frame) - return frame.thing.val - - def portal(codeno, frame): - i = 0 - while i < 10: - driver.can_enter_jit(frame=frame, codeno=codeno, i=i) - driver.jit_merge_point(frame=frame, codeno=codeno, i=i) - nextval = frame.thing.val - if codeno == 0: - subframe = Frame() - subframe.thing = Thing(nextval) - nextval = portal(1, subframe) - elif frame.thing.val > 40: - change(Thing(13)) - nextval = 13 - frame.thing = Thing(nextval + 1) - i += 1 - return frame.thing.val - - driver2 = JitDriver(greens = [], reds = ['n']) - - def main2(bound): - try: - while portal2(bound) == -bound+1: - bound *= 2 - except StackOverflow: - pass - return bound - - def portal2(n): - while True: - driver2.jit_merge_point(n=n) - n -= 1 - if n <= 0: - return n - n = portal2(n) - assert portal2(10) == -9 - - def mainall(codeno, bound): - return main(codeno) + main2(bound) - - res = self.meta_interp(mainall, [0, 1], inline=True, - policy=StopAtXPolicy(change)) - print hex(res) - assert res & 255 == main(0) - bound = res & ~255 - assert 1024 <= bound <= 131072 - assert bound & (bound-1) == 0 # a power of two - - def test_jit_get_stats(self): - driver = JitDriver(greens = [], reds = ['i']) - - def f(): - i = 0 - while i < 100000: - driver.jit_merge_point(i=i) - i += 1 - - def main(): - jit_hooks.stats_set_debug(None, True) - f() - ll_times = jit_hooks.stats_get_loop_run_times(None) - return len(ll_times) - - res = self.meta_interp(main, []) - assert res == 3 - # one for loop, one for entry point and one for the prologue - -class TestTranslationRemoveTypePtrARM(CCompiledMixin): - CPUClass = getcpuclass() - - def _get_TranslationContext(self): - t = TranslationContext() - t.config.translation.gc = DEFL_GC # 'hybrid' or 'minimark' - t.config.translation.gcrootfinder = 'shadowstack' - t.config.translation.list_comprehension_operations = True - t.config.translation.gcremovetypeptr = True - return t - - def test_external_exception_handling_translates(self): - jitdriver = JitDriver(greens = [], reds = ['n', 'total']) - - class ImDone(Exception): - def __init__(self, resvalue): - self.resvalue = resvalue - - @dont_look_inside - def f(x, total): - if x <= 30: - raise ImDone(total * 10) - if x > 200: - return 2 - raise ValueError - @dont_look_inside - def g(x): - if x > 150: - raise ValueError - return 2 - class Base: - def meth(self): - return 2 - class Sub(Base): - def meth(self): - return 1 - @dont_look_inside - def h(x): - if x < 20000: - return Sub() - else: - return Base() - def myportal(i): - set_param(jitdriver, "threshold", 3) - set_param(jitdriver, "trace_eagerness", 2) - total = 0 - n = i - while True: - jitdriver.can_enter_jit(n=n, total=total) - jitdriver.jit_merge_point(n=n, total=total) - try: - total += f(n, total) - except ValueError: - total += 1 - try: - total += g(n) - except ValueError: - total -= 1 - n -= h(n).meth() # this is to force a GUARD_CLASS - def main(i): - try: - myportal(i) - except ImDone, e: - return e.resvalue - - # XXX custom fishing, depends on the exact env var and format - logfile = udir.join('test_ztranslation.log') - os.environ['PYPYLOG'] = 'jit-log-opt:%s' % (logfile,) - try: - res = self.meta_interp(main, [400]) - assert res == main(400) - finally: - del os.environ['PYPYLOG'] - - guard_class = 0 - for line in open(str(logfile)): - if 'guard_class' in line: - guard_class += 1 - # if we get many more guard_classes, it means that we generate - # guards that always fail (the following assert's original purpose - # is to catch the following case: each GUARD_CLASS is misgenerated - # and always fails with "gcremovetypeptr") - assert 0 < guard_class < 10 diff --git a/rpython/jit/backend/arm/test/test_ztranslation_basic.py b/rpython/jit/backend/arm/test/test_ztranslation_basic.py new file mode 100644 --- /dev/null +++ b/rpython/jit/backend/arm/test/test_ztranslation_basic.py @@ -0,0 +1,13 @@ +from rpython.jit.backend.llsupport.test.ztranslation_test import TranslationTest +from rpython.translator.translator import TranslationContext +from rpython.config.translationoption import DEFL_GC +from rpython.jit.backend.arm.test.support import skip_unless_run_slow_tests +skip_unless_run_slow_tests() + + +class TestTranslationARM(TranslationTest): + def _get_TranslationContext(self): + t = TranslationContext() + t.config.translation.gc = DEFL_GC # 'hybrid' or 'minimark' + t.config.translation.gcrootfinder = 'shadowstack' + return t diff --git a/rpython/jit/backend/arm/test/test_ztranslation_call_assembler.py b/rpython/jit/backend/arm/test/test_ztranslation_call_assembler.py new file mode 100644 --- /dev/null +++ b/rpython/jit/backend/arm/test/test_ztranslation_call_assembler.py @@ -0,0 +1,13 @@ +from rpython.jit.backend.llsupport.test.ztranslation_test import TranslationTestCallAssembler +from rpython.translator.translator import TranslationContext +from rpython.config.translationoption import DEFL_GC +from rpython.jit.backend.arm.test.support import skip_unless_run_slow_tests +skip_unless_run_slow_tests() + + +class TestTranslationCallAssemblerARM(TranslationTestCallAssembler): + def _get_TranslationContext(self): + t = TranslationContext() + t.config.translation.gc = DEFL_GC # 'hybrid' or 'minimark' + t.config.translation.gcrootfinder = 'shadowstack' + return t diff --git a/rpython/jit/backend/arm/test/test_ztranslation_external_exception.py b/rpython/jit/backend/arm/test/test_ztranslation_external_exception.py new file mode 100644 --- /dev/null +++ b/rpython/jit/backend/arm/test/test_ztranslation_external_exception.py @@ -0,0 +1,15 @@ +from rpython.jit.backend.llsupport.test.ztranslation_test import TranslationRemoveTypePtrTest +from rpython.translator.translator import TranslationContext +from rpython.config.translationoption import DEFL_GC +from rpython.jit.backend.arm.test.support import skip_unless_run_slow_tests +skip_unless_run_slow_tests() + + +class TestTranslationRemoveTypePtrARM(TranslationRemoveTypePtrTest): + def _get_TranslationContext(self): + t = TranslationContext() + t.config.translation.gc = DEFL_GC # 'hybrid' or 'minimark' + t.config.translation.gcrootfinder = 'shadowstack' + t.config.translation.list_comprehension_operations = True + t.config.translation.gcremovetypeptr = True + return t \ No newline at end of file diff --git a/rpython/jit/backend/arm/test/test_ztranslation_jit_stats.py b/rpython/jit/backend/arm/test/test_ztranslation_jit_stats.py new file mode 100644 --- /dev/null +++ b/rpython/jit/backend/arm/test/test_ztranslation_jit_stats.py @@ -0,0 +1,13 @@ +from rpython.jit.backend.llsupport.test.ztranslation_test import TranslationTestJITStats +from rpython.translator.translator import TranslationContext +from rpython.config.translationoption import DEFL_GC +from rpython.jit.backend.arm.test.support import skip_unless_run_slow_tests +skip_unless_run_slow_tests() + + +class TestTranslationJITStatsARM(TranslationTestJITStats): + def _get_TranslationContext(self): + t = TranslationContext() + t.config.translation.gc = DEFL_GC # 'hybrid' or 'minimark' + t.config.translation.gcrootfinder = 'shadowstack' + return t diff --git a/rpython/jit/backend/x86/test/test_zrpy_gc_boehm.py b/rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py copy from rpython/jit/backend/x86/test/test_zrpy_gc_boehm.py copy to rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py --- a/rpython/jit/backend/x86/test/test_zrpy_gc_boehm.py +++ b/rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py @@ -1,8 +1,8 @@ import weakref from rpython.rlib.jit import JitDriver, dont_look_inside -from rpython.jit.backend.x86.test.test_zrpy_gc import run, get_entry, compile -from rpython.jit.backend.x86.test.test_ztranslation import fix_annotator_for_vrawbuffer +from rpython.jit.backend.llsupport.test.zrpy_gc_test import run, get_entry, compile +from rpython.jit.backend.llsupport.test.ztranslation_test import fix_annotator_for_vrawbuffer class X(object): def __init__(self, x=0): diff --git a/rpython/jit/backend/x86/test/test_zrpy_gc.py b/rpython/jit/backend/llsupport/test/zrpy_gc_test.py copy from rpython/jit/backend/x86/test/test_zrpy_gc.py copy to rpython/jit/backend/llsupport/test/zrpy_gc_test.py diff --git a/rpython/jit/backend/x86/test/test_zrpy_releasegil.py b/rpython/jit/backend/llsupport/test/zrpy_releasegil_test.py copy from rpython/jit/backend/x86/test/test_zrpy_releasegil.py copy to rpython/jit/backend/llsupport/test/zrpy_releasegil_test.py --- a/rpython/jit/backend/x86/test/test_zrpy_releasegil.py +++ b/rpython/jit/backend/llsupport/test/zrpy_releasegil_test.py @@ -5,8 +5,8 @@ from rpython.rtyper.annlowlevel import llhelper -from rpython.jit.backend.x86.test.test_zrpy_gc import BaseFrameworkTests -from rpython.jit.backend.x86.test.test_zrpy_gc import check +from rpython.jit.backend.llsupport.test.zrpy_gc_test import BaseFrameworkTests +from rpython.jit.backend.llsupport.test.zrpy_gc_test import check from rpython.tool.udir import udir diff --git a/rpython/jit/backend/x86/test/test_ztranslation.py b/rpython/jit/backend/llsupport/test/ztranslation_test.py rename from rpython/jit/backend/x86/test/test_ztranslation.py rename to rpython/jit/backend/llsupport/test/ztranslation_test.py --- a/rpython/jit/backend/x86/test/test_ztranslation.py +++ b/rpython/jit/backend/llsupport/test/ztranslation_test.py @@ -1,17 +1,13 @@ -import py, os, sys +import os, sys from rpython.tool.udir import udir from rpython.rlib.jit import JitDriver, unroll_parameters, set_param from rpython.rlib.jit import PARAMETERS, dont_look_inside from rpython.rlib.jit import promote from rpython.rlib import jit_hooks -from rpython.jit.metainterp.jitprof import Profiler from rpython.jit.backend.detect_cpu import getcpuclass from rpython.jit.backend.test.support import CCompiledMixin from rpython.jit.codewriter.policy import StopAtXPolicy -from rpython.translator.translator import TranslationContext -from rpython.jit.backend.x86.arch import IS_X86_32, IS_X86_64 -from rpython.config.translationoption import DEFL_GC -from rpython.rlib import rgc + def fix_annotator_for_vrawbuffer(monkeypatch): from rpython.rlib.nonconst import NonConstant @@ -25,15 +21,9 @@ monkeypatch.setattr(warmspot, 'hook_for_tests', my_hook_for_tests) -class TestTranslationX86(CCompiledMixin): +class TranslationTest(CCompiledMixin): CPUClass = getcpuclass() - def _check_cbuilder(self, cbuilder): - # We assume here that we have sse2. If not, the CPUClass - # needs to be changed to CPU386_NO_SSE2, but well. - assert '-msse2' in cbuilder.eci.compile_extra - assert '-mfpmath=sse' in cbuilder.eci.compile_extra - def test_stuff_translates(self, monkeypatch): fix_annotator_for_vrawbuffer(monkeypatch) # this is a basic test that tries to hit a number of features and their @@ -108,6 +98,10 @@ res = self.meta_interp(main, [40, -49]) assert res == expected + +class TranslationTestCallAssembler(CCompiledMixin): + CPUClass = getcpuclass() + def test_direct_assembler_call_translates(self, monkeypatch): """Test CALL_ASSEMBLER and the recursion limit""" from rpython.rlib.rstackovf import StackOverflow @@ -185,10 +179,14 @@ assert 1024 <= bound <= 131072 assert bound & (bound-1) == 0 # a power of two + +class TranslationTestJITStats(CCompiledMixin): + CPUClass = getcpuclass() + def test_jit_get_stats(self, monkeypatch): fix_annotator_for_vrawbuffer(monkeypatch) driver = JitDriver(greens = [], reds = ['i']) - + def f(): i = 0 while i < 100000: @@ -205,17 +203,10 @@ assert res == 3 # one for loop, one for entry point and one for the prologue -class TestTranslationRemoveTypePtrX86(CCompiledMixin): + +class TranslationRemoveTypePtrTest(CCompiledMixin): CPUClass = getcpuclass() - def _get_TranslationContext(self): - t = TranslationContext() - t.config.translation.gc = DEFL_GC # 'hybrid' or 'minimark' - t.config.translation.gcrootfinder = 'asmgcc' - t.config.translation.list_comprehension_operations = True - t.config.translation.gcremovetypeptr = True - return t - def test_external_exception_handling_translates(self, monkeypatch): fix_annotator_for_vrawbuffer(monkeypatch) jitdriver = JitDriver(greens = [], reds = ['n', 'total']) diff --git a/rpython/jit/backend/x86/test/test_zrpy_gc.py b/rpython/jit/backend/x86/test/test_zrpy_gc.py --- a/rpython/jit/backend/x86/test/test_zrpy_gc.py +++ b/rpython/jit/backend/x86/test/test_zrpy_gc.py @@ -1,775 +1,1 @@ -""" -This is a test that translates a complete JIT together with a GC and runs it. -It is testing that the GC-dependent aspects basically work, mostly the mallocs -and the various cases of write barrier. -""" - -import weakref -import os -from rpython.rlib import rgc -from rpython.rtyper.lltypesystem import lltype -from rpython.rlib.jit import JitDriver, dont_look_inside -from rpython.rlib.jit import elidable, unroll_safe -from rpython.jit.backend.llsupport.gc import GcLLDescr_framework -from rpython.tool.udir import udir -from rpython.config.translationoption import DEFL_GC - - -class X(object): - def __init__(self, x=0): - self.x = x - - next = None - -class CheckError(Exception): - pass - -def check(flag): - if not flag: - raise CheckError - -def get_entry(g): - - def entrypoint(args): - name = '' - n = 2000 - argc = len(args) - if argc > 1: - name = args[1] - if argc > 2: - n = int(args[2]) - r_list = [] - for i in range(20): - r = g(name, n) - r_list.append(r) - rgc.collect() - rgc.collect(); rgc.collect() - freed = 0 - for r in r_list: - if r() is None: - freed += 1 - print freed - return 0 - - return entrypoint - -def get_functions_to_patch(): - from rpython.jit.backend.llsupport import gc - # - can_use_nursery_malloc1 = gc.GcLLDescr_framework.can_use_nursery_malloc - def can_use_nursery_malloc2(*args): - try: - if os.environ['PYPY_NO_INLINE_MALLOC']: - return False - except KeyError: - pass - return can_use_nursery_malloc1(*args) - # - return {(gc.GcLLDescr_framework, 'can_use_nursery_malloc'): - can_use_nursery_malloc2} - -def compile(f, gc, **kwds): - from rpython.annotator.listdef import s_list_of_strings - from rpython.translator.translator import TranslationContext - from rpython.jit.metainterp.warmspot import apply_jit - from rpython.translator.c import genc - # - t = TranslationContext() - t.config.translation.gc = gc - if gc != 'boehm': - t.config.translation.gcremovetypeptr = True - for name, value in kwds.items(): - setattr(t.config.translation, name, value) - ann = t.buildannotator() - ann.build_types(f, [s_list_of_strings], main_entry_point=True) - t.buildrtyper().specialize() - - if kwds['jit']: - patch = get_functions_to_patch() - old_value = {} - try: - for (obj, attr), value in patch.items(): - old_value[obj, attr] = getattr(obj, attr) - setattr(obj, attr, value) - # - apply_jit(t) - # - finally: - for (obj, attr), oldvalue in old_value.items(): - setattr(obj, attr, oldvalue) - - cbuilder = genc.CStandaloneBuilder(t, f, t.config) - cbuilder.generate_source(defines=cbuilder.DEBUG_DEFINES) - cbuilder.compile() - return cbuilder - -def run(cbuilder, args=''): - # - pypylog = udir.join('test_zrpy_gc.log') - data = cbuilder.cmdexec(args, env={'PYPYLOG': ':%s' % pypylog}) - return data.strip() - -# ______________________________________________________________________ - - -class BaseFrameworkTests(object): - - def setup_class(cls): - funcs = [] - name_to_func = {} - for fullname in dir(cls): - if not fullname.startswith('define'): - continue - definefunc = getattr(cls, fullname) - _, name = fullname.split('_', 1) - beforefunc, loopfunc, afterfunc = definefunc.im_func(cls) - if beforefunc is None: - def beforefunc(n, x): - return n, x, None, None, None, None, None, None, None, None, None, '' - if afterfunc is None: - def afterfunc(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - pass - beforefunc.func_name = 'before_'+name - loopfunc.func_name = 'loop_'+name - afterfunc.func_name = 'after_'+name - funcs.append((beforefunc, loopfunc, afterfunc)) - assert name not in name_to_func - name_to_func[name] = len(name_to_func) - print name_to_func - def allfuncs(name, n): - x = X() - x.foo = 2 - main_allfuncs(name, n, x) - x.foo = 5 - return weakref.ref(x) - def main_allfuncs(name, n, x): - num = name_to_func[name] - n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s = funcs[num][0](n, x) - while n > 0: - myjitdriver.can_enter_jit(num=num, n=n, x=x, x0=x0, x1=x1, - x2=x2, x3=x3, x4=x4, x5=x5, x6=x6, x7=x7, l=l, s=s) - myjitdriver.jit_merge_point(num=num, n=n, x=x, x0=x0, x1=x1, - x2=x2, x3=x3, x4=x4, x5=x5, x6=x6, x7=x7, l=l, s=s) - - n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s = funcs[num][1]( - n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s) - funcs[num][2](n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s) - myjitdriver = JitDriver(greens = ['num'], - reds = ['n', 'x', 'x0', 'x1', 'x2', 'x3', 'x4', - 'x5', 'x6', 'x7', 'l', 's']) - cls.main_allfuncs = staticmethod(main_allfuncs) - cls.name_to_func = name_to_func - OLD_DEBUG = GcLLDescr_framework.DEBUG - try: - GcLLDescr_framework.DEBUG = True - cls.cbuilder = compile(get_entry(allfuncs), DEFL_GC, - gcrootfinder=cls.gcrootfinder, jit=True, - thread=True) - finally: - GcLLDescr_framework.DEBUG = OLD_DEBUG - - def _run(self, name, n, env): - res = self.cbuilder.cmdexec("%s %d" %(name, n), env=env) - assert int(res) == 20 - - def run(self, name, n=2000): - pypylog = udir.join('TestCompileFramework.log') - env = {'PYPYLOG': ':%s' % pypylog, - 'PYPY_NO_INLINE_MALLOC': '1'} - self._run(name, n, env) - env['PYPY_NO_INLINE_MALLOC'] = '' - self._run(name, n, env) - - def run_orig(self, name, n, x): - self.main_allfuncs(name, n, x) - - -class CompileFrameworkTests(BaseFrameworkTests): - # Test suite using (so far) the minimark GC. - -## def define_libffi_workaround(cls): -## # XXX: this is a workaround for a bug in database.py. It seems that -## # the problem is triggered by optimizeopt/fficall.py, and in -## # particular by the ``cast_base_ptr_to_instance(Func, llfunc)``: in -## # these tests, that line is the only place where libffi.Func is -## # referenced. -## # -## # The problem occurs because the gctransformer tries to annotate a -## # low-level helper to call the __del__ of libffi.Func when it's too -## # late. -## # -## # This workaround works by forcing the annotator (and all the rest of -## # the toolchain) to see libffi.Func in a "proper" context, not just as -## # the target of cast_base_ptr_to_instance. Note that the function -## # below is *never* called by any actual test, it's just annotated. -## # -## from rpython.rlib.libffi import get_libc_name, CDLL, types, ArgChain -## libc_name = get_libc_name() -## def f(n, x, *args): -## libc = CDLL(libc_name) -## ptr = libc.getpointer('labs', [types.slong], types.slong) -## chain = ArgChain() -## chain.arg(n) -## n = ptr.call(chain, lltype.Signed) -## return (n, x) + args -## return None, f, None - - def define_compile_framework_1(cls): - # a moving GC. Supports malloc_varsize_nonmovable. Simple test, works - # without write_barriers and root stack enumeration. - def f(n, x, *args): - y = X() - y.foo = x.foo - n -= y.foo - return (n, x) + args - return None, f, None - - def test_compile_framework_1(self): - self.run('compile_framework_1') - - def define_compile_framework_2(cls): - # More complex test, requires root stack enumeration but - # not write_barriers. - def f(n, x, *args): - prev = x - for j in range(101): # f() runs 20'000 times, thus allocates - y = X() # a total of 2'020'000 objects - y.foo = prev.foo - prev = y - n -= prev.foo - return (n, x) + args - return None, f, None - - def test_compile_framework_2(self): - self.run('compile_framework_2') - - def define_compile_framework_3(cls): - # Third version of the test. Really requires write_barriers. - def f(n, x, *args): - x.next = None - for j in range(101): # f() runs 20'000 times, thus allocates - y = X() # a total of 2'020'000 objects - y.foo = j+1 - y.next = x.next - x.next = y - check(x.next.foo == 101) - total = 0 - y = x - for j in range(101): - y = y.next - total += y.foo - check(not y.next) - check(total == 101*102/2) - n -= x.foo - return (n, x) + args - return None, f, None - - - - def test_compile_framework_3(self): - x_test = X() - x_test.foo = 5 - self.run_orig('compile_framework_3', 6, x_test) # check that it does not raise CheckError - self.run('compile_framework_3') - - def define_compile_framework_3_extra(cls): - # Extra version of the test, with tons of live vars around the residual - # call that all contain a GC pointer. - @dont_look_inside - def residual(n=26): - x = X() - x.next = X() - x.next.foo = n - return x - # - def before(n, x): - residual(5) - x0 = residual() - x1 = residual() - x2 = residual() - x3 = residual() - x4 = residual() - x5 = residual() - x6 = residual() - x7 = residual() - n *= 19 - return n, None, x0, x1, x2, x3, x4, x5, x6, x7, None, None - def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - x8 = residual() - x9 = residual() - check(x0.next.foo == 26) - check(x1.next.foo == 26) - check(x2.next.foo == 26) - check(x3.next.foo == 26) - check(x4.next.foo == 26) - check(x5.next.foo == 26) - check(x6.next.foo == 26) - check(x7.next.foo == 26) - check(x8.next.foo == 26) - check(x9.next.foo == 26) - x0, x1, x2, x3, x4, x5, x6, x7 = x7, x4, x6, x5, x3, x2, x9, x8 - n -= 1 - return n, None, x0, x1, x2, x3, x4, x5, x6, x7, None, None - return before, f, None - - def test_compile_framework_3_extra(self): - self.run_orig('compile_framework_3_extra', 6, None) # check that it does not raise CheckError - self.run('compile_framework_3_extra') - - def define_compile_framework_4(cls): - # Fourth version of the test, with __del__. - from rpython.rlib.debug import debug_print - class Counter: - cnt = 0 - counter = Counter() - class Z: - def __del__(self): - counter.cnt -= 1 - def before(n, x): - debug_print('counter.cnt =', counter.cnt) - check(counter.cnt < 5) - counter.cnt = n // x.foo - return n, x, None, None, None, None, None, None, None, None, None, None - def f(n, x, *args): - Z() - n -= x.foo - return (n, x) + args - return before, f, None - - def test_compile_framework_4(self): - self.run('compile_framework_4') - - def define_compile_framework_5(cls): - # Test string manipulation. - def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - n -= x.foo - s += str(n) - return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s - def after(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - check(len(s) == 1*5 + 2*45 + 3*450 + 4*500) - return None, f, after - - def test_compile_framework_5(self): - self.run('compile_framework_5') - - def define_compile_framework_7(cls): - # Array of pointers (test the write barrier for setarrayitem_gc) - def before(n, x): - return n, x, None, None, None, None, None, None, None, None, [X(123)], None - def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - if n < 1900: - check(l[0].x == 123) - l = [None] * 16 - l[0] = X(123) - l[1] = X(n) - l[2] = X(n+10) - l[3] = X(n+20) - l[4] = X(n+30) - l[5] = X(n+40) - l[6] = X(n+50) - l[7] = X(n+60) - l[8] = X(n+70) - l[9] = X(n+80) - l[10] = X(n+90) - l[11] = X(n+100) - l[12] = X(n+110) - l[13] = X(n+120) - l[14] = X(n+130) - l[15] = X(n+140) - if n < 1800: - check(len(l) == 16) - check(l[0].x == 123) - check(l[1].x == n) - check(l[2].x == n+10) - check(l[3].x == n+20) - check(l[4].x == n+30) - check(l[5].x == n+40) - check(l[6].x == n+50) - check(l[7].x == n+60) - check(l[8].x == n+70) - check(l[9].x == n+80) - check(l[10].x == n+90) - check(l[11].x == n+100) - check(l[12].x == n+110) - check(l[13].x == n+120) - check(l[14].x == n+130) - check(l[15].x == n+140) - n -= x.foo - return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s - def after(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - check(len(l) == 16) - check(l[0].x == 123) - check(l[1].x == 2) - check(l[2].x == 12) - check(l[3].x == 22) - check(l[4].x == 32) - check(l[5].x == 42) - check(l[6].x == 52) - check(l[7].x == 62) - check(l[8].x == 72) - check(l[9].x == 82) - check(l[10].x == 92) - check(l[11].x == 102) - check(l[12].x == 112) - check(l[13].x == 122) - check(l[14].x == 132) - check(l[15].x == 142) - return before, f, after - - def test_compile_framework_7(self): - self.run('compile_framework_7') - - def define_compile_framework_7_interior(cls): - # Array of structs containing pointers (test the write barrier - # for setinteriorfield_gc) - S = lltype.GcStruct('S', ('i', lltype.Signed)) - A = lltype.GcArray(lltype.Struct('entry', ('x', lltype.Ptr(S)), - ('y', lltype.Ptr(S)), - ('z', lltype.Ptr(S)))) - class Glob: - a = lltype.nullptr(A) - glob = Glob() - # - def make_s(i): - s = lltype.malloc(S) - s.i = i - return s - # - @unroll_safe - def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - a = glob.a - if not a: - a = glob.a = lltype.malloc(A, 10) - i = 0 - while i < 10: - a[i].x = make_s(n + i * 100 + 1) - a[i].y = make_s(n + i * 100 + 2) - a[i].z = make_s(n + i * 100 + 3) - i += 1 - i = 0 - while i < 10: - check(a[i].x.i == n + i * 100 + 1) - check(a[i].y.i == n + i * 100 + 2) - check(a[i].z.i == n + i * 100 + 3) - i += 1 - n -= x.foo - return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s - return None, f, None - - def test_compile_framework_7_interior(self): - self.run('compile_framework_7_interior') - - def define_compile_framework_8(cls): - # Array of pointers, of unknown length (test write_barrier_from_array) - def before(n, x): - return n, x, None, None, None, None, None, None, None, None, [X(123)], None - def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - if n < 1900: - check(l[0].x == 123) - l = [None] * (16 + (n & 7)) - l[0] = X(123) - l[1] = X(n) - l[2] = X(n+10) - l[3] = X(n+20) - l[4] = X(n+30) - l[5] = X(n+40) - l[6] = X(n+50) - l[7] = X(n+60) - l[8] = X(n+70) - l[9] = X(n+80) - l[10] = X(n+90) - l[11] = X(n+100) - l[12] = X(n+110) - l[13] = X(n+120) - l[14] = X(n+130) - l[15] = X(n+140) - if n < 1800: - check(len(l) == 16 + (n & 7)) - check(l[0].x == 123) - check(l[1].x == n) - check(l[2].x == n+10) - check(l[3].x == n+20) - check(l[4].x == n+30) - check(l[5].x == n+40) - check(l[6].x == n+50) - check(l[7].x == n+60) - check(l[8].x == n+70) - check(l[9].x == n+80) - check(l[10].x == n+90) - check(l[11].x == n+100) - check(l[12].x == n+110) - check(l[13].x == n+120) - check(l[14].x == n+130) - check(l[15].x == n+140) - n -= x.foo - return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s - def after(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - check(len(l) >= 16) - check(l[0].x == 123) - check(l[1].x == 2) - check(l[2].x == 12) - check(l[3].x == 22) - check(l[4].x == 32) - check(l[5].x == 42) - check(l[6].x == 52) - check(l[7].x == 62) - check(l[8].x == 72) - check(l[9].x == 82) - check(l[10].x == 92) - check(l[11].x == 102) - check(l[12].x == 112) - check(l[13].x == 122) - check(l[14].x == 132) - check(l[15].x == 142) - return before, f, after - - def test_compile_framework_8(self): - self.run('compile_framework_8') - - def define_compile_framework_9(cls): - # Like compile_framework_8, but with variable indexes and large - # arrays, testing the card_marking case - def before(n, x): - return n, x, None, None, None, None, None, None, None, None, [X(123)], None - def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - if n < 1900: - check(l[0].x == 123) - num = 512 + (n & 7) - l = [None] * num - l[0] = X(123) - l[1] = X(n) - l[2] = X(n+10) - l[3] = X(n+20) - l[4] = X(n+30) - l[5] = X(n+40) - l[6] = X(n+50) - l[7] = X(n+60) - l[num-8] = X(n+70) - l[num-9] = X(n+80) - l[num-10] = X(n+90) - l[num-11] = X(n+100) - l[-12] = X(n+110) - l[-13] = X(n+120) - l[-14] = X(n+130) - l[-15] = X(n+140) - if n < 1800: - num = 512 + (n & 7) - check(len(l) == num) - check(l[0].x == 123) - check(l[1].x == n) - check(l[2].x == n+10) - check(l[3].x == n+20) - check(l[4].x == n+30) - check(l[5].x == n+40) - check(l[6].x == n+50) - check(l[7].x == n+60) - check(l[num-8].x == n+70) - check(l[num-9].x == n+80) - check(l[num-10].x == n+90) - check(l[num-11].x == n+100) - check(l[-12].x == n+110) - check(l[-13].x == n+120) - check(l[-14].x == n+130) - check(l[-15].x == n+140) - n -= x.foo - return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s - def after(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - check(len(l) >= 512) - check(l[0].x == 123) - check(l[1].x == 2) - check(l[2].x == 12) - check(l[3].x == 22) - check(l[4].x == 32) - check(l[5].x == 42) - check(l[6].x == 52) - check(l[7].x == 62) - check(l[-8].x == 72) - check(l[-9].x == 82) - check(l[-10].x == 92) - check(l[-11].x == 102) - check(l[-12].x == 112) - check(l[-13].x == 122) - check(l[-14].x == 132) - check(l[-15].x == 142) - return before, f, after - - def test_compile_framework_9(self): - self.run('compile_framework_9') - - def define_compile_framework_external_exception_handling(cls): - def before(n, x): - x = X(0) - return n, x, None, None, None, None, None, None, None, None, None, None - - @dont_look_inside - def g(x): - if x > 200: - return 2 - raise ValueError - @dont_look_inside - def h(x): - if x > 150: - raise ValueError - return 2 - - def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - try: - x.x += g(n) - except ValueError: - x.x += 1 - try: - x.x += h(n) - except ValueError: - x.x -= 1 - n -= 1 - return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s - - def after(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - check(x.x == 1800 * 2 + 1850 * 2 + 200 - 150) - - return before, f, None - - def test_compile_framework_external_exception_handling(self): - self.run('compile_framework_external_exception_handling') - - def define_compile_framework_bug1(self): - @elidable - def nonmoving(): - x = X(1) - for i in range(7): From noreply at buildbot.pypy.org Fri Apr 12 00:12:28 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Fri, 12 Apr 2013 00:12:28 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: running version of BitBlt Message-ID: <20130411221228.34EDB1C030D@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r250:9a05c60e44e1 Date: 2013-04-10 17:27 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/9a05c60e44e1/ Log: running version of BitBlt diff --git a/BitBltSim.19.cs b/BitBltSim.19.cs --- a/BitBltSim.19.cs +++ b/BitBltSim.19.cs @@ -94,7 +94,8 @@ simDestRaster _ destForm width - 1 // WordSize + 1. sourceForm notNil ifTrue: [simSourceBits _ sourceForm bits. - simSourceRaster _ sourceForm width - 1 // WordSize + 1]. + simSourceRaster _ sourceForm width - 1 // WordSize + 1] + ifFalse: [simSourceRaster _ 0]. halftoneForm notNil ifTrue: [simHalftoneBits _ halftoneForm bits]. simSkew _ (simSx - simDx) bitAnd: WordSize0. @@ -141,7 +142,9 @@ ifTrue: [prevWord _ prevWord bitAnd: simSkewMask. "XXX: Hack to work around out-of-bounds access" - thisWord := simSourceBits at: (simSourceIndex \\ simSourceBits size) + 1. + thisWord := (simSourceIndex < 0 or: [simSourceIndex >= simSourceBits size]) + ifTrue: [simSourceBits at: 1] + ifFalse: [simSourceBits at: simSourceIndex + 1]. "pick up next word" skewWord _ prevWord bitOr: (thisWord bitAnd: simSkewMask bitInvert32). @@ -190,7 +193,6 @@ destForm unhibernate. sourceForm - ifNil: [sourceForm := destForm] ifNotNil: [sourceForm unhibernate]. halftoneForm ifNotNil: [ (halftoneForm isKindOf: Form) @@ -220,6 +222,7 @@ simDy _ clipY]. simDy + simH > (clipY + clipHeight) ifTrue: [simH _ simH - ((simDy + simH) - (clipY + clipHeight))]. + sourceForm isNil ifTrue: [^nil]. simSx < 0 ifTrue: [simDx _ simDx - simSx. simW _ simW + simSx. simSx _ 0]. simSx + simW > sourceForm width diff --git a/images/minibluebookdebug.image b/images/minibluebookdebug.image index 55870b1f6092dbfa3dcb4e4d0c46fec62b223bf2..77abab25338f3dab9a3e19883f8686ca98ac49c9 GIT binary patch [cut] From noreply at buildbot.pypy.org Fri Apr 12 00:12:29 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Fri, 12 Apr 2013 00:12:29 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: refactored sdl connection to avoid double blitting Message-ID: <20130411221229.686FC1C030D@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r251:32ca02e56ca2 Date: 2013-04-10 21:26 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/32ca02e56ca2/ Log: refactored sdl connection to avoid double blitting diff --git a/spyvm/display.py b/spyvm/display.py --- a/spyvm/display.py +++ b/spyvm/display.py @@ -1,6 +1,7 @@ from rpython.rlib.rarithmetic import r_uint from rpython.rtyper.lltypesystem import lltype, rffi from rpython.rlib.runicode import unicode_encode_utf_8 +from rpython.rlib import jit from rsdl import RSDL, RSDL_helper @@ -58,26 +59,11 @@ self.depth = d self.screen = RSDL.SetVideoMode(w, h, 32, 0) assert self.screen - # self.fillwhite() - def set_pixelbuffer(self, pixelbuffer): - if self.has_surface: - RSDL.FreeSurface(self.surface) - pitch = 4 * self.width - rmask, gmask, bmask, amask = r_uint(0x000000FF), r_uint(0x0000FF00), r_uint(0x00FF0000), r_uint(0xFF000000) - self.surface = RSDL.CreateRGBSurfaceFrom(rffi.cast(rffi.VOIDP, pixelbuffer), - self.width, self.height, 32, pitch, - rmask, gmask, bmask, amask) - self.has_surface = True + def get_pixelbuffer(self): + return self.screen.c_pixels - def fillwhite(self): - fmt = self.screen.c_format - color = RSDL.MapRGB(fmt, 255, 255, 255) - RSDL.FillRect(self.screen, lltype.nullptr(RSDL.Rect), color) - RSDL.Flip(self.screen) - - def blit(self): - RSDL.BlitSurface(self.surface, lltype.nullptr(RSDL.Rect), self.screen, lltype.nullptr(RSDL.Rect)) + def flip(self): RSDL.Flip(self.screen) def get_next_event(self): diff --git a/spyvm/model.py b/spyvm/model.py --- a/spyvm/model.py +++ b/spyvm/model.py @@ -698,14 +698,11 @@ def __init__(self, space, w_class, size, depth, display): W_AbstractObjectWithClassReference.__init__(self, space, w_class) - bytelen = NATIVE_DEPTH / depth * size - self.pixelbuffer = lltype.malloc(rffi.ULONGP.TO, bytelen, flavor='raw') + self._real_depth_buffer = [0] * size + self.pixelbuffer = display.get_pixelbuffer() self._realsize = size self.display = display - def __del__(self): - lltype.free(self.pixelbuffer, flavor='raw') - def at0(self, space, index0): val = self.getword(index0) return space.wrap_uint(val) @@ -715,7 +712,7 @@ self.setword(index0, word) def flush_to_screen(self): - self.display.blit() + self.display.flip() def size(self): return self._realsize @@ -739,28 +736,23 @@ class W_DisplayBitmap1Bit(W_DisplayBitmap): - @jit.unroll_safe def getword(self, n): - word = r_uint(0) - pos = n * NATIVE_DEPTH - for i in xrange(32): - word <<= 1 - pixel = self.pixelbuffer[pos] - word |= r_uint(pixel & 0x1) - pos += 1 - return ~word + return self._real_depth_buffer[n] @jit.unroll_safe def setword(self, n, word): - pos = n * NATIVE_DEPTH + self._real_depth_buffer[n] = word + pos = n * NATIVE_DEPTH * 4 mask = r_uint(1) mask <<= 31 for i in xrange(32): bit = mask & word - pixel = r_uint((0x00ffffff * (bit == 0)) | r_uint(0xff000000)) - self.pixelbuffer[pos] = pixel + self.pixelbuffer[pos] = rffi.r_uchar(0xff * (bit == 0)) + self.pixelbuffer[pos + 1] = rffi.r_uchar(0xff * (bit == 0)) + self.pixelbuffer[pos + 2] = rffi.r_uchar(0xff * (bit == 0)) + self.pixelbuffer[pos + 3] = rffi.r_uchar(0xff) mask >>= 1 - pos += 1 + pos += 4 # XXX Shouldn't compiledmethod have class reference for subclassed compiled diff --git a/spyvm/objspace.py b/spyvm/objspace.py --- a/spyvm/objspace.py +++ b/spyvm/objspace.py @@ -1,5 +1,6 @@ from spyvm import constants, model, shadow, wrapper from spyvm.error import UnwrappingError, WrappingError, PrimitiveFailedError +from rpython.rlib import jit from rpython.rlib.objectmodel import instantiate, specialize from rpython.rlib.rarithmetic import intmask, r_uint, int_between diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -592,15 +592,18 @@ w_prev_bitmap = w_prev_display.fetch(interp.space, 0) if isinstance(w_prev_bitmap, model.W_DisplayBitmap): sdldisplay = w_prev_bitmap.display + sdldisplay.set_video_mode(width, height, depth) if isinstance(w_bitmap, model.W_DisplayBitmap): assert (sdldisplay is None) or (sdldisplay is w_bitmap.display) sdldisplay = w_bitmap.display + sdldisplay.set_video_mode(width, height, depth) w_display_bitmap = w_bitmap else: assert isinstance(w_bitmap, model.W_WordsObject) if not sdldisplay: sdldisplay = display.SDLDisplay(interp.image_name) + sdldisplay.set_video_mode(width, height, depth) w_display_bitmap = model.W_DisplayBitmap.create( interp.space, w_bitmap.getclass(interp.space), @@ -612,9 +615,7 @@ w_display_bitmap.setword(idx, word) w_rcvr.store(interp.space, 0, w_display_bitmap) - sdldisplay.set_video_mode(width, height, depth) - sdldisplay.set_pixelbuffer(w_display_bitmap.pixelbuffer) - sdldisplay.blit() + w_display_bitmap.flush_to_screen() interp.space.objtable['w_display'] = w_rcvr return w_rcvr From noreply at buildbot.pypy.org Fri Apr 12 00:12:30 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Fri, 12 Apr 2013 00:12:30 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: added primitive 19 which fails, except when (probably) calling the debugger. Then it quits gracefully. Message-ID: <20130411221230.951E61C030D@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r252:975a2cd34dda Date: 2013-04-10 21:28 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/975a2cd34dda/ Log: added primitive 19 which fails, except when (probably) calling the debugger. Then it quits gracefully. diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -321,6 +321,14 @@ FAIL = 19 + at expose_primitive(FAIL) +def func(interp, s_frame, argcount): + from spyvm.interpreter import ReturnFromTopLevel + if s_frame.w_method()._likely_methodname == 'doesNotUnderstand:': + print 'Probably Debugger called...' + raise ReturnFromTopLevel(interp.space.wrap_string("debugger called")) + raise PrimitiveFailedError() + # ___________________________________________________________________________ # Subscript and Stream Primitives From noreply at buildbot.pypy.org Fri Apr 12 00:12:31 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Fri, 12 Apr 2013 00:12:31 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: (cfbolz, lwassermann): refactored wrap_uint to enable inlining the general case Message-ID: <20130411221231.ABE061C030D@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r253:26ab2618ed58 Date: 2013-04-10 21:30 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/26ab2618ed58/ Log: (cfbolz, lwassermann): refactored wrap_uint to enable inlining the general case added hint to unwrap_array to enable unrolling for common case of constant array diff --git a/spyvm/objspace.py b/spyvm/objspace.py --- a/spyvm/objspace.py +++ b/spyvm/objspace.py @@ -193,11 +193,14 @@ if bytes_len <= 4: return self.wrap_positive_32bit_int(intmask(val)) else: - w_result = model.W_BytesObject(self, - self.classtable['w_LargePositiveInteger'], bytes_len) - for i in range(bytes_len): - w_result.setchar(i, chr(intmask((val >> i*8) & 255))) - return w_result + return self._wrap_uint_loop(val, bytes_len) + + def _wrap_uint_loop(self, val, bytes_len): + w_result = model.W_BytesObject(self, + self.classtable['w_LargePositiveInteger'], bytes_len) + for i in range(bytes_len): + w_result.setchar(i, chr(intmask((val >> i*8) & 255))) + return w_result def wrap_positive_32bit_int(self, val): # This will always return a positive value. @@ -298,6 +301,8 @@ if not isinstance(w_v, model.W_PointersObject): raise UnwrappingError() return w_v + + @jit.look_inside_iff(lambda self, w_array: jit.isconstant(w_array.size())) def unwrap_array(self, w_array): # Check that our argument has pointers format and the class: if not w_array.getclass(self).is_same_object(self.w_Array): From noreply at buildbot.pypy.org Fri Apr 12 00:12:32 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Fri, 12 Apr 2013 00:12:32 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: (cfbolz, lwassermann): prepared a typetest for s_class field Message-ID: <20130411221232.C3FBC1C030D@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r254:db4538a2badf Date: 2013-04-11 15:03 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/db4538a2badf/ Log: (cfbolz, lwassermann): prepared a typetest for s_class field diff --git a/spyvm/model.py b/spyvm/model.py --- a/spyvm/model.py +++ b/spyvm/model.py @@ -17,7 +17,7 @@ import sys from spyvm import constants, error -from rpython.rlib import rrandom, objectmodel, jit +from rpython.rlib import rrandom, objectmodel, jit, signature from rpython.rlib.rarithmetic import intmask, r_uint from rpython.tool.pairtype import extendabletype from rpython.rlib.objectmodel import instantiate, compute_hash @@ -373,7 +373,7 @@ def size(self): return 2 - + at signature.finishsigs class W_AbstractObjectWithClassReference(W_AbstractObjectWithIdentityHash): """Objects with arbitrary class (ie not CompiledMethod, SmallInteger or Float).""" @@ -422,9 +422,13 @@ def has_class(self): return self.s_class is not None + # we would like the following, but that leads to a recursive import + #@signature(signature.types.self(), signature.type.any(), + # returns=signature.types.instance(ClassShadow)) def shadow_of_my_class(self, space): - assert self.s_class is not None - return self.s_class + s_class = self.s_class + assert s_class is not None + return s_class class W_PointersObject(W_AbstractObjectWithClassReference): """Common object.""" @@ -525,10 +529,13 @@ # Should only be used during squeak-image loading. def as_class_get_penumbra(self, space): from spyvm.shadow import ClassShadow - assert self._shadow is None or isinstance(self._shadow, ClassShadow) - if self._shadow is None: - self.store_shadow(ClassShadow(space, self)) - return self._shadow + s_class = self._shadow + if s_class is None: + s_class = ClassShadow(space, self) + self.store_shadow(s_class) + else: + assert isinstance(s_class, ClassShadow) + return s_class def as_blockcontext_get_shadow(self, space): from spyvm.shadow import BlockContextShadow From noreply at buildbot.pypy.org Fri Apr 12 00:12:33 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Fri, 12 Apr 2013 00:12:33 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: (cfbolz, lwassermann): implemented unwrap_uint using polymorphism to get rid of loop and extensive branches Message-ID: <20130411221233.ECC461C030D@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r255:8f0af90c962e Date: 2013-04-11 15:04 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/8f0af90c962e/ Log: (cfbolz, lwassermann): implemented unwrap_uint using polymorphism to get rid of loop and extensive branches diff --git a/spyvm/model.py b/spyvm/model.py --- a/spyvm/model.py +++ b/spyvm/model.py @@ -127,6 +127,9 @@ def rshift(self, space, shift): raise error.PrimitiveFailedError() + def unwrap_uint(self, space): + raise error.UnwrappingError("Got unexpected class in unwrap_uint") + class W_SmallInteger(W_Object): """Boxed integer value""" # TODO can we tell pypy that its never larger then 31-bit? @@ -165,6 +168,14 @@ def rshift(self, space, shift): return space.wrap_int(self.value >> shift) + def unwrap_uint(self, space): + from rpython.rlib.rarithmetic import r_uint + val = self.value + if val < 0: + raise error.UnwrappingError("got negative integer") + return r_uint(val) + + @jit.elidable def as_repr_string(self): return "W_SmallInteger(%d)" % self.value @@ -262,6 +273,10 @@ # and only in this case we do need such a mask return space.wrap_int((self.value >> shift) & mask) + def unwrap_uint(self, space): + from rpython.rlib.rarithmetic import r_uint + return r_uint(self.value) + def clone(self, space): return W_LargePositiveInteger1Word(self.value) @@ -651,6 +666,16 @@ w_result.bytes = list(self.bytes) return w_result + def unwrap_uint(self, space): + # TODO: Completely untested! This failed translation bigtime... + # XXX Probably we want to allow all subclasses + if not self.getclass(space).is_same_object(space.w_LargePositiveInteger): + raise error.UnwrappingError("Failed to convert bytes to word") + word = 0 + for i in range(self.size()): + word += r_uint(ord(self.getchar(i))) << 8*i + return word + class W_WordsObject(W_AbstractObjectWithClassReference): _attrs_ = ['words'] diff --git a/spyvm/objspace.py b/spyvm/objspace.py --- a/spyvm/objspace.py +++ b/spyvm/objspace.py @@ -251,24 +251,7 @@ raise UnwrappingError("expected a W_SmallInteger or W_LargePositiveInteger1Word, got %s" % (w_value,)) def unwrap_uint(self, w_value): - if isinstance(w_value, model.W_SmallInteger): - val = w_value.value - if val < 0: - raise UnwrappingError("got negative integer") - return r_uint(w_value.value) - elif isinstance(w_value, model.W_LargePositiveInteger1Word): - return r_uint(w_value.value) - elif isinstance(w_value, model.W_BytesObject): - # TODO: Completely untested! This failed translation bigtime... - # XXX Probably we want to allow all subclasses - if not w_value.getclass(self).is_same_object(self.w_LargePositiveInteger): - raise UnwrappingError("Failed to convert bytes to word") - word = 0 - for i in range(w_value.size()): - word += r_uint(ord(w_value.getchar(i))) << 8*i - return word - else: - raise UnwrappingError("Got unexpected class in unwrap_uint") + return w_value.unwrap_uint(self) def unwrap_positive_32bit_int(self, w_value): if isinstance(w_value, model.W_SmallInteger): From noreply at buildbot.pypy.org Fri Apr 12 00:12:35 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Fri, 12 Apr 2013 00:12:35 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: some small optimizations to the blitting algorithm Message-ID: <20130411221235.43B311C030D@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r256:a6652f5187c9 Date: 2013-04-11 15:05 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/a6652f5187c9/ Log: some small optimizations to the blitting algorithm diff --git a/BitBltSim.19.cs b/BitBltSim.19.cs --- a/BitBltSim.19.cs +++ b/BitBltSim.19.cs @@ -119,47 +119,37 @@ !BitBlt methodsFor: 'simulation' stamp: 'tfel 3/17/2013 16:17'! copyLoop - | prevWord thisWord skewWord mergeMask - halftoneWord mergeWord | - 1 to: simH do: "here is the vertical loop" + | prevWord thisWord skewWord mergeMask halftoneWord mergeWord noSimSkewMask | + noSimSkewMask _ simSkewMask bitInvert32. + 1 to: simH do: [:i | - (halftoneForm notNil) - ifTrue: - "XXX Accessing simHalftoneBits with wrap-around ... different from BlueBook" - [halftoneWord _ simHalftoneBits at: (1 + (simDy \\ simHalftoneBits size)). + halftoneForm notNil + ifTrue: + [halftoneWord _ simHalftoneBits at: 1 + (simDy \\ simHalftoneBits size). simDy _ simDy + simVDir] ifFalse: [halftoneWord _ AllOnes]. skewWord _ halftoneWord. simPreload - ifTrue: [prevWord _ simSourceBits at: simSourceIndex + 1. - "load the 32bit shifter. TODO: check if this is WordSize dependent" - simSourceIndex _ simSourceIndex + simHDir] + ifTrue: + [prevWord _ simSourceBits at: simSourceIndex + 1. + simSourceIndex _ simSourceIndex + simHDir] ifFalse: [prevWord _ 0]. mergeMask _ simMask1. - 1 to: simNWords do: "here is the inner horizontal loop" - [:word | - sourceForm notNil "if source is used" - ifTrue: - [prevWord _ prevWord bitAnd: simSkewMask. - "XXX: Hack to work around out-of-bounds access" - thisWord := (simSourceIndex < 0 or: [simSourceIndex >= simSourceBits size]) - ifTrue: [simSourceBits at: 1] - ifFalse: [simSourceBits at: simSourceIndex + 1]. - "pick up next word" - skewWord _ - prevWord bitOr: (thisWord bitAnd: simSkewMask bitInvert32). - prevWord _ thisWord. - "Change from BB: bitAnd: AllOnes to stay in word bounds" - skewWord _ ((skewWord bitShift: simSkew) bitAnd: AllOnes) bitOr: - (skewWord bitShift: simSkew - WordSize)]. - "WordSize-bit rotate" - mergeWord _ self merge: (skewWord bitAnd: halftoneWord) - with: (simDestBits at: simDestIndex + 1). - simDestBits - at: simDestIndex + 1 - put: ((mergeMask bitAnd: mergeWord) - bitOr: (mergeMask bitInvert32 - bitAnd: (simDestBits at: simDestIndex + 1))). + 1 to: simNWords do: + [:word | + sourceForm notNil + ifTrue: + [thisWord _ (simSourceIndex <= 0 or: [simSourceIndex >= simSourceBits size]) + ifTrue: [simSourceBits at: 1] + ifFalse: [simSourceBits at: simSourceIndex + 1]. + prevWord _ (prevWord bitAnd: simSkewMask) bitShift: simSkew. + skewWord _ prevWord bitOr: ((thisWord bitAnd: noSimSkewMask) bitShift: simSkew - WordSize). + prevWord _ thisWord]. + halftoneForm notNil + ifTrue: [mergeWord _ self merge: (skewWord bitAnd: halftoneWord) + with: (simDestBits at: simDestIndex + 1)]. + simDestBits at: simDestIndex + 1 put: ((mergeMask bitAnd: mergeWord) + bitOr: (mergeMask bitInvert32 bitAnd: (simDestBits at: simDestIndex + 1))). simSourceIndex _ simSourceIndex + simHDir. simDestIndex _ simDestIndex + simHDir. word = (simNWords - 1) diff --git a/images/minibluebookdebug.image b/images/minibluebookdebug.image index 77abab25338f3dab9a3e19883f8686ca98ac49c9..72834c73d01e0d5de097c1c824971bd952d0e6e8 GIT binary patch [cut] From noreply at buildbot.pypy.org Fri Apr 12 00:12:36 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Fri, 12 Apr 2013 00:12:36 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: added type hints for instance variables of non-varsized pointers objects Message-ID: <20130411221236.5C58D1C030D@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r257:720555f9465b Date: 2013-04-11 20:36 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/720555f9465b/ Log: added type hints for instance variables of non-varsized pointers objects diff --git a/spyvm/fieldtypes.py b/spyvm/fieldtypes.py new file mode 100644 --- /dev/null +++ b/spyvm/fieldtypes.py @@ -0,0 +1,133 @@ +from spyvm import model, shadow + +from rpython.rlib import jit, signature + +LPI = object() +int +float + +object + +maps = dict() + +class VarSizedFieldTypes(): + _immutable_fields_ = [] + _attrs_ = [] + _settled_ = True + + @staticmethod + def of_length(s_class, n): + return nilTyper + + def __init__(self): + pass + + def fetch(self, w_obj, n0): + return w_obj._vars[n0] + + def store(self, w_obj, n0, w_val): + w_obj._vars[n0] = w_val + +class FieldTypes(VarSizedFieldTypes): + _immutable_fields_ = ['types'] + _attrs_ = ['types', 'parent', 'siblings', 'diff'] + _settled_ = True + + def __init__(self, types, parent=None, change=(-1, object)): + self.types = types + self.parent = parent + if parent is not None: + assert change != (-1, object) + self.diff = change + + self.siblings = dict() + + def fetch(self, w_object, n0): + w_result = w_object._vars[n0] + types = self.types + if types[n0] is int: + jit.record_known_class(w_result, model.W_SmallInteger) + elif types[n0] is LPI: + jit.record_known_class(w_result, model.W_LargePositiveInteger1Word) + elif types[n0] is float: + jit.record_known_class(w_result, model.W_Float) + return w_result + + def store(self, w_object, n0, w_value): + types = self.types + changed_type = w_value.fieldtype() + if types[n0] is not changed_type: + w_object.fieldtypes = self.sibling(n0, changed_type) + w_object._vars[n0] = w_value + + + def sibling(self, n0, changed_type): + assert self.types[n0] is not changed_type + change = (n0, changed_type) + parent = self.parent + siblings = self.siblings + if change in siblings: + return siblings[change] + elif parent is None: + return self.descent([change]) + else: + new_fieldtype = parent.ascent([change, self.diff]) + assert new_fieldtype.types == self.types[0:n0] + [changed_type] + self.types[n0+1:] + siblings[change] = new_fieldtype + return new_fieldtype + + def ascent(self, changes): + parent = self.parent + if parent is None: + return self.descent(sorted(changes)) + else: + change = self.diff + if changes[0][0] != change[0]: + changes.append(change) + return parent.ascent(changes) + + def descent(self, changes): + if changes == []: + return self + + change = changes[0] + siblings = self.siblings + if change in siblings: + return siblings[change].descent(changes[1:]) + else: + new_types = list(self.types) + new_types[change[0]] = change[1] + new_fieldtype = FieldTypes(new_types, self, change) + siblings[change] = new_fieldtype + return new_fieldtype.descent(changes[1:]) + + + @staticmethod + def of_length(n): + if n not in maps: + maps[n] = FieldTypes([object] * n) + return maps[n] + + +nilTyper = VarSizedFieldTypes() +def fieldtypes_of_length(s_class, size): + if s_class is None or s_class.isvariable(): + return nilTyper + else: + return FieldTypes.of_length(size) + +def fieldtypes_of(w_obj): + try: + if w_obj.s_class.isvariable(): + return nilTyper + else: + vars = w_obj._vars + size = len(vars) + typer = FieldTypes.of_length(size) + for i, w_val in enumerate(vars): + changed_type = w_val.fieldtype() + if changed_type is not object: + typer = typer.sibling(i, changed_type) + return typer + except AttributeError: + return nilTyper \ No newline at end of file diff --git a/spyvm/model.py b/spyvm/model.py --- a/spyvm/model.py +++ b/spyvm/model.py @@ -130,6 +130,9 @@ def unwrap_uint(self, space): raise error.UnwrappingError("Got unexpected class in unwrap_uint") + def fieldtype(self): + return object + class W_SmallInteger(W_Object): """Boxed integer value""" # TODO can we tell pypy that its never larger then 31-bit? @@ -200,6 +203,9 @@ def clone(self, space): return self + def fieldtype(self): + return int + class W_AbstractObjectWithIdentityHash(W_Object): """Object with explicit hash (ie all except small ints and floats).""" @@ -303,6 +309,10 @@ def invariant(self): return isinstance(self.value, int) + def fieldtype(self): + from spyvm.fieldtype import LPI + return LPI + class W_Float(W_AbstractObjectWithIdentityHash): """Boxed float value.""" _attrs_ = ['value'] @@ -388,6 +398,9 @@ def size(self): return 2 + def fieldtype(self): + return float + @signature.finishsigs class W_AbstractObjectWithClassReference(W_AbstractObjectWithIdentityHash): """Objects with arbitrary class (ie not CompiledMethod, SmallInteger or @@ -447,24 +460,30 @@ class W_PointersObject(W_AbstractObjectWithClassReference): """Common object.""" - _attrs_ = ['_shadow', '_vars'] + _attrs_ = ['_shadow', '_vars', 'fieldtypes'] _shadow = None # Default value @jit.unroll_safe def __init__(self, space, w_class, size): + from spyvm.fieldtypes import fieldtypes_of_length """Create new object with size = fixed + variable size.""" W_AbstractObjectWithClassReference.__init__(self, space, w_class) + vars = self._vars = [None] * size + self.fieldtypes = fieldtypes_of_length(self.s_class, size) + for i in range(size): # do it by hand for the JIT's sake vars[i] = w_nil self._shadow = None # Default value def fillin(self, space, g_self): + from spyvm.fieldtypes import fieldtypes_of self._vars = g_self.get_pointers() self.s_class = g_self.get_class().as_class_get_penumbra(space) self.hash = g_self.get_hash() self.space = space + self.fieldtypes = fieldtypes_of(self) def at0(self, space, index0): # To test, at0 = in varsize part @@ -480,7 +499,9 @@ return self._fetch(n0) def _fetch(self, n0): - return self._vars[n0] + # return self._vars[n0] + fieldtypes = jit.promote(self.fieldtypes) + return fieldtypes.fetch(self, n0) def store(self, space, n0, w_value): if self.has_shadow(): @@ -488,8 +509,9 @@ return self._store(n0, w_value) def _store(self, n0, w_value): - self._vars[n0] = w_value - + # self._vars[n0] = w_value + fieldtypes = jit.promote(self.fieldtypes) + return fieldtypes.store(self, n0, w_value) def varsize(self, space): return self.size() - self.instsize(space) @@ -597,7 +619,8 @@ return True def clone(self, space): - w_result = W_PointersObject(self.space, self.getclass(space), len(self._vars)) + w_result = W_PointersObject(self.space, self.getclass(space), + len(self._vars)) w_result._vars = [self.fetch(space, i) for i in range(len(self._vars))] return w_result @@ -607,6 +630,10 @@ className='W_PointersObject', additionalInformation='len=%d' % self.size()) + def fieldtype(self): + # from spyvm.fieldtype import + return object + class W_BytesObject(W_AbstractObjectWithClassReference): _attrs_ = ['bytes'] diff --git a/spyvm/shadow.py b/spyvm/shadow.py --- a/spyvm/shadow.py +++ b/spyvm/shadow.py @@ -201,7 +201,8 @@ def new(self, extrasize=0): w_cls = self.w_self() if self.instance_kind == POINTERS: - w_new = model.W_PointersObject(self.space, w_cls, self.instsize()+extrasize) + size = self.instsize() + extrasize + w_new = model.W_PointersObject(self.space, w_cls, size) elif self.instance_kind == WORDS: w_new = model.W_WordsObject(self.space, w_cls, extrasize) elif self.instance_kind == BYTES: diff --git a/spyvm/test/test_interpreter.py b/spyvm/test/test_interpreter.py --- a/spyvm/test/test_interpreter.py +++ b/spyvm/test/test_interpreter.py @@ -2,7 +2,10 @@ from spyvm import model, interpreter, primitives, shadow from spyvm import objspace, wrapper, constants -mockclass = objspace.bootstrap_class +def mockclass(space, instsize, w_superclass=None, w_metaclass=None, + name='?', format=shadow.POINTERS, varsized=True): + return objspace.bootstrap_class(space, instsize, w_superclass, w_metaclass, + name, format, varsized) space = objspace.ObjSpace() interp = interpreter.Interpreter(space) diff --git a/spyvm/test/test_shadow.py b/spyvm/test/test_shadow.py --- a/spyvm/test/test_shadow.py +++ b/spyvm/test/test_shadow.py @@ -92,9 +92,9 @@ w_object.store(space, constants.MTHDCTX_METHOD, method) # XXX w_object.store(space, constants.MTHDCTX_CLOSURE_OR_NIL, space.w_nil) - w_object.store(space, constants.MTHDCTX_RECEIVER, 'receiver') + w_object.store(space, constants.MTHDCTX_RECEIVER, space.wrap_string('receiver')) - w_object.store(space, constants.MTHDCTX_TEMP_FRAME_START, 'el') + w_object.store(space, constants.MTHDCTX_TEMP_FRAME_START, space.wrap_string('el')) return w_object def blockcontext(w_sender=space.w_nil, pc=1, stackpointer=1, stacksize=5, @@ -106,7 +106,7 @@ 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') + w_object.store(space, constants.BLKCTX_STACK_START, space.wrap_string('el')) return w_object def test_context(): @@ -121,24 +121,24 @@ assert s_object2.w_self() == w_object2 assert s_object.s_sender() == None assert s_object2.s_sender() == s_object - assert s_object.w_receiver() == 'receiver' + assert s_object.w_receiver().as_string() == 'receiver' s_object2.settemp(0, 'a') s_object2.settemp(1, 'b') assert s_object2.gettemp(1) == 'b' assert s_object2.gettemp(0) == 'a' assert s_object.w_method() == w_m idx = s_object.stackstart() - 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' + w_object.store(space, idx, space.wrap_string('f')) + w_object.store(space, idx + 1, space.wrap_string('g')) + w_object.store(space, idx + 2, space.wrap_string('h')) + assert map(lambda x: x.as_string(), s_object.stack()) == ['f', 'g', 'h' ] + assert s_object.top().as_string() == 'h' s_object.push('i') assert s_object.top() == 'i' - assert s_object.peek(1) == 'h' + assert s_object.peek(1).as_string() == 'h' assert s_object.pop() == 'i' - assert s_object.pop_and_return_n(2) == ['g', 'h'] - assert s_object.pop() == 'f' + assert map(lambda x: x.as_string(), s_object.pop_and_return_n(2)) == ['g', 'h'] + assert s_object.pop().as_string() == 'f' assert s_object.external_stackpointer() == s_object.stackstart() def test_methodcontext(): From noreply at buildbot.pypy.org Fri Apr 12 00:12:37 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Fri, 12 Apr 2013 00:12:37 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: added fieldtypes tests for testing correctnes of neighbour finding Message-ID: <20130411221237.75CA51C030D@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r258:4d577f6b6b0c Date: 2013-04-11 22:25 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/4d577f6b6b0c/ Log: added fieldtypes tests for testing correctnes of neighbour finding changed fieldtypes tags to enable translating added quicksort implementation for changes sorting diff --git a/spyvm/fieldtypes.py b/spyvm/fieldtypes.py --- a/spyvm/fieldtypes.py +++ b/spyvm/fieldtypes.py @@ -1,14 +1,16 @@ from spyvm import model, shadow -from rpython.rlib import jit, signature +from rpython.rlib import objectmodel, jit, signature -LPI = object() -int -float +class TypeTag(): + pass -object +LPI = TypeTag() +SInt = TypeTag() +flt = TypeTag() +obj = TypeTag() -maps = dict() +maps = {} class VarSizedFieldTypes(): _immutable_fields_ = [] @@ -33,23 +35,24 @@ _attrs_ = ['types', 'parent', 'siblings', 'diff'] _settled_ = True - def __init__(self, types, parent=None, change=(-1, object)): + def __init__(self, types, parent=None, change=(-1, obj)): self.types = types self.parent = parent if parent is not None: - assert change != (-1, object) + assert change != (-1, obj) self.diff = change - self.siblings = dict() + self.siblings = {} def fetch(self, w_object, n0): w_result = w_object._vars[n0] + assert w_result is not None types = self.types - if types[n0] is int: + if types[n0] is SInt: jit.record_known_class(w_result, model.W_SmallInteger) elif types[n0] is LPI: jit.record_known_class(w_result, model.W_LargePositiveInteger1Word) - elif types[n0] is float: + elif types[n0] is flt: jit.record_known_class(w_result, model.W_Float) return w_result @@ -72,14 +75,16 @@ return self.descent([change]) else: new_fieldtype = parent.ascent([change, self.diff]) - assert new_fieldtype.types == self.types[0:n0] + [changed_type] + self.types[n0+1:] + if not objectmodel.we_are_translated(): + assert new_fieldtype.types == self.types[0:n0] + [changed_type] + self.types[n0+1:] siblings[change] = new_fieldtype return new_fieldtype def ascent(self, changes): parent = self.parent if parent is None: - return self.descent(sorted(changes)) + sort(changes) + return self.descent(changes) else: change = self.diff if changes[0][0] != change[0]: @@ -105,7 +110,7 @@ @staticmethod def of_length(n): if n not in maps: - maps[n] = FieldTypes([object] * n) + maps[n] = FieldTypes([obj] * n) return maps[n] @@ -126,8 +131,37 @@ typer = FieldTypes.of_length(size) for i, w_val in enumerate(vars): changed_type = w_val.fieldtype() - if changed_type is not object: + if changed_type is not obj: typer = typer.sibling(i, changed_type) return typer except AttributeError: - return nilTyper \ No newline at end of file + return nilTyper + +def sort(an_array): + end = len(an_array) - 1 + sort_quick_inplace(an_array, 0, end) + + +def sort_quick_inplace(an_array, start, end): + assert start >= 0 and end < len(an_array) + + def partition(an_array, start, end): + key = an_array[start][0] + i = start - 1 + j = end + 1 + while True: + i += 1 + j -= 1 + while not an_array[j][0] <= key: + j -= 1 + while not an_array[i][0] >= key: + i += 1 + if j <= i: + return j + else: + an_array[i], an_array[j] = an_array[j], an_array[i] + + if start < end: + mid = partition(an_array, start, end) + sort_quick_inplace(an_array, start, mid) + sort_quick_inplace(an_array, mid + 1, end) \ No newline at end of file diff --git a/spyvm/model.py b/spyvm/model.py --- a/spyvm/model.py +++ b/spyvm/model.py @@ -131,7 +131,8 @@ raise error.UnwrappingError("Got unexpected class in unwrap_uint") def fieldtype(self): - return object + from spyvm.fieldtypes import obj + return obj class W_SmallInteger(W_Object): """Boxed integer value""" @@ -204,7 +205,8 @@ return self def fieldtype(self): - return int + from spyvm.fieldtypes import SInt + return SInt class W_AbstractObjectWithIdentityHash(W_Object): """Object with explicit hash (ie all except small @@ -310,7 +312,7 @@ return isinstance(self.value, int) def fieldtype(self): - from spyvm.fieldtype import LPI + from spyvm.fieldtypes import LPI return LPI class W_Float(W_AbstractObjectWithIdentityHash): @@ -399,7 +401,8 @@ return 2 def fieldtype(self): - return float + from spyvm.fieldtypes import flt + return flt @signature.finishsigs class W_AbstractObjectWithClassReference(W_AbstractObjectWithIdentityHash): @@ -631,8 +634,8 @@ additionalInformation='len=%d' % self.size()) def fieldtype(self): - # from spyvm.fieldtype import - return object + from spyvm.fieldtypes import obj + return obj class W_BytesObject(W_AbstractObjectWithClassReference): _attrs_ = ['bytes'] diff --git a/spyvm/test/test_fieldtypes.py b/spyvm/test/test_fieldtypes.py new file mode 100644 --- /dev/null +++ b/spyvm/test/test_fieldtypes.py @@ -0,0 +1,33 @@ +import py +from spyvm import model, fieldtypes +from spyvm import objspace + +from spyvm.fieldtypes import obj, SInt + +def test_simple_changes(): + a = fieldtypes.FieldTypes.of_length(3) + assert a.types == [obj, obj, obj] + b = a.sibling(1, SInt) + assert b.types == [obj, SInt, obj] + c = a.sibling(1, SInt) + assert b is c + +def test_two_level_changes_identity(): + a = fieldtypes.FieldTypes.of_length(3) + b = a.sibling(1, SInt) + c = a.sibling(0, SInt) + d = b.sibling(0, SInt) + assert d.types == [SInt, SInt, obj] + e = c.sibling(1, SInt) + assert d is e + +def test_numberOfElements(): + a = fieldtypes.FieldTypes.of_length(3) + a.sibling(0, SInt).sibling(1, SInt).sibling(2, SInt) + a.sibling(1, SInt).sibling(2, SInt) + a.sibling(2, SInt).sibling(0, SInt) + assert a.sibling(2, SInt).sibling(0, SInt).parent is a.sibling(0, SInt) + assert len(a.siblings) == 3 + assert len(a.sibling(0, SInt).siblings) == 2 + assert len(a.sibling(1, SInt).siblings) == 2 + assert len(a.sibling(2, SInt).siblings) == 1 # link to [o, i, i] not created \ No newline at end of file From noreply at buildbot.pypy.org Fri Apr 12 00:13:43 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Fri, 12 Apr 2013 00:13:43 +0200 (CEST) Subject: [pypy-commit] pypy default: move assert for clarity Message-ID: <20130411221343.C68031C030D@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63252:613641427033 Date: 2013-04-11 18:13 -0400 http://bitbucket.org/pypy/pypy/changeset/613641427033/ Log: move assert for clarity diff --git a/rpython/rtyper/rlist.py b/rpython/rtyper/rlist.py --- a/rpython/rtyper/rlist.py +++ b/rpython/rtyper/rlist.py @@ -950,9 +950,9 @@ count = l2.ll_length() ll_assert(start >= 0, "l[start:x] = l with unexpectedly negative start") ll_assert(start <= l1.ll_length(), "l[start:x] = l with start > len(l)") + ll_assert(stop <= l1.ll_length(), "stop cannot be past the end of l1") ll_assert(count == stop - start, "setslice cannot resize lists in RPython") - ll_assert(stop <= l1.ll_length(), "stop cannot be past the end of l1") # XXX ...but it would be easy enough to support if really needed ll_arraycopy(l2, l1, 0, start, count) ll_listsetslice.oopspec = 'list.setslice(l1, start, stop, l2)' From noreply at buildbot.pypy.org Fri Apr 12 00:21:16 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Fri, 12 Apr 2013 00:21:16 +0200 (CEST) Subject: [pypy-commit] pypy sqlite-cffi: close merged branch Message-ID: <20130411222116.2CE5B1C30B5@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: sqlite-cffi Changeset: r63253:783ea6d7ecbf Date: 2013-04-11 18:20 -0400 http://bitbucket.org/pypy/pypy/changeset/783ea6d7ecbf/ Log: close merged branch From noreply at buildbot.pypy.org Fri Apr 12 00:21:44 2013 From: noreply at buildbot.pypy.org (amauryfa) Date: Fri, 12 Apr 2013 00:21:44 +0200 (CEST) Subject: [pypy-commit] pypy py3k: Fixes applevel tests to pass with -A. Message-ID: <20130411222144.3F3511C30B5@cobra.cs.uni-duesseldorf.de> Author: Amaury Forgeot d'Arc Branch: py3k Changeset: r63254:24d0665f1432 Date: 2013-04-12 00:20 +0200 http://bitbucket.org/pypy/pypy/changeset/24d0665f1432/ Log: Fixes applevel tests to pass with -A. diff --git a/pypy/objspace/std/test/test_index.py b/pypy/objspace/std/test/test_index.py --- a/pypy/objspace/std/test/test_index.py +++ b/pypy/objspace/std/test/test_index.py @@ -1,44 +1,35 @@ from py.test import raises class AppTest_IndexProtocol: - def setup_class(self): - w_oldstyle = self.space.appexec([], """(): + def setup_class(cls): + cls.w_o = cls.space.appexec([], """(): class oldstyle: def __index__(self): return self.ind - return oldstyle""") + return oldstyle()""") - w_newstyle = self.space.appexec([], """(): + cls.w_n = cls.space.appexec([], """(): class newstyle(object): def __index__(self): return self.ind - return newstyle""") + return newstyle()""") - w_oldstyle_no_index = self.space.appexec([], """(): + cls.w_o_no_index = cls.space.appexec([], """(): class oldstyle_no_index: pass - return oldstyle_no_index""") + return oldstyle_no_index()""") - w_newstyle_no_index = self.space.appexec([], """(): + cls.w_n_no_index = cls.space.appexec([], """(): class newstyle_no_index(object): pass - return newstyle_no_index""") + return newstyle_no_index()""") - w_TrapInt = self.space.appexec([], """(): + cls.w_TrapInt = cls.space.appexec([], """(): class TrapInt(int): def __index__(self): return self return TrapInt""") - self.w_oldstyle = w_oldstyle - self.w_o = self.space.call_function(w_oldstyle) - self.w_o_no_index = self.space.call_function(w_oldstyle_no_index) - self.w_newstyle = w_newstyle - self.w_n = self.space.call_function(w_newstyle) - self.w_n_no_index = self.space.call_function(w_newstyle_no_index) - - self.w_TrapInt = w_TrapInt - def test_basic(self): self.o.ind = -2 self.n.ind = 2 @@ -92,31 +83,26 @@ # This test case isn't run directly. It just defines common tests # to the different sequence types below def setup_method(self, method): - w_oldstyle = self.space.appexec([], """(): - class oldstyle: - def __index__(self): - return self.ind - return oldstyle""") + for name in ('w_o', 'w_o2'): + setattr(self, name, self.space.appexec([], """(): + class oldstyle: + def __index__(self): + return self.ind + return oldstyle()""")) - w_newstyle = self.space.appexec([], """(): - class newstyle(object): - def __index__(self): - return self.ind - return newstyle""") + for name in ('w_n', 'w_n2'): + setattr(self, name, self.space.appexec([], """(): + class newstyle(object): + def __index__(self): + return self.ind + return newstyle()""")) - w_TrapInt = self.space.appexec([], """(): + self.w_TrapInt = self.space.appexec([], """(): class TrapInt(int): def __index__(self): return self return TrapInt""") - self.w_o = self.space.call_function(w_oldstyle) - self.w_n = self.space.call_function(w_newstyle) - self.w_o2 = self.space.call_function(w_oldstyle) - self.w_n2 = self.space.call_function(w_newstyle) - - self.w_TrapInt = w_TrapInt - def test_index(self): self.o.ind = -2 self.n.ind = 2 @@ -204,6 +190,7 @@ SeqTestCase.setup_method(self, method) self.w_seq = self.space.newtuple([self.space.wrap(x) for x in (0,10,20,30,40,50)]) + class StringTestCase(object): def test_startswith(self): self.o.ind = 1 @@ -257,9 +244,9 @@ class AppTest_OverflowTestCase: - def setup_class(self): - self.w_pos = self.space.wrap(2**100) - self.w_neg = self.space.wrap(-2**100) + def setup_class(cls): + cls.w_pos = cls.space.wrap(2**100) + cls.w_neg = cls.space.wrap(-2**100) def test_large_longs(self): assert self.pos.__index__() == self.pos diff --git a/pypy/objspace/std/test/test_newformat.py b/pypy/objspace/std/test/test_newformat.py --- a/pypy/objspace/std/test/test_newformat.py +++ b/pypy/objspace/std/test/test_newformat.py @@ -175,7 +175,8 @@ class AppTestUnicodeFormat(BaseStringFormatTests): def setup_class(cls): - cls.w_s = cls.space.w_unicode + cls.w_s = cls.space.appexec( + [], """(): return str""") def test_string_conversion(self): class x(object): @@ -284,7 +285,8 @@ class AppTestIntFormatting(BaseIntegralFormattingTest): def setup_class(cls): - cls.w_i = cls.space.w_int + cls.w_i = cls.space.appexec( + [], """(): return int""") class AppTestFloatFormatting: diff --git a/pypy/tool/pytest/apptest.py b/pypy/tool/pytest/apptest.py --- a/pypy/tool/pytest/apptest.py +++ b/pypy/tool/pytest/apptest.py @@ -114,7 +114,7 @@ elif isinstance(value, types.ModuleType): name = value.__name__ defs.append("import %s; self.%s = %s\n" % (name, symbol, name)) - elif isinstance(value, (str, unicode, int, float, list, dict)): + elif isinstance(value, (str, unicode, int, long, float, list, tuple, dict)): defs.append("self.%s = %s\n" % (symbol, py3k_repr(value))) source = py.code.Source(target_)[1:] pyfile = udir.join('src.py') From noreply at buildbot.pypy.org Fri Apr 12 03:38:15 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Fri, 12 Apr 2013 03:38:15 +0200 (CEST) Subject: [pypy-commit] pypy default: test and fix for BytesIO.write() return value Message-ID: <20130412013815.251A61C0F12@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63256:5fadf0b41675 Date: 2013-04-11 19:52 -0400 http://bitbucket.org/pypy/pypy/changeset/5fadf0b41675/ Log: test and fix for BytesIO.write() return value diff --git a/pypy/module/_io/interp_bytesio.py b/pypy/module/_io/interp_bytesio.py --- a/pypy/module/_io/interp_bytesio.py +++ b/pypy/module/_io/interp_bytesio.py @@ -96,7 +96,7 @@ buf = space.buffer_w(w_data) length = buf.getlength() if length <= 0: - return + return space.wrap(0) if self.pos + length > len(self.buf): self.buf.extend(['\0'] * (self.pos + length - len(self.buf))) diff --git a/pypy/module/_io/test/test_bytesio.py b/pypy/module/_io/test/test_bytesio.py --- a/pypy/module/_io/test/test_bytesio.py +++ b/pypy/module/_io/test/test_bytesio.py @@ -24,6 +24,7 @@ def test_write(self): import _io f = _io.BytesIO() + assert f.write("") == 0 assert f.write("hello") == 5 import gc; gc.collect() assert f.getvalue() == "hello" From noreply at buildbot.pypy.org Fri Apr 12 03:38:16 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Fri, 12 Apr 2013 03:38:16 +0200 (CEST) Subject: [pypy-commit] pypy default: test BytesIO.readinto() Message-ID: <20130412013816.547231C23C8@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63257:62db528827f5 Date: 2013-04-11 19:55 -0400 http://bitbucket.org/pypy/pypy/changeset/62db528827f5/ Log: test BytesIO.readinto() diff --git a/pypy/module/_io/test/test_bytesio.py b/pypy/module/_io/test/test_bytesio.py --- a/pypy/module/_io/test/test_bytesio.py +++ b/pypy/module/_io/test/test_bytesio.py @@ -74,7 +74,10 @@ import _io b = _io.BytesIO("hello") + a = bytearray('testing') + assert b.readinto(a) == 5 b.close() + assert a == "hellong" raises(ValueError, b.readinto, bytearray("hello")) def test_readline(self): From noreply at buildbot.pypy.org Fri Apr 12 05:45:51 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Fri, 12 Apr 2013 05:45:51 +0200 (CEST) Subject: [pypy-commit] benchmarks default: fix --niceness 0 Message-ID: <20130412034551.A91391C016E@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r204:5c09140d7755 Date: 2013-04-11 23:45 -0400 http://bitbucket.org/pypy/benchmarks/changeset/5c09140d7755/ Log: fix --niceness 0 diff --git a/runner.py b/runner.py --- a/runner.py +++ b/runner.py @@ -274,7 +274,7 @@ revision = options.upload_revision force_host = options.force_host - if options.niceness: + if options.niceness is not None: os.nice(options.niceness - os.nice(0)) results = run_and_store(benchmarks, output_filename, changed_path, From noreply at buildbot.pypy.org Fri Apr 12 05:47:06 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Fri, 12 Apr 2013 05:47:06 +0200 (CEST) Subject: [pypy-commit] buildbot default: just remove niceness until sysadmin can get limits.conf working Message-ID: <20130412034706.316F61C0149@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r779:fc24b0bbf3dd Date: 2013-04-11 23:46 -0400 http://bitbucket.org/pypy/buildbot/changeset/fc24b0bbf3dd/ Log: just remove niceness until sysadmin can get limits.conf working diff --git a/bot2/pypybuildbot/builds.py b/bot2/pypybuildbot/builds.py --- a/bot2/pypybuildbot/builds.py +++ b/bot2/pypybuildbot/builds.py @@ -567,7 +567,6 @@ locks=[lock.access('exclusive')], description="run benchmarks on top of pypy-c", command=["python", "runner.py", '--output-filename', 'result.json', - '--niceness', '0', # can't get limits.conf to allow -10 '--changed', pypy_c_rel, '--baseline', pypy_c_rel, '--args', ',--jit off', From noreply at buildbot.pypy.org Fri Apr 12 06:42:43 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Fri, 12 Apr 2013 06:42:43 +0200 (CEST) Subject: [pypy-commit] pypy default: test and fix for StringIO.readline(None) Message-ID: <20130412044243.BBCAD1C070B@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63258:63d556a4cffc Date: 2013-04-12 00:37 -0400 http://bitbucket.org/pypy/pypy/changeset/63d556a4cffc/ Log: test and fix for StringIO.readline(None) diff --git a/pypy/module/_io/interp_stringio.py b/pypy/module/_io/interp_stringio.py --- a/pypy/module/_io/interp_stringio.py +++ b/pypy/module/_io/interp_stringio.py @@ -169,9 +169,9 @@ self.pos = end return space.wrap(u''.join(self.buf[start:end])) - @unwrap_spec(limit=int) - def readline_w(self, space, limit=-1): + def readline_w(self, space, w_limit=None): self._check_closed(space) + limit = convert_size(space, w_limit) if self.pos >= len(self.buf): return space.wrap(u"") diff --git a/pypy/module/_io/test/test_stringio.py b/pypy/module/_io/test/test_stringio.py --- a/pypy/module/_io/test/test_stringio.py +++ b/pypy/module/_io/test/test_stringio.py @@ -32,7 +32,7 @@ raises(ValueError, sio.read, 1) raises(ValueError, sio.write, u"text") - def testRead(self): + def test_read(self): import io buf = u"1234567890" sio = io.StringIO(buf) @@ -42,6 +42,13 @@ assert buf[5:] == sio.read(900) assert u"" == sio.read() + def test_readline(self): + import io + sio = io.StringIO(u'123\n456') + assert sio.readline(2) == '12' + assert sio.readline(None) == '3\n' + assert sio.readline() == '456' + def test_seek(self): import io From noreply at buildbot.pypy.org Fri Apr 12 06:42:44 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Fri, 12 Apr 2013 06:42:44 +0200 (CEST) Subject: [pypy-commit] pypy default: just set pos directly here instead of calling seek Message-ID: <20130412044244.EF5321C070B@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63259:a3aa1bdf3048 Date: 2013-04-11 23:16 -0400 http://bitbucket.org/pypy/pypy/changeset/a3aa1bdf3048/ Log: just set pos directly here instead of calling seek diff --git a/rpython/rlib/rStringIO.py b/rpython/rlib/rStringIO.py --- a/rpython/rlib/rStringIO.py +++ b/rpython/rlib/rStringIO.py @@ -156,7 +156,7 @@ i += 1 if finished: break - self.seek(i) + self.pos = i return ''.join(self.bigbuffer[p:i]) def truncate(self, size): From noreply at buildbot.pypy.org Fri Apr 12 07:22:34 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Fri, 12 Apr 2013 07:22:34 +0200 (CEST) Subject: [pypy-commit] pypy default: improve BytesIO.readinto() test Message-ID: <20130412052234.EE89E1C094F@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63260:9c7ae3bdbde7 Date: 2013-04-12 01:17 -0400 http://bitbucket.org/pypy/pypy/changeset/9c7ae3bdbde7/ Log: improve BytesIO.readinto() test diff --git a/pypy/module/_io/test/test_bytesio.py b/pypy/module/_io/test/test_bytesio.py --- a/pypy/module/_io/test/test_bytesio.py +++ b/pypy/module/_io/test/test_bytesio.py @@ -74,10 +74,13 @@ import _io b = _io.BytesIO("hello") - a = bytearray('testing') - assert b.readinto(a) == 5 + a1 = bytearray('t') + a2 = bytearray('testing') + assert b.readinto(a1) == 1 + assert b.readinto(a2) == 4 b.close() - assert a == "hellong" + assert a1 == "h" + assert a2 == "elloing" raises(ValueError, b.readinto, bytearray("hello")) def test_readline(self): From noreply at buildbot.pypy.org Fri Apr 12 07:22:36 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Fri, 12 Apr 2013 07:22:36 +0200 (CEST) Subject: [pypy-commit] pypy default: change BytesIO to use RStringIO Message-ID: <20130412052236.381171C1007@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63261:4da612f571cc Date: 2013-04-12 01:08 -0400 http://bitbucket.org/pypy/pypy/changeset/4da612f571cc/ Log: change BytesIO to use RStringIO diff --git a/pypy/module/_io/interp_bytesio.py b/pypy/module/_io/interp_bytesio.py --- a/pypy/module/_io/interp_bytesio.py +++ b/pypy/module/_io/interp_bytesio.py @@ -2,37 +2,25 @@ TypeDef, generic_new_descr, GetSetProperty) from pypy.interpreter.gateway import interp2app, unwrap_spec from pypy.interpreter.error import OperationError, operationerrfmt +from rpython.rlib.rStringIO import RStringIO from rpython.rlib.rarithmetic import r_longlong from pypy.module._io.interp_bufferedio import W_BufferedIOBase from pypy.module._io.interp_iobase import convert_size import sys -def buffer2string(buffer, start, end): - from rpython.rlib.rstring import StringBuilder - builder = StringBuilder(end - start) - for i in range(start, end): - builder.append(buffer[i]) - return builder.build() -class W_BytesIO(W_BufferedIOBase): +class W_BytesIO(RStringIO, W_BufferedIOBase): def __init__(self, space): W_BufferedIOBase.__init__(self, space) - self.pos = 0 - self.string_size = 0 - self.buf = None + RStringIO.__init__(self) def descr_init(self, space, w_initial_bytes=None): - # In case __init__ is called multiple times - self.buf = [] - self.string_size = 0 - self.pos = 0 - if not space.is_none(w_initial_bytes): self.write_w(space, w_initial_bytes) - self.pos = 0 + self.seek(0) def _check_closed(self, space, message=None): - if self.buf is None: + if self.is_closed(): if message is None: message = "I/O operation on closed file" raise OperationError(space.w_ValueError, space.wrap(message)) @@ -40,36 +28,12 @@ def read_w(self, space, w_size=None): self._check_closed(space) size = convert_size(space, w_size) - - # adjust invalid sizes - available = self.string_size - self.pos - if not 0 <= size <= available: - size = available - if size < 0: - size = 0 - - output = buffer2string(self.buf, self.pos, self.pos + size) - self.pos += size - return space.wrap(output) + return space.wrap(self.read(size)) def readline_w(self, space, w_limit=None): self._check_closed(space) limit = convert_size(space, w_limit) - - cur_pos = self.pos - if limit < 0: - end_pos = self.string_size - else: - end_pos = min(cur_pos + limit, self.string_size) - while cur_pos != end_pos: - if self.buf[cur_pos] == '\n': - cur_pos += 1 - break - cur_pos += 1 - - output = buffer2string(self.buf, self.pos, cur_pos) - self.pos = cur_pos - return space.wrap(output) + return space.wrap(self.readline(limit)) def read1_w(self, space, w_size): return self.read_w(space, w_size) @@ -79,56 +43,27 @@ rwbuffer = space.rwbuffer_w(w_buffer) size = rwbuffer.getlength() - if self.pos + size > self.string_size: - size = self.string_size - self.pos - - output = buffer2string(self.buf, self.pos, self.pos + size) - length = len(output) + output = self.read(size) rwbuffer.setslice(0, output) - self.pos += length - return space.wrap(length) + return space.wrap(len(output)) def write_w(self, space, w_data): self._check_closed(space) if space.isinstance_w(w_data, space.w_unicode): raise OperationError(space.w_TypeError, space.wrap( "bytes string of buffer expected")) - buf = space.buffer_w(w_data) - length = buf.getlength() + buf = space.bufferstr_w(w_data) + length = len(buf) if length <= 0: return space.wrap(0) - - if self.pos + length > len(self.buf): - self.buf.extend(['\0'] * (self.pos + length - len(self.buf))) - - if self.pos > self.string_size: - # In case of overseek, pad with null bytes the buffer region - # between the end of stream and the current position. - # - # 0 lo string_size hi - # | |<---used--->|<----------available----------->| - # | | <--to pad-->|<---to write---> | - # 0 buf position - for i in range(self.string_size, self.pos): - self.buf[i] = '\0' - - # Copy the data to the internal buffer, overwriting some of the - # existing data if self->pos < self->string_size. - for i in range(length): - self.buf[self.pos + i] = buf.getitem(i) - self.pos += length - - # Set the new length of the internal string if it has changed - if self.string_size < self.pos: - self.string_size = self.pos - + self.write(buf) return space.wrap(length) def truncate_w(self, space, w_size=None): self._check_closed(space) if space.is_none(w_size): - size = self.pos + size = self.tell() else: size = space.r_longlong_w(w_size) @@ -136,19 +71,16 @@ raise OperationError(space.w_ValueError, space.wrap( "negative size value")) - if size < self.string_size: - self.string_size = size - del self.buf[size:] - + self.truncate(size) return space.wrap(size) def getvalue_w(self, space): self._check_closed(space) - return space.wrap(buffer2string(self.buf, 0, self.string_size)) + return space.wrap(self.getvalue()) def tell_w(self, space): self._check_closed(space) - return space.wrap(self.pos) + return space.wrap(self.tell()) @unwrap_spec(pos=r_longlong, whence=int) def seek_w(self, space, pos, whence=0): @@ -159,24 +91,19 @@ raise OperationError(space.w_ValueError, space.wrap( "negative seek value")) elif whence == 1: - if pos > sys.maxint - self.pos: + if pos > sys.maxint - self.tell(): raise OperationError(space.w_OverflowError, space.wrap( "new position too large")) - pos += self.pos elif whence == 2: - if pos > sys.maxint - self.string_size: + if pos > sys.maxint - self.getsize(): raise OperationError(space.w_OverflowError, space.wrap( "new position too large")) - pos += self.string_size else: raise operationerrfmt(space.w_ValueError, "whence must be between 0 and 2, not %d", whence) - if pos >= 0: - self.pos = pos - else: - self.pos = 0 - return space.wrap(self.pos) + self.seek(pos, whence) + return space.wrap(self.tell()) def readable_w(self, space): return space.w_True @@ -188,17 +115,16 @@ return space.w_True def close_w(self, space): - self.buf = None + self.close() def closed_get_w(self, space): - return space.wrap(self.buf is None) + return space.wrap(self.is_closed()) def getstate_w(self, space): self._check_closed(space) - w_content = space.wrap(buffer2string(self.buf, 0, self.string_size)) return space.newtuple([ - w_content, - space.wrap(self.pos), + space.wrap(self.getvalue()), + space.wrap(self.tell()), self.getdict(space)]) def setstate_w(self, space, w_state): @@ -211,13 +137,13 @@ space.type(w_state).getname(space) ) w_content, w_pos, w_dict = space.unpackiterable(w_state, 3) + self.truncate(0) + self.write_w(space, w_content) pos = space.int_w(w_pos) - self.buf = [] - self.write_w(space, w_content) if pos < 0: raise OperationError(space.w_ValueError, space.wrap( "position value cannot be negative")) - self.pos = pos + self.seek(pos) if not space.is_w(w_dict, space.w_None): space.call_method(self.getdict(space), "update", w_dict) From noreply at buildbot.pypy.org Fri Apr 12 07:22:37 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Fri, 12 Apr 2013 07:22:37 +0200 (CEST) Subject: [pypy-commit] pypy default: mangle RStringIO attr names so they don't clash with implementations Message-ID: <20130412052237.5A2BC1C094F@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63262:1a0242a40bd1 Date: 2013-04-11 21:52 -0400 http://bitbucket.org/pypy/pypy/changeset/1a0242a40bd1/ Log: mangle RStringIO attr names so they don't clash with implementations diff --git a/rpython/rlib/rStringIO.py b/rpython/rlib/rStringIO.py --- a/rpython/rlib/rStringIO.py +++ b/rpython/rlib/rStringIO.py @@ -12,166 +12,166 @@ def __init__(self): # The real content is the join of the following data: - # * the list of characters self.bigbuffer; - # * each of the strings in self.strings. + # * the list of characters self.__bigbuffer; + # * each of the strings in self.__strings. # - self.closed = False - self.strings = None - self.bigbuffer = None - self.pos = AT_END + self.__closed = False + self.__strings = None + self.__bigbuffer = None + self.__pos = AT_END def close(self): - self.closed = True - self.strings = None - self.bigbuffer = None - self.pos = AT_END + self.__closed = True + self.__strings = None + self.__bigbuffer = None + self.__pos = AT_END def is_closed(self): - return self.closed + return self.__closed - def _copy_into_bigbuffer(self): - """Copy all the data into the list of characters self.bigbuffer.""" - if self.bigbuffer is None: - self.bigbuffer = [] - if self.strings is not None: - self.bigbuffer += self.strings.build() - self.strings = None + def __copy_into_bigbuffer(self): + """Copy all the data into the list of characters self.__bigbuffer.""" + if self.__bigbuffer is None: + self.__bigbuffer = [] + if self.__strings is not None: + self.__bigbuffer += self.__strings.build() + self.__strings = None def getvalue(self): - """If self.strings contains more than 1 string, join all the + """If self.__strings contains more than 1 string, join all the strings together. Return the final single string.""" - if self.bigbuffer is not None: - self._copy_into_bigbuffer() - return ''.join(self.bigbuffer) - if self.strings is not None: - return self.strings.build() + if self.__bigbuffer is not None: + self.__copy_into_bigbuffer() + return ''.join(self.__bigbuffer) + if self.__strings is not None: + return self.__strings.build() return '' def getsize(self): result = 0 - if self.bigbuffer is not None: - result += len(self.bigbuffer) - if self.strings is not None: - result += self.strings.getlength() + if self.__bigbuffer is not None: + result += len(self.__bigbuffer) + if self.__strings is not None: + result += self.__strings.getlength() return result def write(self, buffer): # Idea: for the common case of a sequence of write() followed - # by only getvalue(), self.bigbuffer remains empty. It is only + # by only getvalue(), self.__bigbuffer remains empty. It is only # used to handle the more complicated cases. - if self.pos == AT_END: - self._fast_write(buffer) + if self.__pos == AT_END: + self.__fast_write(buffer) else: - self._slow_write(buffer) + self.__slow_write(buffer) - def _fast_write(self, buffer): - if self.strings is None: - self.strings = StringBuilder() - self.strings.append(buffer) + def __fast_write(self, buffer): + if self.__strings is None: + self.__strings = StringBuilder() + self.__strings.append(buffer) - def _slow_write(self, buffer): - p = self.pos + def __slow_write(self, buffer): + p = self.__pos assert p >= 0 endp = p + len(buffer) - if self.bigbuffer is not None and len(self.bigbuffer) >= endp: - # semi-fast path: the write is entirely inside self.bigbuffer + if self.__bigbuffer is not None and len(self.__bigbuffer) >= endp: + # semi-fast path: the write is entirely inside self.__bigbuffer for i in range(len(buffer)): - self.bigbuffer[p + i] = buffer[i] + self.__bigbuffer[p + i] = buffer[i] else: - # slow path: collect all data into self.bigbuffer and + # slow path: collect all data into self.__bigbuffer and # handle the various cases - self._copy_into_bigbuffer() - fitting = len(self.bigbuffer) - p + self.__copy_into_bigbuffer() + fitting = len(self.__bigbuffer) - p if fitting > 0: # the write starts before the end of the data fitting = min(len(buffer), fitting) for i in range(fitting): - self.bigbuffer[p + i] = buffer[i] + self.__bigbuffer[p + i] = buffer[i] if len(buffer) > fitting: # the write extends beyond the end of the data - self.bigbuffer += buffer[fitting:] + self.__bigbuffer += buffer[fitting:] endp = AT_END else: # the write starts at or beyond the end of the data - self.bigbuffer += '\x00' * (-fitting) + buffer + self.__bigbuffer += '\x00' * (-fitting) + buffer endp = AT_END - self.pos = endp + self.__pos = endp def seek(self, position, mode=0): if mode == 1: - if self.pos == AT_END: - self.pos = self.getsize() - position += self.pos + if self.__pos == AT_END: + self.__pos = self.getsize() + position += self.__pos elif mode == 2: if position == 0: - self.pos = AT_END + self.__pos = AT_END return position += self.getsize() if position < 0: position = 0 - self.pos = position + self.__pos = position def tell(self): - if self.pos == AT_END: + if self.__pos == AT_END: result = self.getsize() else: - result = self.pos + result = self.__pos assert result >= 0 return result def read(self, n=-1): - p = self.pos + p = self.__pos if p == 0 and n < 0: - self.pos = AT_END + self.__pos = AT_END return self.getvalue() # reading everything if p == AT_END or n == 0: return '' assert p >= 0 - self._copy_into_bigbuffer() - mysize = len(self.bigbuffer) + self.__copy_into_bigbuffer() + mysize = len(self.__bigbuffer) count = mysize - p if n >= 0: count = min(n, count) if count <= 0: return '' if p == 0 and count == mysize: - self.pos = AT_END - return ''.join(self.bigbuffer) + self.__pos = AT_END + return ''.join(self.__bigbuffer) else: - self.pos = p + count - return ''.join(self.bigbuffer[p:p+count]) + self.__pos = p + count + return ''.join(self.__bigbuffer[p:p+count]) def readline(self, size=-1): - p = self.pos + p = self.__pos if p == AT_END or size == 0: return '' assert p >= 0 - self._copy_into_bigbuffer() - end = len(self.bigbuffer) + self.__copy_into_bigbuffer() + end = len(self.__bigbuffer) if size >= 0 and size < end - p: end = p + size i = p while i < end: - finished = self.bigbuffer[i] == '\n' + finished = self.__bigbuffer[i] == '\n' i += 1 if finished: break - self.pos = i - return ''.join(self.bigbuffer[p:i]) + self.__pos = i + return ''.join(self.__bigbuffer[p:i]) def truncate(self, size): # NB. 'size' is mandatory. This has the same un-Posix-y semantics # than CPython: it never grows the buffer, and it sets the current # position to the end. assert size >= 0 - if self.bigbuffer is None or size > len(self.bigbuffer): - self._copy_into_bigbuffer() + if self.__bigbuffer is None or size > len(self.__bigbuffer): + self.__copy_into_bigbuffer() else: # we can drop all extra strings - if self.strings is not None: - self.strings = None - if size < len(self.bigbuffer): - del self.bigbuffer[size:] - if len(self.bigbuffer) == 0: - self.bigbuffer = None - self.pos = AT_END + if self.__strings is not None: + self.__strings = None + if size < len(self.__bigbuffer): + del self.__bigbuffer[size:] + if len(self.__bigbuffer) == 0: + self.__bigbuffer = None + self.__pos = AT_END From noreply at buildbot.pypy.org Fri Apr 12 07:22:38 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Fri, 12 Apr 2013 07:22:38 +0200 (CEST) Subject: [pypy-commit] pypy default: fix translation Message-ID: <20130412052238.7B2FE1C094F@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63263:7a2e0a6b013b Date: 2013-04-11 23:17 -0400 http://bitbucket.org/pypy/pypy/changeset/7a2e0a6b013b/ Log: fix translation diff --git a/pypy/module/_io/interp_bytesio.py b/pypy/module/_io/interp_bytesio.py --- a/pypy/module/_io/interp_bytesio.py +++ b/pypy/module/_io/interp_bytesio.py @@ -12,7 +12,7 @@ class W_BytesIO(RStringIO, W_BufferedIOBase): def __init__(self, space): W_BufferedIOBase.__init__(self, space) - RStringIO.__init__(self) + self.init() def descr_init(self, space, w_initial_bytes=None): if not space.is_none(w_initial_bytes): diff --git a/pypy/module/cStringIO/interp_stringio.py b/pypy/module/cStringIO/interp_stringio.py --- a/pypy/module/cStringIO/interp_stringio.py +++ b/pypy/module/cStringIO/interp_stringio.py @@ -146,7 +146,7 @@ class W_OutputType(RStringIO, W_InputOutputType): def __init__(self, space): - RStringIO.__init__(self) + self.init() self.space = space def descr_truncate(self, w_size=None): diff --git a/rpython/rlib/rStringIO.py b/rpython/rlib/rStringIO.py --- a/rpython/rlib/rStringIO.py +++ b/rpython/rlib/rStringIO.py @@ -11,6 +11,9 @@ _mixin_ = True # for interp_stringio.py def __init__(self): + self.init() + + def init(self): # The real content is the join of the following data: # * the list of characters self.__bigbuffer; # * each of the strings in self.__strings. From noreply at buildbot.pypy.org Fri Apr 12 07:22:39 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Fri, 12 Apr 2013 07:22:39 +0200 (CEST) Subject: [pypy-commit] pypy default: test and fix for truncate differences between cStringIO and BytesIO Message-ID: <20130412052239.9FDF01C094F@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63264:f2929b44b45b Date: 2013-04-12 00:58 -0400 http://bitbucket.org/pypy/pypy/changeset/f2929b44b45b/ Log: test and fix for truncate differences between cStringIO and BytesIO diff --git a/pypy/module/_io/test/test_bytesio.py b/pypy/module/_io/test/test_bytesio.py --- a/pypy/module/_io/test/test_bytesio.py +++ b/pypy/module/_io/test/test_bytesio.py @@ -52,6 +52,8 @@ f.seek(3) assert f.truncate() == 3 assert f.getvalue() == "hel" + assert f.truncate(2) == 2 + assert f.tell() == 3 def test_setstate(self): # state is (content, position, __dict__) diff --git a/pypy/module/cStringIO/interp_stringio.py b/pypy/module/cStringIO/interp_stringio.py --- a/pypy/module/cStringIO/interp_stringio.py +++ b/pypy/module/cStringIO/interp_stringio.py @@ -159,6 +159,7 @@ if size < 0: raise OperationError(space.w_IOError, space.wrap("negative size")) self.truncate(size) + self.seek(0, 2) @unwrap_spec(buffer='bufferstr') def descr_write(self, buffer): diff --git a/pypy/module/cStringIO/test/test_interp_stringio.py b/pypy/module/cStringIO/test/test_interp_stringio.py --- a/pypy/module/cStringIO/test/test_interp_stringio.py +++ b/pypy/module/cStringIO/test/test_interp_stringio.py @@ -142,8 +142,11 @@ f.write(' world') f.truncate(30) assert f.getvalue() == '\x00' * 20 + 'hello worl' + assert f.tell() == 30 + f.seek(0) f.truncate(25) assert f.getvalue() == '\x00' * 20 + 'hello' + assert f.tell() == 25 f.write('baz') f.write('egg') f.truncate(3) diff --git a/rpython/rlib/rStringIO.py b/rpython/rlib/rStringIO.py --- a/rpython/rlib/rStringIO.py +++ b/rpython/rlib/rStringIO.py @@ -163,9 +163,6 @@ return ''.join(self.__bigbuffer[p:i]) def truncate(self, size): - # NB. 'size' is mandatory. This has the same un-Posix-y semantics - # than CPython: it never grows the buffer, and it sets the current - # position to the end. assert size >= 0 if self.__bigbuffer is None or size > len(self.__bigbuffer): self.__copy_into_bigbuffer() @@ -177,4 +174,3 @@ del self.__bigbuffer[size:] if len(self.__bigbuffer) == 0: self.__bigbuffer = None - self.__pos = AT_END From noreply at buildbot.pypy.org Fri Apr 12 08:50:26 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Fri, 12 Apr 2013 08:50:26 +0200 (CEST) Subject: [pypy-commit] pypy default: another test and fix for BytesIO.truncate() Message-ID: <20130412065026.6310C1C026A@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63265:7c83049dafd8 Date: 2013-04-12 02:49 -0400 http://bitbucket.org/pypy/pypy/changeset/7c83049dafd8/ Log: another test and fix for BytesIO.truncate() diff --git a/pypy/module/_io/interp_bytesio.py b/pypy/module/_io/interp_bytesio.py --- a/pypy/module/_io/interp_bytesio.py +++ b/pypy/module/_io/interp_bytesio.py @@ -62,8 +62,9 @@ def truncate_w(self, space, w_size=None): self._check_closed(space) + pos = self.tell() if space.is_none(w_size): - size = self.tell() + size = pos else: size = space.r_longlong_w(w_size) @@ -72,6 +73,7 @@ "negative size value")) self.truncate(size) + self.seek(pos) return space.wrap(size) def getvalue_w(self, space): diff --git a/pypy/module/_io/test/test_bytesio.py b/pypy/module/_io/test/test_bytesio.py --- a/pypy/module/_io/test/test_bytesio.py +++ b/pypy/module/_io/test/test_bytesio.py @@ -48,7 +48,12 @@ def test_truncate(self): import _io - f = _io.BytesIO("hello") + f = _io.BytesIO() + f.write("hello") + assert f.truncate(0) == 0 + assert f.tell() == 5 + f.seek(0) + f.write("hello") f.seek(3) assert f.truncate() == 3 assert f.getvalue() == "hel" From noreply at buildbot.pypy.org Fri Apr 12 09:14:00 2013 From: noreply at buildbot.pypy.org (bivab) Date: Fri, 12 Apr 2013 09:14:00 +0200 (CEST) Subject: [pypy-commit] pypy default: refactor llsuport/test/z* to avoid them being picked up there and only when imported in the backends Message-ID: <20130412071400.C13C81C07C6@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63266:79586f2fc0d6 Date: 2013-04-12 09:12 +0200 http://bitbucket.org/pypy/pypy/changeset/79586f2fc0d6/ Log: refactor llsuport/test/z* to avoid them being picked up there and only when imported in the backends diff --git a/rpython/jit/backend/arm/test/test_zrpy_gc.py b/rpython/jit/backend/arm/test/test_zrpy_gc.py --- a/rpython/jit/backend/arm/test/test_zrpy_gc.py +++ b/rpython/jit/backend/arm/test/test_zrpy_gc.py @@ -1,4 +1,8 @@ from rpython.jit.backend.arm.test.support import skip_unless_run_slow_tests skip_unless_run_slow_tests() -from rpython.jit.backend.llsupport.test.zrpy_gc_test import TestShadowStack +from rpython.jit.backend.llsupport.test.zrpy_gc_test import CompileFrameworkTests + + +class TestShadowStack(CompileFrameworkTests): + gcrootfinder = "shadowstack" diff --git a/rpython/jit/backend/arm/test/test_zrpy_gc_boehm.py b/rpython/jit/backend/arm/test/test_zrpy_gc_boehm.py --- a/rpython/jit/backend/arm/test/test_zrpy_gc_boehm.py +++ b/rpython/jit/backend/arm/test/test_zrpy_gc_boehm.py @@ -1,3 +1,3 @@ from rpython.jit.backend.arm.test.support import skip_unless_run_slow_tests skip_unless_run_slow_tests() -from rpython.jit.backend.llsupport.test.zrpy_gc_boehm_test import test_compile_boehm +from rpython.jit.backend.llsupport.test.zrpy_gc_boehm_test import compile_boehm_test as test_compile_boehm diff --git a/rpython/jit/backend/arm/test/test_zrpy_releasegil.py b/rpython/jit/backend/arm/test/test_zrpy_releasegil.py --- a/rpython/jit/backend/arm/test/test_zrpy_releasegil.py +++ b/rpython/jit/backend/arm/test/test_zrpy_releasegil.py @@ -1,4 +1,10 @@ from rpython.jit.backend.arm.test.support import skip_unless_run_slow_tests skip_unless_run_slow_tests() -from rpython.jit.backend.llsupport.test.zrpy_releasegil_test import TestShadowStack +from rpython.jit.backend.llsupport.test.zrpy_releasegil_test import ReleaseGILTests + + +class TestShadowStack(ReleaseGILTests): + gcrootfinder = "shadowstack" + + diff --git a/rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py b/rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py --- a/rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py +++ b/rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py @@ -32,7 +32,7 @@ g._dont_inline_ = True return g -def test_compile_boehm(monkeypatch): +def compile_boehm_test(monkeypatch): fix_annotator_for_vrawbuffer(monkeypatch) myjitdriver = JitDriver(greens = [], reds = ['n', 'x']) @dont_look_inside diff --git a/rpython/jit/backend/llsupport/test/zrpy_gc_test.py b/rpython/jit/backend/llsupport/test/zrpy_gc_test.py --- a/rpython/jit/backend/llsupport/test/zrpy_gc_test.py +++ b/rpython/jit/backend/llsupport/test/zrpy_gc_test.py @@ -770,6 +770,3 @@ def test_compile_framework_call_assembler(self): self.run('compile_framework_call_assembler') - -class TestShadowStack(CompileFrameworkTests): - gcrootfinder = "shadowstack" diff --git a/rpython/jit/backend/llsupport/test/zrpy_releasegil_test.py b/rpython/jit/backend/llsupport/test/zrpy_releasegil_test.py --- a/rpython/jit/backend/llsupport/test/zrpy_releasegil_test.py +++ b/rpython/jit/backend/llsupport/test/zrpy_releasegil_test.py @@ -95,10 +95,3 @@ def test_close_stack(self): self.run('close_stack') assert 'call_release_gil' in udir.join('TestCompileFramework.log').read() - - -class TestShadowStack(ReleaseGILTests): - gcrootfinder = "shadowstack" - -class TestAsmGcc(ReleaseGILTests): - gcrootfinder = "asmgcc" diff --git a/rpython/jit/backend/x86/test/test_zrpy_gc.py b/rpython/jit/backend/x86/test/test_zrpy_gc.py --- a/rpython/jit/backend/x86/test/test_zrpy_gc.py +++ b/rpython/jit/backend/x86/test/test_zrpy_gc.py @@ -1,1 +1,5 @@ -from rpython.jit.backend.llsupport.test.zrpy_gc_test import TestShadowStack +from rpython.jit.backend.llsupport.test.zrpy_gc_test import CompileFrameworkTests + + +class TestShadowStack(CompileFrameworkTests): + gcrootfinder = "shadowstack" diff --git a/rpython/jit/backend/x86/test/test_zrpy_gc_boehm.py b/rpython/jit/backend/x86/test/test_zrpy_gc_boehm.py --- a/rpython/jit/backend/x86/test/test_zrpy_gc_boehm.py +++ b/rpython/jit/backend/x86/test/test_zrpy_gc_boehm.py @@ -1,1 +1,1 @@ -from rpython.jit.backend.llsupport.test.zrpy_gc_boehm_test import test_compile_boehm +from rpython.jit.backend.llsupport.test.zrpy_gc_boehm_test import compile_boehm_test as test_compile_boehm diff --git a/rpython/jit/backend/x86/test/test_zrpy_releasegil.py b/rpython/jit/backend/x86/test/test_zrpy_releasegil.py --- a/rpython/jit/backend/x86/test/test_zrpy_releasegil.py +++ b/rpython/jit/backend/x86/test/test_zrpy_releasegil.py @@ -1,1 +1,9 @@ -from rpython.jit.backend.llsupport.test.zrpy_releasegil_test import TestShadowStack, TestAsmGcc +from rpython.jit.backend.llsupport.test.zrpy_releasegil_test import ReleaseGILTests + + +class TestShadowStack(ReleaseGILTests): + gcrootfinder = "shadowstack" + + +class TestAsmGcc(ReleaseGILTests): + gcrootfinder = "asmgcc" From noreply at buildbot.pypy.org Fri Apr 12 09:14:02 2013 From: noreply at buildbot.pypy.org (bivab) Date: Fri, 12 Apr 2013 09:14:02 +0200 (CEST) Subject: [pypy-commit] pypy default: merge heads Message-ID: <20130412071402.0E8A51C07C6@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63267:6ed5e557b6b1 Date: 2013-04-12 09:13 +0200 http://bitbucket.org/pypy/pypy/changeset/6ed5e557b6b1/ Log: merge heads diff --git a/pypy/module/_io/interp_bytesio.py b/pypy/module/_io/interp_bytesio.py --- a/pypy/module/_io/interp_bytesio.py +++ b/pypy/module/_io/interp_bytesio.py @@ -2,37 +2,25 @@ TypeDef, generic_new_descr, GetSetProperty) from pypy.interpreter.gateway import interp2app, unwrap_spec from pypy.interpreter.error import OperationError, operationerrfmt +from rpython.rlib.rStringIO import RStringIO from rpython.rlib.rarithmetic import r_longlong from pypy.module._io.interp_bufferedio import W_BufferedIOBase from pypy.module._io.interp_iobase import convert_size import sys -def buffer2string(buffer, start, end): - from rpython.rlib.rstring import StringBuilder - builder = StringBuilder(end - start) - for i in range(start, end): - builder.append(buffer[i]) - return builder.build() -class W_BytesIO(W_BufferedIOBase): +class W_BytesIO(RStringIO, W_BufferedIOBase): def __init__(self, space): W_BufferedIOBase.__init__(self, space) - self.pos = 0 - self.string_size = 0 - self.buf = None + self.init() def descr_init(self, space, w_initial_bytes=None): - # In case __init__ is called multiple times - self.buf = [] - self.string_size = 0 - self.pos = 0 - if not space.is_none(w_initial_bytes): self.write_w(space, w_initial_bytes) - self.pos = 0 + self.seek(0) def _check_closed(self, space, message=None): - if self.buf is None: + if self.is_closed(): if message is None: message = "I/O operation on closed file" raise OperationError(space.w_ValueError, space.wrap(message)) @@ -40,36 +28,12 @@ def read_w(self, space, w_size=None): self._check_closed(space) size = convert_size(space, w_size) - - # adjust invalid sizes - available = self.string_size - self.pos - if not 0 <= size <= available: - size = available - if size < 0: - size = 0 - - output = buffer2string(self.buf, self.pos, self.pos + size) - self.pos += size - return space.wrap(output) + return space.wrap(self.read(size)) def readline_w(self, space, w_limit=None): self._check_closed(space) limit = convert_size(space, w_limit) - - cur_pos = self.pos - if limit < 0: - end_pos = self.string_size - else: - end_pos = min(cur_pos + limit, self.string_size) - while cur_pos != end_pos: - if self.buf[cur_pos] == '\n': - cur_pos += 1 - break - cur_pos += 1 - - output = buffer2string(self.buf, self.pos, cur_pos) - self.pos = cur_pos - return space.wrap(output) + return space.wrap(self.readline(limit)) def read1_w(self, space, w_size): return self.read_w(space, w_size) @@ -79,56 +43,28 @@ rwbuffer = space.rwbuffer_w(w_buffer) size = rwbuffer.getlength() - if self.pos + size > self.string_size: - size = self.string_size - self.pos - - output = buffer2string(self.buf, self.pos, self.pos + size) - length = len(output) + output = self.read(size) rwbuffer.setslice(0, output) - self.pos += length - return space.wrap(length) + return space.wrap(len(output)) def write_w(self, space, w_data): self._check_closed(space) if space.isinstance_w(w_data, space.w_unicode): raise OperationError(space.w_TypeError, space.wrap( "bytes string of buffer expected")) - buf = space.buffer_w(w_data) - length = buf.getlength() + buf = space.bufferstr_w(w_data) + length = len(buf) if length <= 0: - return - - if self.pos + length > len(self.buf): - self.buf.extend(['\0'] * (self.pos + length - len(self.buf))) - - if self.pos > self.string_size: - # In case of overseek, pad with null bytes the buffer region - # between the end of stream and the current position. - # - # 0 lo string_size hi - # | |<---used--->|<----------available----------->| - # | | <--to pad-->|<---to write---> | - # 0 buf position - for i in range(self.string_size, self.pos): - self.buf[i] = '\0' - - # Copy the data to the internal buffer, overwriting some of the - # existing data if self->pos < self->string_size. - for i in range(length): - self.buf[self.pos + i] = buf.getitem(i) - self.pos += length - - # Set the new length of the internal string if it has changed - if self.string_size < self.pos: - self.string_size = self.pos - + return space.wrap(0) + self.write(buf) return space.wrap(length) def truncate_w(self, space, w_size=None): self._check_closed(space) + pos = self.tell() if space.is_none(w_size): - size = self.pos + size = pos else: size = space.r_longlong_w(w_size) @@ -136,19 +72,17 @@ raise OperationError(space.w_ValueError, space.wrap( "negative size value")) - if size < self.string_size: - self.string_size = size - del self.buf[size:] - + self.truncate(size) + self.seek(pos) return space.wrap(size) def getvalue_w(self, space): self._check_closed(space) - return space.wrap(buffer2string(self.buf, 0, self.string_size)) + return space.wrap(self.getvalue()) def tell_w(self, space): self._check_closed(space) - return space.wrap(self.pos) + return space.wrap(self.tell()) @unwrap_spec(pos=r_longlong, whence=int) def seek_w(self, space, pos, whence=0): @@ -159,24 +93,19 @@ raise OperationError(space.w_ValueError, space.wrap( "negative seek value")) elif whence == 1: - if pos > sys.maxint - self.pos: + if pos > sys.maxint - self.tell(): raise OperationError(space.w_OverflowError, space.wrap( "new position too large")) - pos += self.pos elif whence == 2: - if pos > sys.maxint - self.string_size: + if pos > sys.maxint - self.getsize(): raise OperationError(space.w_OverflowError, space.wrap( "new position too large")) - pos += self.string_size else: raise operationerrfmt(space.w_ValueError, "whence must be between 0 and 2, not %d", whence) - if pos >= 0: - self.pos = pos - else: - self.pos = 0 - return space.wrap(self.pos) + self.seek(pos, whence) + return space.wrap(self.tell()) def readable_w(self, space): return space.w_True @@ -188,17 +117,16 @@ return space.w_True def close_w(self, space): - self.buf = None + self.close() def closed_get_w(self, space): - return space.wrap(self.buf is None) + return space.wrap(self.is_closed()) def getstate_w(self, space): self._check_closed(space) - w_content = space.wrap(buffer2string(self.buf, 0, self.string_size)) return space.newtuple([ - w_content, - space.wrap(self.pos), + space.wrap(self.getvalue()), + space.wrap(self.tell()), self.getdict(space)]) def setstate_w(self, space, w_state): @@ -211,13 +139,13 @@ space.type(w_state).getname(space) ) w_content, w_pos, w_dict = space.unpackiterable(w_state, 3) + self.truncate(0) + self.write_w(space, w_content) pos = space.int_w(w_pos) - self.buf = [] - self.write_w(space, w_content) if pos < 0: raise OperationError(space.w_ValueError, space.wrap( "position value cannot be negative")) - self.pos = pos + self.seek(pos) if not space.is_w(w_dict, space.w_None): space.call_method(self.getdict(space), "update", w_dict) diff --git a/pypy/module/_io/interp_stringio.py b/pypy/module/_io/interp_stringio.py --- a/pypy/module/_io/interp_stringio.py +++ b/pypy/module/_io/interp_stringio.py @@ -169,9 +169,9 @@ self.pos = end return space.wrap(u''.join(self.buf[start:end])) - @unwrap_spec(limit=int) - def readline_w(self, space, limit=-1): + def readline_w(self, space, w_limit=None): self._check_closed(space) + limit = convert_size(space, w_limit) if self.pos >= len(self.buf): return space.wrap(u"") diff --git a/pypy/module/_io/test/test_bytesio.py b/pypy/module/_io/test/test_bytesio.py --- a/pypy/module/_io/test/test_bytesio.py +++ b/pypy/module/_io/test/test_bytesio.py @@ -24,6 +24,7 @@ def test_write(self): import _io f = _io.BytesIO() + assert f.write("") == 0 assert f.write("hello") == 5 import gc; gc.collect() assert f.getvalue() == "hello" @@ -47,10 +48,17 @@ def test_truncate(self): import _io - f = _io.BytesIO("hello") + f = _io.BytesIO() + f.write("hello") + assert f.truncate(0) == 0 + assert f.tell() == 5 + f.seek(0) + f.write("hello") f.seek(3) assert f.truncate() == 3 assert f.getvalue() == "hel" + assert f.truncate(2) == 2 + assert f.tell() == 3 def test_setstate(self): # state is (content, position, __dict__) @@ -73,7 +81,13 @@ import _io b = _io.BytesIO("hello") + a1 = bytearray('t') + a2 = bytearray('testing') + assert b.readinto(a1) == 1 + assert b.readinto(a2) == 4 b.close() + assert a1 == "h" + assert a2 == "elloing" raises(ValueError, b.readinto, bytearray("hello")) def test_readline(self): diff --git a/pypy/module/_io/test/test_stringio.py b/pypy/module/_io/test/test_stringio.py --- a/pypy/module/_io/test/test_stringio.py +++ b/pypy/module/_io/test/test_stringio.py @@ -32,7 +32,7 @@ raises(ValueError, sio.read, 1) raises(ValueError, sio.write, u"text") - def testRead(self): + def test_read(self): import io buf = u"1234567890" sio = io.StringIO(buf) @@ -42,6 +42,13 @@ assert buf[5:] == sio.read(900) assert u"" == sio.read() + def test_readline(self): + import io + sio = io.StringIO(u'123\n456') + assert sio.readline(2) == '12' + assert sio.readline(None) == '3\n' + assert sio.readline() == '456' + def test_seek(self): import io diff --git a/pypy/module/cStringIO/interp_stringio.py b/pypy/module/cStringIO/interp_stringio.py --- a/pypy/module/cStringIO/interp_stringio.py +++ b/pypy/module/cStringIO/interp_stringio.py @@ -146,7 +146,7 @@ class W_OutputType(RStringIO, W_InputOutputType): def __init__(self, space): - RStringIO.__init__(self) + self.init() self.space = space def descr_truncate(self, w_size=None): @@ -159,6 +159,7 @@ if size < 0: raise OperationError(space.w_IOError, space.wrap("negative size")) self.truncate(size) + self.seek(0, 2) @unwrap_spec(buffer='bufferstr') def descr_write(self, buffer): diff --git a/pypy/module/cStringIO/test/test_interp_stringio.py b/pypy/module/cStringIO/test/test_interp_stringio.py --- a/pypy/module/cStringIO/test/test_interp_stringio.py +++ b/pypy/module/cStringIO/test/test_interp_stringio.py @@ -142,8 +142,11 @@ f.write(' world') f.truncate(30) assert f.getvalue() == '\x00' * 20 + 'hello worl' + assert f.tell() == 30 + f.seek(0) f.truncate(25) assert f.getvalue() == '\x00' * 20 + 'hello' + assert f.tell() == 25 f.write('baz') f.write('egg') f.truncate(3) diff --git a/rpython/rlib/rStringIO.py b/rpython/rlib/rStringIO.py --- a/rpython/rlib/rStringIO.py +++ b/rpython/rlib/rStringIO.py @@ -11,167 +11,166 @@ _mixin_ = True # for interp_stringio.py def __init__(self): + self.init() + + def init(self): # The real content is the join of the following data: - # * the list of characters self.bigbuffer; - # * each of the strings in self.strings. + # * the list of characters self.__bigbuffer; + # * each of the strings in self.__strings. # - self.closed = False - self.strings = None - self.bigbuffer = None - self.pos = AT_END + self.__closed = False + self.__strings = None + self.__bigbuffer = None + self.__pos = AT_END def close(self): - self.closed = True - self.strings = None - self.bigbuffer = None - self.pos = AT_END + self.__closed = True + self.__strings = None + self.__bigbuffer = None + self.__pos = AT_END def is_closed(self): - return self.closed + return self.__closed - def _copy_into_bigbuffer(self): - """Copy all the data into the list of characters self.bigbuffer.""" - if self.bigbuffer is None: - self.bigbuffer = [] - if self.strings is not None: - self.bigbuffer += self.strings.build() - self.strings = None + def __copy_into_bigbuffer(self): + """Copy all the data into the list of characters self.__bigbuffer.""" + if self.__bigbuffer is None: + self.__bigbuffer = [] + if self.__strings is not None: + self.__bigbuffer += self.__strings.build() + self.__strings = None def getvalue(self): - """If self.strings contains more than 1 string, join all the + """If self.__strings contains more than 1 string, join all the strings together. Return the final single string.""" - if self.bigbuffer is not None: - self._copy_into_bigbuffer() - return ''.join(self.bigbuffer) - if self.strings is not None: - return self.strings.build() + if self.__bigbuffer is not None: + self.__copy_into_bigbuffer() + return ''.join(self.__bigbuffer) + if self.__strings is not None: + return self.__strings.build() return '' def getsize(self): result = 0 - if self.bigbuffer is not None: - result += len(self.bigbuffer) - if self.strings is not None: - result += self.strings.getlength() + if self.__bigbuffer is not None: + result += len(self.__bigbuffer) + if self.__strings is not None: + result += self.__strings.getlength() return result def write(self, buffer): # Idea: for the common case of a sequence of write() followed - # by only getvalue(), self.bigbuffer remains empty. It is only + # by only getvalue(), self.__bigbuffer remains empty. It is only # used to handle the more complicated cases. - if self.pos == AT_END: - self._fast_write(buffer) + if self.__pos == AT_END: + self.__fast_write(buffer) else: - self._slow_write(buffer) + self.__slow_write(buffer) - def _fast_write(self, buffer): - if self.strings is None: - self.strings = StringBuilder() - self.strings.append(buffer) + def __fast_write(self, buffer): + if self.__strings is None: + self.__strings = StringBuilder() + self.__strings.append(buffer) - def _slow_write(self, buffer): - p = self.pos + def __slow_write(self, buffer): + p = self.__pos assert p >= 0 endp = p + len(buffer) - if self.bigbuffer is not None and len(self.bigbuffer) >= endp: - # semi-fast path: the write is entirely inside self.bigbuffer + if self.__bigbuffer is not None and len(self.__bigbuffer) >= endp: + # semi-fast path: the write is entirely inside self.__bigbuffer for i in range(len(buffer)): - self.bigbuffer[p + i] = buffer[i] + self.__bigbuffer[p + i] = buffer[i] else: - # slow path: collect all data into self.bigbuffer and + # slow path: collect all data into self.__bigbuffer and # handle the various cases - self._copy_into_bigbuffer() - fitting = len(self.bigbuffer) - p + self.__copy_into_bigbuffer() + fitting = len(self.__bigbuffer) - p if fitting > 0: # the write starts before the end of the data fitting = min(len(buffer), fitting) for i in range(fitting): - self.bigbuffer[p + i] = buffer[i] + self.__bigbuffer[p + i] = buffer[i] if len(buffer) > fitting: # the write extends beyond the end of the data - self.bigbuffer += buffer[fitting:] + self.__bigbuffer += buffer[fitting:] endp = AT_END else: # the write starts at or beyond the end of the data - self.bigbuffer += '\x00' * (-fitting) + buffer + self.__bigbuffer += '\x00' * (-fitting) + buffer endp = AT_END - self.pos = endp + self.__pos = endp def seek(self, position, mode=0): if mode == 1: - if self.pos == AT_END: - self.pos = self.getsize() - position += self.pos + if self.__pos == AT_END: + self.__pos = self.getsize() + position += self.__pos elif mode == 2: if position == 0: - self.pos = AT_END + self.__pos = AT_END return position += self.getsize() if position < 0: position = 0 - self.pos = position + self.__pos = position def tell(self): - if self.pos == AT_END: + if self.__pos == AT_END: result = self.getsize() else: - result = self.pos + result = self.__pos assert result >= 0 return result def read(self, n=-1): - p = self.pos + p = self.__pos if p == 0 and n < 0: - self.pos = AT_END + self.__pos = AT_END return self.getvalue() # reading everything if p == AT_END or n == 0: return '' assert p >= 0 - self._copy_into_bigbuffer() - mysize = len(self.bigbuffer) + self.__copy_into_bigbuffer() + mysize = len(self.__bigbuffer) count = mysize - p if n >= 0: count = min(n, count) if count <= 0: return '' if p == 0 and count == mysize: - self.pos = AT_END - return ''.join(self.bigbuffer) + self.__pos = AT_END + return ''.join(self.__bigbuffer) else: - self.pos = p + count - return ''.join(self.bigbuffer[p:p+count]) + self.__pos = p + count + return ''.join(self.__bigbuffer[p:p+count]) def readline(self, size=-1): - p = self.pos + p = self.__pos if p == AT_END or size == 0: return '' assert p >= 0 - self._copy_into_bigbuffer() - end = len(self.bigbuffer) + self.__copy_into_bigbuffer() + end = len(self.__bigbuffer) if size >= 0 and size < end - p: end = p + size i = p while i < end: - finished = self.bigbuffer[i] == '\n' + finished = self.__bigbuffer[i] == '\n' i += 1 if finished: break - self.seek(i) - return ''.join(self.bigbuffer[p:i]) + self.__pos = i + return ''.join(self.__bigbuffer[p:i]) def truncate(self, size): - # NB. 'size' is mandatory. This has the same un-Posix-y semantics - # than CPython: it never grows the buffer, and it sets the current - # position to the end. assert size >= 0 - if self.bigbuffer is None or size > len(self.bigbuffer): - self._copy_into_bigbuffer() + if self.__bigbuffer is None or size > len(self.__bigbuffer): + self.__copy_into_bigbuffer() else: # we can drop all extra strings - if self.strings is not None: - self.strings = None - if size < len(self.bigbuffer): - del self.bigbuffer[size:] - if len(self.bigbuffer) == 0: - self.bigbuffer = None - self.pos = AT_END + if self.__strings is not None: + self.__strings = None + if size < len(self.__bigbuffer): + del self.__bigbuffer[size:] + if len(self.__bigbuffer) == 0: + self.__bigbuffer = None diff --git a/rpython/rtyper/rlist.py b/rpython/rtyper/rlist.py --- a/rpython/rtyper/rlist.py +++ b/rpython/rtyper/rlist.py @@ -950,6 +950,7 @@ count = l2.ll_length() ll_assert(start >= 0, "l[start:x] = l with unexpectedly negative start") ll_assert(start <= l1.ll_length(), "l[start:x] = l with start > len(l)") + ll_assert(stop <= l1.ll_length(), "stop cannot be past the end of l1") ll_assert(count == stop - start, "setslice cannot resize lists in RPython") # XXX ...but it would be easy enough to support if really needed From noreply at buildbot.pypy.org Fri Apr 12 09:48:10 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Fri, 12 Apr 2013 09:48:10 +0200 (CEST) Subject: [pypy-commit] pypy default: have BytesIO.truncate() reset to fast path (AT_END) when possible Message-ID: <20130412074810.05ADB1C088E@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63268:7722fa2d82da Date: 2013-04-12 03:44 -0400 http://bitbucket.org/pypy/pypy/changeset/7722fa2d82da/ Log: have BytesIO.truncate() reset to fast path (AT_END) when possible diff --git a/pypy/module/_io/interp_bytesio.py b/pypy/module/_io/interp_bytesio.py --- a/pypy/module/_io/interp_bytesio.py +++ b/pypy/module/_io/interp_bytesio.py @@ -73,7 +73,10 @@ "negative size value")) self.truncate(size) - self.seek(pos) + if size == pos: + self.seek(0, 2) + else: + self.seek(pos) return space.wrap(size) def getvalue_w(self, space): From noreply at buildbot.pypy.org Fri Apr 12 10:02:21 2013 From: noreply at buildbot.pypy.org (mattip) Date: Fri, 12 Apr 2013 10:02:21 +0200 (CEST) Subject: [pypy-commit] pypy default: skip crashing test on windows Message-ID: <20130412080222.005BD1C1361@cobra.cs.uni-duesseldorf.de> Author: mattip Branch: Changeset: r63269:e8279f674c46 Date: 2013-04-11 23:47 +0300 http://bitbucket.org/pypy/pypy/changeset/e8279f674c46/ Log: skip crashing test on windows diff --git a/rpython/rtyper/lltypesystem/test/test_ll2ctypes.py b/rpython/rtyper/lltypesystem/test/test_ll2ctypes.py --- a/rpython/rtyper/lltypesystem/test/test_ll2ctypes.py +++ b/rpython/rtyper/lltypesystem/test/test_ll2ctypes.py @@ -742,13 +742,17 @@ assert not ALLOCATED # detects memory leaks in the test def test_get_errno(self): - # win64: works with python 2.6.7, but not with 2.7.2 - # XXX check what is different with ctypes! eci = ExternalCompilationInfo(includes=['string.h']) if sys.platform.startswith('win'): underscore_on_windows = '_' - if sys.version.startswith('2.7.2 '): - py.test.skip('ctypes is buggy. errno crashes with win64 and python 2.7.2') + # the default when writing to a invalid fd on windows is to call + # an _invalid_parameter_handler, which by default crashes the + # process. To fix this test, call _set_invalid_parameter_handler + # in the setup_method, and remove it in the teardown. + # Note that cpython before 2.7 did install an _invalid_parameter_handler, + # which is why the test passes there, but this is no longer + # accepted practice. + py.test.skip('need to set an _invalid_parameter_handler') else: underscore_on_windows = '' strlen = rffi.llexternal('strlen', [rffi.CCHARP], rffi.SIZE_T, From noreply at buildbot.pypy.org Fri Apr 12 10:02:23 2013 From: noreply at buildbot.pypy.org (mattip) Date: Fri, 12 Apr 2013 10:02:23 +0200 (CEST) Subject: [pypy-commit] pypy default: fix segfault on windows by SetErrorMode in rtyper tests Message-ID: <20130412080223.6FBE41C1361@cobra.cs.uni-duesseldorf.de> Author: mattip Branch: Changeset: r63270:18e164c14177 Date: 2013-04-12 10:45 +0300 http://bitbucket.org/pypy/pypy/changeset/18e164c14177/ Log: fix segfault on windows by SetErrorMode in rtyper tests diff --git a/rpython/rtyper/lltypesystem/test/test_ll2ctypes.py b/rpython/rtyper/lltypesystem/test/test_ll2ctypes.py --- a/rpython/rtyper/lltypesystem/test/test_ll2ctypes.py +++ b/rpython/rtyper/lltypesystem/test/test_ll2ctypes.py @@ -745,14 +745,16 @@ eci = ExternalCompilationInfo(includes=['string.h']) if sys.platform.startswith('win'): underscore_on_windows = '_' - # the default when writing to a invalid fd on windows is to call - # an _invalid_parameter_handler, which by default crashes the - # process. To fix this test, call _set_invalid_parameter_handler - # in the setup_method, and remove it in the teardown. - # Note that cpython before 2.7 did install an _invalid_parameter_handler, + # Note that cpython before 2.7 installs an _invalid_parameter_handler, # which is why the test passes there, but this is no longer # accepted practice. - py.test.skip('need to set an _invalid_parameter_handler') + import ctypes + SEM_NOGPFAULTERRORBOX = 0x0002 # From MSDN + old_err_mode = ctypes.windll.kernel32.GetErrorMode() + new_err_mode = old_err_mode | SEM_NOGPFAULTERRORBOX + ctypes.windll.kernel32.SetErrorMode(new_err_mode) + assert f(1) == 1 + ctypes.windll.kernel32.SetErrorMode(old_err_mode) else: underscore_on_windows = '' strlen = rffi.llexternal('strlen', [rffi.CCHARP], rffi.SIZE_T, @@ -762,6 +764,8 @@ rffi.SIZE_T) buffer = lltype.malloc(rffi.CCHARP.TO, 5, flavor='raw') written = os_write(12312312, buffer, 5) + if sys.platform.startswith('win'): + ctypes.windll.kernel32.SetErrorMode(old_err_mode) lltype.free(buffer, flavor='raw') assert rffi.cast(rffi.LONG, written) < 0 # the next line is a random external function call, diff --git a/rpython/rtyper/lltypesystem/test/test_llarena.py b/rpython/rtyper/lltypesystem/test/test_llarena.py --- a/rpython/rtyper/lltypesystem/test/test_llarena.py +++ b/rpython/rtyper/lltypesystem/test/test_llarena.py @@ -302,6 +302,7 @@ class TestStandalone(test_standalone.StandaloneTests): def test_compiled_arena_protect(self): + import sys S = lltype.Struct('S', ('x', lltype.Signed)) # def fn(argv): @@ -325,6 +326,15 @@ t, cbuilder = self.compile(fn) data = cbuilder.cmdexec('0') assert data == '133\n' + if sys.platform.startswith('win'): + # Do not open error dialog box + import ctypes + SEM_NOGPFAULTERRORBOX = 0x0002 # From MSDN + old_err_mode = ctypes.windll.kernel32.GetErrorMode() + new_err_mode = old_err_mode | SEM_NOGPFAULTERRORBOX + ctypes.windll.kernel32.SetErrorMode(new_err_mode) if has_protect: cbuilder.cmdexec('1', expect_crash=True) cbuilder.cmdexec('2', expect_crash=True) + if sys.platform.startswith('win'): + ctypes.windll.kernel32.SetErrorMode(old_err_mode) diff --git a/rpython/rtyper/module/test/test_ll_os_environ.py b/rpython/rtyper/module/test/test_ll_os_environ.py --- a/rpython/rtyper/module/test/test_ll_os_environ.py +++ b/rpython/rtyper/module/test/test_ll_os_environ.py @@ -12,6 +12,7 @@ assert f(1) > 0 def test_unset_error(): + import sys def foo(x): if x: os.environ['TEST'] = 'STRING' @@ -26,4 +27,14 @@ return 0 f = compile(foo, [int], backendopt=False) - assert f(1) == 1 + if sys.platform.startswith('win'): + # Do not open error dialog box + import ctypes + SEM_NOGPFAULTERRORBOX = 0x0002 # From MSDN + old_err_mode = ctypes.windll.kernel32.GetErrorMode() + new_err_mode = old_err_mode | SEM_NOGPFAULTERRORBOX + ctypes.windll.kernel32.SetErrorMode(new_err_mode) + assert f(1) == 1 + ctypes.windll.kernel32.SetErrorMode(old_err_mode) + else: + assert f(1) == 1 From noreply at buildbot.pypy.org Fri Apr 12 10:02:25 2013 From: noreply at buildbot.pypy.org (mattip) Date: Fri, 12 Apr 2013 10:02:25 +0200 (CEST) Subject: [pypy-commit] pypy default: merge heads Message-ID: <20130412080225.E5FBB1C1361@cobra.cs.uni-duesseldorf.de> Author: mattip Branch: Changeset: r63271:30b9b28ad51d Date: 2013-04-12 10:53 +0300 http://bitbucket.org/pypy/pypy/changeset/30b9b28ad51d/ Log: merge heads diff too long, truncating to 2000 out of 8786 lines diff --git a/README.rst b/README.rst --- a/README.rst +++ b/README.rst @@ -13,9 +13,9 @@ http://pypy.org/ -The getting-started document will help guide you: +If you want to help developing PyPy, this document might help you: - http://doc.pypy.org/en/latest/getting-started.html + http://doc.pypy.org/ It will also point you to the rest of the documentation which is generated from files in the pypy/doc directory within the source repositories. Enjoy diff --git a/pypy/doc/dir-reference.rst b/pypy/doc/dir-reference.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/dir-reference.rst @@ -0,0 +1,140 @@ +PyPy directory cross-reference +------------------------------ + +Here is a fully referenced alphabetical two-level deep +directory overview of PyPy: + +================================= ============================================ +Directory explanation/links +================================= ============================================ +`pypy/bin/`_ command-line scripts, mainly + `pypy/bin/pyinteractive.py`_ + +`pypy/config/`_ handles the numerous options for building + and running PyPy + +`pypy/doc/`_ text versions of PyPy developer + documentation + +`pypy/doc/config/`_ documentation for the numerous translation + options + +`pypy/doc/discussion/`_ drafts of ideas and documentation + +``doc/*/`` other specific documentation topics or tools + +`pypy/interpreter/`_ `bytecode interpreter`_ and related objects + (frames, functions, modules,...) + +`pypy/interpreter/pyparser/`_ interpreter-level Python source parser + +`pypy/interpreter/astcompiler/`_ interpreter-level bytecode compiler, + via an AST representation + +`pypy/module/`_ contains `mixed modules`_ + implementing core modules with + both application and interpreter level code. + Not all are finished and working. Use + the ``--withmod-xxx`` + or ``--allworkingmodules`` translation + options. + +`pypy/objspace/`_ `object space`_ implementations + +`pypy/objspace/std/`_ the StdObjSpace_ implementing CPython's + objects and types + +`pypy/tool/`_ various utilities and hacks used + from various places + +`pypy/tool/algo/`_ general-purpose algorithmic and mathematic + tools + +`pypy/tool/pytest/`_ support code for our `testing methods`_ + + +`rpython/annotator/`_ `type inferencing code`_ for + `RPython`_ programs + +`rpython/config/`_ handles the numerous options for RPython + + +`rpython/flowspace/`_ the FlowObjSpace_ implementing + `abstract interpretation`_ + +`rpython/rlib/`_ a `"standard library"`_ for RPython_ + programs + +`rpython/rtyper/`_ the `RPython Typer`_ + +`rpython/rtyper/lltypesystem/`_ the `low-level type system`_ for + C-like backends + +`rpython/rtyper/ootypesystem/`_ the `object-oriented type system`_ + for OO backends + +`rpython/memory/`_ the `garbage collector`_ construction + framework + +`rpython/translator/`_ translation_ backends and support code + +`rpython/translator/backendopt/`_ general optimizations that run before a + backend generates code + +`rpython/translator/c/`_ the `GenC backend`_, producing C code + from an + RPython program (generally via the rtyper_) + +`rpython/translator/cli/`_ the `CLI backend`_ for `.NET`_ + (Microsoft CLR or Mono_) + +`pypy/goal/`_ our `main PyPy-translation scripts`_ + live here + +`rpython/translator/jvm/`_ the Java backend + +`rpython/translator/tool/`_ helper tools for translation + +`dotviewer/`_ `graph viewer`_ + +``*/test/`` many directories have a test subdirectory + containing test + modules (see `Testing in PyPy`_) + +``_cache/`` holds cache files from various purposes +================================= ============================================ + +.. _`bytecode interpreter`: interpreter.html +.. _`Testing in PyPy`: coding-guide.html#testing-in-pypy +.. _`mixed modules`: coding-guide.html#mixed-modules +.. _`modules`: coding-guide.html#modules +.. _`basil`: http://people.cs.uchicago.edu/~jriehl/BasilTalk.pdf +.. _`object space`: objspace.html +.. _FlowObjSpace: objspace.html#the-flow-object-space +.. _`transparent proxies`: objspace-proxies.html#tproxy +.. _`Differences between PyPy and CPython`: cpython_differences.html +.. _`What PyPy can do for your objects`: objspace-proxies.html +.. _`Continulets and greenlets`: stackless.html +.. _StdObjSpace: objspace.html#the-standard-object-space +.. _`abstract interpretation`: http://en.wikipedia.org/wiki/Abstract_interpretation +.. _`rpython`: coding-guide.html#rpython +.. _`type inferencing code`: translation.html#the-annotation-pass +.. _`RPython Typer`: translation.html#rpython-typer +.. _`testing methods`: coding-guide.html#testing-in-pypy +.. _`translation`: translation.html +.. _`GenC backend`: translation.html#genc +.. _`CLI backend`: cli-backend.html +.. _`py.py`: getting-started-python.html#the-py.py-interpreter +.. _`translatorshell.py`: getting-started-dev.html#try-out-the-translator +.. _JIT: jit/index.html +.. _`JIT Generation in PyPy`: jit/index.html +.. _`just-in-time compiler generator`: jit/index.html +.. _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 +.. _`main PyPy-translation scripts`: getting-started-python.html#translating-the-pypy-python-interpreter +.. _`.NET`: http://www.microsoft.com/net/ +.. _Mono: http://www.mono-project.com/ +.. _`"standard library"`: rlib.html +.. _`graph viewer`: getting-started-dev.html#try-out-the-translator diff --git a/pypy/doc/getting-started-dev.rst b/pypy/doc/getting-started-dev.rst --- a/pypy/doc/getting-started-dev.rst +++ b/pypy/doc/getting-started-dev.rst @@ -1,13 +1,58 @@ -=============================================================================== -Getting Started with the Translation Toolchain and Development Process -=============================================================================== +============================ +Getting Started with RPython +============================ .. contents:: +RPython is a subset of Python that can be statically compiled. The PyPy +interpreter is written mostly in RPython (with pieces in Python), while +the RPython compiler is written in Python. The hard to understand part +is that Python is a meta-programming language for RPython, that is, +RPython is considered from live objects **after** the imports are done. +This might require more explanation. You start writing RPython from +``entry_point``, a good starting point is +``rpython/translator/goal/targetnopstandalone.py``. This does not do all that +much, but is a start. Now if code analyzed (in this case ``entry_point``) +calls some functions, those calls will be followed. Those followed calls +have to be RPython themselves (and everything they call etc.), however not +entire module files. To show how you can use metaprogramming, we can do +a silly example (note that closures are not RPython):: + + def generator(operation): + if operation == 'add': + def f(a, b): + return a + b + else: + def f(a, b): + return a - b + return f + + add = generator('add') + sub = generator('sub') + + def entry_point(argv): + print add(sub(int(argv[1]), 3) 4) + return 0 + +In this example ``entry_point`` is RPython, ``add`` and ``sub`` are RPython, +however, ``generator`` is not. + +A good introductory level articles are available: + +* Laurence Tratt -- `Fast Enough VMs in Fast Enough Time`_. + +* `How to write interpreters in RPython`_ and `part 2`_ by Andrew Brown. + +.. _`Fast Enough VMs in Fast Enough Time`: http://tratt.net/laurie/tech_articles/articles/fast_enough_vms_in_fast_enough_time + +.. _`How to write interpreters in RPython`: http://morepypy.blogspot.com/2011/04/tutorial-writing-interpreter-with-pypy.html + +.. _`part 2`: http://morepypy.blogspot.com/2011/04/tutorial-part-2-adding-jit.html + .. _`try out the translator`: Trying out the translator -------------------------- +------------------------- The translator is a tool based on the PyPy interpreter which can translate sufficiently static RPython programs into low-level code (in particular it can @@ -28,7 +73,7 @@ >>> t = Translation(snippet.is_perfect_number, [int]) >>> t.view() - + After that, the graph viewer pops up, that lets you interactively inspect the flow graph. To move around, click on something that you want to inspect. To get help about how to use it, press 'H'. To close it again, press 'Q'. @@ -83,10 +128,10 @@ The object returned by ``compile_cli`` or ``compile_jvm`` is a wrapper around the real executable: the parameters are passed as command line arguments, and -the returned value is read from the standard output. +the returned value is read from the standard output. Once you have compiled the snippet, you can also try to launch the -executable directly from the shell. You will find the +executable directly from the shell. You will find the executable in one of the ``/tmp/usession-*`` directories:: # For CLI: diff --git a/pypy/doc/getting-started-python.rst b/pypy/doc/getting-started-python.rst --- a/pypy/doc/getting-started-python.rst +++ b/pypy/doc/getting-started-python.rst @@ -6,7 +6,7 @@ PyPy's Python interpreter is a very compliant Python -interpreter implemented in Python. When translated to C, it passes most of +interpreter implemented in RPython. When compiled, it passes most of `CPythons core language regression tests`_ and comes with many of the extension modules included in the standard library including ``ctypes``. It can run large libraries such as Django_ and Twisted_. There are some small behavioral @@ -147,6 +147,8 @@ Translating using the CLI backend +++++++++++++++++++++++++++++++++ +**Note: the CLI backend is no longer maintained** + To create a standalone .NET executable using the `CLI backend`_:: ./translate.py --backend=cli targetpypystandalone.py diff --git a/pypy/doc/how-to-contribute.rst b/pypy/doc/how-to-contribute.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/how-to-contribute.rst @@ -0,0 +1,78 @@ +How to contribute to PyPy +------------------------- + +This page describes how to contribute to the PyPy project. The first thing +to remember is that PyPy project is very different than most projects out there. +It's also different from a classic compiler project, so academic courses +about compilers often don't apply or lead in the wrong direction. + +Don't just hack +--------------- + +The first and most important rule how not to contribute to PyPy is +"just hacking". This won't work. There are two major reasons why not +-- build times are large and PyPy has very thick layer separation which +make it harder to "just hack a feature". + +Test driven development +----------------------- + +Instead, we practice a lot of test driven development. This is partly because +of very high quality requirements for compilers and partly because there is +simply no other way to get around such complex project, that will keep you sane. +There are probably people out there who are smart enough not to need it, we're +not one of those. You may consider familiarizing yourself with `pytest`_, +since this is a tool we use for tests. +This leads to the next issue: + +Layers +------ + +PyPy has layers. Those layers help us keep the respective parts separated enough +to be worked on independently and make the complexity manageable. This is, +again, just a sanity requirement for such a complex project. For example writing +a new optimization for the JIT usually does **not** involve touching a Python +interpreter at all or the JIT assembler backend or the garbage collector. +Instead it requires writing small tests in +``rpython/jit/metainterp/optimizeopt/test/test_*`` and fixing files there. +After that, you can just compile PyPy and things should just work. + +The short list of layers for further reading. For each of those layers, a good +entry point is a test subdirectory in respective directories. It usually +describes (better or worse) the interfaces between the submodules. For the +``pypy`` subdirectory, most tests are small snippets of python programs that +check for correctness (calls ``AppTestXxx``) that will call the appropriate +part of the interpreter. For the ``rpython`` directory, most tests are small +RPython interpreters that perform certain tasks. To see how they translate +to low-level graphs, run them with ``--view``. To see small interpreters +with a JIT compiler, use ``--viewloops`` option. + +* **python interpreter** - it's the part implemented in the ``pypy/`` directory. + It's implemented in RPython, which is a high level static language with + classes, garbage collection, just-in-time compiler generation and the ability + to call C. A cool part about it is that it can be run untranslated, so all + the tests are runnable without translating PyPy. + + **interpreter** contains the interpreter core + + **objspace** contains implementations of various objects exported to + the Python layer + + **module** directory contains extension modules written in RPython + +* **rpython compiler** that resides in ``rpython/annotator`` and + ``rpython/rtyper`` directories. Consult `introduction to RPython`_ for + further reading + +* **JIT generator** lives in ``rpython/jit`` directory. optimizations live + in ``rpython/jit/metainterp/optimizeopt``, the main JIT in + ``rpython/jit/metainterp`` (runtime part) and + ``rpython/jit/codewriter`` (translation-time part). Backends live in + ``rpython/jit/backend``. + +* **garbage collection** lives in ``rpython/memory`` + +The rest of directories serve specific niche goal and are unlikely a good +entry point. + +.. _`introduction to RPython`: getting-started-dev.rst diff --git a/pypy/doc/index.rst b/pypy/doc/index.rst --- a/pypy/doc/index.rst +++ b/pypy/doc/index.rst @@ -1,15 +1,39 @@ -Welcome to PyPy Development -============================================= +Welcome to PyPy +=============== -The PyPy project aims at producing a flexible and fast Python_ -implementation. The guiding idea is to translate a Python-level -description of the Python language itself to lower level languages. -Rumors have it that the secret goal is being faster-than-C which is -nonsense, isn't it? `more...`_ +The PyPy project aims to produce a flexible and fast Python_ +implementation. This page documents the development of the PyPy +project itself. If you don't know what PyPy is, consult the `PyPy +website`_. If you just want to use PyPy, consult the `download`_ page +and the `getting started with pypy`_ documents. If you want to help +develop PyPy -- keep reading! -Getting into PyPy ... -============================================= +PyPy is written in a language called `RPython`_, which is suitable for +writing dynamic language interpreters (and not much else). RPython is +a subset of Python and is itself written in Python. If you'd like to +learn more about RPython, `Starting with RPython`_ should provide a +reasonable overview. + +**If you would like to contribute to PyPy**, please read `how to +contribute`_ first. PyPy's development style is somewhat different to +that of many other software projects and it often surprises +newcomers. What is **not** necessary is an academic background from +university in writing compilers -- much of it does not apply to PyPy +any way. + +All of the documentation and source code is available under the MIT license, +unless otherwise specified. Consult `LICENSE`_ + +.. _`download`: http://pypy.org/download.html +.. _`getting started with pypy`: getting-started-python.html +.. _`RPython`: coding-guide.html#RPython +.. _`Starting with RPython`: getting-started-dev.html +.. _`how to contribute`: how-to-contribute.html +.. _`PyPy website`: http://pypy.org + +Index of various topics: +======================== * `Getting started`_: how to install and run the PyPy Python interpreter @@ -25,20 +49,32 @@ * `potential project ideas`_: In case you want to get your feet wet... +* `more stuff`_: this is a collection of documentation that's there, but not + particularly organized + Documentation for the PyPy Python Interpreter -=============================================== +============================================= New features of PyPy's Python Interpreter and Translation Framework: * `Differences between PyPy and CPython`_ - * `What PyPy can do for your objects`_ - * `Continulets and greenlets`_ + * `What PyPy can do for your objects`_ - transparent proxy documentation + * `Continulets and greenlets`_ - documentation about stackless features * `JIT Generation in PyPy`_ + * `JIT hooks`_ * `Sandboxing Python code`_ + * `Garbage collection environment variables`_ Status_ of the project. +.. _`Differences between PyPy and CPython`: cpython_differences.html +.. _`What PyPy can do for your objects`: objspace-proxies.html +.. _`Continulets and greenlets_`: stackless.html +.. _`JIT Generation in PyPy`: jit/index.html +.. _`JIT hooks`: jit-hooks.html +.. _`Sandboxing Python code`: sandbox.html +.. _`Garbage collection environment variables`: gc_info.html Mailing lists, bug tracker, IRC channel ============================================= @@ -79,354 +115,6 @@ .. _`speed.pypy.org`: http://speed.pypy.org .. _`RPython toolchain`: translation.html .. _`potential project ideas`: project-ideas.html - -Project Documentation -===================================== - -PyPy was funded by the EU for several years. See the `web site of the EU -project`_ for more details. - -.. _`web site of the EU project`: http://pypy.org - -architecture_ gives a complete view of PyPy's basic design. - -`coding guide`_ helps you to write code for PyPy (especially also describes -coding in RPython a bit). - -`sprint reports`_ lists reports written at most of our sprints, from -2003 to the present. - -`papers, talks and related projects`_ lists presentations -and related projects as well as our published papers. - -`PyPy video documentation`_ is a page linking to the videos (e.g. of talks and -introductions) that are available. - -`Technical reports`_ is a page that contains links to the -reports that we submitted to the European Union. - -`development methodology`_ describes our sprint-driven approach. - -`LICENSE`_ contains licensing details (basically a straight MIT-license). - -`Glossary`_ of PyPy words to help you align your inner self with -the PyPy universe. - - -Status -=================================== - -PyPy can be used to run Python programs on Linux, OS/X, -Windows, on top of .NET, and on top of Java. -To dig into PyPy it is recommended to try out the current -Mercurial default branch, which is always working or mostly working, -instead of the latest release, which is `2.0 beta1`__. - -.. __: release-2.0.0-beta1.html - -PyPy is mainly developed on Linux and Mac OS X. Windows is supported, -but platform-specific bugs tend to take longer before we notice and fix -them. Linux 64-bit machines are supported (though it may also take some -time before we notice and fix bugs). - -PyPy's own tests `summary`_, daily updated, run through BuildBot infrastructure. -You can also find CPython's compliance tests run with compiled ``pypy-c`` -executables there. - - -Source Code Documentation -=============================================== - -`object spaces`_ discusses the object space interface -and several implementations. - -`bytecode interpreter`_ explains the basic mechanisms -of the bytecode interpreter and virtual machine. - -`interpreter optimizations`_ describes our various strategies for -improving the performance of our interpreter, including alternative -object implementations (for strings, dictionaries and lists) in the -standard object space. - -`translation`_ is a detailed overview of our translation process. The -rtyper_ is the largest component of our translation process. - -`dynamic-language translation`_ is a paper that describes -the translation process, especially the flow object space -and the annotator in detail. (This document is one -of the `EU reports`_.) - -`low-level encapsulation`_ describes how our approach hides -away a lot of low level details. This document is also part -of the `EU reports`_. - -`translation aspects`_ describes how we weave different -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. - -`rlib`_ describes some modules that can be used when implementing programs in -RPython. - -`configuration documentation`_ describes the various configuration options that -allow you to customize PyPy. - -`CLI backend`_ describes the details of the .NET backend. - -`JIT Generation in PyPy`_ describes how we produce the Python Just-in-time Compiler -from our Python interpreter. - - - -.. _`FAQ`: faq.html -.. _Glossary: glossary.html -.. _`PyPy video documentation`: video-index.html -.. _parser: parser.html -.. _`development methodology`: dev_method.html -.. _`sprint reports`: sprint-reports.html -.. _`papers, talks and related projects`: extradoc.html -.. _`object spaces`: objspace.html -.. _`interpreter optimizations`: interpreter-optimizations.html -.. _`translation`: translation.html -.. _`dynamic-language translation`: https://bitbucket.org/pypy/extradoc/raw/tip/eu-report/D05.1_Publish_on_translating_a_very-high-level_description.pdf -.. _`low-level encapsulation`: low-level-encapsulation.html -.. _`translation aspects`: translation-aspects.html -.. _`configuration documentation`: config/ -.. _`coding guide`: coding-guide.html -.. _`architecture`: architecture.html -.. _`getting started`: getting-started.html -.. _`bytecode interpreter`: interpreter.html -.. _`EU reports`: index-report.html -.. _`Technical reports`: index-report.html -.. _`summary`: http://buildbot.pypy.org/summary -.. _`ideas for PyPy related projects`: project-ideas.html -.. _`Nightly builds and benchmarks`: http://tuatara.cs.uni-duesseldorf.de/benchmark.html -.. _`directory reference`: -.. _`rlib`: rlib.html -.. _`Sandboxing Python code`: sandbox.html -.. _`LICENSE`: https://bitbucket.org/pypy/pypy/src/default/LICENSE - -PyPy directory cross-reference ------------------------------- - -Here is a fully referenced alphabetical two-level deep -directory overview of PyPy: - -================================= ============================================ -Directory explanation/links -================================= ============================================ -`pypy/bin/`_ command-line scripts, mainly - `pypy/bin/pyinteractive.py`_ - -`pypy/config/`_ handles the numerous options for building - and running PyPy - -`pypy/doc/`_ text versions of PyPy developer - documentation - -`pypy/doc/config/`_ documentation for the numerous translation - options - -`pypy/doc/discussion/`_ drafts of ideas and documentation - -``doc/*/`` other specific documentation topics or tools - -`pypy/interpreter/`_ `bytecode interpreter`_ and related objects - (frames, functions, modules,...) - -`pypy/interpreter/pyparser/`_ interpreter-level Python source parser - -`pypy/interpreter/astcompiler/`_ interpreter-level bytecode compiler, - via an AST representation - -`pypy/module/`_ contains `mixed modules`_ - implementing core modules with - both application and interpreter level code. - Not all are finished and working. Use - the ``--withmod-xxx`` - or ``--allworkingmodules`` translation - options. - -`pypy/objspace/`_ `object space`_ implementations - -`pypy/objspace/std/`_ the StdObjSpace_ implementing CPython's - objects and types - -`pypy/tool/`_ various utilities and hacks used - from various places - -`pypy/tool/algo/`_ general-purpose algorithmic and mathematic - tools - -`pypy/tool/pytest/`_ support code for our `testing methods`_ - - -`rpython/annotator/`_ `type inferencing code`_ for - `RPython`_ programs - -`rpython/config/`_ handles the numerous options for RPython - - -`rpython/flowspace/`_ the FlowObjSpace_ implementing - `abstract interpretation`_ - -`rpython/rlib/`_ a `"standard library"`_ for RPython_ - programs - -`rpython/rtyper/`_ the `RPython Typer`_ - -`rpython/rtyper/lltypesystem/`_ the `low-level type system`_ for - C-like backends - -`rpython/rtyper/ootypesystem/`_ the `object-oriented type system`_ - for OO backends - -`rpython/memory/`_ the `garbage collector`_ construction - framework - -`rpython/translator/`_ translation_ backends and support code - -`rpython/translator/backendopt/`_ general optimizations that run before a - backend generates code - -`rpython/translator/c/`_ the `GenC backend`_, producing C code - from an - RPython program (generally via the rtyper_) - -`rpython/translator/cli/`_ the `CLI backend`_ for `.NET`_ - (Microsoft CLR or Mono_) - -`pypy/goal/`_ our `main PyPy-translation scripts`_ - live here - -`rpython/translator/jvm/`_ the Java backend - -`rpython/translator/tool/`_ helper tools for translation - -`dotviewer/`_ `graph viewer`_ - -``*/test/`` many directories have a test subdirectory - containing test - modules (see `Testing in PyPy`_) - -``_cache/`` holds cache files from various purposes -================================= ============================================ - -.. _`bytecode interpreter`: interpreter.html -.. _`Testing in PyPy`: coding-guide.html#testing-in-pypy -.. _`mixed modules`: coding-guide.html#mixed-modules -.. _`modules`: coding-guide.html#modules -.. _`basil`: http://people.cs.uchicago.edu/~jriehl/BasilTalk.pdf -.. _`object space`: objspace.html -.. _FlowObjSpace: objspace.html#the-flow-object-space -.. _`transparent proxies`: objspace-proxies.html#tproxy -.. _`Differences between PyPy and CPython`: cpython_differences.html -.. _`What PyPy can do for your objects`: objspace-proxies.html -.. _`Continulets and greenlets`: stackless.html -.. _StdObjSpace: objspace.html#the-standard-object-space -.. _`abstract interpretation`: http://en.wikipedia.org/wiki/Abstract_interpretation -.. _`rpython`: coding-guide.html#rpython -.. _`type inferencing code`: translation.html#the-annotation-pass -.. _`RPython Typer`: translation.html#rpython-typer -.. _`testing methods`: coding-guide.html#testing-in-pypy -.. _`translation`: translation.html -.. _`GenC backend`: translation.html#genc -.. _`CLI backend`: cli-backend.html -.. _`py.py`: getting-started-python.html#the-py.py-interpreter -.. _`translatorshell.py`: getting-started-dev.html#try-out-the-translator -.. _JIT: jit/index.html -.. _`JIT Generation in PyPy`: jit/index.html -.. _`just-in-time compiler generator`: jit/index.html -.. _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 -.. _`main PyPy-translation scripts`: getting-started-python.html#translating-the-pypy-python-interpreter -.. _`.NET`: http://www.microsoft.com/net/ -.. _Mono: http://www.mono-project.com/ -.. _`"standard library"`: rlib.html -.. _`graph viewer`: getting-started-dev.html#try-out-the-translator - - -.. The following documentation is important and reasonably up-to-date: - -.. extradoc: should this be integrated one level up: dcolish? - - -.. toctree:: - :maxdepth: 1 - :hidden: - - getting-started.rst - getting-started-python.rst - getting-started-dev.rst - windows.rst - faq.rst - commandline_ref.rst - architecture.rst - coding-guide.rst - cpython_differences.rst - garbage_collection.rst - gc_info.rst - interpreter.rst - objspace.rst - __pypy__-module.rst - objspace-proxies.rst - config/index.rst - - dev_method.rst - extending.rst - - extradoc.rst - video-index.rst - - glossary.rst - - contributor.rst - - interpreter-optimizations.rst - configuration.rst - parser.rst - rlib.rst - rtyper.rst - rffi.rst - - translation.rst - jit/index.rst - jit/overview.rst - jit/pyjitpl5.rst - - index-of-release-notes.rst - - ctypes-implementation.rst - - how-to-release.rst - - index-report.rst - - stackless.rst - sandbox.rst - - discussions.rst - - cleanup.rst - - sprint-reports.rst - - eventhistory.rst - statistic/index.rst - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`search` -* :ref:`glossary` - +.. _`more stuff`: project-documentation.html .. include:: _ref.txt diff --git a/pypy/doc/needswork.txt b/pypy/doc/needswork.txt deleted file mode 100644 --- a/pypy/doc/needswork.txt +++ /dev/null @@ -1,3 +0,0 @@ -.. warning:: - - This documentation needs work (as discussed during the Gothenburg sprint in 2011) diff --git a/pypy/doc/objspace-proxies.rst b/pypy/doc/objspace-proxies.rst --- a/pypy/doc/objspace-proxies.rst +++ b/pypy/doc/objspace-proxies.rst @@ -5,7 +5,6 @@ .. contents:: - Thanks to the `Object Space`_ architecture, any feature that is based on proxying, extending, changing or otherwise controlling the behavior of all objects in a running program is easy to implement on diff --git a/pypy/doc/project-documentation.rst b/pypy/doc/project-documentation.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/project-documentation.rst @@ -0,0 +1,177 @@ + +Project Documentation +===================================== + +`architecture`_ gives a complete view of PyPy's basic design. + +`coding guide`_ helps you to write code for PyPy (especially also describes +coding in RPython a bit). + +`sprint reports`_ lists reports written at most of our sprints, from +2003 to the present. + +`papers, talks and related projects`_ lists presentations +and related projects as well as our published papers. + +`PyPy video documentation`_ is a page linking to the videos (e.g. of talks and +introductions) that are available. + +`Technical reports`_ is a page that contains links to the +reports that we submitted to the European Union. + +`development methodology`_ describes our sprint-driven approach. + +`LICENSE`_ contains licensing details (basically a straight MIT-license). + +`Glossary`_ of PyPy words to help you align your inner self with +the PyPy universe. + +Source Code Documentation +=============================================== + +`object spaces`_ discusses the object space interface +and several implementations. + +`bytecode interpreter`_ explains the basic mechanisms +of the bytecode interpreter and virtual machine. + +`interpreter optimizations`_ describes our various strategies for +improving the performance of our interpreter, including alternative +object implementations (for strings, dictionaries and lists) in the +standard object space. + +`translation`_ is a detailed overview of our translation process. The +rtyper_ is the largest component of our translation process. + +`dynamic-language translation`_ is a paper that describes +the translation process, especially the flow object space +and the annotator in detail. (This document is one +of the `EU reports`_.) + +`low-level encapsulation`_ describes how our approach hides +away a lot of low level details. This document is also part +of the `EU reports`_. + +`translation aspects`_ describes how we weave different +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. + +`rlib`_ describes some modules that can be used when implementing programs in +RPython. + +`configuration documentation`_ describes the various configuration options that +allow you to customize PyPy. + +`pypy on windows`_ + +`command line reference`_ + +`CLI backend`_ describes the details of the .NET backend. + +`JIT Generation in PyPy`_ describes how we produce the Python Just-in-time Compiler +from our Python interpreter. + +`directory cross-reference`_ + +.. _`garbage collector`: garbage_collection.html +.. _`directory cross-reference`: dir-reference.html +.. _`pypy on windows`: windows.html +.. _`command line reference`: commandline_ref.html +.. _`FAQ`: faq.html +.. _Glossary: glossary.html +.. _`PyPy video documentation`: video-index.html +.. _parser: parser.html +.. _`development methodology`: dev_method.html +.. _`sprint reports`: sprint-reports.html +.. _`papers, talks and related projects`: extradoc.html +.. _`object spaces`: objspace.html +.. _`interpreter optimizations`: interpreter-optimizations.html +.. _`translation`: translation.html +.. _`dynamic-language translation`: https://bitbucket.org/pypy/extradoc/raw/tip/eu-report/D05.1_Publish_on_translating_a_very-high-level_description.pdf +.. _`low-level encapsulation`: low-level-encapsulation.html +.. _`translation aspects`: translation-aspects.html +.. _`configuration documentation`: config/ +.. _`coding guide`: coding-guide.html +.. _`Architecture`: architecture.html +.. _`getting started`: getting-started.html +.. _`bytecode interpreter`: interpreter.html +.. _`EU reports`: index-report.html +.. _`Technical reports`: index-report.html +.. _`summary`: http://buildbot.pypy.org/summary +.. _`ideas for PyPy related projects`: project-ideas.html +.. _`Nightly builds and benchmarks`: http://tuatara.cs.uni-duesseldorf.de/benchmark.html +.. _`directory reference`: +.. _`rlib`: rlib.html +.. _`Sandboxing Python code`: sandbox.html +.. _`LICENSE`: https://bitbucket.org/pypy/pypy/src/default/LICENSE + +.. The following documentation is important and reasonably up-to-date: + +.. extradoc: should this be integrated one level up: dcolish? + +.. toctree:: + :maxdepth: 1 + :hidden: + + interpreter.rst + objspace.rst + __pypy__-module.rst + objspace-proxies.rst + config/index.rst + + dev_method.rst + extending.rst + + extradoc.rst + video-index.rst + + glossary.rst + + contributor.rst + + interpreter-optimizations.rst + configuration.rst + parser.rst + rlib.rst + rtyper.rst + rffi.rst + + translation.rst + jit/index.rst + jit/overview.rst + jit/pyjitpl5.rst + + index-of-release-notes.rst + + ctypes-implementation.rst + + how-to-release.rst + + index-report.rst + + stackless.rst + sandbox.rst + + discussions.rst + + cleanup.rst + + sprint-reports.rst + + eventhistory.rst + statistic/index.rst + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`search` +* :ref:`glossary` + +.. include:: _ref.txt diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -46,6 +46,10 @@ Fix a bug which casused cffi to return the wrong result when calling a C function which calls a Python callback which forces the frames +.. branch: virtual-raw-mallocs +JIT optimizations which makes cffi calls even faster, by removing the need to +allocate a temporary buffer where to store the arguments. + .. branches we don't care about .. branch: autoreds .. branch: reflex-support @@ -121,3 +125,4 @@ cffi implementation of sqlite3 .. branch: release-2.0-beta2 +.. branch: unbreak-freebsd diff --git a/pypy/module/_cffi_backend/ccallback.py b/pypy/module/_cffi_backend/ccallback.py --- a/pypy/module/_cffi_backend/ccallback.py +++ b/pypy/module/_cffi_backend/ccallback.py @@ -134,7 +134,7 @@ # W_CTypePrimitiveSigned.convert_from_object() in order # to write a whole 'ffi_arg'. value = misc.as_long(space, w_res) - misc.write_raw_integer_data(ll_res, value, SIZE_OF_FFI_ARG) + misc.write_raw_signed_data(ll_res, value, SIZE_OF_FFI_ARG) return else: # zero extension: fill the '*result' with zeros, and (on big- diff --git a/pypy/module/_cffi_backend/cdataobj.py b/pypy/module/_cffi_backend/cdataobj.py --- a/pypy/module/_cffi_backend/cdataobj.py +++ b/pypy/module/_cffi_backend/cdataobj.py @@ -280,8 +280,13 @@ return self.ctype.iter(self) @specialize.argtype(1) - def write_raw_integer_data(self, source): - misc.write_raw_integer_data(self._cdata, source, self.ctype.size) + def write_raw_signed_data(self, source): + misc.write_raw_signed_data(self._cdata, source, self.ctype.size) + keepalive_until_here(self) + + @specialize.argtype(1) + def write_raw_unsigned_data(self, source): + misc.write_raw_unsigned_data(self._cdata, source, self.ctype.size) keepalive_until_here(self) def write_raw_float_data(self, source): diff --git a/pypy/module/_cffi_backend/ctypeprim.py b/pypy/module/_cffi_backend/ctypeprim.py --- a/pypy/module/_cffi_backend/ctypeprim.py +++ b/pypy/module/_cffi_backend/ctypeprim.py @@ -63,7 +63,7 @@ else: value = self._cast_generic(w_ob) w_cdata = cdataobj.W_CDataMem(space, self.size, self) - w_cdata.write_raw_integer_data(value) + self.write_raw_integer_data(w_cdata, value) return w_cdata def _cast_result(self, intvalue): @@ -94,6 +94,9 @@ from pypy.module._cffi_backend import newtype return newtype.new_primitive_type(self.space, "int") + def write_raw_integer_data(self, w_cdata, value): + w_cdata.write_raw_unsigned_data(value) + class W_CTypePrimitiveChar(W_CTypePrimitiveCharOrUniChar): _attrs_ = [] @@ -185,10 +188,10 @@ if self.size < rffi.sizeof(lltype.Signed): if r_uint(value) - self.vmin > self.vrangemax: self._overflow(w_ob) - misc.write_raw_integer_data(cdata, value, self.size) + misc.write_raw_signed_data(cdata, value, self.size) else: value = misc.as_long_long(self.space, w_ob) - misc.write_raw_integer_data(cdata, value, self.size) + misc.write_raw_signed_data(cdata, value, self.size) def get_vararg_type(self): if self.size < rffi.sizeof(rffi.INT): @@ -196,6 +199,9 @@ return newtype.new_primitive_type(self.space, "int") return self + def write_raw_integer_data(self, w_cdata, value): + w_cdata.write_raw_signed_data(value) + class W_CTypePrimitiveUnsigned(W_CTypePrimitive): _attrs_ = ['value_fits_long', 'value_fits_ulong', 'vrangemax'] @@ -222,10 +228,10 @@ if self.value_fits_long: if value > self.vrangemax: self._overflow(w_ob) - misc.write_raw_integer_data(cdata, value, self.size) + misc.write_raw_unsigned_data(cdata, value, self.size) else: value = misc.as_unsigned_long_long(self.space, w_ob, strict=True) - misc.write_raw_integer_data(cdata, value, self.size) + misc.write_raw_unsigned_data(cdata, value, self.size) def convert_to_object(self, cdata): if self.value_fits_ulong: @@ -244,6 +250,9 @@ return newtype.new_primitive_type(self.space, "int") return self + def write_raw_integer_data(self, w_cdata, value): + w_cdata.write_raw_unsigned_data(value) + class W_CTypePrimitiveBool(W_CTypePrimitiveUnsigned): _attrs_ = [] diff --git a/pypy/module/_cffi_backend/ctypestruct.py b/pypy/module/_cffi_backend/ctypestruct.py --- a/pypy/module/_cffi_backend/ctypestruct.py +++ b/pypy/module/_cffi_backend/ctypestruct.py @@ -242,11 +242,13 @@ # value = misc.as_long_long(space, w_ob) if isinstance(ctype, ctypeprim.W_CTypePrimitiveSigned): + is_signed = True fmin = -(r_longlong(1) << (self.bitsize - 1)) fmax = (r_longlong(1) << (self.bitsize - 1)) - 1 if fmax == 0: fmax = 1 # special case to let "int x:1" receive "1" else: + is_signed = False fmin = r_longlong(0) fmax = r_longlong((r_ulonglong(1) << self.bitsize) - 1) if value < fmin or value > fmax: @@ -258,7 +260,10 @@ rawvalue = r_ulonglong(value) << self.bitshift rawfielddata = misc.read_raw_unsigned_data(cdata, ctype.size) rawfielddata = (rawfielddata & ~rawmask) | (rawvalue & rawmask) - misc.write_raw_integer_data(cdata, rawfielddata, ctype.size) + if is_signed: + misc.write_raw_signed_data(cdata, rawfielddata, ctype.size) + else: + misc.write_raw_unsigned_data(cdata, rawfielddata, ctype.size) W_CField.typedef = TypeDef( diff --git a/pypy/module/_cffi_backend/misc.py b/pypy/module/_cffi_backend/misc.py --- a/pypy/module/_cffi_backend/misc.py +++ b/pypy/module/_cffi_backend/misc.py @@ -9,6 +9,7 @@ from rpython.rtyper.lltypesystem import lltype, llmemory, rffi from rpython.translator.tool.cbuild import ExternalCompilationInfo + # ____________________________________________________________ _prim_signed_types = unrolling_iterable([ @@ -65,19 +66,22 @@ return rffi.cast(rffi.LONGDOUBLEP, target)[0] @specialize.argtype(1) -def write_raw_integer_data(target, source, size): - if is_signed_integer_type(lltype.typeOf(source)): - for TP, TPP in _prim_signed_types: - if size == rffi.sizeof(TP): - rffi.cast(TPP, target)[0] = rffi.cast(TP, source) - return - else: - for TP, TPP in _prim_unsigned_types: - if size == rffi.sizeof(TP): - rffi.cast(TPP, target)[0] = rffi.cast(TP, source) - return +def write_raw_unsigned_data(target, source, size): + for TP, TPP in _prim_unsigned_types: + if size == rffi.sizeof(TP): + rffi.cast(TPP, target)[0] = rffi.cast(TP, source) + return raise NotImplementedError("bad integer size") + at specialize.argtype(1) +def write_raw_signed_data(target, source, size): + for TP, TPP in _prim_signed_types: + if size == rffi.sizeof(TP): + rffi.cast(TPP, target)[0] = rffi.cast(TP, source) + return + raise NotImplementedError("bad integer size") + + def write_raw_float_data(target, source, size): for TP, TPP in _prim_float_types: if size == rffi.sizeof(TP): diff --git a/pypy/module/_io/interp_bytesio.py b/pypy/module/_io/interp_bytesio.py --- a/pypy/module/_io/interp_bytesio.py +++ b/pypy/module/_io/interp_bytesio.py @@ -2,37 +2,25 @@ TypeDef, generic_new_descr, GetSetProperty) from pypy.interpreter.gateway import interp2app, unwrap_spec from pypy.interpreter.error import OperationError, operationerrfmt +from rpython.rlib.rStringIO import RStringIO from rpython.rlib.rarithmetic import r_longlong from pypy.module._io.interp_bufferedio import W_BufferedIOBase from pypy.module._io.interp_iobase import convert_size import sys -def buffer2string(buffer, start, end): - from rpython.rlib.rstring import StringBuilder - builder = StringBuilder(end - start) - for i in range(start, end): - builder.append(buffer[i]) - return builder.build() -class W_BytesIO(W_BufferedIOBase): +class W_BytesIO(RStringIO, W_BufferedIOBase): def __init__(self, space): W_BufferedIOBase.__init__(self, space) - self.pos = 0 - self.string_size = 0 - self.buf = None + self.init() def descr_init(self, space, w_initial_bytes=None): - # In case __init__ is called multiple times - self.buf = [] - self.string_size = 0 - self.pos = 0 - if not space.is_none(w_initial_bytes): self.write_w(space, w_initial_bytes) - self.pos = 0 + self.seek(0) def _check_closed(self, space, message=None): - if self.buf is None: + if self.is_closed(): if message is None: message = "I/O operation on closed file" raise OperationError(space.w_ValueError, space.wrap(message)) @@ -40,36 +28,12 @@ def read_w(self, space, w_size=None): self._check_closed(space) size = convert_size(space, w_size) - - # adjust invalid sizes - available = self.string_size - self.pos - if not 0 <= size <= available: - size = available - if size < 0: - size = 0 - - output = buffer2string(self.buf, self.pos, self.pos + size) - self.pos += size - return space.wrap(output) + return space.wrap(self.read(size)) def readline_w(self, space, w_limit=None): self._check_closed(space) limit = convert_size(space, w_limit) - - cur_pos = self.pos - if limit < 0: - end_pos = self.string_size - else: - end_pos = min(cur_pos + limit, self.string_size) - while cur_pos != end_pos: - if self.buf[cur_pos] == '\n': - cur_pos += 1 - break - cur_pos += 1 - - output = buffer2string(self.buf, self.pos, cur_pos) - self.pos = cur_pos - return space.wrap(output) + return space.wrap(self.readline(limit)) def read1_w(self, space, w_size): return self.read_w(space, w_size) @@ -79,56 +43,28 @@ rwbuffer = space.rwbuffer_w(w_buffer) size = rwbuffer.getlength() - if self.pos + size > self.string_size: - size = self.string_size - self.pos - - output = buffer2string(self.buf, self.pos, self.pos + size) - length = len(output) + output = self.read(size) rwbuffer.setslice(0, output) - self.pos += length - return space.wrap(length) + return space.wrap(len(output)) def write_w(self, space, w_data): self._check_closed(space) if space.isinstance_w(w_data, space.w_unicode): raise OperationError(space.w_TypeError, space.wrap( "bytes string of buffer expected")) - buf = space.buffer_w(w_data) - length = buf.getlength() + buf = space.bufferstr_w(w_data) + length = len(buf) if length <= 0: - return - - if self.pos + length > len(self.buf): - self.buf.extend(['\0'] * (self.pos + length - len(self.buf))) - - if self.pos > self.string_size: - # In case of overseek, pad with null bytes the buffer region - # between the end of stream and the current position. - # - # 0 lo string_size hi - # | |<---used--->|<----------available----------->| - # | | <--to pad-->|<---to write---> | - # 0 buf position - for i in range(self.string_size, self.pos): - self.buf[i] = '\0' - - # Copy the data to the internal buffer, overwriting some of the - # existing data if self->pos < self->string_size. - for i in range(length): - self.buf[self.pos + i] = buf.getitem(i) - self.pos += length - - # Set the new length of the internal string if it has changed - if self.string_size < self.pos: - self.string_size = self.pos - + return space.wrap(0) + self.write(buf) return space.wrap(length) def truncate_w(self, space, w_size=None): self._check_closed(space) + pos = self.tell() if space.is_none(w_size): - size = self.pos + size = pos else: size = space.r_longlong_w(w_size) @@ -136,19 +72,20 @@ raise OperationError(space.w_ValueError, space.wrap( "negative size value")) - if size < self.string_size: - self.string_size = size - del self.buf[size:] - + self.truncate(size) + if size == pos: + self.seek(0, 2) + else: + self.seek(pos) return space.wrap(size) def getvalue_w(self, space): self._check_closed(space) - return space.wrap(buffer2string(self.buf, 0, self.string_size)) + return space.wrap(self.getvalue()) def tell_w(self, space): self._check_closed(space) - return space.wrap(self.pos) + return space.wrap(self.tell()) @unwrap_spec(pos=r_longlong, whence=int) def seek_w(self, space, pos, whence=0): @@ -159,24 +96,19 @@ raise OperationError(space.w_ValueError, space.wrap( "negative seek value")) elif whence == 1: - if pos > sys.maxint - self.pos: + if pos > sys.maxint - self.tell(): raise OperationError(space.w_OverflowError, space.wrap( "new position too large")) - pos += self.pos elif whence == 2: - if pos > sys.maxint - self.string_size: + if pos > sys.maxint - self.getsize(): raise OperationError(space.w_OverflowError, space.wrap( "new position too large")) - pos += self.string_size else: raise operationerrfmt(space.w_ValueError, "whence must be between 0 and 2, not %d", whence) - if pos >= 0: - self.pos = pos - else: - self.pos = 0 - return space.wrap(self.pos) + self.seek(pos, whence) + return space.wrap(self.tell()) def readable_w(self, space): return space.w_True @@ -188,17 +120,16 @@ return space.w_True def close_w(self, space): - self.buf = None + self.close() def closed_get_w(self, space): - return space.wrap(self.buf is None) + return space.wrap(self.is_closed()) def getstate_w(self, space): self._check_closed(space) - w_content = space.wrap(buffer2string(self.buf, 0, self.string_size)) return space.newtuple([ - w_content, - space.wrap(self.pos), + space.wrap(self.getvalue()), + space.wrap(self.tell()), self.getdict(space)]) def setstate_w(self, space, w_state): @@ -211,13 +142,13 @@ space.type(w_state).getname(space) ) w_content, w_pos, w_dict = space.unpackiterable(w_state, 3) + self.truncate(0) + self.write_w(space, w_content) pos = space.int_w(w_pos) - self.buf = [] - self.write_w(space, w_content) if pos < 0: raise OperationError(space.w_ValueError, space.wrap( "position value cannot be negative")) - self.pos = pos + self.seek(pos) if not space.is_w(w_dict, space.w_None): space.call_method(self.getdict(space), "update", w_dict) diff --git a/pypy/module/_io/interp_stringio.py b/pypy/module/_io/interp_stringio.py --- a/pypy/module/_io/interp_stringio.py +++ b/pypy/module/_io/interp_stringio.py @@ -169,9 +169,9 @@ self.pos = end return space.wrap(u''.join(self.buf[start:end])) - @unwrap_spec(limit=int) - def readline_w(self, space, limit=-1): + def readline_w(self, space, w_limit=None): self._check_closed(space) + limit = convert_size(space, w_limit) if self.pos >= len(self.buf): return space.wrap(u"") diff --git a/pypy/module/_io/test/test_bytesio.py b/pypy/module/_io/test/test_bytesio.py --- a/pypy/module/_io/test/test_bytesio.py +++ b/pypy/module/_io/test/test_bytesio.py @@ -24,6 +24,7 @@ def test_write(self): import _io f = _io.BytesIO() + assert f.write("") == 0 assert f.write("hello") == 5 import gc; gc.collect() assert f.getvalue() == "hello" @@ -47,10 +48,17 @@ def test_truncate(self): import _io - f = _io.BytesIO("hello") + f = _io.BytesIO() + f.write("hello") + assert f.truncate(0) == 0 + assert f.tell() == 5 + f.seek(0) + f.write("hello") f.seek(3) assert f.truncate() == 3 assert f.getvalue() == "hel" + assert f.truncate(2) == 2 + assert f.tell() == 3 def test_setstate(self): # state is (content, position, __dict__) @@ -73,7 +81,13 @@ import _io b = _io.BytesIO("hello") + a1 = bytearray('t') + a2 = bytearray('testing') + assert b.readinto(a1) == 1 + assert b.readinto(a2) == 4 b.close() + assert a1 == "h" + assert a2 == "elloing" raises(ValueError, b.readinto, bytearray("hello")) def test_readline(self): diff --git a/pypy/module/_io/test/test_stringio.py b/pypy/module/_io/test/test_stringio.py --- a/pypy/module/_io/test/test_stringio.py +++ b/pypy/module/_io/test/test_stringio.py @@ -32,7 +32,7 @@ raises(ValueError, sio.read, 1) raises(ValueError, sio.write, u"text") - def testRead(self): + def test_read(self): import io buf = u"1234567890" sio = io.StringIO(buf) @@ -42,6 +42,13 @@ assert buf[5:] == sio.read(900) assert u"" == sio.read() + def test_readline(self): + import io + sio = io.StringIO(u'123\n456') + assert sio.readline(2) == '12' + assert sio.readline(None) == '3\n' + assert sio.readline() == '456' + def test_seek(self): import io diff --git a/pypy/module/cStringIO/interp_stringio.py b/pypy/module/cStringIO/interp_stringio.py --- a/pypy/module/cStringIO/interp_stringio.py +++ b/pypy/module/cStringIO/interp_stringio.py @@ -146,7 +146,7 @@ class W_OutputType(RStringIO, W_InputOutputType): def __init__(self, space): - RStringIO.__init__(self) + self.init() self.space = space def descr_truncate(self, w_size=None): @@ -159,6 +159,7 @@ if size < 0: raise OperationError(space.w_IOError, space.wrap("negative size")) self.truncate(size) + self.seek(0, 2) @unwrap_spec(buffer='bufferstr') def descr_write(self, buffer): diff --git a/pypy/module/cStringIO/test/test_interp_stringio.py b/pypy/module/cStringIO/test/test_interp_stringio.py --- a/pypy/module/cStringIO/test/test_interp_stringio.py +++ b/pypy/module/cStringIO/test/test_interp_stringio.py @@ -142,8 +142,11 @@ f.write(' world') f.truncate(30) assert f.getvalue() == '\x00' * 20 + 'hello worl' + assert f.tell() == 30 + f.seek(0) f.truncate(25) assert f.getvalue() == '\x00' * 20 + 'hello' + assert f.tell() == 25 f.write('baz') f.write('egg') f.truncate(3) diff --git a/pypy/module/pypyjit/test_pypy_c/test__ffi.py b/pypy/module/pypyjit/test_pypy_c/test__ffi.py deleted file mode 100644 --- a/pypy/module/pypyjit/test_pypy_c/test__ffi.py +++ /dev/null @@ -1,211 +0,0 @@ -import sys, py -from pypy.module.pypyjit.test_pypy_c.test_00_model import BaseTestPyPyC - -class Test__ffi(BaseTestPyPyC): - - def test__ffi_call(self): - from rpython.rlib.test.test_clibffi import get_libm_name - def main(libm_name): - try: - from _ffi import CDLL, types - except ImportError: - sys.stderr.write('SKIP: cannot import _ffi\n') - return 0 - - libm = CDLL(libm_name) - pow = libm.getfunc('pow', [types.double, types.double], - types.double) - i = 0 - res = 0 - while i < 300: - tmp = pow(2, 3) # ID: fficall - res += tmp - i += 1 - return pow.getaddr(), res - # - libm_name = get_libm_name(sys.platform) - log = self.run(main, [libm_name]) - pow_addr, res = log.result - assert res == 8.0 * 300 - py.test.xfail() # XXX re-optimize _ffi for the JIT? - loop, = log.loops_by_filename(self.filepath) - if 'ConstClass(pow)' in repr(loop): # e.g. OS/X - pow_addr = 'ConstClass(pow)' - assert loop.match_by_id('fficall', """ - guard_not_invalidated(descr=...) - i17 = force_token() - setfield_gc(p0, i17, descr=<.* .*PyFrame.vable_token .*>) - f21 = call_release_gil(%s, 2.000000, 3.000000, descr=) - guard_not_forced(descr=...) - guard_no_exception(descr=...) - """ % pow_addr) - - - def test__ffi_call_frame_does_not_escape(self): - from rpython.rlib.test.test_clibffi import get_libm_name - def main(libm_name): - try: - from _ffi import CDLL, types - except ImportError: - sys.stderr.write('SKIP: cannot import _ffi\n') - return 0 - - libm = CDLL(libm_name) - pow = libm.getfunc('pow', [types.double, types.double], - types.double) - - def mypow(a, b): - return pow(a, b) - - i = 0 - res = 0 - while i < 300: - tmp = mypow(2, 3) - res += tmp - i += 1 - return pow.getaddr(), res - # - libm_name = get_libm_name(sys.platform) - log = self.run(main, [libm_name]) - pow_addr, res = log.result - assert res == 8.0 * 300 - loop, = log.loops_by_filename(self.filepath) - opnames = log.opnames(loop.allops()) - # we only force the virtualref, not its content - assert opnames.count('new_with_vtable') == 1 - - def test__ffi_call_releases_gil(self): - from rpython.rlib.clibffi import get_libc_name - def main(libc_name, n): - import time - import os - from threading import Thread - # - if os.name == 'nt': - from _ffi import WinDLL, types - libc = WinDLL('Kernel32.dll') - sleep = libc.getfunc('Sleep', [types.uint], types.uint) - delays = [0]*n + [1000] - else: - from _ffi import CDLL, types - libc = CDLL(libc_name) - sleep = libc.getfunc('sleep', [types.uint], types.uint) - delays = [0]*n + [1] - # - def loop_of_sleeps(i, delays): - for delay in delays: - sleep(delay) # ID: sleep - # - threads = [Thread(target=loop_of_sleeps, args=[i, delays]) for i in range(5)] - start = time.time() - for i, thread in enumerate(threads): - thread.start() - for thread in threads: - thread.join() - end = time.time() - return end - start - log = self.run(main, [get_libc_name(), 200], threshold=150, - import_site=True) - assert 1 <= log.result <= 1.5 # at most 0.5 seconds of overhead - loops = log.loops_by_id('sleep') - assert len(loops) == 1 # make sure that we actually JITted the loop - - - def test_ctypes_call(self): - from rpython.rlib.test.test_clibffi import get_libm_name - def main(libm_name): - import ctypes - libm = ctypes.CDLL(libm_name) - fabs = libm.fabs - fabs.argtypes = [ctypes.c_double] - fabs.restype = ctypes.c_double - x = -4 - i = 0 - while i < 300: - x = fabs(x) - x = x - 100 - i += 1 - return fabs._ptr.getaddr(), x - - libm_name = get_libm_name(sys.platform) - log = self.run(main, [libm_name], import_site=True) - fabs_addr, res = log.result - assert res == -4.0 - loop, = log.loops_by_filename(self.filepath) - ops = loop.allops() - opnames = log.opnames(ops) - assert opnames.count('new_with_vtable') == 1 # only the virtualref - py.test.xfail() # XXX re-optimize _ffi for the JIT? - assert opnames.count('call_release_gil') == 1 - idx = opnames.index('call_release_gil') - call = ops[idx] - assert (call.args[0] == 'ConstClass(fabs)' or # e.g. OS/X - int(call.args[0]) == fabs_addr) - - - def test__ffi_struct(self): - def main(): - from _ffi import _StructDescr, Field, types - fields = [ - Field('x', types.slong), - ] - descr = _StructDescr('foo', fields) - struct = descr.allocate() - i = 0 - while i < 300: - x = struct.getfield('x') # ID: getfield - x = x+1 - struct.setfield('x', x) # ID: setfield - i += 1 - return struct.getfield('x') - # - log = self.run(main, []) - py.test.xfail() # XXX re-optimize _ffi for the JIT? - loop, = log.loops_by_filename(self.filepath) - assert loop.match_by_id('getfield', """ - guard_not_invalidated(descr=...) - i57 = getfield_raw(i46, descr=) - """) - assert loop.match_by_id('setfield', """ - setfield_raw(i44, i57, descr=) - """) - - - def test__cffi_call(self): - from rpython.rlib.test.test_clibffi import get_libm_name - def main(libm_name): - try: - import _cffi_backend - except ImportError: - sys.stderr.write('SKIP: cannot import _cffi_backend\n') - return 0 - - libm = _cffi_backend.load_library(libm_name) - BDouble = _cffi_backend.new_primitive_type("double") - BPow = _cffi_backend.new_function_type([BDouble, BDouble], BDouble) - pow = libm.load_function(BPow, 'pow') - i = 0 - res = 0 - while i < 300: - tmp = pow(2, 3) # ID: cfficall - res += tmp - i += 1 - BLong = _cffi_backend.new_primitive_type("long") - pow_addr = int(_cffi_backend.cast(BLong, pow)) - return pow_addr, res - # - libm_name = get_libm_name(sys.platform) - log = self.run(main, [libm_name]) - pow_addr, res = log.result - assert res == 8.0 * 300 - loop, = log.loops_by_filename(self.filepath) - if 'ConstClass(pow)' in repr(loop): # e.g. OS/X - pow_addr = 'ConstClass(pow)' - assert loop.match_by_id('cfficall', """ - ... - f1 = call_release_gil(..., descr=) - ... - """) - # so far just check that call_release_gil() is produced. - # later, also check that the arguments to call_release_gil() - # are constants, and that the numerous raw_mallocs are removed diff --git a/pypy/module/pypyjit/test_pypy_c/test_ffi.py b/pypy/module/pypyjit/test_pypy_c/test_ffi.py new file mode 100644 --- /dev/null +++ b/pypy/module/pypyjit/test_pypy_c/test_ffi.py @@ -0,0 +1,279 @@ +import sys, py +from pypy.module.pypyjit.test_pypy_c.test_00_model import BaseTestPyPyC + +class Test__ffi(BaseTestPyPyC): + + def test__ffi_call(self): + from rpython.rlib.test.test_clibffi import get_libm_name + def main(libm_name): + try: + from _ffi import CDLL, types + except ImportError: + sys.stderr.write('SKIP: cannot import _ffi\n') + return 0 + + libm = CDLL(libm_name) + pow = libm.getfunc('pow', [types.double, types.double], + types.double) + i = 0 + res = 0 + while i < 300: + tmp = pow(2, 3) # ID: fficall + res += tmp + i += 1 + return pow.getaddr(), res + # + libm_name = get_libm_name(sys.platform) + log = self.run(main, [libm_name]) + pow_addr, res = log.result + assert res == 8.0 * 300 + py.test.xfail() # XXX re-optimize _ffi for the JIT? + loop, = log.loops_by_filename(self.filepath) + if 'ConstClass(pow)' in repr(loop): # e.g. OS/X + pow_addr = 'ConstClass(pow)' + assert loop.match_by_id('fficall', """ + guard_not_invalidated(descr=...) + i17 = force_token() + setfield_gc(p0, i17, descr=<.* .*PyFrame.vable_token .*>) + f21 = call_release_gil(%s, 2.000000, 3.000000, descr=) + guard_not_forced(descr=...) + guard_no_exception(descr=...) + """ % pow_addr) + + + def test__ffi_call_frame_does_not_escape(self): + from rpython.rlib.test.test_clibffi import get_libm_name + def main(libm_name): + try: + from _ffi import CDLL, types + except ImportError: + sys.stderr.write('SKIP: cannot import _ffi\n') + return 0 + + libm = CDLL(libm_name) + pow = libm.getfunc('pow', [types.double, types.double], + types.double) + + def mypow(a, b): + return pow(a, b) + + i = 0 + res = 0 + while i < 300: + tmp = mypow(2, 3) + res += tmp + i += 1 + return pow.getaddr(), res + # + libm_name = get_libm_name(sys.platform) + log = self.run(main, [libm_name]) + pow_addr, res = log.result + assert res == 8.0 * 300 + loop, = log.loops_by_filename(self.filepath) + opnames = log.opnames(loop.allops()) + # we only force the virtualref, not its content + assert opnames.count('new_with_vtable') == 1 + + def test__ffi_call_releases_gil(self): + from rpython.rlib.clibffi import get_libc_name + def main(libc_name, n): + import time + import os + from threading import Thread + # + if os.name == 'nt': + from _ffi import WinDLL, types + libc = WinDLL('Kernel32.dll') + sleep = libc.getfunc('Sleep', [types.uint], types.uint) + delays = [0]*n + [1000] + else: + from _ffi import CDLL, types + libc = CDLL(libc_name) + sleep = libc.getfunc('sleep', [types.uint], types.uint) + delays = [0]*n + [1] + # + def loop_of_sleeps(i, delays): + for delay in delays: + sleep(delay) # ID: sleep + # + threads = [Thread(target=loop_of_sleeps, args=[i, delays]) for i in range(5)] + start = time.time() + for i, thread in enumerate(threads): + thread.start() + for thread in threads: + thread.join() + end = time.time() + return end - start + log = self.run(main, [get_libc_name(), 200], threshold=150, + import_site=True) + assert 1 <= log.result <= 1.5 # at most 0.5 seconds of overhead + loops = log.loops_by_id('sleep') + assert len(loops) == 1 # make sure that we actually JITted the loop + + def test_ctypes_call(self): + from rpython.rlib.test.test_clibffi import get_libm_name + def main(libm_name): + import ctypes + libm = ctypes.CDLL(libm_name) + fabs = libm.fabs + fabs.argtypes = [ctypes.c_double] + fabs.restype = ctypes.c_double + x = -4 + i = 0 + while i < 300: + x = fabs(x) + x = x - 100 + i += 1 + return fabs._ptr.getaddr(), x + + libm_name = get_libm_name(sys.platform) + log = self.run(main, [libm_name], import_site=True) + fabs_addr, res = log.result + assert res == -4.0 + loop, = log.loops_by_filename(self.filepath) + ops = loop.allops() + opnames = log.opnames(ops) + assert opnames.count('new_with_vtable') == 1 # only the virtualref + py.test.xfail() # XXX re-optimize _ffi for the JIT? + assert opnames.count('call_release_gil') == 1 + idx = opnames.index('call_release_gil') + call = ops[idx] + assert (call.args[0] == 'ConstClass(fabs)' or # e.g. OS/X + int(call.args[0]) == fabs_addr) + + + def test__ffi_struct(self): + def main(): + from _ffi import _StructDescr, Field, types + fields = [ + Field('x', types.slong), + ] + descr = _StructDescr('foo', fields) + struct = descr.allocate() + i = 0 + while i < 300: + x = struct.getfield('x') # ID: getfield + x = x+1 + struct.setfield('x', x) # ID: setfield + i += 1 + return struct.getfield('x') + # + log = self.run(main, []) + py.test.xfail() # XXX re-optimize _ffi for the JIT? + loop, = log.loops_by_filename(self.filepath) + assert loop.match_by_id('getfield', """ + guard_not_invalidated(descr=...) + i57 = getfield_raw(i46, descr=) + """) + assert loop.match_by_id('setfield', """ + setfield_raw(i44, i57, descr=) + """) + + + def test__cffi_call(self): + from rpython.rlib.test.test_clibffi import get_libm_name + def main(libm_name): + try: + import _cffi_backend + except ImportError: + sys.stderr.write('SKIP: cannot import _cffi_backend\n') + return 0 + + libm = _cffi_backend.load_library(libm_name) + BDouble = _cffi_backend.new_primitive_type("double") + BInt = _cffi_backend.new_primitive_type("int") + BPow = _cffi_backend.new_function_type([BDouble, BInt], BDouble) + ldexp = libm.load_function(BPow, 'ldexp') + i = 0 + res = 0 + while i < 300: + tmp = ldexp(1, 3) # ID: cfficall + res += tmp + i += 1 + BLong = _cffi_backend.new_primitive_type("long") + ldexp_addr = int(_cffi_backend.cast(BLong, ldexp)) + return ldexp_addr, res + # + libm_name = get_libm_name(sys.platform) + log = self.run(main, [libm_name]) + ldexp_addr, res = log.result + assert res == 8.0 * 300 + loop, = log.loops_by_filename(self.filepath) + if 'ConstClass(ldexp)' in repr(loop): # e.g. OS/X + ldexp_addr = 'ConstClass(ldexp)' + assert loop.match_by_id('cfficall', """ + ... + f1 = call_release_gil(..., descr=) + ... + """) + ops = loop.ops_by_id('cfficall') + assert 'raw_malloc' not in str(ops) + assert 'raw_free' not in str(ops) + assert 'getarrayitem_raw' not in log.opnames(ops) + assert 'setarrayitem_raw' not in log.opnames(ops) + # so far just check that call_release_gil() is produced. + # later, also check that the arguments to call_release_gil() + # are constants + # are constants, and that the numerous raw_mallocs are removed + + def test_cffi_call_guard_not_forced_fails(self): + # this is the test_pypy_c equivalent of + # rpython/jit/metainterp/test/test_fficall::test_guard_not_forced_fails + # + # it requires cffi to be installed for pypy in order to run + def main(): + import sys From noreply at buildbot.pypy.org Fri Apr 12 10:02:27 2013 From: noreply at buildbot.pypy.org (mattip) Date: Fri, 12 Apr 2013 10:02:27 +0200 (CEST) Subject: [pypy-commit] pypy default: skip test (fow now?) that not only crashes but seems to ruin the rest of the test run on buildbot Message-ID: <20130412080227.249B41C1361@cobra.cs.uni-duesseldorf.de> Author: mattip Branch: Changeset: r63272:1d1c1b2fe42a Date: 2013-04-12 11:01 +0300 http://bitbucket.org/pypy/pypy/changeset/1d1c1b2fe42a/ Log: skip test (fow now?) that not only crashes but seems to ruin the rest of the test run on buildbot diff --git a/rpython/jit/backend/test/test_zll_stress_0.py b/rpython/jit/backend/test/test_zll_stress_0.py --- a/rpython/jit/backend/test/test_zll_stress_0.py +++ b/rpython/jit/backend/test/test_zll_stress_0.py @@ -1,4 +1,7 @@ from rpython.jit.backend.test import zll_stress - +import py def test_stress_0(): + import sys + if sys.platform.startswith('win'): + py.test.skip('crashes test platform, fix crash and reenable test') zll_stress.do_test_stress(0) From noreply at buildbot.pypy.org Fri Apr 12 10:29:56 2013 From: noreply at buildbot.pypy.org (timfel) Date: Fri, 12 Apr 2013 10:29:56 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: Open files in binary mode, to avoid automatic line-conversion on windows Message-ID: <20130412082956.345A01C07C6@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: Changeset: r259:f80ccde97eb0 Date: 2013-04-12 10:26 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/f80ccde97eb0/ Log: Open files in binary mode, to avoid automatic line-conversion on windows diff --git a/spyvm/test/test_miniimage.py b/spyvm/test/test_miniimage.py --- a/spyvm/test/test_miniimage.py +++ b/spyvm/test/test_miniimage.py @@ -28,7 +28,7 @@ return perform(space.wrap_string(name), "asSymbol") def open_miniimage(space): - return squeakimage.reader_for_image(space, squeakimage.Stream(mini_image.open())) + return squeakimage.reader_for_image(space, squeakimage.Stream(mini_image.open(mode="rb"))) def get_reader(): return reader diff --git a/spyvm/tool/analyseimage.py b/spyvm/tool/analyseimage.py --- a/spyvm/tool/analyseimage.py +++ b/spyvm/tool/analyseimage.py @@ -11,10 +11,10 @@ minitest_image = image_dir.join('minitest.image') def get_miniimage(space): - return squeakimage.reader_for_image(space, squeakimage.Stream(mini_image.open())) + return squeakimage.reader_for_image(space, squeakimage.Stream(mini_image.open(mode="rb"))) def get_minitestimage(space): - return squeakimage.reader_for_image(space, squeakimage.Stream(minitest_image.open())) + return squeakimage.reader_for_image(space, squeakimage.Stream(minitest_image.open(mode="rb"))) def create_image(space, image_reader): image_reader.initialize() diff --git a/targetimageloadingsmalltalk.py b/targetimageloadingsmalltalk.py --- a/targetimageloadingsmalltalk.py +++ b/targetimageloadingsmalltalk.py @@ -90,7 +90,7 @@ path = "Squeak.image" try: - f = open_file_as_stream(path, buffering=0) + f = open_file_as_stream(path, mode="rb", buffering=0) except OSError as e: os.write(2, "%s -- %s (LoadError)\n" % (os.strerror(e.errno), path)) return 1 From noreply at buildbot.pypy.org Fri Apr 12 10:29:57 2013 From: noreply at buildbot.pypy.org (timfel) Date: Fri, 12 Apr 2013 10:29:57 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: fix whitespace Message-ID: <20130412082957.4722A1C1007@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: Changeset: r260:0ea590b8c8e0 Date: 2013-04-12 10:27 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/0ea590b8c8e0/ Log: fix whitespace diff --git a/spyvm/squeakimage.py b/spyvm/squeakimage.py --- a/spyvm/squeakimage.py +++ b/spyvm/squeakimage.py @@ -71,7 +71,7 @@ return swapped_chrs2int(data_peek) else: return chrs2int(data_peek) - + def next(self): integer = self.peek() @@ -146,19 +146,19 @@ if sys.maxint == 2 ** 63 - 1: image_versions.update({ -0x5ff6ff0000000000: - # signed version of 0xA009010000000000: + # signed version of 0xA009010000000000: ImageVersion(68000, False, True, False, False), 0x00000000000109A2: ImageVersion(68002, True, True, True, False), -0x5df6ff0000000000: - # signed version of 0xA209010000000000: - ImageVersion(68002, False, True, True, False), + # signed version of 0xA209010000000000: + ImageVersion(68002, False, True, True, False), 0x00000000000109A3: ImageVersion(68003, True, True, True, True ), -0x5cf6ff0000000000: - # signed version of 0xA309010000000000: - ImageVersion(68003, False, True, True, True ), + # signed version of 0xA309010000000000: + ImageVersion(68003, False, True, True, True ), }) - + def version(magic): ver = image_versions.get(magic, None) if ver is None: @@ -198,8 +198,8 @@ pass # raise original error raise - - + + def reader_for_image(space, stream): ver = version_from_stream(stream) if not ver.is_big_endian: @@ -207,7 +207,7 @@ return ImageReader(space, stream, ver) class ImageReader(object): - + def __init__(self, space, stream, version): self.space = space self.stream = stream @@ -594,5 +594,3 @@ def iscompact(self): return 0 < self.classid < 32 - - diff --git a/spyvm/test/test_miniimage.py b/spyvm/test/test_miniimage.py --- a/spyvm/test/test_miniimage.py +++ b/spyvm/test/test_miniimage.py @@ -32,16 +32,16 @@ def get_reader(): return reader - + def get_image(): return image - + def get_float_class(): image = get_image() return image.special(constants.SO_FLOAT_CLASS) # ------ tests ------------------------------------------ - + def test_miniimageexists(): assert mini_image.check(dir=False) @@ -52,26 +52,26 @@ assert reader.oldbaseaddress == -1221464064 assert reader.specialobjectspointer == -1221336216 -def test_read_all_header(): +def test_read_all_header(): reader = open_miniimage(space) reader.read_header() next = reader.stream.peek() - assert next != 0 #expects object header, which must not be 0x00000000 - - + assert next != 0 #expects object header, which must not be 0x00000000 + + def test_all_pointers_are_valid(): reader = get_reader() for each in reader.chunks.itervalues(): - if each.format < 5: + if each.format < 5: for pointer in each.data: if (pointer & 1) != 1: - assert pointer in reader.chunks - - + assert pointer in reader.chunks + + def test_there_are_31_compact_classes(): reader = get_reader() assert len(reader.compactclasses) == 31 - + def test_float_class_size(): w_float_class = get_float_class() assert w_float_class.size() == 9 @@ -81,7 +81,7 @@ 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") - + def test_str_w_object(): w_float_class = get_float_class() w_float_class.as_class_get_shadow(space) @@ -102,38 +102,38 @@ w = image.special(constants.SO_TRUE) w.shadow_of_my_class(space) assert str(w) == "a True" #yes, with article - + def test_scheduler(): image = get_image() w = image.special(constants.SO_SCHEDULERASSOCIATIONPOINTER) w0 = w.fetch(space, 0) - assert str(w0) == "Processor" + assert str(w0) == "Processor" w0 = w.fetch(space, 1) w0.shadow_of_my_class(space) - assert str(w0) == "a ProcessorScheduler" - + assert str(w0) == "a ProcessorScheduler" + def test_special_classes0(): image = get_image() # w = image.special(constants.SO_BITMAP_CLASS) - # assert str(w) == "Bitmap class" + # assert str(w) == "Bitmap class" w = image.special(constants.SO_SMALLINTEGER_CLASS) - assert str(w) == "SmallInteger class" + assert str(w) == "SmallInteger class" w = image.special(constants.SO_STRING_CLASS) - assert str(w) == "String class" + assert str(w) == "String class" w = image.special(constants.SO_ARRAY_CLASS) - assert str(w) == "Array class" + assert str(w) == "Array class" w = image.special(constants.SO_FLOAT_CLASS) - assert str(w) == "Float class" + assert str(w) == "Float class" w = image.special(constants.SO_METHODCONTEXT_CLASS) - assert str(w) == "MethodContext class" + assert str(w) == "MethodContext class" w = image.special(constants.SO_BLOCKCONTEXT_CLASS) - assert str(w) == "BlockContext class" + assert str(w) == "BlockContext class" w = image.special(constants.SO_POINT_CLASS) - assert str(w) == "Point class" + assert str(w) == "Point class" w = image.special(constants.SO_LARGEPOSITIVEINTEGER_CLASS) - assert str(w) == "LargePositiveInteger class" + assert str(w) == "LargePositiveInteger class" w = image.special(constants.SO_MESSAGE_CLASS) - assert str(w) == "Message class" + assert str(w) == "Message class" # to be continued @@ -144,7 +144,7 @@ SO_LOW_SPACE_SEMAPHORE = 17 SO_SEMAPHORE_CLASS = 18 SO_CHARACTER_CLASS = 19""" - + def test_name_of_shadow_of_specials(): image = get_image() w_doesnot = image.special(constants.SO_DOES_NOT_UNDERSTAND) @@ -162,8 +162,8 @@ w = image.special(constants.SO_DOES_NOT_UNDERSTAND) assert str(w) == "doesNotUnderstand:" assert str(w.getclass(space)) == "Symbol class" # for some strange reason not a symbol - - + + """ SO_DOES_NOT_UNDERSTAND = 20 SO_CANNOT_RETURN = 21 @@ -181,7 +181,7 @@ SO_A_POINT = 33 SO_CANNOT_INTERPRET = 34 SO_A_METHODCONTEXT = 35 # deprecated in closure images - SO_BLOCKCLOSURE_CLASS = 36 + SO_BLOCKCLOSURE_CLASS = 36 SO_A_BLOCKCONTEXT = 37 # deprecated in closure images SO_EXTERNAL_OBJECTS_ARRAY = 38 SO_PSEUDOCONTEXT_CLASS = 39 @@ -209,7 +209,7 @@ assert w_true.is_same_object(space.w_true) w_false = image.special(constants.SO_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 spyvm import wrapper @@ -221,32 +221,32 @@ interp.interpret_with_w_frame(w_ctx) def test_compile_method(): - sourcecode = """fib - ^self < 2 - ifTrue: [ 1 ] + sourcecode = """fib + ^self < 2 + ifTrue: [ 1 ] ifFalse: [ (self - 1) fib + (self - 2) fib ]""" 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): +def w(any): # XXX could put this on the space? if any is None: return space.w_nil if isinstance(any, str): # assume never have strings of length 1 - if len(any) == 1: + if len(any) == 1: return space.wrap_chr(any) else: return space.wrap_string(any) if isinstance(any, bool): return space.wrap_bool(any) - if isinstance(any, int): + if isinstance(any, int): return space.wrap_int(any) if isinstance(any, float): return space.wrap_float(any) else: - raise Exception + raise Exception def test_become(): sourcecode = """ @@ -268,7 +268,7 @@ (p1 -> p2 = a) ifFalse: [^10]. (p1 == a key) ifFalse: [^11]. (p2 == a value) ifFalse: [^12]. - + ^42""" perform(w(10).getclass(space), "compile:classified:notifying:", w(sourcecode), w('pypy'), w(None)) w_result = perform(w(10), "testBecome") @@ -404,4 +404,4 @@ interp.step(s_ctx) assert s_ctx.top().value == 2 interp.step(s_ctx) - assert s_ctx.top().value == 3 \ No newline at end of file + assert s_ctx.top().value == 3 diff --git a/spyvm/tool/analyseimage.py b/spyvm/tool/analyseimage.py --- a/spyvm/tool/analyseimage.py +++ b/spyvm/tool/analyseimage.py @@ -1,8 +1,8 @@ import py -from spyvm import squeakimage -from spyvm import constants -from spyvm import model -from spyvm import interpreter +from spyvm import squeakimage +from spyvm import constants +from spyvm import model +from spyvm import interpreter import sys image_dir = py.path.local(__file__).dirpath().dirpath().dirpath('images') @@ -18,7 +18,7 @@ def create_image(space, image_reader): image_reader.initialize() - + image = squeakimage.SqueakImage() image.from_reader(space, image_reader) return image From noreply at buildbot.pypy.org Fri Apr 12 10:29:59 2013 From: noreply at buildbot.pypy.org (timfel) Date: Fri, 12 Apr 2013 10:29:59 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: merge default Message-ID: <20130412082959.099A61C07C6@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: Changeset: r261:6194910649dc Date: 2013-04-12 10:28 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/6194910649dc/ Log: merge default diff --git a/BitBltSim.19.cs b/BitBltSim.19.cs --- a/BitBltSim.19.cs +++ b/BitBltSim.19.cs @@ -94,7 +94,8 @@ simDestRaster _ destForm width - 1 // WordSize + 1. sourceForm notNil ifTrue: [simSourceBits _ sourceForm bits. - simSourceRaster _ sourceForm width - 1 // WordSize + 1]. + simSourceRaster _ sourceForm width - 1 // WordSize + 1] + ifFalse: [simSourceRaster _ 0]. halftoneForm notNil ifTrue: [simHalftoneBits _ halftoneForm bits]. simSkew _ (simSx - simDx) bitAnd: WordSize0. @@ -118,45 +119,37 @@ !BitBlt methodsFor: 'simulation' stamp: 'tfel 3/17/2013 16:17'! copyLoop - | prevWord thisWord skewWord mergeMask - halftoneWord mergeWord | - 1 to: simH do: "here is the vertical loop" + | prevWord thisWord skewWord mergeMask halftoneWord mergeWord noSimSkewMask | + noSimSkewMask _ simSkewMask bitInvert32. + 1 to: simH do: [:i | - (halftoneForm notNil) - ifTrue: - "XXX Accessing simHalftoneBits with wrap-around ... different from BlueBook" - [halftoneWord _ simHalftoneBits at: (1 + (simDy \\ simHalftoneBits size)). + halftoneForm notNil + ifTrue: + [halftoneWord _ simHalftoneBits at: 1 + (simDy \\ simHalftoneBits size). simDy _ simDy + simVDir] ifFalse: [halftoneWord _ AllOnes]. skewWord _ halftoneWord. simPreload - ifTrue: [prevWord _ simSourceBits at: simSourceIndex + 1. - "load the 32bit shifter. TODO: check if this is WordSize dependent" - simSourceIndex _ simSourceIndex + simHDir] + ifTrue: + [prevWord _ simSourceBits at: simSourceIndex + 1. + simSourceIndex _ simSourceIndex + simHDir] ifFalse: [prevWord _ 0]. mergeMask _ simMask1. - 1 to: simNWords do: "here is the inner horizontal loop" - [:word | - sourceForm notNil "if source is used" - ifTrue: - [prevWord _ prevWord bitAnd: simSkewMask. - "XXX: Hack to work around out-of-bounds access" - thisWord := simSourceBits at: (simSourceIndex \\ simSourceBits size) + 1. - "pick up next word" - skewWord _ - prevWord bitOr: (thisWord bitAnd: simSkewMask bitInvert32). - prevWord _ thisWord. - "Change from BB: bitAnd: AllOnes to stay in word bounds" - skewWord _ ((skewWord bitShift: simSkew) bitAnd: AllOnes) bitOr: - (skewWord bitShift: simSkew - WordSize)]. - "WordSize-bit rotate" - mergeWord _ self merge: (skewWord bitAnd: halftoneWord) - with: (simDestBits at: simDestIndex + 1). - simDestBits - at: simDestIndex + 1 - put: ((mergeMask bitAnd: mergeWord) - bitOr: (mergeMask bitInvert32 - bitAnd: (simDestBits at: simDestIndex + 1))). + 1 to: simNWords do: + [:word | + sourceForm notNil + ifTrue: + [thisWord _ (simSourceIndex <= 0 or: [simSourceIndex >= simSourceBits size]) + ifTrue: [simSourceBits at: 1] + ifFalse: [simSourceBits at: simSourceIndex + 1]. + prevWord _ (prevWord bitAnd: simSkewMask) bitShift: simSkew. + skewWord _ prevWord bitOr: ((thisWord bitAnd: noSimSkewMask) bitShift: simSkew - WordSize). + prevWord _ thisWord]. + halftoneForm notNil + ifTrue: [mergeWord _ self merge: (skewWord bitAnd: halftoneWord) + with: (simDestBits at: simDestIndex + 1)]. + simDestBits at: simDestIndex + 1 put: ((mergeMask bitAnd: mergeWord) + bitOr: (mergeMask bitInvert32 bitAnd: (simDestBits at: simDestIndex + 1))). simSourceIndex _ simSourceIndex + simHDir. simDestIndex _ simDestIndex + simHDir. word = (simNWords - 1) @@ -190,7 +183,6 @@ destForm unhibernate. sourceForm - ifNil: [sourceForm := destForm] ifNotNil: [sourceForm unhibernate]. halftoneForm ifNotNil: [ (halftoneForm isKindOf: Form) @@ -220,6 +212,7 @@ simDy _ clipY]. simDy + simH > (clipY + clipHeight) ifTrue: [simH _ simH - ((simDy + simH) - (clipY + clipHeight))]. + sourceForm isNil ifTrue: [^nil]. simSx < 0 ifTrue: [simDx _ simDx - simSx. simW _ simW + simSx. simSx _ 0]. simSx + simW > sourceForm width diff --git a/images/minibluebookdebug.image b/images/minibluebookdebug.image index 55870b1f6092dbfa3dcb4e4d0c46fec62b223bf2..72834c73d01e0d5de097c1c824971bd952d0e6e8 GIT binary patch [cut] diff --git a/spyvm/display.py b/spyvm/display.py --- a/spyvm/display.py +++ b/spyvm/display.py @@ -1,6 +1,7 @@ from rpython.rlib.rarithmetic import r_uint from rpython.rtyper.lltypesystem import lltype, rffi from rpython.rlib.runicode import unicode_encode_utf_8 +from rpython.rlib import jit from rsdl import RSDL, RSDL_helper @@ -58,26 +59,11 @@ self.depth = d self.screen = RSDL.SetVideoMode(w, h, 32, 0) assert self.screen - # self.fillwhite() - def set_pixelbuffer(self, pixelbuffer): - if self.has_surface: - RSDL.FreeSurface(self.surface) - pitch = 4 * self.width - rmask, gmask, bmask, amask = r_uint(0x000000FF), r_uint(0x0000FF00), r_uint(0x00FF0000), r_uint(0xFF000000) - self.surface = RSDL.CreateRGBSurfaceFrom(rffi.cast(rffi.VOIDP, pixelbuffer), - self.width, self.height, 32, pitch, - rmask, gmask, bmask, amask) - self.has_surface = True + def get_pixelbuffer(self): + return self.screen.c_pixels - def fillwhite(self): - fmt = self.screen.c_format - color = RSDL.MapRGB(fmt, 255, 255, 255) - RSDL.FillRect(self.screen, lltype.nullptr(RSDL.Rect), color) - RSDL.Flip(self.screen) - - def blit(self): - RSDL.BlitSurface(self.surface, lltype.nullptr(RSDL.Rect), self.screen, lltype.nullptr(RSDL.Rect)) + def flip(self): RSDL.Flip(self.screen) def get_next_event(self): diff --git a/spyvm/fieldtypes.py b/spyvm/fieldtypes.py new file mode 100644 --- /dev/null +++ b/spyvm/fieldtypes.py @@ -0,0 +1,167 @@ +from spyvm import model, shadow + +from rpython.rlib import objectmodel, jit, signature + +class TypeTag(): + pass + +LPI = TypeTag() +SInt = TypeTag() +flt = TypeTag() +obj = TypeTag() + +maps = {} + +class VarSizedFieldTypes(): + _immutable_fields_ = [] + _attrs_ = [] + _settled_ = True + + @staticmethod + def of_length(s_class, n): + return nilTyper + + def __init__(self): + pass + + def fetch(self, w_obj, n0): + return w_obj._vars[n0] + + def store(self, w_obj, n0, w_val): + w_obj._vars[n0] = w_val + +class FieldTypes(VarSizedFieldTypes): + _immutable_fields_ = ['types'] + _attrs_ = ['types', 'parent', 'siblings', 'diff'] + _settled_ = True + + def __init__(self, types, parent=None, change=(-1, obj)): + self.types = types + self.parent = parent + if parent is not None: + assert change != (-1, obj) + self.diff = change + + self.siblings = {} + + def fetch(self, w_object, n0): + w_result = w_object._vars[n0] + assert w_result is not None + types = self.types + if types[n0] is SInt: + jit.record_known_class(w_result, model.W_SmallInteger) + elif types[n0] is LPI: + jit.record_known_class(w_result, model.W_LargePositiveInteger1Word) + elif types[n0] is flt: + jit.record_known_class(w_result, model.W_Float) + return w_result + + def store(self, w_object, n0, w_value): + types = self.types + changed_type = w_value.fieldtype() + if types[n0] is not changed_type: + w_object.fieldtypes = self.sibling(n0, changed_type) + w_object._vars[n0] = w_value + + + def sibling(self, n0, changed_type): + assert self.types[n0] is not changed_type + change = (n0, changed_type) + parent = self.parent + siblings = self.siblings + if change in siblings: + return siblings[change] + elif parent is None: + return self.descent([change]) + else: + new_fieldtype = parent.ascent([change, self.diff]) + if not objectmodel.we_are_translated(): + assert new_fieldtype.types == self.types[0:n0] + [changed_type] + self.types[n0+1:] + siblings[change] = new_fieldtype + return new_fieldtype + + def ascent(self, changes): + parent = self.parent + if parent is None: + sort(changes) + return self.descent(changes) + else: + change = self.diff + if changes[0][0] != change[0]: + changes.append(change) + return parent.ascent(changes) + + def descent(self, changes): + if changes == []: + return self + + change = changes[0] + siblings = self.siblings + if change in siblings: + return siblings[change].descent(changes[1:]) + else: + new_types = list(self.types) + new_types[change[0]] = change[1] + new_fieldtype = FieldTypes(new_types, self, change) + siblings[change] = new_fieldtype + return new_fieldtype.descent(changes[1:]) + + + @staticmethod + def of_length(n): + if n not in maps: + maps[n] = FieldTypes([obj] * n) + return maps[n] + + +nilTyper = VarSizedFieldTypes() +def fieldtypes_of_length(s_class, size): + if s_class is None or s_class.isvariable(): + return nilTyper + else: + return FieldTypes.of_length(size) + +def fieldtypes_of(w_obj): + try: + if w_obj.s_class.isvariable(): + return nilTyper + else: + vars = w_obj._vars + size = len(vars) + typer = FieldTypes.of_length(size) + for i, w_val in enumerate(vars): + changed_type = w_val.fieldtype() + if changed_type is not obj: + typer = typer.sibling(i, changed_type) + return typer + except AttributeError: + return nilTyper + +def sort(an_array): + end = len(an_array) - 1 + sort_quick_inplace(an_array, 0, end) + + +def sort_quick_inplace(an_array, start, end): + assert start >= 0 and end < len(an_array) + + def partition(an_array, start, end): + key = an_array[start][0] + i = start - 1 + j = end + 1 + while True: + i += 1 + j -= 1 + while not an_array[j][0] <= key: + j -= 1 + while not an_array[i][0] >= key: + i += 1 + if j <= i: + return j + else: + an_array[i], an_array[j] = an_array[j], an_array[i] + + if start < end: + mid = partition(an_array, start, end) + sort_quick_inplace(an_array, start, mid) + sort_quick_inplace(an_array, mid + 1, end) \ No newline at end of file diff --git a/spyvm/model.py b/spyvm/model.py --- a/spyvm/model.py +++ b/spyvm/model.py @@ -17,7 +17,7 @@ import sys from spyvm import constants, error -from rpython.rlib import rrandom, objectmodel, jit +from rpython.rlib import rrandom, objectmodel, jit, signature from rpython.rlib.rarithmetic import intmask, r_uint from rpython.tool.pairtype import extendabletype from rpython.rlib.objectmodel import instantiate, compute_hash @@ -127,6 +127,13 @@ def rshift(self, space, shift): raise error.PrimitiveFailedError() + def unwrap_uint(self, space): + raise error.UnwrappingError("Got unexpected class in unwrap_uint") + + def fieldtype(self): + from spyvm.fieldtypes import obj + return obj + class W_SmallInteger(W_Object): """Boxed integer value""" # TODO can we tell pypy that its never larger then 31-bit? @@ -165,6 +172,14 @@ def rshift(self, space, shift): return space.wrap_int(self.value >> shift) + def unwrap_uint(self, space): + from rpython.rlib.rarithmetic import r_uint + val = self.value + if val < 0: + raise error.UnwrappingError("got negative integer") + return r_uint(val) + + @jit.elidable def as_repr_string(self): return "W_SmallInteger(%d)" % self.value @@ -189,6 +204,10 @@ def clone(self, space): return self + def fieldtype(self): + from spyvm.fieldtypes import SInt + return SInt + class W_AbstractObjectWithIdentityHash(W_Object): """Object with explicit hash (ie all except small ints and floats).""" @@ -262,6 +281,10 @@ # and only in this case we do need such a mask return space.wrap_int((self.value >> shift) & mask) + def unwrap_uint(self, space): + from rpython.rlib.rarithmetic import r_uint + return r_uint(self.value) + def clone(self, space): return W_LargePositiveInteger1Word(self.value) @@ -288,6 +311,10 @@ def invariant(self): return isinstance(self.value, int) + def fieldtype(self): + from spyvm.fieldtypes import LPI + return LPI + class W_Float(W_AbstractObjectWithIdentityHash): """Boxed float value.""" _attrs_ = ['value'] @@ -373,7 +400,11 @@ def size(self): return 2 + def fieldtype(self): + from spyvm.fieldtypes import flt + return flt + at signature.finishsigs class W_AbstractObjectWithClassReference(W_AbstractObjectWithIdentityHash): """Objects with arbitrary class (ie not CompiledMethod, SmallInteger or Float).""" @@ -422,30 +453,40 @@ def has_class(self): return self.s_class is not None + # we would like the following, but that leads to a recursive import + #@signature(signature.types.self(), signature.type.any(), + # returns=signature.types.instance(ClassShadow)) def shadow_of_my_class(self, space): - assert self.s_class is not None - return self.s_class + s_class = self.s_class + assert s_class is not None + return s_class class W_PointersObject(W_AbstractObjectWithClassReference): """Common object.""" - _attrs_ = ['_shadow', '_vars'] + _attrs_ = ['_shadow', '_vars', 'fieldtypes'] _shadow = None # Default value @jit.unroll_safe def __init__(self, space, w_class, size): + from spyvm.fieldtypes import fieldtypes_of_length """Create new object with size = fixed + variable size.""" W_AbstractObjectWithClassReference.__init__(self, space, w_class) + vars = self._vars = [None] * size + self.fieldtypes = fieldtypes_of_length(self.s_class, size) + for i in range(size): # do it by hand for the JIT's sake vars[i] = w_nil self._shadow = None # Default value def fillin(self, space, g_self): + from spyvm.fieldtypes import fieldtypes_of self._vars = g_self.get_pointers() self.s_class = g_self.get_class().as_class_get_penumbra(space) self.hash = g_self.get_hash() self.space = space + self.fieldtypes = fieldtypes_of(self) def at0(self, space, index0): # To test, at0 = in varsize part @@ -461,7 +502,9 @@ return self._fetch(n0) def _fetch(self, n0): - return self._vars[n0] + # return self._vars[n0] + fieldtypes = jit.promote(self.fieldtypes) + return fieldtypes.fetch(self, n0) def store(self, space, n0, w_value): if self.has_shadow(): @@ -469,8 +512,9 @@ return self._store(n0, w_value) def _store(self, n0, w_value): - self._vars[n0] = w_value - + # self._vars[n0] = w_value + fieldtypes = jit.promote(self.fieldtypes) + return fieldtypes.store(self, n0, w_value) def varsize(self, space): return self.size() - self.instsize(space) @@ -525,10 +569,13 @@ # Should only be used during squeak-image loading. def as_class_get_penumbra(self, space): from spyvm.shadow import ClassShadow - assert self._shadow is None or isinstance(self._shadow, ClassShadow) - if self._shadow is None: - self.store_shadow(ClassShadow(space, self)) - return self._shadow + s_class = self._shadow + if s_class is None: + s_class = ClassShadow(space, self) + self.store_shadow(s_class) + else: + assert isinstance(s_class, ClassShadow) + return s_class def as_blockcontext_get_shadow(self, space): from spyvm.shadow import BlockContextShadow @@ -575,7 +622,8 @@ return True def clone(self, space): - w_result = W_PointersObject(self.space, self.getclass(space), len(self._vars)) + w_result = W_PointersObject(self.space, self.getclass(space), + len(self._vars)) w_result._vars = [self.fetch(space, i) for i in range(len(self._vars))] return w_result @@ -585,6 +633,10 @@ className='W_PointersObject', additionalInformation='len=%d' % self.size()) + def fieldtype(self): + from spyvm.fieldtypes import obj + return obj + class W_BytesObject(W_AbstractObjectWithClassReference): _attrs_ = ['bytes'] @@ -644,6 +696,16 @@ w_result.bytes = list(self.bytes) return w_result + def unwrap_uint(self, space): + # TODO: Completely untested! This failed translation bigtime... + # XXX Probably we want to allow all subclasses + if not self.getclass(space).is_same_object(space.w_LargePositiveInteger): + raise error.UnwrappingError("Failed to convert bytes to word") + word = 0 + for i in range(self.size()): + word += r_uint(ord(self.getchar(i))) << 8*i + return word + class W_WordsObject(W_AbstractObjectWithClassReference): _attrs_ = ['words'] @@ -698,14 +760,11 @@ def __init__(self, space, w_class, size, depth, display): W_AbstractObjectWithClassReference.__init__(self, space, w_class) - bytelen = NATIVE_DEPTH / depth * size - self.pixelbuffer = lltype.malloc(rffi.ULONGP.TO, bytelen, flavor='raw') + self._real_depth_buffer = [0] * size + self.pixelbuffer = display.get_pixelbuffer() self._realsize = size self.display = display - def __del__(self): - lltype.free(self.pixelbuffer, flavor='raw') - def at0(self, space, index0): val = self.getword(index0) return space.wrap_uint(val) @@ -715,7 +774,7 @@ self.setword(index0, word) def flush_to_screen(self): - self.display.blit() + self.display.flip() def size(self): return self._realsize @@ -739,28 +798,23 @@ class W_DisplayBitmap1Bit(W_DisplayBitmap): - @jit.unroll_safe def getword(self, n): - word = r_uint(0) - pos = n * NATIVE_DEPTH - for i in xrange(32): - word <<= 1 - pixel = self.pixelbuffer[pos] - word |= r_uint(pixel & 0x1) - pos += 1 - return ~word + return self._real_depth_buffer[n] @jit.unroll_safe def setword(self, n, word): - pos = n * NATIVE_DEPTH + self._real_depth_buffer[n] = word + pos = n * NATIVE_DEPTH * 4 mask = r_uint(1) mask <<= 31 for i in xrange(32): bit = mask & word - pixel = r_uint((0x00ffffff * (bit == 0)) | r_uint(0xff000000)) - self.pixelbuffer[pos] = pixel + self.pixelbuffer[pos] = rffi.r_uchar(0xff * (bit == 0)) + self.pixelbuffer[pos + 1] = rffi.r_uchar(0xff * (bit == 0)) + self.pixelbuffer[pos + 2] = rffi.r_uchar(0xff * (bit == 0)) + self.pixelbuffer[pos + 3] = rffi.r_uchar(0xff) mask >>= 1 - pos += 1 + pos += 4 # XXX Shouldn't compiledmethod have class reference for subclassed compiled diff --git a/spyvm/objspace.py b/spyvm/objspace.py --- a/spyvm/objspace.py +++ b/spyvm/objspace.py @@ -1,5 +1,6 @@ from spyvm import constants, model, shadow, wrapper from spyvm.error import UnwrappingError, WrappingError, PrimitiveFailedError +from rpython.rlib import jit from rpython.rlib.objectmodel import instantiate, specialize from rpython.rlib.rarithmetic import intmask, r_uint, int_between @@ -192,11 +193,14 @@ if bytes_len <= 4: return self.wrap_positive_32bit_int(intmask(val)) else: - w_result = model.W_BytesObject(self, - self.classtable['w_LargePositiveInteger'], bytes_len) - for i in range(bytes_len): - w_result.setchar(i, chr(intmask((val >> i*8) & 255))) - return w_result + return self._wrap_uint_loop(val, bytes_len) + + def _wrap_uint_loop(self, val, bytes_len): + w_result = model.W_BytesObject(self, + self.classtable['w_LargePositiveInteger'], bytes_len) + for i in range(bytes_len): + w_result.setchar(i, chr(intmask((val >> i*8) & 255))) + return w_result def wrap_positive_32bit_int(self, val): # This will always return a positive value. @@ -247,24 +251,7 @@ raise UnwrappingError("expected a W_SmallInteger or W_LargePositiveInteger1Word, got %s" % (w_value,)) def unwrap_uint(self, w_value): - if isinstance(w_value, model.W_SmallInteger): - val = w_value.value - if val < 0: - raise UnwrappingError("got negative integer") - return r_uint(w_value.value) - elif isinstance(w_value, model.W_LargePositiveInteger1Word): - return r_uint(w_value.value) - elif isinstance(w_value, model.W_BytesObject): - # TODO: Completely untested! This failed translation bigtime... - # XXX Probably we want to allow all subclasses - if not w_value.getclass(self).is_same_object(self.w_LargePositiveInteger): - raise UnwrappingError("Failed to convert bytes to word") - word = 0 - for i in range(w_value.size()): - word += r_uint(ord(w_value.getchar(i))) << 8*i - return word - else: - raise UnwrappingError("Got unexpected class in unwrap_uint") + return w_value.unwrap_uint(self) def unwrap_positive_32bit_int(self, w_value): if isinstance(w_value, model.W_SmallInteger): @@ -297,6 +284,8 @@ if not isinstance(w_v, model.W_PointersObject): raise UnwrappingError() return w_v + + @jit.look_inside_iff(lambda self, w_array: jit.isconstant(w_array.size())) def unwrap_array(self, w_array): # Check that our argument has pointers format and the class: if not w_array.getclass(self).is_same_object(self.w_Array): diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -321,6 +321,14 @@ FAIL = 19 + at expose_primitive(FAIL) +def func(interp, s_frame, argcount): + from spyvm.interpreter import ReturnFromTopLevel + if s_frame.w_method()._likely_methodname == 'doesNotUnderstand:': + print 'Probably Debugger called...' + raise ReturnFromTopLevel(interp.space.wrap_string("debugger called")) + raise PrimitiveFailedError() + # ___________________________________________________________________________ # Subscript and Stream Primitives @@ -592,15 +600,18 @@ w_prev_bitmap = w_prev_display.fetch(interp.space, 0) if isinstance(w_prev_bitmap, model.W_DisplayBitmap): sdldisplay = w_prev_bitmap.display + sdldisplay.set_video_mode(width, height, depth) if isinstance(w_bitmap, model.W_DisplayBitmap): assert (sdldisplay is None) or (sdldisplay is w_bitmap.display) sdldisplay = w_bitmap.display + sdldisplay.set_video_mode(width, height, depth) w_display_bitmap = w_bitmap else: assert isinstance(w_bitmap, model.W_WordsObject) if not sdldisplay: sdldisplay = display.SDLDisplay(interp.image_name) + sdldisplay.set_video_mode(width, height, depth) w_display_bitmap = model.W_DisplayBitmap.create( interp.space, w_bitmap.getclass(interp.space), @@ -612,9 +623,7 @@ w_display_bitmap.setword(idx, word) w_rcvr.store(interp.space, 0, w_display_bitmap) - sdldisplay.set_video_mode(width, height, depth) - sdldisplay.set_pixelbuffer(w_display_bitmap.pixelbuffer) - sdldisplay.blit() + w_display_bitmap.flush_to_screen() interp.space.objtable['w_display'] = w_rcvr return w_rcvr diff --git a/spyvm/shadow.py b/spyvm/shadow.py --- a/spyvm/shadow.py +++ b/spyvm/shadow.py @@ -201,7 +201,8 @@ def new(self, extrasize=0): w_cls = self.w_self() if self.instance_kind == POINTERS: - w_new = model.W_PointersObject(self.space, w_cls, self.instsize()+extrasize) + size = self.instsize() + extrasize + w_new = model.W_PointersObject(self.space, w_cls, size) elif self.instance_kind == WORDS: w_new = model.W_WordsObject(self.space, w_cls, extrasize) elif self.instance_kind == BYTES: diff --git a/spyvm/test/test_fieldtypes.py b/spyvm/test/test_fieldtypes.py new file mode 100644 --- /dev/null +++ b/spyvm/test/test_fieldtypes.py @@ -0,0 +1,33 @@ +import py +from spyvm import model, fieldtypes +from spyvm import objspace + +from spyvm.fieldtypes import obj, SInt + +def test_simple_changes(): + a = fieldtypes.FieldTypes.of_length(3) + assert a.types == [obj, obj, obj] + b = a.sibling(1, SInt) + assert b.types == [obj, SInt, obj] + c = a.sibling(1, SInt) + assert b is c + +def test_two_level_changes_identity(): + a = fieldtypes.FieldTypes.of_length(3) + b = a.sibling(1, SInt) + c = a.sibling(0, SInt) + d = b.sibling(0, SInt) + assert d.types == [SInt, SInt, obj] + e = c.sibling(1, SInt) + assert d is e + +def test_numberOfElements(): + a = fieldtypes.FieldTypes.of_length(3) + a.sibling(0, SInt).sibling(1, SInt).sibling(2, SInt) + a.sibling(1, SInt).sibling(2, SInt) + a.sibling(2, SInt).sibling(0, SInt) + assert a.sibling(2, SInt).sibling(0, SInt).parent is a.sibling(0, SInt) + assert len(a.siblings) == 3 + assert len(a.sibling(0, SInt).siblings) == 2 + assert len(a.sibling(1, SInt).siblings) == 2 + assert len(a.sibling(2, SInt).siblings) == 1 # link to [o, i, i] not created \ No newline at end of file diff --git a/spyvm/test/test_interpreter.py b/spyvm/test/test_interpreter.py --- a/spyvm/test/test_interpreter.py +++ b/spyvm/test/test_interpreter.py @@ -2,7 +2,10 @@ from spyvm import model, interpreter, primitives, shadow from spyvm import objspace, wrapper, constants -mockclass = objspace.bootstrap_class +def mockclass(space, instsize, w_superclass=None, w_metaclass=None, + name='?', format=shadow.POINTERS, varsized=True): + return objspace.bootstrap_class(space, instsize, w_superclass, w_metaclass, + name, format, varsized) space = objspace.ObjSpace() interp = interpreter.Interpreter(space) diff --git a/spyvm/test/test_shadow.py b/spyvm/test/test_shadow.py --- a/spyvm/test/test_shadow.py +++ b/spyvm/test/test_shadow.py @@ -92,9 +92,9 @@ w_object.store(space, constants.MTHDCTX_METHOD, method) # XXX w_object.store(space, constants.MTHDCTX_CLOSURE_OR_NIL, space.w_nil) - w_object.store(space, constants.MTHDCTX_RECEIVER, 'receiver') + w_object.store(space, constants.MTHDCTX_RECEIVER, space.wrap_string('receiver')) - w_object.store(space, constants.MTHDCTX_TEMP_FRAME_START, 'el') + w_object.store(space, constants.MTHDCTX_TEMP_FRAME_START, space.wrap_string('el')) return w_object def blockcontext(w_sender=space.w_nil, pc=1, stackpointer=1, stacksize=5, @@ -106,7 +106,7 @@ 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') + w_object.store(space, constants.BLKCTX_STACK_START, space.wrap_string('el')) return w_object def test_context(): @@ -121,24 +121,24 @@ assert s_object2.w_self() == w_object2 assert s_object.s_sender() == None assert s_object2.s_sender() == s_object - assert s_object.w_receiver() == 'receiver' + assert s_object.w_receiver().as_string() == 'receiver' s_object2.settemp(0, 'a') s_object2.settemp(1, 'b') assert s_object2.gettemp(1) == 'b' assert s_object2.gettemp(0) == 'a' assert s_object.w_method() == w_m idx = s_object.stackstart() - 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' + w_object.store(space, idx, space.wrap_string('f')) + w_object.store(space, idx + 1, space.wrap_string('g')) + w_object.store(space, idx + 2, space.wrap_string('h')) + assert map(lambda x: x.as_string(), s_object.stack()) == ['f', 'g', 'h' ] + assert s_object.top().as_string() == 'h' s_object.push('i') assert s_object.top() == 'i' - assert s_object.peek(1) == 'h' + assert s_object.peek(1).as_string() == 'h' assert s_object.pop() == 'i' - assert s_object.pop_and_return_n(2) == ['g', 'h'] - assert s_object.pop() == 'f' + assert map(lambda x: x.as_string(), s_object.pop_and_return_n(2)) == ['g', 'h'] + assert s_object.pop().as_string() == 'f' assert s_object.external_stackpointer() == s_object.stackstart() def test_methodcontext(): From noreply at buildbot.pypy.org Fri Apr 12 12:42:02 2013 From: noreply at buildbot.pypy.org (mattip) Date: Fri, 12 Apr 2013 12:42:02 +0200 (CEST) Subject: [pypy-commit] pypy default: make test that fails on windows more robust Message-ID: <20130412104202.BBA731C026A@cobra.cs.uni-duesseldorf.de> Author: mattip Branch: Changeset: r63273:edbc461c0354 Date: 2013-04-12 13:19 +0300 http://bitbucket.org/pypy/pypy/changeset/edbc461c0354/ Log: make test that fails on windows more robust diff --git a/rpython/rlib/test/test_rsocket.py b/rpython/rlib/test/test_rsocket.py --- a/rpython/rlib/test/test_rsocket.py +++ b/rpython/rlib/test/test_rsocket.py @@ -165,8 +165,12 @@ s2 = RSocket(AF_INET, SOCK_STREAM) s2.settimeout(10.0) # test one side with timeouts so select is used, shouldn't affect test def connecting(): - s2.connect(addr) - lock.release() + try: + s2.connect(addr) + lock.release() + except: + import traceback + traceback.print_exc() lock = thread.allocate_lock() lock.acquire() thread.start_new_thread(connecting, ()) @@ -174,6 +178,7 @@ fd1, addr2 = sock.accept() s1 = RSocket(fd=fd1) print 'connection accepted' + assert not lock.locked() lock.acquire() print 'connecting side knows that the connection was accepted too' assert addr.eq(s2.getpeername()) From noreply at buildbot.pypy.org Fri Apr 12 12:42:04 2013 From: noreply at buildbot.pypy.org (mattip) Date: Fri, 12 Apr 2013 12:42:04 +0200 (CEST) Subject: [pypy-commit] pypy default: do not open dialog box on segfault in windows Message-ID: <20130412104204.0586C1C026A@cobra.cs.uni-duesseldorf.de> Author: mattip Branch: Changeset: r63274:a3a2da007295 Date: 2013-04-12 13:41 +0300 http://bitbucket.org/pypy/pypy/changeset/a3a2da007295/ Log: do not open dialog box on segfault in windows diff --git a/pypy/module/cpyext/test/test_cpyext.py b/pypy/module/cpyext/test/test_cpyext.py --- a/pypy/module/cpyext/test/test_cpyext.py +++ b/pypy/module/cpyext/test/test_cpyext.py @@ -1,6 +1,6 @@ import sys import weakref -import os.path +import os import py @@ -19,6 +19,14 @@ from rpython.tool.identity_dict import identity_dict from rpython.tool import leakfinder +if os.name == 'nt': + # Do not open dreaded dialog box on segfault + import ctypes + SEM_NOGPFAULTERRORBOX = 0x0002 # From MSDN + old_err_mode = ctypes.windll.kernel32.GetErrorMode() + new_err_mode = old_err_mode | SEM_NOGPFAULTERRORBOX + ctypes.windll.kernel32.SetErrorMode(new_err_mode) + @api.cpython_api([], api.PyObject) def PyPy_Crash1(space): 1/0 From noreply at buildbot.pypy.org Fri Apr 12 13:10:40 2013 From: noreply at buildbot.pypy.org (fijal) Date: Fri, 12 Apr 2013 13:10:40 +0200 (CEST) Subject: [pypy-commit] pypy default: fix links Message-ID: <20130412111040.BEA7E1C026A@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r63275:ca3decc664c8 Date: 2013-04-12 13:10 +0200 http://bitbucket.org/pypy/pypy/changeset/ca3decc664c8/ Log: fix links diff --git a/pypy/doc/index.rst b/pypy/doc/index.rst --- a/pypy/doc/index.rst +++ b/pypy/doc/index.rst @@ -31,6 +31,7 @@ .. _`Starting with RPython`: getting-started-dev.html .. _`how to contribute`: how-to-contribute.html .. _`PyPy website`: http://pypy.org +.. _`LICENSE`: https://bitbucket.org/pypy/pypy/src/default/LICENSE Index of various topics: ======================== @@ -66,11 +67,9 @@ * `Sandboxing Python code`_ * `Garbage collection environment variables`_ -Status_ of the project. - .. _`Differences between PyPy and CPython`: cpython_differences.html .. _`What PyPy can do for your objects`: objspace-proxies.html -.. _`Continulets and greenlets_`: stackless.html +.. _`Continulets and greenlets`: stackless.html .. _`JIT Generation in PyPy`: jit/index.html .. _`JIT hooks`: jit-hooks.html .. _`Sandboxing Python code`: sandbox.html From noreply at buildbot.pypy.org Fri Apr 12 14:10:03 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 12 Apr 2013 14:10:03 +0200 (CEST) Subject: [pypy-commit] pypy stm-gc-2: tweaks Message-ID: <20130412121003.EA8441C070B@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: stm-gc-2 Changeset: r63276:ecd0227c4dfb Date: 2013-04-10 20:32 +0200 http://bitbucket.org/pypy/pypy/changeset/ecd0227c4dfb/ Log: tweaks diff --git a/rpython/memory/gc/stmshared.py b/rpython/memory/gc/stmshared.py --- a/rpython/memory/gc/stmshared.py +++ b/rpython/memory/gc/stmshared.py @@ -98,41 +98,36 @@ self.pages_for_size = lltype.malloc( rffi.CArray(PAGE_PTR), length, flavor='raw', zero=True) # - # This array contains 'length' chained lists of free object locations. - self.free_objects_for_size = lltype.malloc( + # This array contains 'length' chained lists of free locations. + self.free_loc_for_size = lltype.malloc( rffi.CArray(llmemory.Address), length, flavor='raw', zero=True) # if not we_are_translated(): self._seen_pages = set() - def free(self): - lltype.free(self.free_objects_for_size, flavor='raw') - lltype.free(self.pages_for_size, flavor='raw') - self.delete() - def _malloc_size_class(self, size_class): """Malloc one object of the given size_class (== number of WORDs).""" ll_assert(size_class > 0, "malloc_size_class: null or neg size_class") ll_assert(size_class <= self.sharedarea.small_request_threshold, "malloc_size_class: too big") # - # The result is simply 'free_objects_for_size[size_class]' - result = self.free_objects_for_size[size_class] + # The result is simply 'free_loc_for_size[size_class]' + result = self.free_loc_for_size[size_class] if not result: result = self._allocate_new_page(size_class) - self.free_objects_for_size[size_class] = result.address[0] + self.free_loc_for_size[size_class] = result.address[0] llarena.arena_reset(result, llmemory.sizeof(llmemory.Address), 0) return result _malloc_size_class._always_inline_ = True - def _free_size_class(self, obj, size_class): - """Free a single object 'obj', which is of the given size_class.""" - # just link 'obj' to the start of 'free_objects_for_size[size_class]' - obj = llarena.getfakearenaaddress(obj) - llarena.arena_reset(obj, size_class << WORD_POWER_2, 0) - llarena.arena_reserve(obj, llmemory.sizeof(llmemory.Address)) - obj.address[0] = self.free_objects_for_size[size_class] - self.free_objects_for_size[size_class] = obj + def _free_size_class(self, adr, size_class): + """Free a single location 'adr', which is of the given size_class.""" + # just link 'adr' to the start of 'free_loc_for_size[size_class]' + adr = llarena.getfakearenaaddress(adr) + llarena.arena_reset(adr, size_class << WORD_POWER_2, 0) + llarena.arena_reserve(adr, llmemory.sizeof(llmemory.Address)) + adr.address[0] = self.free_loc_for_size[size_class] + self.free_loc_for_size[size_class] = adr _free_size_class._always_inline_ = True def _allocate_new_page(self, size_class): @@ -141,7 +136,7 @@ result = llarena.arena_malloc(self.sharedarea.page_size, 0) if not result: fatalerror("FIXME: Out of memory! (should raise MemoryError)") - return PAGE_NULL + return NULL if not we_are_translated(): self._seen_pages.add(result) llarena.arena_reserve(result, llmemory.sizeof(PAGE_HEADER)) @@ -153,9 +148,9 @@ # # Initialize the chained list in the page head = result + llmemory.sizeof(PAGE_HEADER) - ll_assert(not self.free_objects_for_size[size_class], - "free_objects_for_size is supposed to contain NULL here") - self.free_objects_for_size[size_class] = head + ll_assert(not self.free_loc_for_size[size_class], + "free_loc_for_size is supposed to contain NULL here") + self.free_loc_for_size[size_class] = head # i = self.sharedarea.nblocks_for_size[size_class] nsize = size_class << WORD_POWER_2 @@ -180,11 +175,11 @@ if nsize <= self.sharedarea.small_request_threshold: size_class = (nsize + WORD_POWER_2 - 1) >> WORD_POWER_2 result = self._malloc_size_class(size_class) - llarena.arena_reserve(result, _dummy_size(totalsize)) - return result else: - XXX - #llarena.arena_malloc(llmemory.raw_malloc_usage(totalsize), 0) + result = llarena.arena_malloc( + llmemory.raw_malloc_usage(totalsize), 0) + llarena.arena_reserve(result, _dummy_size(totalsize)) + return result + self.gc.gcheaderbuilder.size_gc_header def add_regular(self, obj): """After malloc_object(), register the object in the internal chained @@ -193,12 +188,12 @@ self.chained_list = obj def free_object(self, obj): + adr1 = obj - self.gc.gcheaderbuilder.size_gc_header osize = self.gc.get_size_incl_hash(obj) if osize <= self.sharedarea.small_request_threshold: size_class = (osize + WORD_POWER_2 - 1) >> WORD_POWER_2 - self._free_size_class(obj, size_class) + self._free_size_class(adr1, size_class) else: - adr1 = obj - self.gc.gcheaderbuilder.size_gc_header llarena.arena_free(llarena.getfakearenaaddress(adr1)) def free_and_clear(self): @@ -214,6 +209,8 @@ self.free_object(lst.pop()) def delete(self): + lltype.free(self.free_loc_for_size, flavor='raw') + lltype.free(self.pages_for_size, flavor='raw') free_non_gc_object(self) diff --git a/rpython/memory/gc/stmtls.py b/rpython/memory/gc/stmtls.py --- a/rpython/memory/gc/stmtls.py +++ b/rpython/memory/gc/stmtls.py @@ -77,7 +77,7 @@ self._cleanup_state() self._unregister_with_C_code() self.local_weakrefs.delete() - self.sharedarea_tls.free() + self.sharedarea_tls.delete() self._free_nursery(self.nursery_start) free_non_gc_object(self) diff --git a/rpython/memory/gc/test/test_stmshared.py b/rpython/memory/gc/test/test_stmshared.py --- a/rpython/memory/gc/test/test_stmshared.py +++ b/rpython/memory/gc/test/test_stmshared.py @@ -3,8 +3,21 @@ from rpython.memory.gc.stmshared import StmGCThreadLocalAllocator +class FakeGC: + class gcheaderbuilder: + size_gc_header = 3 + def __init__(self): + self._object_sizes = {} + def set_size(self, obj, size): + assert obj not in self._object_sizes + self._object_sizes[obj] = size + def get_size_incl_hash(self, obj): + return self._object_sizes[obj] + + def test_simple(): - shared = StmGCSharedArea("gc", 10*WORD, 2*WORD) + gc = FakeGC() + shared = StmGCSharedArea(gc, 10*WORD, 2*WORD) shared.setup() thl1 = StmGCThreadLocalAllocator(shared) thl1.malloc_object(2*WORD-1) @@ -19,16 +32,7 @@ assert len(thl1._seen_pages) == 3 thl1.malloc_object(2*WORD) assert len(thl1._seen_pages) == 3 - thl1.free() - -class FakeGC: - def __init__(self): - self._object_sizes = {} - def set_size(self, obj, size): - assert obj not in self._object_sizes - self._object_sizes[obj] = size - def get_size_incl_hash(self, obj): - return self._object_sizes[obj] + thl1.delete() def test_free(): gc = FakeGC() @@ -40,4 +44,14 @@ thl1.free_object(obj) obj2 = thl1.malloc_object(2*WORD) assert obj2 == obj # reusing the same location - thl1.free() + thl1.delete() + +def test_big_object(): + gc = FakeGC() + shared = StmGCSharedArea(gc, 10*WORD, 2*WORD) + shared.setup() + thl1 = StmGCThreadLocalAllocator(shared) + obj = thl1.malloc_object(3*WORD) + gc.set_size(obj, 3*WORD) + thl1.free_object(obj) + thl1.delete() From noreply at buildbot.pypy.org Fri Apr 12 14:10:05 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 12 Apr 2013 14:10:05 +0200 (CEST) Subject: [pypy-commit] pypy default: annlowlevel.backend_optimize() should also enable inlining of Message-ID: <20130412121005.594321C070B@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63277:e56b02cf916b Date: 2013-04-12 13:50 +0200 http://bitbucket.org/pypy/pypy/changeset/e56b02cf916b/ Log: annlowlevel.backend_optimize() should also enable inlining of pre- existing graphs into the new graphs. diff --git a/rpython/rtyper/annlowlevel.py b/rpython/rtyper/annlowlevel.py --- a/rpython/rtyper/annlowlevel.py +++ b/rpython/rtyper/annlowlevel.py @@ -301,7 +301,8 @@ from rpython.translator.backendopt.all import backend_optimizations translator = self.rtyper.annotator.translator newgraphs = self.newgraphs.keys() - backend_optimizations(translator, newgraphs, secondary=True, **flags) + backend_optimizations(translator, newgraphs, secondary=True, + inline_graph_from_anywhere=True, **flags) self.newgraphs.clear() # ____________________________________________________________ diff --git a/rpython/translator/backendopt/all.py b/rpython/translator/backendopt/all.py --- a/rpython/translator/backendopt/all.py +++ b/rpython/translator/backendopt/all.py @@ -31,7 +31,8 @@ return func -def backend_optimizations(translator, graphs=None, secondary=False, **kwds): +def backend_optimizations(translator, graphs=None, secondary=False, + inline_graph_from_anywhere=False, **kwds): # sensible keywords are # raisingop2direct_call, inline_threshold, mallocs # merge_if_blocks, constfold, heap2stack @@ -86,7 +87,8 @@ threshold = 0 inline_malloc_removal_phase(config, translator, graphs, threshold, - inline_heuristic=heuristic) + inline_heuristic=heuristic, + inline_graph_from_anywhere=inline_graph_from_anywhere) constfold(config, graphs) if config.clever_malloc_removal: @@ -147,7 +149,8 @@ def inline_malloc_removal_phase(config, translator, graphs, inline_threshold, inline_heuristic, - call_count_pred=None): + call_count_pred=None, + inline_graph_from_anywhere=False): type_system = translator.rtyper.type_system.name # inline functions in each other @@ -158,7 +161,8 @@ inline.auto_inline_graphs(translator, graphs, inline_threshold, heuristic=inline_heuristic, - call_count_pred=call_count_pred) + call_count_pred=call_count_pred, + inline_graph_from_anywhere=inline_graph_from_anywhere) if config.print_statistics: print "after inlining:" diff --git a/rpython/translator/backendopt/inline.py b/rpython/translator/backendopt/inline.py --- a/rpython/translator/backendopt/inline.py +++ b/rpython/translator/backendopt/inline.py @@ -608,8 +608,9 @@ return (0.9999 * measure_median_execution_cost(graph) + count), True -def inlinable_static_callers(graphs, store_calls=False): - ok_to_call = set(graphs) +def inlinable_static_callers(graphs, store_calls=False, ok_to_call=None): + if ok_to_call is None: + ok_to_call = set(graphs) result = [] def add(parentgraph, block, op, graph): if store_calls: @@ -773,11 +774,16 @@ return count def auto_inline_graphs(translator, graphs, threshold, call_count_pred=None, - heuristic=inlining_heuristic): - callgraph = inlinable_static_callers(graphs) - count = auto_inlining(translator, threshold, callgraph=callgraph, - heuristic=heuristic, - call_count_pred=call_count_pred) - log.inlining('inlined %d callsites.' % (count,)) - for graph in graphs: - removenoops.remove_duplicate_casts(graph, translator) + heuristic=inlining_heuristic, + inline_graph_from_anywhere=False): + if inline_graph_from_anywhere: + ok_to_call = set(translator.graphs) + else: + ok_to_call = None + callgraph = inlinable_static_callers(graphs, ok_to_call=ok_to_call) + count = auto_inlining(translator, threshold, callgraph=callgraph, + heuristic=heuristic, + call_count_pred=call_count_pred) + log.inlining('inlined %d callsites.' % (count,)) + for graph in graphs: + removenoops.remove_duplicate_casts(graph, translator) diff --git a/rpython/translator/backendopt/test/test_inline.py b/rpython/translator/backendopt/test/test_inline.py --- a/rpython/translator/backendopt/test/test_inline.py +++ b/rpython/translator/backendopt/test/test_inline.py @@ -9,6 +9,7 @@ from rpython.translator.backendopt.inline import collect_called_graphs from rpython.translator.backendopt.inline import measure_median_execution_cost from rpython.translator.backendopt.inline import instrument_inline_candidates +from rpython.translator.backendopt.inline import auto_inline_graphs from rpython.translator.backendopt.checkvirtual import check_virtual_methods from rpython.translator.translator import TranslationContext, graphof from rpython.rtyper.llinterp import LLInterpreter @@ -625,6 +626,19 @@ res = eval_func([]) assert res == 5 + def test_auto_inline_graphs_from_anywhere(self): + def leaf(n): + return n + def f(n): + return leaf(n) + t = self.translate(f, [int]) + f_graph = graphof(t, f) + assert len(collect_called_graphs(f_graph, t)) == 1 + auto_inline_graphs(t, [f_graph], 32) + assert len(collect_called_graphs(f_graph, t)) == 1 + auto_inline_graphs(t, [f_graph], 32, inline_graph_from_anywhere=True) + assert len(collect_called_graphs(f_graph, t)) == 0 + class TestInlineOOType(OORtypeMixin, BaseTestInline): From noreply at buildbot.pypy.org Fri Apr 12 14:10:06 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 12 Apr 2013 14:10:06 +0200 (CEST) Subject: [pypy-commit] pypy default: merge heads Message-ID: <20130412121006.93E1F1C070B@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63278:9f9aee523a00 Date: 2013-04-12 14:12 +0200 http://bitbucket.org/pypy/pypy/changeset/9f9aee523a00/ Log: merge heads diff --git a/pypy/doc/index.rst b/pypy/doc/index.rst --- a/pypy/doc/index.rst +++ b/pypy/doc/index.rst @@ -31,6 +31,7 @@ .. _`Starting with RPython`: getting-started-dev.html .. _`how to contribute`: how-to-contribute.html .. _`PyPy website`: http://pypy.org +.. _`LICENSE`: https://bitbucket.org/pypy/pypy/src/default/LICENSE Index of various topics: ======================== @@ -66,11 +67,9 @@ * `Sandboxing Python code`_ * `Garbage collection environment variables`_ -Status_ of the project. - .. _`Differences between PyPy and CPython`: cpython_differences.html .. _`What PyPy can do for your objects`: objspace-proxies.html -.. _`Continulets and greenlets_`: stackless.html +.. _`Continulets and greenlets`: stackless.html .. _`JIT Generation in PyPy`: jit/index.html .. _`JIT hooks`: jit-hooks.html .. _`Sandboxing Python code`: sandbox.html diff --git a/pypy/module/cpyext/test/test_cpyext.py b/pypy/module/cpyext/test/test_cpyext.py --- a/pypy/module/cpyext/test/test_cpyext.py +++ b/pypy/module/cpyext/test/test_cpyext.py @@ -1,6 +1,6 @@ import sys import weakref -import os.path +import os import py @@ -19,6 +19,14 @@ from rpython.tool.identity_dict import identity_dict from rpython.tool import leakfinder +if os.name == 'nt': + # Do not open dreaded dialog box on segfault + import ctypes + SEM_NOGPFAULTERRORBOX = 0x0002 # From MSDN + old_err_mode = ctypes.windll.kernel32.GetErrorMode() + new_err_mode = old_err_mode | SEM_NOGPFAULTERRORBOX + ctypes.windll.kernel32.SetErrorMode(new_err_mode) + @api.cpython_api([], api.PyObject) def PyPy_Crash1(space): 1/0 diff --git a/rpython/rlib/test/test_rsocket.py b/rpython/rlib/test/test_rsocket.py --- a/rpython/rlib/test/test_rsocket.py +++ b/rpython/rlib/test/test_rsocket.py @@ -165,8 +165,12 @@ s2 = RSocket(AF_INET, SOCK_STREAM) s2.settimeout(10.0) # test one side with timeouts so select is used, shouldn't affect test def connecting(): - s2.connect(addr) - lock.release() + try: + s2.connect(addr) + lock.release() + except: + import traceback + traceback.print_exc() lock = thread.allocate_lock() lock.acquire() thread.start_new_thread(connecting, ()) @@ -174,6 +178,7 @@ fd1, addr2 = sock.accept() s1 = RSocket(fd=fd1) print 'connection accepted' + assert not lock.locked() lock.acquire() print 'connecting side knows that the connection was accepted too' assert addr.eq(s2.getpeername()) From noreply at buildbot.pypy.org Fri Apr 12 16:00:29 2013 From: noreply at buildbot.pypy.org (timfel) Date: Fri, 12 Apr 2013 16:00:29 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: add overflow checking to LPI lshift (because debug build assertion failed) Message-ID: <20130412140029.6E0811C08F6@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: Changeset: r262:96cf1b58e649 Date: 2013-04-12 15:30 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/96cf1b58e649/ Log: add overflow checking to LPI lshift (because debug build assertion failed) diff --git a/spyvm/model.py b/spyvm/model.py --- a/spyvm/model.py +++ b/spyvm/model.py @@ -262,12 +262,15 @@ return "W_LargePositiveInteger1Word(%d)" % r_uint(self.value) def lshift(self, space, shift): - from rpython.rlib.rarithmetic import intmask, r_uint + from rpython.rlib.rarithmetic import ovfcheck, intmask, r_uint # shift > 0, therefore the highest bit of upperbound is not set, # i.e. upperbound is positive upperbound = intmask(r_uint(-1) >> shift) if 0 <= self.value <= upperbound: - shifted = intmask(self.value << shift) + try: + shifted = intmask(ovfcheck(self.value << shift)) + except OverflowError: + raise error.PrimitiveFailedError() return space.wrap_positive_32bit_int(shifted) else: raise error.PrimitiveFailedError() diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -219,8 +219,7 @@ # #bitShift: -- return the shifted value @expose_primitive(BIT_SHIFT, unwrap_spec=[object, int]) def func(interp, s_frame, receiver, argument): - # Failing! Use ovfcheck_lfshift - # (http://codespeak.net/pypy/dist/pypy/doc/coding-guide.html#integer-types) + # overflow-checking done in lshift implementations if argument > 0: return receiver.lshift(interp.space, argument) else: From noreply at buildbot.pypy.org Fri Apr 12 16:00:30 2013 From: noreply at buildbot.pypy.org (timfel) Date: Fri, 12 Apr 2013 16:00:30 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: make sure we don't left shift by more than wordsize Message-ID: <20130412140030.8DDBB1C08F6@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: Changeset: r263:5c6f91a09689 Date: 2013-04-12 15:59 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/5c6f91a09689/ Log: make sure we don't left shift by more than wordsize diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -219,11 +219,15 @@ # #bitShift: -- return the shifted value @expose_primitive(BIT_SHIFT, unwrap_spec=[object, int]) def func(interp, s_frame, receiver, argument): - # overflow-checking done in lshift implementations - if argument > 0: - return receiver.lshift(interp.space, argument) + from rpython.rlib.rarithmetic import LONG_BIT + if -LONG_BIT < argument < LONG_BIT: + # overflow-checking done in lshift implementations + if argument > 0: + return receiver.lshift(interp.space, argument) + else: + return receiver.rshift(interp.space, -argument) else: - return receiver.rshift(interp.space, -argument) + raise PrimitiveFailedError() # ___________________________________________________________________________ # Float Primitives From noreply at buildbot.pypy.org Fri Apr 12 16:00:31 2013 From: noreply at buildbot.pypy.org (timfel) Date: Fri, 12 Apr 2013 16:00:31 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: whitespace fixes Message-ID: <20130412140031.BF6671C08F6@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: Changeset: r264:d935fb6d419b Date: 2013-04-12 15:59 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/d935fb6d419b/ Log: whitespace fixes diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -46,7 +46,7 @@ prim_table_implemented_only = [] # indicates that what is pushed is an index1, but it is unwrapped and -# converted to an index0 +# converted to an index0 index1_0 = object() char = object() pos_32bit_int = object() @@ -208,14 +208,14 @@ if argument == 0: raise PrimitiveFailedError() return interp.space.wrap_int(receiver // argument) - + # #// -- return the result of a division, rounded towards negative infinite @expose_primitive(QUO, unwrap_spec=[int, int]) def func(interp, s_frame, receiver, argument): if argument == 0: raise PrimitiveFailedError() return interp.space.wrap_int(receiver // argument) - + # #bitShift: -- return the shifted value @expose_primitive(BIT_SHIFT, unwrap_spec=[object, int]) def func(interp, s_frame, receiver, argument): @@ -394,7 +394,7 @@ ARRAY_BECOME_ONE_WAY = 72 # Blue Book: primitiveBecome INST_VAR_AT = 73 INST_VAR_AT_PUT = 74 -AS_OOP = 75 +AS_OOP = 75 STORE_STACKP = 76 # Blue Book: primitiveAsObject SOME_INSTANCE = 77 NEXT_INSTANCE = 78 @@ -481,7 +481,7 @@ if not rgc.get_gcflag_extra(gcref): rgc.toggle_gcflag_extra(gcref) w_obj = rgc.try_cast_gcref_to_instance(model.W_Object, gcref) - if (w_obj is not None and w_obj.has_class() + if (w_obj is not None and w_obj.has_class() and w_obj.getclass(interp.space) is w_class): match_w.append(w_obj) pending.extend(rgc.get_rpy_referents(gcref)) @@ -525,7 +525,7 @@ # I/O Primitives MOUSE_POINT = 90 -TEST_DISPLAY_DEPTH = 91 +TEST_DISPLAY_DEPTH = 91 SET_DISPLAY_MODE = 92 INPUT_SEMAPHORE = 93 GET_NEXT_EVENT = 94 @@ -633,10 +633,10 @@ @expose_primitive(STRING_REPLACE, unwrap_spec=[object, index1_0, index1_0, object, index1_0]) def func(interp, s_frame, w_rcvr, start, stop, w_replacement, repStart): - """replaceFrom: start to: stop with: replacement startingAt: repStart - Primitive. This destructively replaces elements from start to stop in the - receiver starting at index, repStart, in the collection, replacement. Answer - the receiver. Range checks are performed in the primitive only. Essential + """replaceFrom: start to: stop with: replacement startingAt: repStart + Primitive. This destructively replaces elements from start to stop in the + receiver starting at index, repStart, in the collection, replacement. Answer + the receiver. Range checks are performed in the primitive only. Essential for Pharo Candle Symbols. | index repOff | repOff := repStart - start. @@ -645,7 +645,7 @@ whileTrue: [self at: index put: (replacement at: repOff + index)]""" if (start < 0 or start - 1 > stop or repStart < 0): raise PrimitiveFailedError() - # This test deliberately test for equal W_Object class. The Smalltalk classes + # This test deliberately test for equal W_Object class. The Smalltalk classes # might be different (e.g. Symbol and ByteString) if w_rcvr.__class__ is not w_replacement.__class__: raise PrimitiveFailedError() @@ -761,7 +761,7 @@ def func(interp, s_frame, argument_count): if argument_count == 0: s_frame.pop() - return interp.space.wrap_string(interp.image_name) + return interp.space.wrap_string(interp.image_name) elif argument_count == 1: pass # XXX raise PrimitiveFailedError @@ -947,7 +947,7 @@ FLOAT_GREATEROREQUAL = 46 FLOAT_EQUAL = 47 FLOAT_NOTEQUAL = 48 - + bool_ops = { LESSTHAN: operator.lt, GREATERTHAN: operator.gt, @@ -973,7 +973,7 @@ w_res = interp.space.wrap_bool(res) return w_res make_func(op) - + # ___________________________________________________________________________ # Quick Push Const Primitives @@ -1007,7 +1007,7 @@ (PUSH_TWO, "w_two"), ]: make_push_const_func(code, name) - + # ___________________________________________________________________________ # Control Primitives @@ -1061,7 +1061,7 @@ 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(interp.space) @@ -1091,7 +1091,7 @@ if len(args_w) != exp_arg_cnt: raise PrimitiveFailedError() - + # Push all the items from the array for i in range(exp_arg_cnt): s_block_ctx.push(args_w[i]) @@ -1194,7 +1194,7 @@ if not (outer_ctxt_class is space.w_MethodContext or outer_ctxt_class is space.w_BlockContext): raise PrimitiveFailedError() - + # additionally to the smalltalk implementation, this also pushes # args and copiedValues s_new_frame = block.asContextWithSender(s_frame.w_self(), args_w) From noreply at buildbot.pypy.org Fri Apr 12 16:26:37 2013 From: noreply at buildbot.pypy.org (alex_gaynor) Date: Fri, 12 Apr 2013 16:26:37 +0200 (CEST) Subject: [pypy-commit] pypy default: remove some if 0:s Message-ID: <20130412142637.6E71F1C07C6@cobra.cs.uni-duesseldorf.de> Author: Alex Gaynor Branch: Changeset: r63279:77328bd10f85 Date: 2013-04-12 07:26 -0700 http://bitbucket.org/pypy/pypy/changeset/77328bd10f85/ Log: remove some if 0:s diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py --- a/pypy/interpreter/pyopcode.py +++ b/pypy/interpreter/pyopcode.py @@ -255,19 +255,7 @@ "code=%d, name=%s" % (self.last_instr, opcode, methodname)) - try: - res = meth(oparg, next_instr) - except Exception: - if 0: - import dis, sys - print "*** %s at offset %d (%s)" % (sys.exc_info()[0], - self.last_instr, - methodname) - try: - dis.dis(co_code) - except: - pass - raise + res = meth(oparg, next_instr) if res is not None: next_instr = res diff --git a/rpython/rtyper/extfunc.py b/rpython/rtyper/extfunc.py --- a/rpython/rtyper/extfunc.py +++ b/rpython/rtyper/extfunc.py @@ -1,7 +1,6 @@ from rpython.rtyper import extregistry from rpython.rtyper.extregistry import ExtRegistryEntry from rpython.rtyper.lltypesystem.lltype import typeOf -from rpython.flowspace.model import Constant from rpython.annotator import model as annmodel from rpython.annotator.signature import annotation @@ -29,14 +28,9 @@ register_external(funcs[0], *val.def_args, **val.def_kwds) return return val - except (SystemExit, MemoryError, KeyboardInterrupt), e: + except (SystemExit, MemoryError, KeyboardInterrupt): raise except: - if 0: - import traceback - print >> sys.stderr, 'WARNING: cannot register', func_or_list, ':' - traceback.print_exc() - import pdb; pdb.set_trace() exc, exc_inst, tb = sys.exc_info() for func in funcs: # if the function has already been registered and we got @@ -250,7 +244,7 @@ signature_args = args signature_result = annotation(result, None) - name=export_name + name = export_name if llimpl: lltypeimpl = staticmethod(llimpl) if ooimpl: From noreply at buildbot.pypy.org Fri Apr 12 16:29:15 2013 From: noreply at buildbot.pypy.org (mattip) Date: Fri, 12 Apr 2013 16:29:15 +0200 (CEST) Subject: [pypy-commit] pypy py3k: fix translation Message-ID: <20130412142915.676C11C088E@cobra.cs.uni-duesseldorf.de> Author: mattip Branch: py3k Changeset: r63280:17314bb8cd1a Date: 2013-04-12 17:27 +0300 http://bitbucket.org/pypy/pypy/changeset/17314bb8cd1a/ Log: fix translation diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py --- a/rpython/rlib/rposix.py +++ b/rpython/rlib/rposix.py @@ -103,10 +103,10 @@ _set_errno(rffi.cast(INT, errno)) if os.name == 'nt': - is_valid_fd = rffi.llexternal( + is_valid_fd = jit.dont_look_inside(rffi.llexternal( "_PyVerify_fd", [rffi.INT], rffi.INT, compilation_info=errno_eci, - ) + )) @jit.dont_look_inside def validate_fd(fd): if not is_valid_fd(fd): From noreply at buildbot.pypy.org Fri Apr 12 16:34:29 2013 From: noreply at buildbot.pypy.org (mattip) Date: Fri, 12 Apr 2013 16:34:29 +0200 (CEST) Subject: [pypy-commit] pypy default: document merged branch Message-ID: <20130412143429.AACBE1C07C6@cobra.cs.uni-duesseldorf.de> Author: mattip Branch: Changeset: r63281:a541f60c2172 Date: 2013-04-12 17:34 +0300 http://bitbucket.org/pypy/pypy/changeset/a541f60c2172/ Log: document merged branch diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -50,6 +50,9 @@ JIT optimizations which makes cffi calls even faster, by removing the need to allocate a temporary buffer where to store the arguments. +.. branch: improve-docs-2 +Improve documents and straighten out links + .. branches we don't care about .. branch: autoreds .. branch: reflex-support From noreply at buildbot.pypy.org Fri Apr 12 17:14:42 2013 From: noreply at buildbot.pypy.org (mattip) Date: Fri, 12 Apr 2013 17:14:42 +0200 (CEST) Subject: [pypy-commit] pypy win32-fixes2: create branch for win32 fixes Message-ID: <20130412151442.2D0931C07C6@cobra.cs.uni-duesseldorf.de> Author: mattip Branch: win32-fixes2 Changeset: r63282:4beb09eba63c Date: 2013-04-12 18:11 +0300 http://bitbucket.org/pypy/pypy/changeset/4beb09eba63c/ Log: create branch for win32 fixes From noreply at buildbot.pypy.org Fri Apr 12 17:14:43 2013 From: noreply at buildbot.pypy.org (mattip) Date: Fri, 12 Apr 2013 17:14:43 +0200 (CEST) Subject: [pypy-commit] pypy default: backout changeset 1d1c1b2fe42a, belongs on branch not default Message-ID: <20130412151443.A29121C07C6@cobra.cs.uni-duesseldorf.de> Author: mattip Branch: Changeset: r63283:318f165c9ecb Date: 2013-04-12 18:13 +0300 http://bitbucket.org/pypy/pypy/changeset/318f165c9ecb/ Log: backout changeset 1d1c1b2fe42a, belongs on branch not default diff --git a/rpython/jit/backend/test/test_zll_stress_0.py b/rpython/jit/backend/test/test_zll_stress_0.py --- a/rpython/jit/backend/test/test_zll_stress_0.py +++ b/rpython/jit/backend/test/test_zll_stress_0.py @@ -1,7 +1,4 @@ from rpython.jit.backend.test import zll_stress -import py + def test_stress_0(): - import sys - if sys.platform.startswith('win'): - py.test.skip('crashes test platform, fix crash and reenable test') zll_stress.do_test_stress(0) From noreply at buildbot.pypy.org Fri Apr 12 19:16:09 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Fri, 12 Apr 2013 19:16:09 +0200 (CEST) Subject: [pypy-commit] pypy default: test and fix for BytesIO.__init__() Message-ID: <20130412171609.DFD701C010B@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63284:61d35aaefb02 Date: 2013-04-12 13:14 -0400 http://bitbucket.org/pypy/pypy/changeset/61d35aaefb02/ Log: test and fix for BytesIO.__init__() diff --git a/pypy/module/_io/interp_bytesio.py b/pypy/module/_io/interp_bytesio.py --- a/pypy/module/_io/interp_bytesio.py +++ b/pypy/module/_io/interp_bytesio.py @@ -15,6 +15,7 @@ self.init() def descr_init(self, space, w_initial_bytes=None): + self.init() if not space.is_none(w_initial_bytes): self.write_w(space, w_initial_bytes) self.seek(0) diff --git a/pypy/module/_io/test/test_bytesio.py b/pypy/module/_io/test/test_bytesio.py --- a/pypy/module/_io/test/test_bytesio.py +++ b/pypy/module/_io/test/test_bytesio.py @@ -4,6 +4,15 @@ def test_init(self): import _io raises(TypeError, _io.BytesIO, u"12345") + buf = "1234567890" + b = _io.BytesIO(buf) + assert b.getvalue() == buf + b = _io.BytesIO(None) + assert b.getvalue() == "" + b.__init__(buf * 2) + assert b.getvalue() == buf * 2 + b.__init__(buf) + assert b.getvalue() == buf def test_init_kwargs(self): import _io From noreply at buildbot.pypy.org Fri Apr 12 19:26:27 2013 From: noreply at buildbot.pypy.org (antocuni) Date: Fri, 12 Apr 2013 19:26:27 +0200 (CEST) Subject: [pypy-commit] pypy default: use char instead of signed, so that the offsets are the same on 32 or 64 bits Message-ID: <20130412172627.4CFCC1C010B@cobra.cs.uni-duesseldorf.de> Author: Antonio Cuni Branch: Changeset: r63285:b50b0681136a Date: 2013-04-12 19:28 +0200 http://bitbucket.org/pypy/pypy/changeset/b50b0681136a/ Log: use char instead of signed, so that the offsets are the same on 32 or 64 bits diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py --- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py @@ -1747,9 +1747,9 @@ ops = """ [i1] i2 = call('malloc', 10, descr=raw_malloc_descr) - setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) - setarrayitem_raw(i2, 2, 456, descr=rawarraydescr) - setarrayitem_raw(i2, 1, 123, descr=rawarraydescr) + setarrayitem_raw(i2, 0, i1, descr=rawarraydescr_char) + setarrayitem_raw(i2, 2, 456, descr=rawarraydescr_char) + setarrayitem_raw(i2, 1, 123, descr=rawarraydescr_char) label('foo') # we expect the buffer to be forced *after* the label escape(i2) call('free', i2, descr=raw_free_descr) @@ -1759,11 +1759,11 @@ [i1] label('foo') i2 = call('malloc', 10, descr=raw_malloc_descr) - setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) - i3 = int_add(i2, 8) - setarrayitem_raw(i3, 0, 123, descr=rawarraydescr) - i4 = int_add(i2, 16) - setarrayitem_raw(i4, 0, 456, descr=rawarraydescr) + setarrayitem_raw(i2, 0, i1, descr=rawarraydescr_char) + i3 = int_add(i2, 1) + setarrayitem_raw(i3, 0, 123, descr=rawarraydescr_char) + i4 = int_add(i2, 2) + setarrayitem_raw(i4, 0, 456, descr=rawarraydescr_char) escape(i2) call('free', i2, descr=raw_free_descr) jump(i1) From noreply at buildbot.pypy.org Fri Apr 12 19:37:51 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Fri, 12 Apr 2013 19:37:51 +0200 (CEST) Subject: [pypy-commit] pypy default: this assert is not always true Message-ID: <20130412173751.A4E291C010B@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63286:2d1d3438b94c Date: 2013-04-12 13:36 -0400 http://bitbucket.org/pypy/pypy/changeset/2d1d3438b94c/ Log: this assert is not always true diff --git a/rpython/rlib/test/test_rsocket.py b/rpython/rlib/test/test_rsocket.py --- a/rpython/rlib/test/test_rsocket.py +++ b/rpython/rlib/test/test_rsocket.py @@ -178,7 +178,6 @@ fd1, addr2 = sock.accept() s1 = RSocket(fd=fd1) print 'connection accepted' - assert not lock.locked() lock.acquire() print 'connecting side knows that the connection was accepted too' assert addr.eq(s2.getpeername()) From noreply at buildbot.pypy.org Fri Apr 12 19:53:44 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Fri, 12 Apr 2013 19:53:44 +0200 (CEST) Subject: [pypy-commit] pypy default: unhandled exception in thread should do exactly this Message-ID: <20130412175344.AB57F1C07C6@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63287:e2745fcf0ffe Date: 2013-04-12 13:47 -0400 http://bitbucket.org/pypy/pypy/changeset/e2745fcf0ffe/ Log: unhandled exception in thread should do exactly this diff --git a/rpython/rlib/test/test_rsocket.py b/rpython/rlib/test/test_rsocket.py --- a/rpython/rlib/test/test_rsocket.py +++ b/rpython/rlib/test/test_rsocket.py @@ -165,12 +165,8 @@ s2 = RSocket(AF_INET, SOCK_STREAM) s2.settimeout(10.0) # test one side with timeouts so select is used, shouldn't affect test def connecting(): - try: - s2.connect(addr) - lock.release() - except: - import traceback - traceback.print_exc() + s2.connect(addr) + lock.release() lock = thread.allocate_lock() lock.acquire() thread.start_new_thread(connecting, ()) From noreply at buildbot.pypy.org Fri Apr 12 20:09:22 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Fri, 12 Apr 2013 20:09:22 +0200 (CEST) Subject: [pypy-commit] pypy default: clean up win SetErrorMode changes Message-ID: <20130412180922.605B21C026A@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63288:100a93fe4df3 Date: 2013-04-12 14:09 -0400 http://bitbucket.org/pypy/pypy/changeset/100a93fe4df3/ Log: clean up win SetErrorMode changes diff --git a/pypy/module/cpyext/test/test_cpyext.py b/pypy/module/cpyext/test/test_cpyext.py --- a/pypy/module/cpyext/test/test_cpyext.py +++ b/pypy/module/cpyext/test/test_cpyext.py @@ -19,13 +19,20 @@ from rpython.tool.identity_dict import identity_dict from rpython.tool import leakfinder -if os.name == 'nt': - # Do not open dreaded dialog box on segfault - import ctypes - SEM_NOGPFAULTERRORBOX = 0x0002 # From MSDN - old_err_mode = ctypes.windll.kernel32.GetErrorMode() - new_err_mode = old_err_mode | SEM_NOGPFAULTERRORBOX - ctypes.windll.kernel32.SetErrorMode(new_err_mode) +def setup_module(module): + if os.name == 'nt': + # Do not open dreaded dialog box on segfault + import ctypes + SEM_NOGPFAULTERRORBOX = 0x0002 # From MSDN + old_err_mode = ctypes.windll.kernel32.GetErrorMode() + new_err_mode = old_err_mode | SEM_NOGPFAULTERRORBOX + ctypes.windll.kernel32.SetErrorMode(new_err_mode) + module.old_err_mode = old_err_mode + +def teardown_module(module): + if os.name == 'nt': + import ctypes + ctypes.windll.kernel32.SetErrorMode(module.old_err_mode) @api.cpython_api([], api.PyObject) def PyPy_Crash1(space): diff --git a/rpython/rtyper/lltypesystem/test/test_ll2ctypes.py b/rpython/rtyper/lltypesystem/test/test_ll2ctypes.py --- a/rpython/rtyper/lltypesystem/test/test_ll2ctypes.py +++ b/rpython/rtyper/lltypesystem/test/test_ll2ctypes.py @@ -753,8 +753,6 @@ old_err_mode = ctypes.windll.kernel32.GetErrorMode() new_err_mode = old_err_mode | SEM_NOGPFAULTERRORBOX ctypes.windll.kernel32.SetErrorMode(new_err_mode) - assert f(1) == 1 - ctypes.windll.kernel32.SetErrorMode(old_err_mode) else: underscore_on_windows = '' strlen = rffi.llexternal('strlen', [rffi.CCHARP], rffi.SIZE_T, diff --git a/rpython/rtyper/module/test/test_ll_os_environ.py b/rpython/rtyper/module/test/test_ll_os_environ.py --- a/rpython/rtyper/module/test/test_ll_os_environ.py +++ b/rpython/rtyper/module/test/test_ll_os_environ.py @@ -34,7 +34,6 @@ old_err_mode = ctypes.windll.kernel32.GetErrorMode() new_err_mode = old_err_mode | SEM_NOGPFAULTERRORBOX ctypes.windll.kernel32.SetErrorMode(new_err_mode) - assert f(1) == 1 + assert f(1) == 1 + if sys.platform.startswith('win'): ctypes.windll.kernel32.SetErrorMode(old_err_mode) - else: - assert f(1) == 1 From noreply at buildbot.pypy.org Fri Apr 12 20:12:15 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Fri, 12 Apr 2013 20:12:15 +0200 (CEST) Subject: [pypy-commit] pypy default: another cleanup Message-ID: <20130412181215.CE1941C026A@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63289:3befe7a7717e Date: 2013-04-12 14:12 -0400 http://bitbucket.org/pypy/pypy/changeset/3befe7a7717e/ Log: another cleanup diff --git a/rpython/rtyper/lltypesystem/test/test_llarena.py b/rpython/rtyper/lltypesystem/test/test_llarena.py --- a/rpython/rtyper/lltypesystem/test/test_llarena.py +++ b/rpython/rtyper/lltypesystem/test/test_llarena.py @@ -326,15 +326,15 @@ t, cbuilder = self.compile(fn) data = cbuilder.cmdexec('0') assert data == '133\n' - if sys.platform.startswith('win'): - # Do not open error dialog box - import ctypes - SEM_NOGPFAULTERRORBOX = 0x0002 # From MSDN - old_err_mode = ctypes.windll.kernel32.GetErrorMode() - new_err_mode = old_err_mode | SEM_NOGPFAULTERRORBOX - ctypes.windll.kernel32.SetErrorMode(new_err_mode) if has_protect: + if sys.platform.startswith('win'): + # Do not open error dialog box + import ctypes + SEM_NOGPFAULTERRORBOX = 0x0002 # From MSDN + old_err_mode = ctypes.windll.kernel32.GetErrorMode() + new_err_mode = old_err_mode | SEM_NOGPFAULTERRORBOX + ctypes.windll.kernel32.SetErrorMode(new_err_mode) cbuilder.cmdexec('1', expect_crash=True) cbuilder.cmdexec('2', expect_crash=True) - if sys.platform.startswith('win'): - ctypes.windll.kernel32.SetErrorMode(old_err_mode) + if sys.platform.startswith('win'): + ctypes.windll.kernel32.SetErrorMode(old_err_mode) From noreply at buildbot.pypy.org Fri Apr 12 21:30:37 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Fri, 12 Apr 2013 21:30:37 +0200 (CEST) Subject: [pypy-commit] buildbot default: upload before running tests Message-ID: <20130412193037.95A291C026A@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r780:6d626710010e Date: 2013-04-12 15:30 -0400 http://bitbucket.org/pypy/buildbot/changeset/6d626710010e/ Log: upload before running tests diff --git a/bot2/pypybuildbot/builds.py b/bot2/pypybuildbot/builds.py --- a/bot2/pypybuildbot/builds.py +++ b/bot2/pypybuildbot/builds.py @@ -409,8 +409,6 @@ self.addStep(Translate(translationArgs, targetArgs, interpreter=interpreter)) - add_translated_tests(self, prefix, platform, app_tests, lib_python, pypyjit) - name = build_name(platform, pypyjit, translationArgs) self.addStep(ShellCmd( description="compress pypy-c", @@ -427,6 +425,8 @@ workdir='.', blocksize=100 * 1024)) + add_translated_tests(self, prefix, platform, app_tests, lib_python, pypyjit) + class TranslatedTests(factory.BuildFactory): ''' From noreply at buildbot.pypy.org Fri Apr 12 21:38:55 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Fri, 12 Apr 2013 21:38:55 +0200 (CEST) Subject: [pypy-commit] buildbot default: add freebsd8 build on ananke Message-ID: <20130412193855.739B91C010B@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r781:7c9a2cfe7eaf Date: 2013-04-12 15:38 -0400 http://bitbucket.org/pypy/buildbot/changeset/7c9a2cfe7eaf/ Log: add freebsd8 build on ananke diff --git a/bot2/pypybuildbot/master.py b/bot2/pypybuildbot/master.py --- a/bot2/pypybuildbot/master.py +++ b/bot2/pypybuildbot/master.py @@ -180,7 +180,8 @@ JITMACOSX64 = "pypy-c-jit-macosx-x86-64" JITWIN32 = "pypy-c-jit-win-x86-32" JITWIN64 = "pypy-c-jit-win-x86-64" -JITFREEBSD64 = 'pypy-c-jit-freebsd-7-x86-64' +JITFREEBSD764 = 'pypy-c-jit-freebsd-7-x86-64' +JITFREEBSD864 = 'pypy-c-jit-freebsd-8-x86-64' JITFREEBSD964 = 'pypy-c-jit-freebsd-9-x86-64' JITINDIANA32 = "pypy-c-jit-indiana-x86-32" @@ -215,7 +216,8 @@ # other platforms MACOSX32, # on minime JITWIN32, # on aurora - JITFREEBSD64, # on headless + JITFREEBSD764, # on headless + JITFREEBSD864, # on ananke JITFREEBSD964, # on exarkun's freebsd JITMACOSX64, # on xerxes ], branch=None, hour=0, minute=0), @@ -358,9 +360,15 @@ 'factory' : pypyJITTranslatedTestFactoryWin, 'category' : 'win32', }, - {"name" : JITFREEBSD64, + {"name" : JITFREEBSD764, "slavenames": ['headless'], - 'builddir' : JITFREEBSD64, + 'builddir' : JITFREEBSD764, + 'factory' : pypyJITTranslatedTestFactoryFreeBSD, + "category": 'freebsd64' + }, + {"name": JITFREEBSD864, + "slavenames": ['ananke'], + 'builddir' : JITFREEBSD864, 'factory' : pypyJITTranslatedTestFactoryFreeBSD, "category": 'freebsd64' }, From noreply at buildbot.pypy.org Fri Apr 12 21:49:01 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Fri, 12 Apr 2013 21:49:01 +0200 (CEST) Subject: [pypy-commit] pypy default: we should try _minimal_curses first now that pypy has _curses Message-ID: <20130412194901.9EF1F1C010B@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63290:d56f457a3357 Date: 2013-04-12 15:48 -0400 http://bitbucket.org/pypy/pypy/changeset/d56f457a3357/ Log: we should try _minimal_curses first now that pypy has _curses diff --git a/pypy/module/_minimal_curses/__init__.py b/pypy/module/_minimal_curses/__init__.py --- a/pypy/module/_minimal_curses/__init__.py +++ b/pypy/module/_minimal_curses/__init__.py @@ -1,8 +1,8 @@ try: - import _curses + import _minimal_curses as _curses # when running on top of pypy-c except ImportError: try: - import _minimal_curses as _curses # when running on top of pypy-c + import _curses except ImportError: import py py.test.skip("no _curses or _minimal_curses module") #no _curses at all From noreply at buildbot.pypy.org Fri Apr 12 21:57:06 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Fri, 12 Apr 2013 21:57:06 +0200 (CEST) Subject: [pypy-commit] pypy default: which makes this workaround unnecessary Message-ID: <20130412195706.F1CD61C010B@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63291:28b8773e4b91 Date: 2013-04-12 15:56 -0400 http://bitbucket.org/pypy/pypy/changeset/28b8773e4b91/ Log: which makes this workaround unnecessary diff --git a/pypy/module/_minimal_curses/__init__.py b/pypy/module/_minimal_curses/__init__.py --- a/pypy/module/_minimal_curses/__init__.py +++ b/pypy/module/_minimal_curses/__init__.py @@ -27,7 +27,6 @@ } for i in dir(_curses): - i = str(i) # workaround for pypy 2.0-beta2 val = getattr(_curses, i) if i.isupper() and type(val) is int: Module.interpleveldefs[i] = "space.wrap(%s)" % val From noreply at buildbot.pypy.org Fri Apr 12 22:16:57 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Fri, 12 Apr 2013 22:16:57 +0200 (CEST) Subject: [pypy-commit] pypy default: actually prefer _curses, and enhance comments Message-ID: <20130412201657.AD81F1C010B@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63292:c0886eb2c291 Date: 2013-04-12 16:15 -0400 http://bitbucket.org/pypy/pypy/changeset/c0886eb2c291/ Log: actually prefer _curses, and enhance comments diff --git a/pypy/module/_minimal_curses/__init__.py b/pypy/module/_minimal_curses/__init__.py --- a/pypy/module/_minimal_curses/__init__.py +++ b/pypy/module/_minimal_curses/__init__.py @@ -1,11 +1,13 @@ try: - import _minimal_curses as _curses # when running on top of pypy-c + import _curses except ImportError: try: - import _curses + # when running on top of pypy before it had _curses, settle for minimal + # we prefer _curses so any constants added make it into _minimal_curses + import _minimal_curses as _curses except ImportError: import py - py.test.skip("no _curses or _minimal_curses module") #no _curses at all + py.test.skip("no _curses or _minimal_curses module") # no _curses at all from pypy.interpreter.mixedmodule import MixedModule from pypy.module._minimal_curses import fficurses # for side effects @@ -27,6 +29,7 @@ } for i in dir(_curses): + i = str(i) # workaround for pypy 2.0-beta2 val = getattr(_curses, i) if i.isupper() and type(val) is int: Module.interpleveldefs[i] = "space.wrap(%s)" % val From noreply at buildbot.pypy.org Fri Apr 12 22:48:22 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Fri, 12 Apr 2013 22:48:22 +0200 (CEST) Subject: [pypy-commit] pypy py3k: skip pending calls, as we do on default Message-ID: <20130412204822.CE0501C010B@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63293:444360de280a Date: 2013-04-12 13:47 -0700 http://bitbucket.org/pypy/pypy/changeset/444360de280a/ Log: skip pending calls, as we do on default diff --git a/lib-python/3/test/test_capi.py b/lib-python/3/test/test_capi.py --- a/lib-python/3/test/test_capi.py +++ b/lib-python/3/test/test_capi.py @@ -55,6 +55,8 @@ def test_memoryview_from_NULL_pointer(self): self.assertRaises(ValueError, _testcapi.make_memoryview_from_NULL_pointer) + at unittest.skipIf(support.check_impl_detail(pypy=True), + 'Py_AddPendingCall not currently supported.') @unittest.skipUnless(threading, 'Threading required for this test.') class TestPendingCalls(unittest.TestCase): From noreply at buildbot.pypy.org Fri Apr 12 22:48:24 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Fri, 12 Apr 2013 22:48:24 +0200 (CEST) Subject: [pypy-commit] pypy py3k: quiet a compiler warning Message-ID: <20130412204824.4E5CC1C010B@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63294:ba2d0170f09e Date: 2013-04-12 13:47 -0700 http://bitbucket.org/pypy/pypy/changeset/ba2d0170f09e/ Log: quiet a compiler warning diff --git a/pypy/module/cpyext/include/pyerrors.h b/pypy/module/cpyext/include/pyerrors.h --- a/pypy/module/cpyext/include/pyerrors.h +++ b/pypy/module/cpyext/include/pyerrors.h @@ -12,7 +12,7 @@ PyObject_IsSubclass((x), PyExc_BaseException))) #define PyExceptionInstance_Check(x) \ - (PyObject_IsSubclass((x)->ob_type, PyExc_BaseException)) + (PyObject_IsSubclass((PyObject *)Py_TYPE(x), PyExc_BaseException)) PyObject *PyErr_NewException(const char *name, PyObject *base, PyObject *dict); PyObject *PyErr_NewExceptionWithDoc(const char *name, const char *doc, PyObject *base, PyObject *dict); From noreply at buildbot.pypy.org Fri Apr 12 23:25:59 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 12 Apr 2013 23:25:59 +0200 (CEST) Subject: [pypy-commit] buildbot default: Don't haltOnFailure after PyPyUpload, now that it's no longer the last Message-ID: <20130412212559.EAECB1C010B@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r782:91ac184cbe43 Date: 2013-04-12 23:25 +0200 http://bitbucket.org/pypy/buildbot/changeset/91ac184cbe43/ Log: Don't haltOnFailure after PyPyUpload, now that it's no longer the last one. diff --git a/bot2/pypybuildbot/builds.py b/bot2/pypybuildbot/builds.py --- a/bot2/pypybuildbot/builds.py +++ b/bot2/pypybuildbot/builds.py @@ -43,6 +43,7 @@ class PyPyUpload(transfer.FileUpload): parms = transfer.FileUpload.parms + ['basename'] + haltOnFailure = False def start(self): properties = self.build.getProperties() @@ -412,6 +413,7 @@ name = build_name(platform, pypyjit, translationArgs) self.addStep(ShellCmd( description="compress pypy-c", + haltOnFailure=False, command=prefix + ["python", "pypy/tool/release/package.py", ".", WithProperties(name), 'pypy', '.'], From noreply at buildbot.pypy.org Fri Apr 12 23:26:01 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 12 Apr 2013 23:26:01 +0200 (CEST) Subject: [pypy-commit] buildbot default: merge heads Message-ID: <20130412212601.1F8091C010B@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r783:75fbd7e5fff6 Date: 2013-04-12 23:25 +0200 http://bitbucket.org/pypy/buildbot/changeset/75fbd7e5fff6/ Log: merge heads diff --git a/bot2/pypybuildbot/master.py b/bot2/pypybuildbot/master.py --- a/bot2/pypybuildbot/master.py +++ b/bot2/pypybuildbot/master.py @@ -180,7 +180,8 @@ JITMACOSX64 = "pypy-c-jit-macosx-x86-64" JITWIN32 = "pypy-c-jit-win-x86-32" JITWIN64 = "pypy-c-jit-win-x86-64" -JITFREEBSD64 = 'pypy-c-jit-freebsd-7-x86-64' +JITFREEBSD764 = 'pypy-c-jit-freebsd-7-x86-64' +JITFREEBSD864 = 'pypy-c-jit-freebsd-8-x86-64' JITFREEBSD964 = 'pypy-c-jit-freebsd-9-x86-64' JITINDIANA32 = "pypy-c-jit-indiana-x86-32" @@ -215,7 +216,8 @@ # other platforms MACOSX32, # on minime JITWIN32, # on aurora - JITFREEBSD64, # on headless + JITFREEBSD764, # on headless + JITFREEBSD864, # on ananke JITFREEBSD964, # on exarkun's freebsd JITMACOSX64, # on xerxes ], branch=None, hour=0, minute=0), @@ -358,9 +360,15 @@ 'factory' : pypyJITTranslatedTestFactoryWin, 'category' : 'win32', }, - {"name" : JITFREEBSD64, + {"name" : JITFREEBSD764, "slavenames": ['headless'], - 'builddir' : JITFREEBSD64, + 'builddir' : JITFREEBSD764, + 'factory' : pypyJITTranslatedTestFactoryFreeBSD, + "category": 'freebsd64' + }, + {"name": JITFREEBSD864, + "slavenames": ['ananke'], + 'builddir' : JITFREEBSD864, 'factory' : pypyJITTranslatedTestFactoryFreeBSD, "category": 'freebsd64' }, From noreply at buildbot.pypy.org Sat Apr 13 00:26:54 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Sat, 13 Apr 2013 00:26:54 +0200 (CEST) Subject: [pypy-commit] pypy py3k: this is an AttributeError on py3 Message-ID: <20130412222654.D7E141C010B@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63295:a0bb65dcbc1e Date: 2013-04-12 15:25 -0700 http://bitbucket.org/pypy/pypy/changeset/a0bb65dcbc1e/ Log: this is an AttributeError on py3 diff --git a/pypy/module/cpyext/test/test_typeobject.py b/pypy/module/cpyext/test/test_typeobject.py --- a/pypy/module/cpyext/test/test_typeobject.py +++ b/pypy/module/cpyext/test/test_typeobject.py @@ -48,7 +48,7 @@ obj.int_member = 42 raises(TypeError, "obj.int_member = 'not a number'") raises(TypeError, "del obj.int_member") - raises(TypeError, "obj.int_member_readonly = 42") + raises(AttributeError, "obj.int_member_readonly = 42") exc = raises(TypeError, "del obj.int_member_readonly") assert "readonly" in str(exc.value) raises(SystemError, "obj.broken_member") From noreply at buildbot.pypy.org Sat Apr 13 00:26:56 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Sat, 13 Apr 2013 00:26:56 +0200 (CEST) Subject: [pypy-commit] pypy py3k: latest slotdefs Message-ID: <20130412222656.508911C010B@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63296:e508ea132134 Date: 2013-04-12 15:25 -0700 http://bitbucket.org/pypy/pypy/changeset/e508ea132134/ Log: latest slotdefs diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py --- a/pypy/module/cpyext/slotdefs.py +++ b/pypy/module/cpyext/slotdefs.py @@ -481,27 +481,23 @@ "x.__delitem__(y) <==> del x[y]"), BINSLOT("__add__", nb_add, slot_nb_add, - "+"), + "+"), RBINSLOT("__radd__", nb_add, slot_nb_add, "+"), BINSLOT("__sub__", nb_subtract, slot_nb_subtract, - "-"), + "-"), RBINSLOT("__rsub__", nb_subtract, slot_nb_subtract, "-"), BINSLOT("__mul__", nb_multiply, slot_nb_multiply, - "*"), + "*"), RBINSLOT("__rmul__", nb_multiply, slot_nb_multiply, "*"), - BINSLOT("__div__", nb_divide, slot_nb_divide, - "/"), - RBINSLOT("__rdiv__", nb_divide, slot_nb_divide, - "/"), BINSLOT("__mod__", nb_remainder, slot_nb_remainder, - "%"), + "%"), RBINSLOT("__rmod__", nb_remainder, slot_nb_remainder, "%"), BINSLOTNOTINFIX("__divmod__", nb_divmod, slot_nb_divmod, - "divmod(x, y)"), + "divmod(x, y)"), RBINSLOTNOTINFIX("__rdivmod__", nb_divmod, slot_nb_divmod, "divmod(y, x)"), NBSLOT("__pow__", nb_power, slot_nb_power, wrap_ternaryfunc, @@ -527,38 +523,30 @@ RBINSLOT("__ror__", nb_or, slot_nb_or, "|"), UNSLOT("__int__", nb_int, slot_nb_int, wrap_unaryfunc, "int(x)"), - UNSLOT("__long__", nb_long, slot_nb_long, wrap_unaryfunc, - "long(x)"), UNSLOT("__float__", nb_float, slot_nb_float, wrap_unaryfunc, "float(x)"), - UNSLOT("__oct__", nb_oct, slot_nb_oct, wrap_unaryfunc, - "oct(x)"), - UNSLOT("__hex__", nb_hex, slot_nb_hex, wrap_unaryfunc, - "hex(x)"), NBSLOT("__index__", nb_index, slot_nb_index, wrap_unaryfunc, "x[y:z] <==> x[y.__index__():z.__index__()]"), IBSLOT("__iadd__", nb_inplace_add, slot_nb_inplace_add, - wrap_binaryfunc, "+"), + wrap_binaryfunc, "+="), IBSLOT("__isub__", nb_inplace_subtract, slot_nb_inplace_subtract, - wrap_binaryfunc, "-"), + wrap_binaryfunc, "-="), IBSLOT("__imul__", nb_inplace_multiply, slot_nb_inplace_multiply, - wrap_binaryfunc, "*"), - IBSLOT("__idiv__", nb_inplace_divide, slot_nb_inplace_divide, - wrap_binaryfunc, "/"), + wrap_binaryfunc, "*="), IBSLOT("__imod__", nb_inplace_remainder, slot_nb_inplace_remainder, - wrap_binaryfunc, "%"), + wrap_binaryfunc, "%="), IBSLOT("__ipow__", nb_inplace_power, slot_nb_inplace_power, - wrap_binaryfunc, "**"), + wrap_binaryfunc, "**="), IBSLOT("__ilshift__", nb_inplace_lshift, slot_nb_inplace_lshift, - wrap_binaryfunc, "<<"), + wrap_binaryfunc, "<<="), IBSLOT("__irshift__", nb_inplace_rshift, slot_nb_inplace_rshift, - wrap_binaryfunc, ">>"), + wrap_binaryfunc, ">>="), IBSLOT("__iand__", nb_inplace_and, slot_nb_inplace_and, - wrap_binaryfunc, "&"), + wrap_binaryfunc, "&="), IBSLOT("__ixor__", nb_inplace_xor, slot_nb_inplace_xor, - wrap_binaryfunc, "^"), + wrap_binaryfunc, "^="), IBSLOT("__ior__", nb_inplace_or, slot_nb_inplace_or, - wrap_binaryfunc, "|"), + wrap_binaryfunc, "|="), BINSLOT("__floordiv__", nb_floor_divide, slot_nb_floor_divide, "//"), RBINSLOT("__rfloordiv__", nb_floor_divide, slot_nb_floor_divide, "//"), BINSLOT("__truediv__", nb_true_divide, slot_nb_true_divide, "/"), @@ -570,12 +558,8 @@ TPSLOT("__str__", tp_str, slot_tp_str, wrap_unaryfunc, "x.__str__() <==> str(x)"), - TPSLOT("__str__", tp_print, NULL, NULL, ""), TPSLOT("__repr__", tp_repr, slot_tp_repr, wrap_unaryfunc, "x.__repr__() <==> repr(x)"), - TPSLOT("__repr__", tp_print, NULL, NULL, ""), - TPSLOT("__cmp__", tp_compare, _PyObject_SlotCompare, wrap_cmpfunc, - "x.__cmp__(y) <==> cmp(x,y)"), TPSLOT("__hash__", tp_hash, slot_tp_hash, wrap_hashfunc, "x.__hash__() <==> hash(x)"), FLSLOT("__call__", tp_call, slot_tp_call, (wrapperfunc)wrap_call, @@ -615,7 +599,7 @@ wrap_descr_delete, "descr.__delete__(obj)"), FLSLOT("__init__", tp_init, slot_tp_init, (wrapperfunc)wrap_init, "x.__init__(...) initializes x; " - "see x.__class__.__doc__ for signature", + "see help(type(x)) for signature", PyWrapperFlag_KEYWORDS), TPSLOT("__new__", tp_new, slot_tp_new, NULL, ""), TPSLOT("__del__", tp_del, slot_tp_del, NULL, ""), From noreply at buildbot.pypy.org Sat Apr 13 00:26:57 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Sat, 13 Apr 2013 00:26:57 +0200 (CEST) Subject: [pypy-commit] pypy py3k: tp_compare is gone in py3, kill Message-ID: <20130412222657.947FA1C010B@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63297:5ea602d6bb08 Date: 2013-04-12 15:26 -0700 http://bitbucket.org/pypy/pypy/changeset/5ea602d6bb08/ Log: tp_compare is gone in py3, kill diff --git a/pypy/module/cpyext/test/comparisons.c b/pypy/module/cpyext/test/comparisons.c --- a/pypy/module/cpyext/test/comparisons.c +++ b/pypy/module/cpyext/test/comparisons.c @@ -73,23 +73,6 @@ }; -static int cmp_compare(PyObject *self, PyObject *other) { - return -1; -} - -PyTypeObject OldCmpType = { - PyVarObject_HEAD_INIT(NULL, 0) - "comparisons.OldCmpType", /* tp_name */ - sizeof(CmpObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - 0, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - (cmpfunc)cmp_compare, /* tp_compare */ -}; - - static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "comparisons", @@ -105,8 +88,6 @@ if (PyType_Ready(&CmpType) < 0) return NULL; - if (PyType_Ready(&OldCmpType) < 0) - return NULL; m = PyModule_Create(&moduledef); if (m == NULL) return NULL; @@ -115,7 +96,5 @@ return NULL; if (PyDict_SetItemString(d, "CmpType", (PyObject *)&CmpType) < 0) return NULL; - if (PyDict_SetItemString(d, "OldCmpType", (PyObject *)&OldCmpType) < 0) - return NULL; return m; } diff --git a/pypy/module/cpyext/test/test_typeobject.py b/pypy/module/cpyext/test/test_typeobject.py --- a/pypy/module/cpyext/test/test_typeobject.py +++ b/pypy/module/cpyext/test/test_typeobject.py @@ -217,11 +217,6 @@ assert cmpr.__le__(4) is NotImplemented - def test_tpcompare(self): - module = self.import_module("comparisons") - cmpr = module.OldCmpType() - assert cmpr < cmpr - def test_hash(self): module = self.import_module("comparisons") cmpr = module.CmpType() From noreply at buildbot.pypy.org Sat Apr 13 00:41:41 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Sat, 13 Apr 2013 00:41:41 +0200 (CEST) Subject: [pypy-commit] pypy py3k: switch to PyModule_Create Message-ID: <20130412224141.9EE481C026A@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63298:319813f454d6 Date: 2013-04-12 15:41 -0700 http://bitbucket.org/pypy/pypy/changeset/319813f454d6/ Log: switch to PyModule_Create diff --git a/pypy/module/cpyext/test/test_version.py b/pypy/module/cpyext/test/test_version.py --- a/pypy/module/cpyext/test/test_version.py +++ b/pypy/module/cpyext/test/test_version.py @@ -6,10 +6,18 @@ def test_versions(self): import sys init = """ + static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "foo", /* m_name */ + NULL, /* m_doc */ + -1, /* m_size */ + NULL /* m_methods */ + }; if (Py_IsInitialized()) { - PyObject *m = Py_InitModule("foo", NULL); + PyObject *m = PyModule_Create(&moduledef); PyModule_AddStringConstant(m, "py_version", PY_VERSION); PyModule_AddStringConstant(m, "pypy_version", PYPY_VERSION); + return m; } """ module = self.import_module(name='foo', init=init) From noreply at buildbot.pypy.org Sat Apr 13 01:02:13 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Sat, 13 Apr 2013 01:02:13 +0200 (CEST) Subject: [pypy-commit] pypy stdlib-2.7.4: merge default Message-ID: <20130412230213.7B3F11C026A@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: stdlib-2.7.4 Changeset: r63299:132d55a4f411 Date: 2013-04-12 17:51 -0400 http://bitbucket.org/pypy/pypy/changeset/132d55a4f411/ Log: merge default diff too long, truncating to 2000 out of 8430 lines diff --git a/README.rst b/README.rst --- a/README.rst +++ b/README.rst @@ -13,9 +13,9 @@ http://pypy.org/ -The getting-started document will help guide you: +If you want to help developing PyPy, this document might help you: - http://doc.pypy.org/en/latest/getting-started.html + http://doc.pypy.org/ It will also point you to the rest of the documentation which is generated from files in the pypy/doc directory within the source repositories. Enjoy diff --git a/pypy/doc/dir-reference.rst b/pypy/doc/dir-reference.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/dir-reference.rst @@ -0,0 +1,140 @@ +PyPy directory cross-reference +------------------------------ + +Here is a fully referenced alphabetical two-level deep +directory overview of PyPy: + +================================= ============================================ +Directory explanation/links +================================= ============================================ +`pypy/bin/`_ command-line scripts, mainly + `pypy/bin/pyinteractive.py`_ + +`pypy/config/`_ handles the numerous options for building + and running PyPy + +`pypy/doc/`_ text versions of PyPy developer + documentation + +`pypy/doc/config/`_ documentation for the numerous translation + options + +`pypy/doc/discussion/`_ drafts of ideas and documentation + +``doc/*/`` other specific documentation topics or tools + +`pypy/interpreter/`_ `bytecode interpreter`_ and related objects + (frames, functions, modules,...) + +`pypy/interpreter/pyparser/`_ interpreter-level Python source parser + +`pypy/interpreter/astcompiler/`_ interpreter-level bytecode compiler, + via an AST representation + +`pypy/module/`_ contains `mixed modules`_ + implementing core modules with + both application and interpreter level code. + Not all are finished and working. Use + the ``--withmod-xxx`` + or ``--allworkingmodules`` translation + options. + +`pypy/objspace/`_ `object space`_ implementations + +`pypy/objspace/std/`_ the StdObjSpace_ implementing CPython's + objects and types + +`pypy/tool/`_ various utilities and hacks used + from various places + +`pypy/tool/algo/`_ general-purpose algorithmic and mathematic + tools + +`pypy/tool/pytest/`_ support code for our `testing methods`_ + + +`rpython/annotator/`_ `type inferencing code`_ for + `RPython`_ programs + +`rpython/config/`_ handles the numerous options for RPython + + +`rpython/flowspace/`_ the FlowObjSpace_ implementing + `abstract interpretation`_ + +`rpython/rlib/`_ a `"standard library"`_ for RPython_ + programs + +`rpython/rtyper/`_ the `RPython Typer`_ + +`rpython/rtyper/lltypesystem/`_ the `low-level type system`_ for + C-like backends + +`rpython/rtyper/ootypesystem/`_ the `object-oriented type system`_ + for OO backends + +`rpython/memory/`_ the `garbage collector`_ construction + framework + +`rpython/translator/`_ translation_ backends and support code + +`rpython/translator/backendopt/`_ general optimizations that run before a + backend generates code + +`rpython/translator/c/`_ the `GenC backend`_, producing C code + from an + RPython program (generally via the rtyper_) + +`rpython/translator/cli/`_ the `CLI backend`_ for `.NET`_ + (Microsoft CLR or Mono_) + +`pypy/goal/`_ our `main PyPy-translation scripts`_ + live here + +`rpython/translator/jvm/`_ the Java backend + +`rpython/translator/tool/`_ helper tools for translation + +`dotviewer/`_ `graph viewer`_ + +``*/test/`` many directories have a test subdirectory + containing test + modules (see `Testing in PyPy`_) + +``_cache/`` holds cache files from various purposes +================================= ============================================ + +.. _`bytecode interpreter`: interpreter.html +.. _`Testing in PyPy`: coding-guide.html#testing-in-pypy +.. _`mixed modules`: coding-guide.html#mixed-modules +.. _`modules`: coding-guide.html#modules +.. _`basil`: http://people.cs.uchicago.edu/~jriehl/BasilTalk.pdf +.. _`object space`: objspace.html +.. _FlowObjSpace: objspace.html#the-flow-object-space +.. _`transparent proxies`: objspace-proxies.html#tproxy +.. _`Differences between PyPy and CPython`: cpython_differences.html +.. _`What PyPy can do for your objects`: objspace-proxies.html +.. _`Continulets and greenlets`: stackless.html +.. _StdObjSpace: objspace.html#the-standard-object-space +.. _`abstract interpretation`: http://en.wikipedia.org/wiki/Abstract_interpretation +.. _`rpython`: coding-guide.html#rpython +.. _`type inferencing code`: translation.html#the-annotation-pass +.. _`RPython Typer`: translation.html#rpython-typer +.. _`testing methods`: coding-guide.html#testing-in-pypy +.. _`translation`: translation.html +.. _`GenC backend`: translation.html#genc +.. _`CLI backend`: cli-backend.html +.. _`py.py`: getting-started-python.html#the-py.py-interpreter +.. _`translatorshell.py`: getting-started-dev.html#try-out-the-translator +.. _JIT: jit/index.html +.. _`JIT Generation in PyPy`: jit/index.html +.. _`just-in-time compiler generator`: jit/index.html +.. _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 +.. _`main PyPy-translation scripts`: getting-started-python.html#translating-the-pypy-python-interpreter +.. _`.NET`: http://www.microsoft.com/net/ +.. _Mono: http://www.mono-project.com/ +.. _`"standard library"`: rlib.html +.. _`graph viewer`: getting-started-dev.html#try-out-the-translator diff --git a/pypy/doc/getting-started-dev.rst b/pypy/doc/getting-started-dev.rst --- a/pypy/doc/getting-started-dev.rst +++ b/pypy/doc/getting-started-dev.rst @@ -1,13 +1,58 @@ -=============================================================================== -Getting Started with the Translation Toolchain and Development Process -=============================================================================== +============================ +Getting Started with RPython +============================ .. contents:: +RPython is a subset of Python that can be statically compiled. The PyPy +interpreter is written mostly in RPython (with pieces in Python), while +the RPython compiler is written in Python. The hard to understand part +is that Python is a meta-programming language for RPython, that is, +RPython is considered from live objects **after** the imports are done. +This might require more explanation. You start writing RPython from +``entry_point``, a good starting point is +``rpython/translator/goal/targetnopstandalone.py``. This does not do all that +much, but is a start. Now if code analyzed (in this case ``entry_point``) +calls some functions, those calls will be followed. Those followed calls +have to be RPython themselves (and everything they call etc.), however not +entire module files. To show how you can use metaprogramming, we can do +a silly example (note that closures are not RPython):: + + def generator(operation): + if operation == 'add': + def f(a, b): + return a + b + else: + def f(a, b): + return a - b + return f + + add = generator('add') + sub = generator('sub') + + def entry_point(argv): + print add(sub(int(argv[1]), 3) 4) + return 0 + +In this example ``entry_point`` is RPython, ``add`` and ``sub`` are RPython, +however, ``generator`` is not. + +A good introductory level articles are available: + +* Laurence Tratt -- `Fast Enough VMs in Fast Enough Time`_. + +* `How to write interpreters in RPython`_ and `part 2`_ by Andrew Brown. + +.. _`Fast Enough VMs in Fast Enough Time`: http://tratt.net/laurie/tech_articles/articles/fast_enough_vms_in_fast_enough_time + +.. _`How to write interpreters in RPython`: http://morepypy.blogspot.com/2011/04/tutorial-writing-interpreter-with-pypy.html + +.. _`part 2`: http://morepypy.blogspot.com/2011/04/tutorial-part-2-adding-jit.html + .. _`try out the translator`: Trying out the translator -------------------------- +------------------------- The translator is a tool based on the PyPy interpreter which can translate sufficiently static RPython programs into low-level code (in particular it can @@ -28,7 +73,7 @@ >>> t = Translation(snippet.is_perfect_number, [int]) >>> t.view() - + After that, the graph viewer pops up, that lets you interactively inspect the flow graph. To move around, click on something that you want to inspect. To get help about how to use it, press 'H'. To close it again, press 'Q'. @@ -83,10 +128,10 @@ The object returned by ``compile_cli`` or ``compile_jvm`` is a wrapper around the real executable: the parameters are passed as command line arguments, and -the returned value is read from the standard output. +the returned value is read from the standard output. Once you have compiled the snippet, you can also try to launch the -executable directly from the shell. You will find the +executable directly from the shell. You will find the executable in one of the ``/tmp/usession-*`` directories:: # For CLI: diff --git a/pypy/doc/getting-started-python.rst b/pypy/doc/getting-started-python.rst --- a/pypy/doc/getting-started-python.rst +++ b/pypy/doc/getting-started-python.rst @@ -6,7 +6,7 @@ PyPy's Python interpreter is a very compliant Python -interpreter implemented in Python. When translated to C, it passes most of +interpreter implemented in RPython. When compiled, it passes most of `CPythons core language regression tests`_ and comes with many of the extension modules included in the standard library including ``ctypes``. It can run large libraries such as Django_ and Twisted_. There are some small behavioral @@ -147,6 +147,8 @@ Translating using the CLI backend +++++++++++++++++++++++++++++++++ +**Note: the CLI backend is no longer maintained** + To create a standalone .NET executable using the `CLI backend`_:: ./translate.py --backend=cli targetpypystandalone.py diff --git a/pypy/doc/how-to-contribute.rst b/pypy/doc/how-to-contribute.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/how-to-contribute.rst @@ -0,0 +1,78 @@ +How to contribute to PyPy +------------------------- + +This page describes how to contribute to the PyPy project. The first thing +to remember is that PyPy project is very different than most projects out there. +It's also different from a classic compiler project, so academic courses +about compilers often don't apply or lead in the wrong direction. + +Don't just hack +--------------- + +The first and most important rule how not to contribute to PyPy is +"just hacking". This won't work. There are two major reasons why not +-- build times are large and PyPy has very thick layer separation which +make it harder to "just hack a feature". + +Test driven development +----------------------- + +Instead, we practice a lot of test driven development. This is partly because +of very high quality requirements for compilers and partly because there is +simply no other way to get around such complex project, that will keep you sane. +There are probably people out there who are smart enough not to need it, we're +not one of those. You may consider familiarizing yourself with `pytest`_, +since this is a tool we use for tests. +This leads to the next issue: + +Layers +------ + +PyPy has layers. Those layers help us keep the respective parts separated enough +to be worked on independently and make the complexity manageable. This is, +again, just a sanity requirement for such a complex project. For example writing +a new optimization for the JIT usually does **not** involve touching a Python +interpreter at all or the JIT assembler backend or the garbage collector. +Instead it requires writing small tests in +``rpython/jit/metainterp/optimizeopt/test/test_*`` and fixing files there. +After that, you can just compile PyPy and things should just work. + +The short list of layers for further reading. For each of those layers, a good +entry point is a test subdirectory in respective directories. It usually +describes (better or worse) the interfaces between the submodules. For the +``pypy`` subdirectory, most tests are small snippets of python programs that +check for correctness (calls ``AppTestXxx``) that will call the appropriate +part of the interpreter. For the ``rpython`` directory, most tests are small +RPython interpreters that perform certain tasks. To see how they translate +to low-level graphs, run them with ``--view``. To see small interpreters +with a JIT compiler, use ``--viewloops`` option. + +* **python interpreter** - it's the part implemented in the ``pypy/`` directory. + It's implemented in RPython, which is a high level static language with + classes, garbage collection, just-in-time compiler generation and the ability + to call C. A cool part about it is that it can be run untranslated, so all + the tests are runnable without translating PyPy. + + **interpreter** contains the interpreter core + + **objspace** contains implementations of various objects exported to + the Python layer + + **module** directory contains extension modules written in RPython + +* **rpython compiler** that resides in ``rpython/annotator`` and + ``rpython/rtyper`` directories. Consult `introduction to RPython`_ for + further reading + +* **JIT generator** lives in ``rpython/jit`` directory. optimizations live + in ``rpython/jit/metainterp/optimizeopt``, the main JIT in + ``rpython/jit/metainterp`` (runtime part) and + ``rpython/jit/codewriter`` (translation-time part). Backends live in + ``rpython/jit/backend``. + +* **garbage collection** lives in ``rpython/memory`` + +The rest of directories serve specific niche goal and are unlikely a good +entry point. + +.. _`introduction to RPython`: getting-started-dev.rst diff --git a/pypy/doc/index.rst b/pypy/doc/index.rst --- a/pypy/doc/index.rst +++ b/pypy/doc/index.rst @@ -1,15 +1,40 @@ -Welcome to PyPy Development -============================================= +Welcome to PyPy +=============== -The PyPy project aims at producing a flexible and fast Python_ -implementation. The guiding idea is to translate a Python-level -description of the Python language itself to lower level languages. -Rumors have it that the secret goal is being faster-than-C which is -nonsense, isn't it? `more...`_ +The PyPy project aims to produce a flexible and fast Python_ +implementation. This page documents the development of the PyPy +project itself. If you don't know what PyPy is, consult the `PyPy +website`_. If you just want to use PyPy, consult the `download`_ page +and the `getting started with pypy`_ documents. If you want to help +develop PyPy -- keep reading! -Getting into PyPy ... -============================================= +PyPy is written in a language called `RPython`_, which is suitable for +writing dynamic language interpreters (and not much else). RPython is +a subset of Python and is itself written in Python. If you'd like to +learn more about RPython, `Starting with RPython`_ should provide a +reasonable overview. + +**If you would like to contribute to PyPy**, please read `how to +contribute`_ first. PyPy's development style is somewhat different to +that of many other software projects and it often surprises +newcomers. What is **not** necessary is an academic background from +university in writing compilers -- much of it does not apply to PyPy +any way. + +All of the documentation and source code is available under the MIT license, +unless otherwise specified. Consult `LICENSE`_ + +.. _`download`: http://pypy.org/download.html +.. _`getting started with pypy`: getting-started-python.html +.. _`RPython`: coding-guide.html#RPython +.. _`Starting with RPython`: getting-started-dev.html +.. _`how to contribute`: how-to-contribute.html +.. _`PyPy website`: http://pypy.org +.. _`LICENSE`: https://bitbucket.org/pypy/pypy/src/default/LICENSE + +Index of various topics: +======================== * `Getting started`_: how to install and run the PyPy Python interpreter @@ -25,20 +50,30 @@ * `potential project ideas`_: In case you want to get your feet wet... +* `more stuff`_: this is a collection of documentation that's there, but not + particularly organized + Documentation for the PyPy Python Interpreter -=============================================== +============================================= New features of PyPy's Python Interpreter and Translation Framework: * `Differences between PyPy and CPython`_ - * `What PyPy can do for your objects`_ - * `Continulets and greenlets`_ + * `What PyPy can do for your objects`_ - transparent proxy documentation + * `Continulets and greenlets`_ - documentation about stackless features * `JIT Generation in PyPy`_ + * `JIT hooks`_ * `Sandboxing Python code`_ + * `Garbage collection environment variables`_ -Status_ of the project. - +.. _`Differences between PyPy and CPython`: cpython_differences.html +.. _`What PyPy can do for your objects`: objspace-proxies.html +.. _`Continulets and greenlets`: stackless.html +.. _`JIT Generation in PyPy`: jit/index.html +.. _`JIT hooks`: jit-hooks.html +.. _`Sandboxing Python code`: sandbox.html +.. _`Garbage collection environment variables`: gc_info.html Mailing lists, bug tracker, IRC channel ============================================= @@ -79,354 +114,6 @@ .. _`speed.pypy.org`: http://speed.pypy.org .. _`RPython toolchain`: translation.html .. _`potential project ideas`: project-ideas.html - -Project Documentation -===================================== - -PyPy was funded by the EU for several years. See the `web site of the EU -project`_ for more details. - -.. _`web site of the EU project`: http://pypy.org - -architecture_ gives a complete view of PyPy's basic design. - -`coding guide`_ helps you to write code for PyPy (especially also describes -coding in RPython a bit). - -`sprint reports`_ lists reports written at most of our sprints, from -2003 to the present. - -`papers, talks and related projects`_ lists presentations -and related projects as well as our published papers. - -`PyPy video documentation`_ is a page linking to the videos (e.g. of talks and -introductions) that are available. - -`Technical reports`_ is a page that contains links to the -reports that we submitted to the European Union. - -`development methodology`_ describes our sprint-driven approach. - -`LICENSE`_ contains licensing details (basically a straight MIT-license). - -`Glossary`_ of PyPy words to help you align your inner self with -the PyPy universe. - - -Status -=================================== - -PyPy can be used to run Python programs on Linux, OS/X, -Windows, on top of .NET, and on top of Java. -To dig into PyPy it is recommended to try out the current -Mercurial default branch, which is always working or mostly working, -instead of the latest release, which is `2.0 beta1`__. - -.. __: release-2.0.0-beta1.html - -PyPy is mainly developed on Linux and Mac OS X. Windows is supported, -but platform-specific bugs tend to take longer before we notice and fix -them. Linux 64-bit machines are supported (though it may also take some -time before we notice and fix bugs). - -PyPy's own tests `summary`_, daily updated, run through BuildBot infrastructure. -You can also find CPython's compliance tests run with compiled ``pypy-c`` -executables there. - - -Source Code Documentation -=============================================== - -`object spaces`_ discusses the object space interface -and several implementations. - -`bytecode interpreter`_ explains the basic mechanisms -of the bytecode interpreter and virtual machine. - -`interpreter optimizations`_ describes our various strategies for -improving the performance of our interpreter, including alternative -object implementations (for strings, dictionaries and lists) in the -standard object space. - -`translation`_ is a detailed overview of our translation process. The -rtyper_ is the largest component of our translation process. - -`dynamic-language translation`_ is a paper that describes -the translation process, especially the flow object space -and the annotator in detail. (This document is one -of the `EU reports`_.) - -`low-level encapsulation`_ describes how our approach hides -away a lot of low level details. This document is also part -of the `EU reports`_. - -`translation aspects`_ describes how we weave different -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. - -`rlib`_ describes some modules that can be used when implementing programs in -RPython. - -`configuration documentation`_ describes the various configuration options that -allow you to customize PyPy. - -`CLI backend`_ describes the details of the .NET backend. - -`JIT Generation in PyPy`_ describes how we produce the Python Just-in-time Compiler -from our Python interpreter. - - - -.. _`FAQ`: faq.html -.. _Glossary: glossary.html -.. _`PyPy video documentation`: video-index.html -.. _parser: parser.html -.. _`development methodology`: dev_method.html -.. _`sprint reports`: sprint-reports.html -.. _`papers, talks and related projects`: extradoc.html -.. _`object spaces`: objspace.html -.. _`interpreter optimizations`: interpreter-optimizations.html -.. _`translation`: translation.html -.. _`dynamic-language translation`: https://bitbucket.org/pypy/extradoc/raw/tip/eu-report/D05.1_Publish_on_translating_a_very-high-level_description.pdf -.. _`low-level encapsulation`: low-level-encapsulation.html -.. _`translation aspects`: translation-aspects.html -.. _`configuration documentation`: config/ -.. _`coding guide`: coding-guide.html -.. _`architecture`: architecture.html -.. _`getting started`: getting-started.html -.. _`bytecode interpreter`: interpreter.html -.. _`EU reports`: index-report.html -.. _`Technical reports`: index-report.html -.. _`summary`: http://buildbot.pypy.org/summary -.. _`ideas for PyPy related projects`: project-ideas.html -.. _`Nightly builds and benchmarks`: http://tuatara.cs.uni-duesseldorf.de/benchmark.html -.. _`directory reference`: -.. _`rlib`: rlib.html -.. _`Sandboxing Python code`: sandbox.html -.. _`LICENSE`: https://bitbucket.org/pypy/pypy/src/default/LICENSE - -PyPy directory cross-reference ------------------------------- - -Here is a fully referenced alphabetical two-level deep -directory overview of PyPy: - -================================= ============================================ -Directory explanation/links -================================= ============================================ -`pypy/bin/`_ command-line scripts, mainly - `pypy/bin/pyinteractive.py`_ - -`pypy/config/`_ handles the numerous options for building - and running PyPy - -`pypy/doc/`_ text versions of PyPy developer - documentation - -`pypy/doc/config/`_ documentation for the numerous translation - options - -`pypy/doc/discussion/`_ drafts of ideas and documentation - -``doc/*/`` other specific documentation topics or tools - -`pypy/interpreter/`_ `bytecode interpreter`_ and related objects - (frames, functions, modules,...) - -`pypy/interpreter/pyparser/`_ interpreter-level Python source parser - -`pypy/interpreter/astcompiler/`_ interpreter-level bytecode compiler, - via an AST representation - -`pypy/module/`_ contains `mixed modules`_ - implementing core modules with - both application and interpreter level code. - Not all are finished and working. Use - the ``--withmod-xxx`` - or ``--allworkingmodules`` translation - options. - -`pypy/objspace/`_ `object space`_ implementations - -`pypy/objspace/std/`_ the StdObjSpace_ implementing CPython's - objects and types - -`pypy/tool/`_ various utilities and hacks used - from various places - -`pypy/tool/algo/`_ general-purpose algorithmic and mathematic - tools - -`pypy/tool/pytest/`_ support code for our `testing methods`_ - - -`rpython/annotator/`_ `type inferencing code`_ for - `RPython`_ programs - -`rpython/config/`_ handles the numerous options for RPython - - -`rpython/flowspace/`_ the FlowObjSpace_ implementing - `abstract interpretation`_ - -`rpython/rlib/`_ a `"standard library"`_ for RPython_ - programs - -`rpython/rtyper/`_ the `RPython Typer`_ - -`rpython/rtyper/lltypesystem/`_ the `low-level type system`_ for - C-like backends - -`rpython/rtyper/ootypesystem/`_ the `object-oriented type system`_ - for OO backends - -`rpython/memory/`_ the `garbage collector`_ construction - framework - -`rpython/translator/`_ translation_ backends and support code - -`rpython/translator/backendopt/`_ general optimizations that run before a - backend generates code - -`rpython/translator/c/`_ the `GenC backend`_, producing C code - from an - RPython program (generally via the rtyper_) - -`rpython/translator/cli/`_ the `CLI backend`_ for `.NET`_ - (Microsoft CLR or Mono_) - -`pypy/goal/`_ our `main PyPy-translation scripts`_ - live here - -`rpython/translator/jvm/`_ the Java backend - -`rpython/translator/tool/`_ helper tools for translation - -`dotviewer/`_ `graph viewer`_ - -``*/test/`` many directories have a test subdirectory - containing test - modules (see `Testing in PyPy`_) - -``_cache/`` holds cache files from various purposes -================================= ============================================ - -.. _`bytecode interpreter`: interpreter.html -.. _`Testing in PyPy`: coding-guide.html#testing-in-pypy -.. _`mixed modules`: coding-guide.html#mixed-modules -.. _`modules`: coding-guide.html#modules -.. _`basil`: http://people.cs.uchicago.edu/~jriehl/BasilTalk.pdf -.. _`object space`: objspace.html -.. _FlowObjSpace: objspace.html#the-flow-object-space -.. _`transparent proxies`: objspace-proxies.html#tproxy -.. _`Differences between PyPy and CPython`: cpython_differences.html -.. _`What PyPy can do for your objects`: objspace-proxies.html -.. _`Continulets and greenlets`: stackless.html -.. _StdObjSpace: objspace.html#the-standard-object-space -.. _`abstract interpretation`: http://en.wikipedia.org/wiki/Abstract_interpretation -.. _`rpython`: coding-guide.html#rpython -.. _`type inferencing code`: translation.html#the-annotation-pass -.. _`RPython Typer`: translation.html#rpython-typer -.. _`testing methods`: coding-guide.html#testing-in-pypy -.. _`translation`: translation.html -.. _`GenC backend`: translation.html#genc -.. _`CLI backend`: cli-backend.html -.. _`py.py`: getting-started-python.html#the-py.py-interpreter -.. _`translatorshell.py`: getting-started-dev.html#try-out-the-translator -.. _JIT: jit/index.html -.. _`JIT Generation in PyPy`: jit/index.html -.. _`just-in-time compiler generator`: jit/index.html -.. _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 -.. _`main PyPy-translation scripts`: getting-started-python.html#translating-the-pypy-python-interpreter -.. _`.NET`: http://www.microsoft.com/net/ -.. _Mono: http://www.mono-project.com/ -.. _`"standard library"`: rlib.html -.. _`graph viewer`: getting-started-dev.html#try-out-the-translator - - -.. The following documentation is important and reasonably up-to-date: - -.. extradoc: should this be integrated one level up: dcolish? - - -.. toctree:: - :maxdepth: 1 - :hidden: - - getting-started.rst - getting-started-python.rst - getting-started-dev.rst - windows.rst - faq.rst - commandline_ref.rst - architecture.rst - coding-guide.rst - cpython_differences.rst - garbage_collection.rst - gc_info.rst - interpreter.rst - objspace.rst - __pypy__-module.rst - objspace-proxies.rst - config/index.rst - - dev_method.rst - extending.rst - - extradoc.rst - video-index.rst - - glossary.rst - - contributor.rst - - interpreter-optimizations.rst - configuration.rst - parser.rst - rlib.rst - rtyper.rst - rffi.rst - - translation.rst - jit/index.rst - jit/overview.rst - jit/pyjitpl5.rst - - index-of-release-notes.rst - - ctypes-implementation.rst - - how-to-release.rst - - index-report.rst - - stackless.rst - sandbox.rst - - discussions.rst - - cleanup.rst - - sprint-reports.rst - - eventhistory.rst - statistic/index.rst - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`search` -* :ref:`glossary` - +.. _`more stuff`: project-documentation.html .. include:: _ref.txt diff --git a/pypy/doc/needswork.txt b/pypy/doc/needswork.txt deleted file mode 100644 --- a/pypy/doc/needswork.txt +++ /dev/null @@ -1,3 +0,0 @@ -.. warning:: - - This documentation needs work (as discussed during the Gothenburg sprint in 2011) diff --git a/pypy/doc/objspace-proxies.rst b/pypy/doc/objspace-proxies.rst --- a/pypy/doc/objspace-proxies.rst +++ b/pypy/doc/objspace-proxies.rst @@ -5,7 +5,6 @@ .. contents:: - Thanks to the `Object Space`_ architecture, any feature that is based on proxying, extending, changing or otherwise controlling the behavior of all objects in a running program is easy to implement on diff --git a/pypy/doc/project-documentation.rst b/pypy/doc/project-documentation.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/project-documentation.rst @@ -0,0 +1,177 @@ + +Project Documentation +===================================== + +`architecture`_ gives a complete view of PyPy's basic design. + +`coding guide`_ helps you to write code for PyPy (especially also describes +coding in RPython a bit). + +`sprint reports`_ lists reports written at most of our sprints, from +2003 to the present. + +`papers, talks and related projects`_ lists presentations +and related projects as well as our published papers. + +`PyPy video documentation`_ is a page linking to the videos (e.g. of talks and +introductions) that are available. + +`Technical reports`_ is a page that contains links to the +reports that we submitted to the European Union. + +`development methodology`_ describes our sprint-driven approach. + +`LICENSE`_ contains licensing details (basically a straight MIT-license). + +`Glossary`_ of PyPy words to help you align your inner self with +the PyPy universe. + +Source Code Documentation +=============================================== + +`object spaces`_ discusses the object space interface +and several implementations. + +`bytecode interpreter`_ explains the basic mechanisms +of the bytecode interpreter and virtual machine. + +`interpreter optimizations`_ describes our various strategies for +improving the performance of our interpreter, including alternative +object implementations (for strings, dictionaries and lists) in the +standard object space. + +`translation`_ is a detailed overview of our translation process. The +rtyper_ is the largest component of our translation process. + +`dynamic-language translation`_ is a paper that describes +the translation process, especially the flow object space +and the annotator in detail. (This document is one +of the `EU reports`_.) + +`low-level encapsulation`_ describes how our approach hides +away a lot of low level details. This document is also part +of the `EU reports`_. + +`translation aspects`_ describes how we weave different +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. + +`rlib`_ describes some modules that can be used when implementing programs in +RPython. + +`configuration documentation`_ describes the various configuration options that +allow you to customize PyPy. + +`pypy on windows`_ + +`command line reference`_ + +`CLI backend`_ describes the details of the .NET backend. + +`JIT Generation in PyPy`_ describes how we produce the Python Just-in-time Compiler +from our Python interpreter. + +`directory cross-reference`_ + +.. _`garbage collector`: garbage_collection.html +.. _`directory cross-reference`: dir-reference.html +.. _`pypy on windows`: windows.html +.. _`command line reference`: commandline_ref.html +.. _`FAQ`: faq.html +.. _Glossary: glossary.html +.. _`PyPy video documentation`: video-index.html +.. _parser: parser.html +.. _`development methodology`: dev_method.html +.. _`sprint reports`: sprint-reports.html +.. _`papers, talks and related projects`: extradoc.html +.. _`object spaces`: objspace.html +.. _`interpreter optimizations`: interpreter-optimizations.html +.. _`translation`: translation.html +.. _`dynamic-language translation`: https://bitbucket.org/pypy/extradoc/raw/tip/eu-report/D05.1_Publish_on_translating_a_very-high-level_description.pdf +.. _`low-level encapsulation`: low-level-encapsulation.html +.. _`translation aspects`: translation-aspects.html +.. _`configuration documentation`: config/ +.. _`coding guide`: coding-guide.html +.. _`Architecture`: architecture.html +.. _`getting started`: getting-started.html +.. _`bytecode interpreter`: interpreter.html +.. _`EU reports`: index-report.html +.. _`Technical reports`: index-report.html +.. _`summary`: http://buildbot.pypy.org/summary +.. _`ideas for PyPy related projects`: project-ideas.html +.. _`Nightly builds and benchmarks`: http://tuatara.cs.uni-duesseldorf.de/benchmark.html +.. _`directory reference`: +.. _`rlib`: rlib.html +.. _`Sandboxing Python code`: sandbox.html +.. _`LICENSE`: https://bitbucket.org/pypy/pypy/src/default/LICENSE + +.. The following documentation is important and reasonably up-to-date: + +.. extradoc: should this be integrated one level up: dcolish? + +.. toctree:: + :maxdepth: 1 + :hidden: + + interpreter.rst + objspace.rst + __pypy__-module.rst + objspace-proxies.rst + config/index.rst + + dev_method.rst + extending.rst + + extradoc.rst + video-index.rst + + glossary.rst + + contributor.rst + + interpreter-optimizations.rst + configuration.rst + parser.rst + rlib.rst + rtyper.rst + rffi.rst + + translation.rst + jit/index.rst + jit/overview.rst + jit/pyjitpl5.rst + + index-of-release-notes.rst + + ctypes-implementation.rst + + how-to-release.rst + + index-report.rst + + stackless.rst + sandbox.rst + + discussions.rst + + cleanup.rst + + sprint-reports.rst + + eventhistory.rst + statistic/index.rst + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`search` +* :ref:`glossary` + +.. include:: _ref.txt diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -46,6 +46,13 @@ Fix a bug which casused cffi to return the wrong result when calling a C function which calls a Python callback which forces the frames +.. branch: virtual-raw-mallocs +JIT optimizations which makes cffi calls even faster, by removing the need to +allocate a temporary buffer where to store the arguments. + +.. branch: improve-docs-2 +Improve documents and straighten out links + .. branches we don't care about .. branch: autoreds .. branch: reflex-support @@ -121,3 +128,4 @@ cffi implementation of sqlite3 .. branch: release-2.0-beta2 +.. branch: unbreak-freebsd diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py --- a/pypy/interpreter/pyopcode.py +++ b/pypy/interpreter/pyopcode.py @@ -255,19 +255,7 @@ "code=%d, name=%s" % (self.last_instr, opcode, methodname)) - try: - res = meth(oparg, next_instr) - except Exception: - if 0: - import dis, sys - print "*** %s at offset %d (%s)" % (sys.exc_info()[0], - self.last_instr, - methodname) - try: - dis.dis(co_code) - except: - pass - raise + res = meth(oparg, next_instr) if res is not None: next_instr = res diff --git a/pypy/module/_cffi_backend/ccallback.py b/pypy/module/_cffi_backend/ccallback.py --- a/pypy/module/_cffi_backend/ccallback.py +++ b/pypy/module/_cffi_backend/ccallback.py @@ -134,7 +134,7 @@ # W_CTypePrimitiveSigned.convert_from_object() in order # to write a whole 'ffi_arg'. value = misc.as_long(space, w_res) - misc.write_raw_integer_data(ll_res, value, SIZE_OF_FFI_ARG) + misc.write_raw_signed_data(ll_res, value, SIZE_OF_FFI_ARG) return else: # zero extension: fill the '*result' with zeros, and (on big- diff --git a/pypy/module/_cffi_backend/cdataobj.py b/pypy/module/_cffi_backend/cdataobj.py --- a/pypy/module/_cffi_backend/cdataobj.py +++ b/pypy/module/_cffi_backend/cdataobj.py @@ -280,8 +280,13 @@ return self.ctype.iter(self) @specialize.argtype(1) - def write_raw_integer_data(self, source): - misc.write_raw_integer_data(self._cdata, source, self.ctype.size) + def write_raw_signed_data(self, source): + misc.write_raw_signed_data(self._cdata, source, self.ctype.size) + keepalive_until_here(self) + + @specialize.argtype(1) + def write_raw_unsigned_data(self, source): + misc.write_raw_unsigned_data(self._cdata, source, self.ctype.size) keepalive_until_here(self) def write_raw_float_data(self, source): diff --git a/pypy/module/_cffi_backend/ctypeprim.py b/pypy/module/_cffi_backend/ctypeprim.py --- a/pypy/module/_cffi_backend/ctypeprim.py +++ b/pypy/module/_cffi_backend/ctypeprim.py @@ -63,7 +63,7 @@ else: value = self._cast_generic(w_ob) w_cdata = cdataobj.W_CDataMem(space, self.size, self) - w_cdata.write_raw_integer_data(value) + self.write_raw_integer_data(w_cdata, value) return w_cdata def _cast_result(self, intvalue): @@ -94,6 +94,9 @@ from pypy.module._cffi_backend import newtype return newtype.new_primitive_type(self.space, "int") + def write_raw_integer_data(self, w_cdata, value): + w_cdata.write_raw_unsigned_data(value) + class W_CTypePrimitiveChar(W_CTypePrimitiveCharOrUniChar): _attrs_ = [] @@ -185,10 +188,10 @@ if self.size < rffi.sizeof(lltype.Signed): if r_uint(value) - self.vmin > self.vrangemax: self._overflow(w_ob) - misc.write_raw_integer_data(cdata, value, self.size) + misc.write_raw_signed_data(cdata, value, self.size) else: value = misc.as_long_long(self.space, w_ob) - misc.write_raw_integer_data(cdata, value, self.size) + misc.write_raw_signed_data(cdata, value, self.size) def get_vararg_type(self): if self.size < rffi.sizeof(rffi.INT): @@ -196,6 +199,9 @@ return newtype.new_primitive_type(self.space, "int") return self + def write_raw_integer_data(self, w_cdata, value): + w_cdata.write_raw_signed_data(value) + class W_CTypePrimitiveUnsigned(W_CTypePrimitive): _attrs_ = ['value_fits_long', 'value_fits_ulong', 'vrangemax'] @@ -222,10 +228,10 @@ if self.value_fits_long: if value > self.vrangemax: self._overflow(w_ob) - misc.write_raw_integer_data(cdata, value, self.size) + misc.write_raw_unsigned_data(cdata, value, self.size) else: value = misc.as_unsigned_long_long(self.space, w_ob, strict=True) - misc.write_raw_integer_data(cdata, value, self.size) + misc.write_raw_unsigned_data(cdata, value, self.size) def convert_to_object(self, cdata): if self.value_fits_ulong: @@ -244,6 +250,9 @@ return newtype.new_primitive_type(self.space, "int") return self + def write_raw_integer_data(self, w_cdata, value): + w_cdata.write_raw_unsigned_data(value) + class W_CTypePrimitiveBool(W_CTypePrimitiveUnsigned): _attrs_ = [] diff --git a/pypy/module/_cffi_backend/ctypestruct.py b/pypy/module/_cffi_backend/ctypestruct.py --- a/pypy/module/_cffi_backend/ctypestruct.py +++ b/pypy/module/_cffi_backend/ctypestruct.py @@ -242,11 +242,13 @@ # value = misc.as_long_long(space, w_ob) if isinstance(ctype, ctypeprim.W_CTypePrimitiveSigned): + is_signed = True fmin = -(r_longlong(1) << (self.bitsize - 1)) fmax = (r_longlong(1) << (self.bitsize - 1)) - 1 if fmax == 0: fmax = 1 # special case to let "int x:1" receive "1" else: + is_signed = False fmin = r_longlong(0) fmax = r_longlong((r_ulonglong(1) << self.bitsize) - 1) if value < fmin or value > fmax: @@ -258,7 +260,10 @@ rawvalue = r_ulonglong(value) << self.bitshift rawfielddata = misc.read_raw_unsigned_data(cdata, ctype.size) rawfielddata = (rawfielddata & ~rawmask) | (rawvalue & rawmask) - misc.write_raw_integer_data(cdata, rawfielddata, ctype.size) + if is_signed: + misc.write_raw_signed_data(cdata, rawfielddata, ctype.size) + else: + misc.write_raw_unsigned_data(cdata, rawfielddata, ctype.size) W_CField.typedef = TypeDef( diff --git a/pypy/module/_cffi_backend/misc.py b/pypy/module/_cffi_backend/misc.py --- a/pypy/module/_cffi_backend/misc.py +++ b/pypy/module/_cffi_backend/misc.py @@ -9,6 +9,7 @@ from rpython.rtyper.lltypesystem import lltype, llmemory, rffi from rpython.translator.tool.cbuild import ExternalCompilationInfo + # ____________________________________________________________ _prim_signed_types = unrolling_iterable([ @@ -65,19 +66,22 @@ return rffi.cast(rffi.LONGDOUBLEP, target)[0] @specialize.argtype(1) -def write_raw_integer_data(target, source, size): - if is_signed_integer_type(lltype.typeOf(source)): - for TP, TPP in _prim_signed_types: - if size == rffi.sizeof(TP): - rffi.cast(TPP, target)[0] = rffi.cast(TP, source) - return - else: - for TP, TPP in _prim_unsigned_types: - if size == rffi.sizeof(TP): - rffi.cast(TPP, target)[0] = rffi.cast(TP, source) - return +def write_raw_unsigned_data(target, source, size): + for TP, TPP in _prim_unsigned_types: + if size == rffi.sizeof(TP): + rffi.cast(TPP, target)[0] = rffi.cast(TP, source) + return raise NotImplementedError("bad integer size") + at specialize.argtype(1) +def write_raw_signed_data(target, source, size): + for TP, TPP in _prim_signed_types: + if size == rffi.sizeof(TP): + rffi.cast(TPP, target)[0] = rffi.cast(TP, source) + return + raise NotImplementedError("bad integer size") + + def write_raw_float_data(target, source, size): for TP, TPP in _prim_float_types: if size == rffi.sizeof(TP): diff --git a/pypy/module/_io/interp_bytesio.py b/pypy/module/_io/interp_bytesio.py --- a/pypy/module/_io/interp_bytesio.py +++ b/pypy/module/_io/interp_bytesio.py @@ -2,37 +2,26 @@ TypeDef, generic_new_descr, GetSetProperty) from pypy.interpreter.gateway import interp2app, unwrap_spec from pypy.interpreter.error import OperationError, operationerrfmt +from rpython.rlib.rStringIO import RStringIO from rpython.rlib.rarithmetic import r_longlong from pypy.module._io.interp_bufferedio import W_BufferedIOBase from pypy.module._io.interp_iobase import convert_size import sys -def buffer2string(buffer, start, end): - from rpython.rlib.rstring import StringBuilder - builder = StringBuilder(end - start) - for i in range(start, end): - builder.append(buffer[i]) - return builder.build() -class W_BytesIO(W_BufferedIOBase): +class W_BytesIO(RStringIO, W_BufferedIOBase): def __init__(self, space): W_BufferedIOBase.__init__(self, space) - self.pos = 0 - self.string_size = 0 - self.buf = None + self.init() def descr_init(self, space, w_initial_bytes=None): - # In case __init__ is called multiple times - self.buf = [] - self.string_size = 0 - self.pos = 0 - + self.init() if not space.is_none(w_initial_bytes): self.write_w(space, w_initial_bytes) - self.pos = 0 + self.seek(0) def _check_closed(self, space, message=None): - if self.buf is None: + if self.is_closed(): if message is None: message = "I/O operation on closed file" raise OperationError(space.w_ValueError, space.wrap(message)) @@ -40,36 +29,12 @@ def read_w(self, space, w_size=None): self._check_closed(space) size = convert_size(space, w_size) - - # adjust invalid sizes - available = self.string_size - self.pos - if not 0 <= size <= available: - size = available - if size < 0: - size = 0 - - output = buffer2string(self.buf, self.pos, self.pos + size) - self.pos += size - return space.wrap(output) + return space.wrap(self.read(size)) def readline_w(self, space, w_limit=None): self._check_closed(space) limit = convert_size(space, w_limit) - - cur_pos = self.pos - if limit < 0: - end_pos = self.string_size - else: - end_pos = min(cur_pos + limit, self.string_size) - while cur_pos != end_pos: - if self.buf[cur_pos] == '\n': - cur_pos += 1 - break - cur_pos += 1 - - output = buffer2string(self.buf, self.pos, cur_pos) - self.pos = cur_pos - return space.wrap(output) + return space.wrap(self.readline(limit)) def read1_w(self, space, w_size): return self.read_w(space, w_size) @@ -79,56 +44,28 @@ rwbuffer = space.rwbuffer_w(w_buffer) size = rwbuffer.getlength() - if self.pos + size > self.string_size: - size = self.string_size - self.pos - - output = buffer2string(self.buf, self.pos, self.pos + size) - length = len(output) + output = self.read(size) rwbuffer.setslice(0, output) - self.pos += length - return space.wrap(length) + return space.wrap(len(output)) def write_w(self, space, w_data): self._check_closed(space) if space.isinstance_w(w_data, space.w_unicode): raise OperationError(space.w_TypeError, space.wrap( "bytes string of buffer expected")) - buf = space.buffer_w(w_data) - length = buf.getlength() + buf = space.bufferstr_w(w_data) + length = len(buf) if length <= 0: - return - - if self.pos + length > len(self.buf): - self.buf.extend(['\0'] * (self.pos + length - len(self.buf))) - - if self.pos > self.string_size: - # In case of overseek, pad with null bytes the buffer region - # between the end of stream and the current position. - # - # 0 lo string_size hi - # | |<---used--->|<----------available----------->| - # | | <--to pad-->|<---to write---> | - # 0 buf position - for i in range(self.string_size, self.pos): - self.buf[i] = '\0' - - # Copy the data to the internal buffer, overwriting some of the - # existing data if self->pos < self->string_size. - for i in range(length): - self.buf[self.pos + i] = buf.getitem(i) - self.pos += length - - # Set the new length of the internal string if it has changed - if self.string_size < self.pos: - self.string_size = self.pos - + return space.wrap(0) + self.write(buf) return space.wrap(length) def truncate_w(self, space, w_size=None): self._check_closed(space) + pos = self.tell() if space.is_none(w_size): - size = self.pos + size = pos else: size = space.r_longlong_w(w_size) @@ -136,19 +73,20 @@ raise OperationError(space.w_ValueError, space.wrap( "negative size value")) - if size < self.string_size: - self.string_size = size - del self.buf[size:] - + self.truncate(size) + if size == pos: + self.seek(0, 2) + else: + self.seek(pos) return space.wrap(size) def getvalue_w(self, space): self._check_closed(space) - return space.wrap(buffer2string(self.buf, 0, self.string_size)) + return space.wrap(self.getvalue()) def tell_w(self, space): self._check_closed(space) - return space.wrap(self.pos) + return space.wrap(self.tell()) @unwrap_spec(pos=r_longlong, whence=int) def seek_w(self, space, pos, whence=0): @@ -159,24 +97,19 @@ raise OperationError(space.w_ValueError, space.wrap( "negative seek value")) elif whence == 1: - if pos > sys.maxint - self.pos: + if pos > sys.maxint - self.tell(): raise OperationError(space.w_OverflowError, space.wrap( "new position too large")) - pos += self.pos elif whence == 2: - if pos > sys.maxint - self.string_size: + if pos > sys.maxint - self.getsize(): raise OperationError(space.w_OverflowError, space.wrap( "new position too large")) - pos += self.string_size else: raise operationerrfmt(space.w_ValueError, "whence must be between 0 and 2, not %d", whence) - if pos >= 0: - self.pos = pos - else: - self.pos = 0 - return space.wrap(self.pos) + self.seek(pos, whence) + return space.wrap(self.tell()) def readable_w(self, space): self._check_closed(space) @@ -191,17 +124,16 @@ return space.w_True def close_w(self, space): - self.buf = None + self.close() def closed_get_w(self, space): - return space.wrap(self.buf is None) + return space.wrap(self.is_closed()) def getstate_w(self, space): self._check_closed(space) - w_content = space.wrap(buffer2string(self.buf, 0, self.string_size)) return space.newtuple([ - w_content, - space.wrap(self.pos), + space.wrap(self.getvalue()), + space.wrap(self.tell()), self.getdict(space)]) def setstate_w(self, space, w_state): @@ -214,13 +146,13 @@ space.type(w_state).getname(space) ) w_content, w_pos, w_dict = space.unpackiterable(w_state, 3) + self.truncate(0) + self.write_w(space, w_content) pos = space.int_w(w_pos) - self.buf = [] - self.write_w(space, w_content) if pos < 0: raise OperationError(space.w_ValueError, space.wrap( "position value cannot be negative")) - self.pos = pos + self.seek(pos) if not space.is_w(w_dict, space.w_None): space.call_method(self.getdict(space), "update", w_dict) diff --git a/pypy/module/_io/interp_stringio.py b/pypy/module/_io/interp_stringio.py --- a/pypy/module/_io/interp_stringio.py +++ b/pypy/module/_io/interp_stringio.py @@ -169,9 +169,9 @@ self.pos = end return space.wrap(u''.join(self.buf[start:end])) - @unwrap_spec(limit=int) - def readline_w(self, space, limit=-1): + def readline_w(self, space, w_limit=None): self._check_closed(space) + limit = convert_size(space, w_limit) if self.pos >= len(self.buf): return space.wrap(u"") diff --git a/pypy/module/_io/test/test_bytesio.py b/pypy/module/_io/test/test_bytesio.py --- a/pypy/module/_io/test/test_bytesio.py +++ b/pypy/module/_io/test/test_bytesio.py @@ -4,6 +4,15 @@ def test_init(self): import _io raises(TypeError, _io.BytesIO, u"12345") + buf = "1234567890" + b = _io.BytesIO(buf) + assert b.getvalue() == buf + b = _io.BytesIO(None) + assert b.getvalue() == "" + b.__init__(buf * 2) + assert b.getvalue() == buf * 2 + b.__init__(buf) + assert b.getvalue() == buf def test_init_kwargs(self): import _io @@ -27,6 +36,7 @@ def test_write(self): import _io f = _io.BytesIO() + assert f.write("") == 0 assert f.write("hello") == 5 import gc; gc.collect() assert f.getvalue() == "hello" @@ -50,10 +60,17 @@ def test_truncate(self): import _io - f = _io.BytesIO("hello") + f = _io.BytesIO() + f.write("hello") + assert f.truncate(0) == 0 + assert f.tell() == 5 + f.seek(0) + f.write("hello") f.seek(3) assert f.truncate() == 3 assert f.getvalue() == "hel" + assert f.truncate(2) == 2 + assert f.tell() == 3 def test_setstate(self): # state is (content, position, __dict__) @@ -76,7 +93,13 @@ import _io b = _io.BytesIO("hello") + a1 = bytearray('t') + a2 = bytearray('testing') + assert b.readinto(a1) == 1 + assert b.readinto(a2) == 4 b.close() + assert a1 == "h" + assert a2 == "elloing" raises(ValueError, b.readinto, bytearray("hello")) def test_readline(self): diff --git a/pypy/module/_io/test/test_stringio.py b/pypy/module/_io/test/test_stringio.py --- a/pypy/module/_io/test/test_stringio.py +++ b/pypy/module/_io/test/test_stringio.py @@ -32,7 +32,7 @@ raises(ValueError, sio.read, 1) raises(ValueError, sio.write, u"text") - def testRead(self): + def test_read(self): import io buf = u"1234567890" sio = io.StringIO(buf) @@ -42,6 +42,13 @@ assert buf[5:] == sio.read(900) assert u"" == sio.read() + def test_readline(self): + import io + sio = io.StringIO(u'123\n456') + assert sio.readline(2) == '12' + assert sio.readline(None) == '3\n' + assert sio.readline() == '456' + def test_seek(self): import io diff --git a/pypy/module/_minimal_curses/__init__.py b/pypy/module/_minimal_curses/__init__.py --- a/pypy/module/_minimal_curses/__init__.py +++ b/pypy/module/_minimal_curses/__init__.py @@ -2,10 +2,12 @@ import _curses except ImportError: try: - import _minimal_curses as _curses # when running on top of pypy-c + # when running on top of pypy before it had _curses, settle for minimal + # we prefer _curses so any constants added make it into _minimal_curses + import _minimal_curses as _curses except ImportError: import py - py.test.skip("no _curses or _minimal_curses module") #no _curses at all + py.test.skip("no _curses or _minimal_curses module") # no _curses at all from pypy.interpreter.mixedmodule import MixedModule from pypy.module._minimal_curses import fficurses # for side effects diff --git a/pypy/module/cStringIO/interp_stringio.py b/pypy/module/cStringIO/interp_stringio.py --- a/pypy/module/cStringIO/interp_stringio.py +++ b/pypy/module/cStringIO/interp_stringio.py @@ -146,7 +146,7 @@ class W_OutputType(RStringIO, W_InputOutputType): def __init__(self, space): - RStringIO.__init__(self) + self.init() self.space = space def descr_truncate(self, w_size=None): @@ -159,6 +159,7 @@ if size < 0: raise OperationError(space.w_IOError, space.wrap("negative size")) self.truncate(size) + self.seek(0, 2) @unwrap_spec(buffer='bufferstr') def descr_write(self, buffer): diff --git a/pypy/module/cStringIO/test/test_interp_stringio.py b/pypy/module/cStringIO/test/test_interp_stringio.py --- a/pypy/module/cStringIO/test/test_interp_stringio.py +++ b/pypy/module/cStringIO/test/test_interp_stringio.py @@ -142,8 +142,11 @@ f.write(' world') f.truncate(30) assert f.getvalue() == '\x00' * 20 + 'hello worl' + assert f.tell() == 30 + f.seek(0) f.truncate(25) assert f.getvalue() == '\x00' * 20 + 'hello' + assert f.tell() == 25 f.write('baz') f.write('egg') f.truncate(3) diff --git a/pypy/module/cpyext/test/test_cpyext.py b/pypy/module/cpyext/test/test_cpyext.py --- a/pypy/module/cpyext/test/test_cpyext.py +++ b/pypy/module/cpyext/test/test_cpyext.py @@ -1,6 +1,6 @@ import sys import weakref -import os.path +import os import py @@ -19,6 +19,21 @@ from rpython.tool.identity_dict import identity_dict from rpython.tool import leakfinder +def setup_module(module): + if os.name == 'nt': + # Do not open dreaded dialog box on segfault + import ctypes + SEM_NOGPFAULTERRORBOX = 0x0002 # From MSDN + old_err_mode = ctypes.windll.kernel32.GetErrorMode() + new_err_mode = old_err_mode | SEM_NOGPFAULTERRORBOX + ctypes.windll.kernel32.SetErrorMode(new_err_mode) + module.old_err_mode = old_err_mode + +def teardown_module(module): + if os.name == 'nt': + import ctypes + ctypes.windll.kernel32.SetErrorMode(module.old_err_mode) + @api.cpython_api([], api.PyObject) def PyPy_Crash1(space): 1/0 diff --git a/pypy/module/pypyjit/test_pypy_c/test__ffi.py b/pypy/module/pypyjit/test_pypy_c/test__ffi.py deleted file mode 100644 --- a/pypy/module/pypyjit/test_pypy_c/test__ffi.py +++ /dev/null @@ -1,211 +0,0 @@ -import sys, py -from pypy.module.pypyjit.test_pypy_c.test_00_model import BaseTestPyPyC - -class Test__ffi(BaseTestPyPyC): - - def test__ffi_call(self): - from rpython.rlib.test.test_clibffi import get_libm_name - def main(libm_name): - try: - from _ffi import CDLL, types - except ImportError: - sys.stderr.write('SKIP: cannot import _ffi\n') - return 0 - - libm = CDLL(libm_name) - pow = libm.getfunc('pow', [types.double, types.double], - types.double) - i = 0 - res = 0 - while i < 300: - tmp = pow(2, 3) # ID: fficall - res += tmp - i += 1 - return pow.getaddr(), res - # - libm_name = get_libm_name(sys.platform) - log = self.run(main, [libm_name]) - pow_addr, res = log.result - assert res == 8.0 * 300 - py.test.xfail() # XXX re-optimize _ffi for the JIT? - loop, = log.loops_by_filename(self.filepath) - if 'ConstClass(pow)' in repr(loop): # e.g. OS/X - pow_addr = 'ConstClass(pow)' - assert loop.match_by_id('fficall', """ - guard_not_invalidated(descr=...) - i17 = force_token() - setfield_gc(p0, i17, descr=<.* .*PyFrame.vable_token .*>) - f21 = call_release_gil(%s, 2.000000, 3.000000, descr=) - guard_not_forced(descr=...) - guard_no_exception(descr=...) - """ % pow_addr) - - - def test__ffi_call_frame_does_not_escape(self): - from rpython.rlib.test.test_clibffi import get_libm_name - def main(libm_name): - try: - from _ffi import CDLL, types - except ImportError: - sys.stderr.write('SKIP: cannot import _ffi\n') - return 0 - - libm = CDLL(libm_name) - pow = libm.getfunc('pow', [types.double, types.double], - types.double) - - def mypow(a, b): - return pow(a, b) - - i = 0 - res = 0 - while i < 300: - tmp = mypow(2, 3) - res += tmp - i += 1 - return pow.getaddr(), res - # - libm_name = get_libm_name(sys.platform) - log = self.run(main, [libm_name]) - pow_addr, res = log.result - assert res == 8.0 * 300 - loop, = log.loops_by_filename(self.filepath) - opnames = log.opnames(loop.allops()) - # we only force the virtualref, not its content - assert opnames.count('new_with_vtable') == 1 - - def test__ffi_call_releases_gil(self): - from rpython.rlib.clibffi import get_libc_name - def main(libc_name, n): - import time - import os - from threading import Thread - # - if os.name == 'nt': - from _ffi import WinDLL, types - libc = WinDLL('Kernel32.dll') - sleep = libc.getfunc('Sleep', [types.uint], types.uint) - delays = [0]*n + [1000] - else: - from _ffi import CDLL, types - libc = CDLL(libc_name) - sleep = libc.getfunc('sleep', [types.uint], types.uint) - delays = [0]*n + [1] - # - def loop_of_sleeps(i, delays): - for delay in delays: - sleep(delay) # ID: sleep - # - threads = [Thread(target=loop_of_sleeps, args=[i, delays]) for i in range(5)] - start = time.time() - for i, thread in enumerate(threads): - thread.start() - for thread in threads: - thread.join() - end = time.time() - return end - start - log = self.run(main, [get_libc_name(), 200], threshold=150, - import_site=True) - assert 1 <= log.result <= 1.5 # at most 0.5 seconds of overhead - loops = log.loops_by_id('sleep') - assert len(loops) == 1 # make sure that we actually JITted the loop - - - def test_ctypes_call(self): - from rpython.rlib.test.test_clibffi import get_libm_name - def main(libm_name): - import ctypes - libm = ctypes.CDLL(libm_name) - fabs = libm.fabs - fabs.argtypes = [ctypes.c_double] - fabs.restype = ctypes.c_double - x = -4 - i = 0 - while i < 300: - x = fabs(x) - x = x - 100 - i += 1 - return fabs._ptr.getaddr(), x - - libm_name = get_libm_name(sys.platform) - log = self.run(main, [libm_name], import_site=True) - fabs_addr, res = log.result - assert res == -4.0 - loop, = log.loops_by_filename(self.filepath) - ops = loop.allops() - opnames = log.opnames(ops) - assert opnames.count('new_with_vtable') == 1 # only the virtualref - py.test.xfail() # XXX re-optimize _ffi for the JIT? - assert opnames.count('call_release_gil') == 1 - idx = opnames.index('call_release_gil') - call = ops[idx] - assert (call.args[0] == 'ConstClass(fabs)' or # e.g. OS/X - int(call.args[0]) == fabs_addr) - - - def test__ffi_struct(self): - def main(): - from _ffi import _StructDescr, Field, types - fields = [ - Field('x', types.slong), - ] - descr = _StructDescr('foo', fields) - struct = descr.allocate() - i = 0 - while i < 300: - x = struct.getfield('x') # ID: getfield - x = x+1 - struct.setfield('x', x) # ID: setfield - i += 1 - return struct.getfield('x') - # - log = self.run(main, []) - py.test.xfail() # XXX re-optimize _ffi for the JIT? - loop, = log.loops_by_filename(self.filepath) - assert loop.match_by_id('getfield', """ - guard_not_invalidated(descr=...) - i57 = getfield_raw(i46, descr=) - """) - assert loop.match_by_id('setfield', """ - setfield_raw(i44, i57, descr=) - """) - - - def test__cffi_call(self): - from rpython.rlib.test.test_clibffi import get_libm_name - def main(libm_name): - try: - import _cffi_backend - except ImportError: - sys.stderr.write('SKIP: cannot import _cffi_backend\n') - return 0 - - libm = _cffi_backend.load_library(libm_name) - BDouble = _cffi_backend.new_primitive_type("double") - BPow = _cffi_backend.new_function_type([BDouble, BDouble], BDouble) - pow = libm.load_function(BPow, 'pow') - i = 0 - res = 0 - while i < 300: - tmp = pow(2, 3) # ID: cfficall - res += tmp - i += 1 - BLong = _cffi_backend.new_primitive_type("long") - pow_addr = int(_cffi_backend.cast(BLong, pow)) - return pow_addr, res - # - libm_name = get_libm_name(sys.platform) - log = self.run(main, [libm_name]) - pow_addr, res = log.result - assert res == 8.0 * 300 - loop, = log.loops_by_filename(self.filepath) - if 'ConstClass(pow)' in repr(loop): # e.g. OS/X - pow_addr = 'ConstClass(pow)' - assert loop.match_by_id('cfficall', """ - ... - f1 = call_release_gil(..., descr=) - ... - """) - # so far just check that call_release_gil() is produced. - # later, also check that the arguments to call_release_gil() - # are constants, and that the numerous raw_mallocs are removed diff --git a/pypy/module/pypyjit/test_pypy_c/test_ffi.py b/pypy/module/pypyjit/test_pypy_c/test_ffi.py new file mode 100644 --- /dev/null +++ b/pypy/module/pypyjit/test_pypy_c/test_ffi.py @@ -0,0 +1,279 @@ +import sys, py +from pypy.module.pypyjit.test_pypy_c.test_00_model import BaseTestPyPyC + +class Test__ffi(BaseTestPyPyC): + + def test__ffi_call(self): + from rpython.rlib.test.test_clibffi import get_libm_name + def main(libm_name): + try: + from _ffi import CDLL, types + except ImportError: + sys.stderr.write('SKIP: cannot import _ffi\n') + return 0 + + libm = CDLL(libm_name) + pow = libm.getfunc('pow', [types.double, types.double], + types.double) + i = 0 + res = 0 + while i < 300: + tmp = pow(2, 3) # ID: fficall + res += tmp + i += 1 + return pow.getaddr(), res + # + libm_name = get_libm_name(sys.platform) + log = self.run(main, [libm_name]) + pow_addr, res = log.result + assert res == 8.0 * 300 + py.test.xfail() # XXX re-optimize _ffi for the JIT? + loop, = log.loops_by_filename(self.filepath) + if 'ConstClass(pow)' in repr(loop): # e.g. OS/X + pow_addr = 'ConstClass(pow)' + assert loop.match_by_id('fficall', """ + guard_not_invalidated(descr=...) + i17 = force_token() + setfield_gc(p0, i17, descr=<.* .*PyFrame.vable_token .*>) + f21 = call_release_gil(%s, 2.000000, 3.000000, descr=) + guard_not_forced(descr=...) + guard_no_exception(descr=...) + """ % pow_addr) + + + def test__ffi_call_frame_does_not_escape(self): + from rpython.rlib.test.test_clibffi import get_libm_name + def main(libm_name): + try: + from _ffi import CDLL, types + except ImportError: + sys.stderr.write('SKIP: cannot import _ffi\n') + return 0 + + libm = CDLL(libm_name) + pow = libm.getfunc('pow', [types.double, types.double], + types.double) + + def mypow(a, b): + return pow(a, b) + + i = 0 + res = 0 + while i < 300: + tmp = mypow(2, 3) + res += tmp + i += 1 + return pow.getaddr(), res + # + libm_name = get_libm_name(sys.platform) + log = self.run(main, [libm_name]) + pow_addr, res = log.result + assert res == 8.0 * 300 + loop, = log.loops_by_filename(self.filepath) + opnames = log.opnames(loop.allops()) + # we only force the virtualref, not its content + assert opnames.count('new_with_vtable') == 1 + + def test__ffi_call_releases_gil(self): + from rpython.rlib.clibffi import get_libc_name + def main(libc_name, n): + import time + import os + from threading import Thread + # + if os.name == 'nt': + from _ffi import WinDLL, types + libc = WinDLL('Kernel32.dll') + sleep = libc.getfunc('Sleep', [types.uint], types.uint) + delays = [0]*n + [1000] + else: + from _ffi import CDLL, types + libc = CDLL(libc_name) + sleep = libc.getfunc('sleep', [types.uint], types.uint) + delays = [0]*n + [1] + # + def loop_of_sleeps(i, delays): + for delay in delays: + sleep(delay) # ID: sleep + # + threads = [Thread(target=loop_of_sleeps, args=[i, delays]) for i in range(5)] + start = time.time() + for i, thread in enumerate(threads): + thread.start() + for thread in threads: + thread.join() + end = time.time() + return end - start + log = self.run(main, [get_libc_name(), 200], threshold=150, + import_site=True) + assert 1 <= log.result <= 1.5 # at most 0.5 seconds of overhead + loops = log.loops_by_id('sleep') + assert len(loops) == 1 # make sure that we actually JITted the loop + + def test_ctypes_call(self): + from rpython.rlib.test.test_clibffi import get_libm_name + def main(libm_name): + import ctypes + libm = ctypes.CDLL(libm_name) + fabs = libm.fabs + fabs.argtypes = [ctypes.c_double] + fabs.restype = ctypes.c_double + x = -4 + i = 0 + while i < 300: + x = fabs(x) + x = x - 100 + i += 1 + return fabs._ptr.getaddr(), x + + libm_name = get_libm_name(sys.platform) From noreply at buildbot.pypy.org Sat Apr 13 01:02:14 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Sat, 13 Apr 2013 01:02:14 +0200 (CEST) Subject: [pypy-commit] pypy stdlib-2.7.4: test and fix for TextIO flush error on close Message-ID: <20130412230214.C670C1C026A@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: stdlib-2.7.4 Changeset: r63300:ccbca586192b Date: 2013-04-12 19:00 -0400 http://bitbucket.org/pypy/pypy/changeset/ccbca586192b/ Log: test and fix for TextIO flush error on close diff --git a/pypy/module/_io/interp_textio.py b/pypy/module/_io/interp_textio.py --- a/pypy/module/_io/interp_textio.py +++ b/pypy/module/_io/interp_textio.py @@ -497,7 +497,8 @@ try: space.call_method(self, "flush") finally: - return space.call_method(self.w_buffer, "close") + ret = space.call_method(self.w_buffer, "close") + return ret # _____________________________________________________________ # read methods diff --git a/pypy/module/_io/test/test_textio.py b/pypy/module/_io/test/test_textio.py --- a/pypy/module/_io/test/test_textio.py +++ b/pypy/module/_io/test/test_textio.py @@ -199,6 +199,15 @@ b.name = "dummy" assert repr(t) == "<_io.TextIOWrapper name='dummy' encoding='utf-8'>" + def test_flush_error_on_close(self): + import _io + txt = _io.TextIOWrapper(_io.BytesIO(""), encoding="ascii") + def bad_flush(): + raise IOError() + txt.flush = bad_flush + raises(IOError, txt.close) # exception not swallowed + assert txt.closed + class AppTestIncrementalNewlineDecoder: def test_newline_decoder(self): From noreply at buildbot.pypy.org Sat Apr 13 01:12:27 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Sat, 13 Apr 2013 01:12:27 +0200 (CEST) Subject: [pypy-commit] pypy py3k: explicitly flush here because stdout is not always line buffered Message-ID: <20130412231228.001AD1C026A@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63301:6402218c0442 Date: 2013-04-12 16:11 -0700 http://bitbucket.org/pypy/pypy/changeset/6402218c0442/ Log: explicitly flush here because stdout is not always line buffered diff --git a/pypy/module/cpyext/test/test_pyfile.py b/pypy/module/cpyext/test/test_pyfile.py --- a/pypy/module/cpyext/test/test_pyfile.py +++ b/pypy/module/cpyext/test/test_pyfile.py @@ -65,11 +65,10 @@ api.PyFile_SetBufSize() def test_file_writestring(self, space, api, capfd): - s = rffi.str2charp("test\n") - try: - api.PyFile_WriteString(s, space.sys.get("stdout")) - finally: - rffi.free_charp(s) + w_stdout = space.sys.get("stdout") + with rffi.scoped_str2charp("test\n") as s: + api.PyFile_WriteString(s, w_stdout) + space.call_method(w_stdout, "flush") out, err = capfd.readouterr() out = out.replace('\r\n', '\n') assert out == "test\n" From noreply at buildbot.pypy.org Sat Apr 13 01:39:14 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Sat, 13 Apr 2013 01:39:14 +0200 (CEST) Subject: [pypy-commit] pypy default: enhance FakeObjSpace so checkmodule works for _io Message-ID: <20130412233914.BC83B1C070B@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63302:cb88984431b7 Date: 2013-04-12 19:34 -0400 http://bitbucket.org/pypy/pypy/changeset/cb88984431b7/ Log: enhance FakeObjSpace so checkmodule works for _io diff --git a/pypy/module/_io/test/test_ztranslation.py b/pypy/module/_io/test/test_ztranslation.py new file mode 100644 --- /dev/null +++ b/pypy/module/_io/test/test_ztranslation.py @@ -0,0 +1,4 @@ +from pypy.objspace.fake.checkmodule import checkmodule + +def test_checkmodule(): + checkmodule('_io') diff --git a/pypy/objspace/fake/objspace.py b/pypy/objspace/fake/objspace.py --- a/pypy/objspace/fake/objspace.py +++ b/pypy/objspace/fake/objspace.py @@ -58,6 +58,10 @@ class W_MyType(W_MyObject): def __init__(self): self.mro_w = [w_some_obj(), w_some_obj()] + self.dict_w = {'__str__': w_some_obj()} + + def get_module(self): + return w_some_obj() def w_some_obj(): if NonConstant(False): @@ -318,7 +322,7 @@ ObjSpace.ExceptionTable + ['int', 'str', 'float', 'long', 'tuple', 'list', 'dict', 'unicode', 'complex', 'slice', 'bool', - 'basestring', 'object']): + 'basestring', 'object', 'bytearray']): setattr(FakeObjSpace, 'w_' + name, w_some_obj()) FakeObjSpace.w_type = w_some_type() # From noreply at buildbot.pypy.org Sat Apr 13 01:39:16 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Sat, 13 Apr 2013 01:39:16 +0200 (CEST) Subject: [pypy-commit] pypy stdlib-2.7.4: merge default Message-ID: <20130412233916.1D5E21C07C6@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: stdlib-2.7.4 Changeset: r63303:e21d1c57481c Date: 2013-04-12 19:38 -0400 http://bitbucket.org/pypy/pypy/changeset/e21d1c57481c/ Log: merge default diff --git a/pypy/module/_io/test/test_ztranslation.py b/pypy/module/_io/test/test_ztranslation.py new file mode 100644 --- /dev/null +++ b/pypy/module/_io/test/test_ztranslation.py @@ -0,0 +1,4 @@ +from pypy.objspace.fake.checkmodule import checkmodule + +def test_checkmodule(): + checkmodule('_io') diff --git a/pypy/objspace/fake/objspace.py b/pypy/objspace/fake/objspace.py --- a/pypy/objspace/fake/objspace.py +++ b/pypy/objspace/fake/objspace.py @@ -58,6 +58,10 @@ class W_MyType(W_MyObject): def __init__(self): self.mro_w = [w_some_obj(), w_some_obj()] + self.dict_w = {'__str__': w_some_obj()} + + def get_module(self): + return w_some_obj() def w_some_obj(): if NonConstant(False): @@ -318,7 +322,7 @@ ObjSpace.ExceptionTable + ['int', 'str', 'float', 'long', 'tuple', 'list', 'dict', 'unicode', 'complex', 'slice', 'bool', - 'basestring', 'object']): + 'basestring', 'object', 'bytearray']): setattr(FakeObjSpace, 'w_' + name, w_some_obj()) FakeObjSpace.w_type = w_some_type() # From noreply at buildbot.pypy.org Sat Apr 13 04:10:59 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Sat, 13 Apr 2013 04:10:59 +0200 (CEST) Subject: [pypy-commit] pypy default: unhandled exceptions in threads should print tracebacks like cpython, test Message-ID: <20130413021059.9A91C1C026A@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63304:bb0fb0211de3 Date: 2013-04-12 22:10 -0400 http://bitbucket.org/pypy/pypy/changeset/bb0fb0211de3/ Log: unhandled exceptions in threads should print tracebacks like cpython, test diff --git a/pypy/module/thread/os_thread.py b/pypy/module/thread/os_thread.py --- a/pypy/module/thread/os_thread.py +++ b/pypy/module/thread/os_thread.py @@ -132,7 +132,7 @@ if not e.match(space, space.w_SystemExit): ident = rthread.get_ident() where = 'thread %d started by ' % ident - e.write_unraisable(space, where, w_callable) + e.write_unraisable(space, where, w_callable, with_traceback=True) e.clear(space) # clean up space.threadlocals to remove the ExecutionContext # entry corresponding to the current thread diff --git a/pypy/module/thread/test/test_thread.py b/pypy/module/thread/test/test_thread.py --- a/pypy/module/thread/test/test_thread.py +++ b/pypy/module/thread/test/test_thread.py @@ -129,10 +129,10 @@ sys.stderr = StringIO.StringIO() thread.start_new_thread(fn3, ()) self.waitfor(lambda: "ValueError" in sys.stderr.getvalue()) - result = sys.stderr.getvalue() - assert "ValueError" in result - assert "hello world" in result - assert len(result.splitlines()) == 1 + result = sys.stderr.getvalue().splitlines() + #assert result[0].startswith("Unhandled exception in thread ") + assert result[1].startswith("Traceback ") + assert result[-1] == "ValueError: hello world" finally: sys.stderr = prev From noreply at buildbot.pypy.org Sat Apr 13 13:59:21 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sat, 13 Apr 2013 13:59:21 +0200 (CEST) Subject: [pypy-commit] pypy stm-gc-2: Add a possible idea (from Remi) Message-ID: <20130413115921.C90D71C0250@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: stm-gc-2 Changeset: r63305:19470a5a0223 Date: 2013-04-13 13:56 +0200 http://bitbucket.org/pypy/pypy/changeset/19470a5a0223/ Log: Add a possible idea (from Remi) diff --git a/TODO b/TODO --- a/TODO +++ b/TODO @@ -4,6 +4,11 @@ ------------------------------------------------------------ +try to let non-atomic inevitable transactions run for longer, until +another thread starts waiting for the mutex + +------------------------------------------------------------ + RPyAssert(i < len(lst)): if lst is global this turns into tons of code ------------------------------------------------------------ From noreply at buildbot.pypy.org Sat Apr 13 14:46:33 2013 From: noreply at buildbot.pypy.org (bivab) Date: Sat, 13 Apr 2013 14:46:33 +0200 (CEST) Subject: [pypy-commit] pypy default: fix for _write_barrier_fastpath, missing a check to select the correct slowpath helper Message-ID: <20130413124633.9D0C01C05C8@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63306:9e042c93925f Date: 2013-04-13 14:30 +0200 http://bitbucket.org/pypy/pypy/changeset/9e042c93925f/ Log: fix for _write_barrier_fastpath, missing a check to select the correct slowpath helper diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -630,7 +630,9 @@ # argument the address of the structure we are writing into # (the first argument to COND_CALL_GC_WB). helper_num = card_marking - if self._regalloc is not None and self._regalloc.vfprm.reg_bindings: + if is_frame: + helper_num = 4 + elif self._regalloc is not None and self._regalloc.vfprm.reg_bindings: helper_num += 2 if self.wb_slowpath[helper_num] == 0: # tests only assert not we_are_translated() From noreply at buildbot.pypy.org Sat Apr 13 15:18:26 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sat, 13 Apr 2013 15:18:26 +0200 (CEST) Subject: [pypy-commit] pypy stm-gc-2: Restore the original support: when there is an inevitable transaction, Message-ID: <20130413131826.43AD31C0250@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: stm-gc-2 Changeset: r63307:7cb672c3e357 Date: 2013-04-13 14:50 +0200 http://bitbucket.org/pypy/pypy/changeset/7cb672c3e357/ Log: Restore the original support: when there is an inevitable transaction, other concurrent transactions may run until they attempt to commit. diff --git a/rpython/translator/stm/src_stm/et.c b/rpython/translator/stm/src_stm/et.c --- a/rpython/translator/stm/src_stm/et.c +++ b/rpython/translator/stm/src_stm/et.c @@ -35,7 +35,6 @@ /************************************************************/ typedef Unsigned revision_t; -#define INEVITABLE ((revision_t)-1) #define LOCKED ((revision_t)-0x10000) #include "atomic_ops.h" @@ -70,7 +69,9 @@ struct FXCache recent_reads_cache; }; -static volatile revision_t global_cur_time = 2; /* always mult of 2 */ +/* 'global_cur_time' is normally a multiple of 2, except when we turn + a transaction inevitable: we then add 1 to it. */ +static volatile revision_t global_cur_time = 2; static volatile revision_t next_locked_value = LOCKED + 3; /* always odd */ static __thread struct tx_descriptor *thread_descriptor = NULL; @@ -317,18 +318,8 @@ static revision_t GetGlobalCurTime(struct tx_descriptor *d) { - revision_t t; assert(!is_inevitable(d)); // must not be myself inevitable - while (1) - { - t = global_cur_time; - if (t != INEVITABLE) - return t; - // there is another transaction that is inevitable - inev_mutex_acquire(); // wait until released - inev_mutex_release(); - // retry - } + return global_cur_time & ~1; } static _Bool ValidateDuringTransaction(struct tx_descriptor *d, @@ -659,7 +650,7 @@ { // no-one else can have changed global_cur_time if I'm inevitable cur_time = d->start_time; - if (!bool_cas(&global_cur_time, INEVITABLE, cur_time + 2)) + if (!bool_cas(&global_cur_time, cur_time + 1, cur_time + 2)) { assert(!"global_cur_time modified even though we are inev."); abort(); @@ -671,8 +662,8 @@ while (1) { cur_time = global_cur_time; - if (cur_time == INEVITABLE) - { + if (cur_time & 1) + { // there is another inevitable transaction CancelLocks(d); inev_mutex_acquire(); // wait until released inev_mutex_release(); @@ -710,6 +701,22 @@ update_reads_size_limit(d); } +static revision_t acquire_inev_mutex_and_mark_global_cur_time(void) +{ + revision_t cur_time; + + inev_mutex_acquire(); + while (1) + { + cur_time = global_cur_time; + assert((cur_time & 1) == 0); + if (bool_cas(&global_cur_time, cur_time, cur_time + 1)) + break; + /* else try again */ + } + return cur_time; +} + void BecomeInevitable(const char *why) { revision_t cur_time; @@ -727,18 +734,13 @@ } #endif - inev_mutex_acquire(); - cur_time = global_cur_time; - while (!bool_cas(&global_cur_time, cur_time, INEVITABLE)) - cur_time = global_cur_time; /* try again */ - assert(cur_time != INEVITABLE); - + cur_time = acquire_inev_mutex_and_mark_global_cur_time(); if (d->start_time != cur_time) { d->start_time = cur_time; if (!ValidateDuringTransaction(d, 0)) { - global_cur_time = cur_time; // must restore the old value + global_cur_time = cur_time; // revert from (cur_time + 1) inev_mutex_release(); AbortTransaction(3); } @@ -756,11 +758,7 @@ revision_t cur_time; init_transaction(d); - inev_mutex_acquire(); - cur_time = global_cur_time; - while (!bool_cas(&global_cur_time, cur_time, INEVITABLE)) - cur_time = global_cur_time; /* try again */ - assert(cur_time != INEVITABLE); + cur_time = acquire_inev_mutex_and_mark_global_cur_time(); d->start_time = cur_time; make_inevitable(d); } @@ -888,7 +886,7 @@ if (bool_cas(&next_locked_value, d->my_lock, d->my_lock + 2)) break; } - if (d->my_lock < LOCKED || d->my_lock == INEVITABLE) + if (d->my_lock < LOCKED || d->my_lock == (revision_t)-1) { /* XXX fix this limitation */ fprintf(stderr, "XXX error: too many threads ever created " From noreply at buildbot.pypy.org Sat Apr 13 15:18:27 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sat, 13 Apr 2013 15:18:27 +0200 (CEST) Subject: [pypy-commit] pypy default: Fix for translator.backendopt.test.test_all:test_secondary_backendopt. Message-ID: <20130413131827.C56FB1C070B@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63308:7bf34a0b593b Date: 2013-04-13 15:07 +0200 http://bitbucket.org/pypy/pypy/changeset/7bf34a0b593b/ Log: Fix for translator.backendopt.test.test_all:test_secondary_backendopt. diff --git a/rpython/translator/backendopt/inline.py b/rpython/translator/backendopt/inline.py --- a/rpython/translator/backendopt/inline.py +++ b/rpython/translator/backendopt/inline.py @@ -777,7 +777,10 @@ heuristic=inlining_heuristic, inline_graph_from_anywhere=False): if inline_graph_from_anywhere: - ok_to_call = set(translator.graphs) + # it's ok to inline calls to any graph, with the exception of + # graphs that would be already exception-transformed + ok_to_call = set([graph for graph in translator.graphs + if not hasattr(graph, 'exceptiontransformed')]) else: ok_to_call = None callgraph = inlinable_static_callers(graphs, ok_to_call=ok_to_call) From noreply at buildbot.pypy.org Sat Apr 13 15:37:57 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sat, 13 Apr 2013 15:37:57 +0200 (CEST) Subject: [pypy-commit] pypy stm-gc-2: Fixes Message-ID: <20130413133757.BBF991C070B@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: stm-gc-2 Changeset: r63309:331f03eb4d9e Date: 2013-04-13 15:35 +0200 http://bitbucket.org/pypy/pypy/changeset/331f03eb4d9e/ Log: Fixes diff --git a/rpython/memory/gc/stmgc.py b/rpython/memory/gc/stmgc.py --- a/rpython/memory/gc/stmgc.py +++ b/rpython/memory/gc/stmgc.py @@ -8,6 +8,7 @@ from rpython.rlib.debug import ll_assert, debug_start, debug_stop, fatalerror from rpython.rlib.debug import debug_print from rpython.rlib import rthread +from rpython.memory.gc import stmshared WORD = LONG_BIT // 8 @@ -160,18 +161,15 @@ 'stm_operations': 'use_real_one', 'nursery_size': 32*1024*1024, # 32 MB - #"page_size": 1024*WORD, # copied from minimark.py - #"arena_size": 65536*WORD, # copied from minimark.py - #"small_request_threshold": 35*WORD, # copied from minimark.py + "page_size": stmshared.TRANSLATED_PAGE_SIZE, + "small_request_threshold":stmshared.TRANSLATED_SMALL_REQUEST_THRESHOLD, } def __init__(self, config, stm_operations='use_emulator', nursery_size=1024, - #page_size=16*WORD, - #arena_size=64*WORD, - #small_request_threshold=5*WORD, - #ArenaCollectionClass=None, + page_size=14*WORD, + small_request_threshold=5*WORD, **kwds): MovingGCBase.__init__(self, config, multithread=True, **kwds) # @@ -182,11 +180,11 @@ from rpython.translator.stm.stmgcintf import StmOperations stm_operations = StmOperations() # - from rpython.memory.gc import stmshared self.stm_operations = stm_operations self.nursery_size = nursery_size #self.maximum_extra_threshold = 0 - self.sharedarea = stmshared.StmGCSharedArea(self) + self.sharedarea = stmshared.StmGCSharedArea(self, page_size, + small_request_threshold) # def _stm_duplicate(obj): # indirection to hide 'self' return self.stm_duplicate(obj) @@ -450,7 +448,7 @@ if tls.is_in_nursery(obj): size_gc_header = self.gcheaderbuilder.size_gc_header size = self.get_size(obj) - shadowhdr = tls.sharedarea_tls.malloc_object( + shadowhdr = tls.sharedarea_tls.malloc_object_addr( size_gc_header + size) # XXX must initialize the shadow enough to be considered # a valid gc object by the next major collection diff --git a/rpython/memory/gc/stmshared.py b/rpython/memory/gc/stmshared.py --- a/rpython/memory/gc/stmshared.py +++ b/rpython/memory/gc/stmshared.py @@ -96,11 +96,13 @@ # which store objects of size N. length = sharedarea.small_request_threshold / WORD + 1 self.pages_for_size = lltype.malloc( - rffi.CArray(PAGE_PTR), length, flavor='raw', zero=True) + rffi.CArray(PAGE_PTR), length, flavor='raw', zero=True, + track_allocation=False) # # This array contains 'length' chained lists of free locations. self.free_loc_for_size = lltype.malloc( - rffi.CArray(llmemory.Address), length, flavor='raw', zero=True) + rffi.CArray(llmemory.Address), length, flavor='raw', zero=True, + track_allocation=False) # if not we_are_translated(): self._seen_pages = set() @@ -168,18 +170,21 @@ return head - def malloc_object(self, totalsize): + def malloc_object_addr(self, totalsize): """Malloc. You should also call add_regular() later, or keep it in some other data structure. Note that it is not zero-filled.""" nsize = llmemory.raw_malloc_usage(totalsize) if nsize <= self.sharedarea.small_request_threshold: size_class = (nsize + WORD_POWER_2 - 1) >> WORD_POWER_2 - result = self._malloc_size_class(size_class) + return self._malloc_size_class(size_class) else: - result = llarena.arena_malloc( + return llarena.arena_malloc( llmemory.raw_malloc_usage(totalsize), 0) - llarena.arena_reserve(result, _dummy_size(totalsize)) - return result + self.gc.gcheaderbuilder.size_gc_header + + def malloc_object(self, totalsize): + addr = self.malloc_object_addr(totalsize) + llarena.arena_reserve(addr, _dummy_size(totalsize)) + return addr + self.gc.gcheaderbuilder.size_gc_header def add_regular(self, obj): """After malloc_object(), register the object in the internal chained @@ -209,8 +214,10 @@ self.free_object(lst.pop()) def delete(self): - lltype.free(self.free_loc_for_size, flavor='raw') - lltype.free(self.pages_for_size, flavor='raw') + lltype.free(self.free_loc_for_size, flavor='raw', + track_allocation=False) + lltype.free(self.pages_for_size, flavor='raw', + track_allocation=False) free_non_gc_object(self) diff --git a/rpython/memory/gc/stmtls.py b/rpython/memory/gc/stmtls.py --- a/rpython/memory/gc/stmtls.py +++ b/rpython/memory/gc/stmtls.py @@ -517,7 +517,7 @@ llmemory.sizeof(lltype.Signed)) else: newtotalsize = totalsize_without_hash - newaddr = self.sharedarea_tls.malloc_object(newtotalsize) + newaddr = self.sharedarea_tls.malloc_object_addr(newtotalsize) # # Initialize the copy by doing a memcpy of the bytes. # The object header of localobj will then be fixed by the C code. From noreply at buildbot.pypy.org Sat Apr 13 16:33:36 2013 From: noreply at buildbot.pypy.org (bivab) Date: Sat, 13 Apr 2013 16:33:36 +0200 (CEST) Subject: [pypy-commit] pypy default: reenable the debugging code injection, fixes test_ztranslation_jit_stats.py Message-ID: <20130413143336.883C91C070B@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63310:db0bef5be316 Date: 2013-04-13 16:31 +0200 http://bitbucket.org/pypy/pypy/changeset/db0bef5be316/ Log: reenable the debugging code injection, fixes test_ztranslation_jit_stats.py diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -537,7 +537,7 @@ clt.allgcrefs = [] clt.frame_info.clear() # for now - if False and log: + if log: operations = self._inject_debugging_code(looptoken, operations, 'e', looptoken.number) From noreply at buildbot.pypy.org Sat Apr 13 16:33:37 2013 From: noreply at buildbot.pypy.org (bivab) Date: Sat, 13 Apr 2013 16:33:37 +0200 (CEST) Subject: [pypy-commit] pypy default: merge heads Message-ID: <20130413143337.D7E481C070B@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63311:862eefdcacca Date: 2013-04-13 16:33 +0200 http://bitbucket.org/pypy/pypy/changeset/862eefdcacca/ Log: merge heads diff --git a/rpython/translator/backendopt/inline.py b/rpython/translator/backendopt/inline.py --- a/rpython/translator/backendopt/inline.py +++ b/rpython/translator/backendopt/inline.py @@ -777,7 +777,10 @@ heuristic=inlining_heuristic, inline_graph_from_anywhere=False): if inline_graph_from_anywhere: - ok_to_call = set(translator.graphs) + # it's ok to inline calls to any graph, with the exception of + # graphs that would be already exception-transformed + ok_to_call = set([graph for graph in translator.graphs + if not hasattr(graph, 'exceptiontransformed')]) else: ok_to_call = None callgraph = inlinable_static_callers(graphs, ok_to_call=ok_to_call) From noreply at buildbot.pypy.org Sat Apr 13 18:13:12 2013 From: noreply at buildbot.pypy.org (bivab) Date: Sat, 13 Apr 2013 18:13:12 +0200 (CEST) Subject: [pypy-commit] pypy default: preallocate list to hold the locations of arguments to a call Message-ID: <20130413161312.327CA1C0250@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63312:1bd588482153 Date: 2013-04-13 18:00 +0200 http://bitbucket.org/pypy/pypy/changeset/1bd588482153/ Log: preallocate list to hold the locations of arguments to a call diff --git a/rpython/jit/backend/arm/regalloc.py b/rpython/jit/backend/arm/regalloc.py --- a/rpython/jit/backend/arm/regalloc.py +++ b/rpython/jit/backend/arm/regalloc.py @@ -554,10 +554,9 @@ return self._prepare_call(op) def _prepare_call(self, op, force_store=[], save_all_regs=False): - args = [] - args.append(None) + args = [None] * (op.numargs()+1) for i in range(op.numargs()): - args.append(self.loc(op.getarg(i))) + args[i+1] = self.loc(op.getarg(i)) # spill variables that need to be saved around calls self.vfprm.before_call(save_all_regs=save_all_regs) if not save_all_regs: From noreply at buildbot.pypy.org Sat Apr 13 18:13:13 2013 From: noreply at buildbot.pypy.org (bivab) Date: Sat, 13 Apr 2013 18:13:13 +0200 (CEST) Subject: [pypy-commit] pypy default: move GIL related shared code to llsupport Message-ID: <20130413161313.701181C0250@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63313:9ae6d332e291 Date: 2013-04-13 18:09 +0200 http://bitbucket.org/pypy/pypy/changeset/9ae6d332e291/ Log: move GIL related shared code to llsupport diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -74,29 +74,6 @@ def setup_failure_recovery(self): self.failure_recovery_code = [0, 0, 0, 0] - @staticmethod - def _release_gil_shadowstack(): - before = rffi.aroundstate.before - if before: - before() - - @staticmethod - def _reacquire_gil_shadowstack(): - after = rffi.aroundstate.after - if after: - after() - - _NOARG_FUNC = lltype.Ptr(lltype.FuncType([], lltype.Void)) - - def _build_release_gil(self, gcrootmap): - assert gcrootmap.is_shadow_stack - releasegil_func = llhelper(self._NOARG_FUNC, - self._release_gil_shadowstack) - reacqgil_func = llhelper(self._NOARG_FUNC, - self._reacquire_gil_shadowstack) - self.releasegil_addr = rffi.cast(lltype.Signed, releasegil_func) - self.reacqgil_addr = rffi.cast(lltype.Signed, reacqgil_func) - def _build_propagate_exception_path(self): if not self.cpu.propagate_exception_descr: return # not supported (for tests, or non-translated) diff --git a/rpython/jit/backend/llsupport/assembler.py b/rpython/jit/backend/llsupport/assembler.py --- a/rpython/jit/backend/llsupport/assembler.py +++ b/rpython/jit/backend/llsupport/assembler.py @@ -9,7 +9,7 @@ debug_print) from rpython.rlib.rarithmetic import r_uint from rpython.rlib.objectmodel import specialize, compute_unique_id -from rpython.rtyper.annlowlevel import cast_instance_to_gcref +from rpython.rtyper.annlowlevel import cast_instance_to_gcref, llhelper from rpython.rtyper.lltypesystem import rffi, lltype @@ -282,6 +282,69 @@ debug_print(prefix + ':' + str(struct.i)) debug_stop('jit-backend-counts') + @staticmethod + @rgc.no_collect + def _release_gil_asmgcc(css): + # similar to trackgcroot.py:pypy_asm_stackwalk, first part + from rpython.memory.gctransform import asmgcroot + new = rffi.cast(asmgcroot.ASM_FRAMEDATA_HEAD_PTR, css) + next = asmgcroot.gcrootanchor.next + new.next = next + new.prev = asmgcroot.gcrootanchor + asmgcroot.gcrootanchor.next = new + next.prev = new + # and now release the GIL + before = rffi.aroundstate.before + if before: + before() + + @staticmethod + @rgc.no_collect + def _reacquire_gil_asmgcc(css): + # first reacquire the GIL + after = rffi.aroundstate.after + if after: + after() + # similar to trackgcroot.py:pypy_asm_stackwalk, second part + from rpython.memory.gctransform import asmgcroot + old = rffi.cast(asmgcroot.ASM_FRAMEDATA_HEAD_PTR, css) + prev = old.prev + next = old.next + prev.next = next + next.prev = prev + + @staticmethod + @rgc.no_collect + def _release_gil_shadowstack(): + before = rffi.aroundstate.before + if before: + before() + + @staticmethod + @rgc.no_collect + def _reacquire_gil_shadowstack(): + after = rffi.aroundstate.after + if after: + after() + + _NOARG_FUNC = lltype.Ptr(lltype.FuncType([], lltype.Void)) + _CLOSESTACK_FUNC = lltype.Ptr(lltype.FuncType([rffi.LONGP], + lltype.Void)) + + def _build_release_gil(self, gcrootmap): + if gcrootmap.is_shadow_stack: + releasegil_func = llhelper(self._NOARG_FUNC, + self._release_gil_shadowstack) + reacqgil_func = llhelper(self._NOARG_FUNC, + self._reacquire_gil_shadowstack) + else: + releasegil_func = llhelper(self._CLOSESTACK_FUNC, + self._release_gil_asmgcc) + reacqgil_func = llhelper(self._CLOSESTACK_FUNC, + self._reacquire_gil_asmgcc) + self.releasegil_addr = self.cpu.cast_ptr_to_int(releasegil_func) + self.reacqgil_addr = self.cpu.cast_ptr_to_int(reacqgil_func) + def debug_bridge(descr_number, rawstart, codeendpos): diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -367,69 +367,6 @@ else: self.wb_slowpath[withcards + 2 * withfloats] = rawstart - @staticmethod - @rgc.no_collect - def _release_gil_asmgcc(css): - # similar to trackgcroot.py:pypy_asm_stackwalk, first part - from rpython.memory.gctransform import asmgcroot - new = rffi.cast(asmgcroot.ASM_FRAMEDATA_HEAD_PTR, css) - next = asmgcroot.gcrootanchor.next - new.next = next - new.prev = asmgcroot.gcrootanchor - asmgcroot.gcrootanchor.next = new - next.prev = new - # and now release the GIL - before = rffi.aroundstate.before - if before: - before() - - @staticmethod - @rgc.no_collect - def _reacquire_gil_asmgcc(css): - # first reacquire the GIL - after = rffi.aroundstate.after - if after: - after() - # similar to trackgcroot.py:pypy_asm_stackwalk, second part - from rpython.memory.gctransform import asmgcroot - old = rffi.cast(asmgcroot.ASM_FRAMEDATA_HEAD_PTR, css) - prev = old.prev - next = old.next - prev.next = next - next.prev = prev - - @staticmethod - @rgc.no_collect - def _release_gil_shadowstack(): - before = rffi.aroundstate.before - if before: - before() - - @staticmethod - @rgc.no_collect - def _reacquire_gil_shadowstack(): - after = rffi.aroundstate.after - if after: - after() - - _NOARG_FUNC = lltype.Ptr(lltype.FuncType([], lltype.Void)) - _CLOSESTACK_FUNC = lltype.Ptr(lltype.FuncType([rffi.LONGP], - lltype.Void)) - - def _build_release_gil(self, gcrootmap): - if gcrootmap.is_shadow_stack: - releasegil_func = llhelper(self._NOARG_FUNC, - self._release_gil_shadowstack) - reacqgil_func = llhelper(self._NOARG_FUNC, - self._reacquire_gil_shadowstack) - else: - releasegil_func = llhelper(self._CLOSESTACK_FUNC, - self._release_gil_asmgcc) - reacqgil_func = llhelper(self._CLOSESTACK_FUNC, - self._reacquire_gil_asmgcc) - self.releasegil_addr = self.cpu.cast_ptr_to_int(releasegil_func) - self.reacqgil_addr = self.cpu.cast_ptr_to_int(reacqgil_func) - def assemble_loop(self, loopname, inputargs, operations, looptoken, log): '''adds the following attributes to looptoken: _ll_function_addr (address of the generated func, as an int) From noreply at buildbot.pypy.org Sat Apr 13 18:13:14 2013 From: noreply at buildbot.pypy.org (bivab) Date: Sat, 13 Apr 2013 18:13:14 +0200 (CEST) Subject: [pypy-commit] pypy default: fix argument and return value handling in call_release_gil and call_reacquire_gil. Fixes test_zrpy_releasegil.py failures Message-ID: <20130413161314.BA7731C0250@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63314:295a4447f6ba Date: 2013-04-13 18:12 +0200 http://bitbucket.org/pypy/pypy/changeset/295a4447f6ba/ Log: fix argument and return value handling in call_release_gil and call_reacquire_gil. Fixes test_zrpy_releasegil.py failures diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -1266,7 +1266,7 @@ resloc = arglocs[0] if gcrootmap: - self.call_release_gil(gcrootmap, arglocs, fcond) + self.call_release_gil(gcrootmap, arglocs, regalloc, fcond) # do the call self._store_force_index(guard_op) # @@ -1278,37 +1278,32 @@ resloc, (size, signed)) # then reopen the stack if gcrootmap: - self.call_reacquire_gil(gcrootmap, resloc, fcond) + self.call_reacquire_gil(gcrootmap, resloc, regalloc, fcond) self._emit_guard_may_force(guard_op, arglocs[numargs+1:], numargs) return fcond - def call_release_gil(self, gcrootmap, save_registers, fcond): - # First, we need to save away the registers listed in - # 'save_registers' that are not callee-save. + def call_release_gil(self, gcrootmap, save_registers, regalloc, fcond): + # Save caller saved registers and do the call # NOTE: We assume that the floating point registers won't be modified. - regs_to_save = [] - for reg in self._regalloc.rm.save_around_call_regs: - if reg in save_registers: - regs_to_save.append(reg) assert gcrootmap.is_shadow_stack - with saved_registers(self.mc, regs_to_save): + with saved_registers(self.mc, regalloc.rm.save_around_call_regs): self._emit_call(imm(self.releasegil_addr), [], fcond) - def call_reacquire_gil(self, gcrootmap, save_loc, fcond): - # save the previous result into the stack temporarily. + def call_reacquire_gil(self, gcrootmap, save_loc, regalloc, fcond): + # save the previous result into the stack temporarily, in case it is in + # a caller saved register. # NOTE: like with call_release_gil(), we assume that we don't need to # save vfp regs in this case. Besides the result location regs_to_save = [] vfp_regs_to_save = [] - if save_loc.is_reg(): + if save_loc and save_loc in regalloc.rm.save_around_call_regs: regs_to_save.append(save_loc) - if save_loc.is_vfp_reg(): + regs_to_save.append(r.ip) # for alingment + elif save_loc and save_loc in regalloc.vfprm.save_around_call_regs: vfp_regs_to_save.append(save_loc) + assert gcrootmap.is_shadow_stack # call the reopenstack() function (also reacquiring the GIL) - if len(regs_to_save) % 2 != 1: - regs_to_save.append(r.ip) # for alingment - assert gcrootmap.is_shadow_stack with saved_registers(self.mc, regs_to_save, vfp_regs_to_save): self._emit_call(imm(self.reacqgil_addr), [], fcond) From noreply at buildbot.pypy.org Sat Apr 13 19:48:53 2013 From: noreply at buildbot.pypy.org (alex_gaynor) Date: Sat, 13 Apr 2013 19:48:53 +0200 (CEST) Subject: [pypy-commit] pypy virtualref-virtualizable: A branch in which to try to make: Message-ID: <20130413174853.303E61C05C8@cobra.cs.uni-duesseldorf.de> Author: Alex Gaynor Branch: virtualref-virtualizable Changeset: r63315:178860c995f4 Date: 2013-04-13 10:48 -0700 http://bitbucket.org/pypy/pypy/changeset/178860c995f4/ Log: A branch in which to try to make: jit_force_virtual(p1) where p1 is a virtualref to the top virtualizable be optimized away. Start with some small cleanups to the test file. diff --git a/rpython/jit/metainterp/test/test_virtualizable.py b/rpython/jit/metainterp/test/test_virtualizable.py --- a/rpython/jit/metainterp/test/test_virtualizable.py +++ b/rpython/jit/metainterp/test/test_virtualizable.py @@ -1,20 +1,22 @@ import py + +from rpython.jit.codewriter import heaptracker +from rpython.jit.codewriter.policy import StopAtXPolicy +from rpython.jit.metainterp.optimizeopt.test.test_util import LLtypeMixin +from rpython.jit.metainterp.test.support import LLJitMixin, OOJitMixin +from rpython.jit.metainterp.warmspot import get_translator +from rpython.rlib.jit import JitDriver, hint, dont_look_inside, promote +from rpython.rlib.rarithmetic import intmask +from rpython.rtyper.annlowlevel import hlstr from rpython.rtyper.extregistry import ExtRegistryEntry from rpython.rtyper.lltypesystem import lltype, lloperation, rclass, llmemory -from rpython.rtyper.annlowlevel import llhelper -from rpython.rtyper.rclass import IR_IMMUTABLE, IR_IMMUTABLE_ARRAY -from rpython.jit.codewriter.policy import StopAtXPolicy -from rpython.jit.codewriter import heaptracker -from rpython.rlib.jit import JitDriver, hint, dont_look_inside, promote -from rpython.rlib.rarithmetic import intmask -from rpython.jit.metainterp.test.support import LLJitMixin, OOJitMixin -from rpython.rtyper.rclass import FieldListAccessor -from rpython.jit.metainterp.warmspot import get_stats, get_translator -from rpython.jit.metainterp import history -from rpython.jit.metainterp.optimizeopt.test.test_util import LLtypeMixin +from rpython.rtyper.rclass import IR_IMMUTABLE, IR_IMMUTABLE_ARRAY, FieldListAccessor + def promote_virtualizable(*args): pass + + class Entry(ExtRegistryEntry): "Annotation and rtyping of LLOp instances, which are callable." _about_ = promote_virtualizable @@ -46,7 +48,7 @@ ('inst_node', lltype.Ptr(LLtypeMixin.NODE)), hints = {'virtualizable2_accessor': FieldListAccessor()}) XY._hints['virtualizable2_accessor'].initialize( - XY, {'inst_x' : IR_IMMUTABLE, 'inst_node' : IR_IMMUTABLE}) + XY, {'inst_x': IR_IMMUTABLE, 'inst_node': IR_IMMUTABLE}) xy_vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) heaptracker.set_testing_vtable_for_gcstruct(XY, xy_vtable, 'XY') @@ -73,7 +75,7 @@ x = xy.inst_x xy.inst_x = x + 1 n -= 1 - promote_virtualizable(xy, 'inst_x') + promote_virtualizable(xy, 'inst_x') return xy.inst_x res = self.meta_interp(f, [20]) assert res == 30 @@ -97,7 +99,7 @@ x = xy.inst_x xy.inst_x = x + 10 n -= 1 - promote_virtualizable(xy, 'inst_x') + promote_virtualizable(xy, 'inst_x') return xy.inst_x assert f(5) == 185 res = self.meta_interp(f, [5]) @@ -118,10 +120,10 @@ x = xy.inst_x if n <= 10: x += 1000 - promote_virtualizable(xy, 'inst_x') + promote_virtualizable(xy, 'inst_x') xy.inst_x = x + 1 n -= 1 - promote_virtualizable(xy, 'inst_x') + promote_virtualizable(xy, 'inst_x') return xy.inst_x res = self.meta_interp(f, [18]) assert res == 10118 @@ -164,7 +166,7 @@ xy.inst_x = x + 1 m = (m+1) & 3 # the loop gets unrolled 4 times n -= 1 - promote_virtualizable(xy, 'inst_x') + promote_virtualizable(xy, 'inst_x') return xy.inst_x def f(n): res = 0 @@ -194,7 +196,7 @@ promote_virtualizable(xy, 'inst_x') xy.inst_x = value + 100 # virtualized away n -= 1 - promote_virtualizable(xy, 'inst_x') + promote_virtualizable(xy, 'inst_x') return xy.inst_x res = self.meta_interp(f, [20]) assert res == 134 @@ -212,8 +214,8 @@ ('inst_l2', lltype.Ptr(lltype.GcArray(lltype.Signed))), hints = {'virtualizable2_accessor': FieldListAccessor()}) XY2._hints['virtualizable2_accessor'].initialize( - XY2, {'inst_x' : IR_IMMUTABLE, - 'inst_l1' : IR_IMMUTABLE_ARRAY, 'inst_l2' : IR_IMMUTABLE_ARRAY}) + XY2, {'inst_x': IR_IMMUTABLE, + 'inst_l1': IR_IMMUTABLE_ARRAY, 'inst_l2': IR_IMMUTABLE_ARRAY}) xy2_vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) heaptracker.set_testing_vtable_for_gcstruct(XY2, xy2_vtable, 'XY2') @@ -241,11 +243,11 @@ while n > 0: myjitdriver.can_enter_jit(xy2=xy2, n=n) myjitdriver.jit_merge_point(xy2=xy2, n=n) - promote_virtualizable(xy2, 'inst_l1') + promote_virtualizable(xy2, 'inst_l1') promote_virtualizable(xy2, 'inst_l2') xy2.inst_l1[2] += xy2.inst_l2[0] n -= 1 - promote_virtualizable(xy2, 'inst_l1') + promote_virtualizable(xy2, 'inst_l1') return xy2.inst_l1[2] res = self.meta_interp(f, [16]) assert res == 3001 + 16 * 80 @@ -292,7 +294,7 @@ myjitdriver.can_enter_jit(xy2=xy2, n=n) myjitdriver.jit_merge_point(xy2=xy2, n=n) promote_virtualizable(xy2, 'inst_l1') - promote_virtualizable(xy2, 'inst_l2') + promote_virtualizable(xy2, 'inst_l2') xy2.inst_l1[1] += len(xy2.inst_l2) n -= 1 def f(n): @@ -373,7 +375,7 @@ promote_virtualizable(xy2, 'inst_l2') xy2.inst_l2[0] = value + 100 # virtualized away n -= 1 - promote_virtualizable(xy2, 'inst_l2') + promote_virtualizable(xy2, 'inst_l2') return xy2.inst_l2[0] expected = f(20) res = self.meta_interp(f, [20], enable_opts='') @@ -406,8 +408,8 @@ myjitdriver.can_enter_jit(xy2=xy2, n=n) myjitdriver.jit_merge_point(xy2=xy2, n=n) parent = xy2.parent - promote_virtualizable(parent, 'inst_x') - promote_virtualizable(parent, 'inst_l2') + promote_virtualizable(parent, 'inst_x') + promote_virtualizable(parent, 'inst_l2') parent.inst_l2[0] += parent.inst_x n -= 1 def f(n): @@ -473,9 +475,9 @@ def __init__(self, l, s): self.l = l self.s = s - + def f(n, a): - frame = Frame([a,a+1,a+2,a+3], 0) + frame = Frame([a, a+1, a+2, a+3], 0) x = 0 while n > 0: myjitdriver.can_enter_jit(frame=frame, n=n, x=x) @@ -544,7 +546,7 @@ def f(n): BaseFrame([]) # hack to force 'x' to be in BaseFrame - frame = Frame([1,2,3]) + frame = Frame([1, 2, 3]) z = 0 while n > 0: jitdriver.can_enter_jit(frame=frame, n=n, z=z) @@ -560,9 +562,10 @@ def test_external_read(self): jitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) - + class Frame(object): _virtualizable2_ = ['x', 'y'] + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -592,9 +595,10 @@ def test_external_read_with_exception(self): jitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) - + class Frame(object): _virtualizable2_ = ['x', 'y'] + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -634,6 +638,7 @@ class Frame(object): _virtualizable2_ = ['x', 'y'] + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -663,9 +668,10 @@ def test_external_read_sometimes(self): jitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) - + class Frame(object): _virtualizable2_ = ['x', 'y'] + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -699,11 +705,13 @@ def test_external_read_sometimes_with_virtuals(self): jitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) - + class Frame(object): _virtualizable2_ = ['x', 'y'] + class Y: pass + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -742,11 +750,13 @@ def test_external_read_sometimes_changing_virtuals(self): jitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) - + class Frame(object): _virtualizable2_ = ['x', 'y'] + class Y: pass + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -790,11 +800,13 @@ def test_external_read_sometimes_with_exception(self): jitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) - + class Frame(object): _virtualizable2_ = ['x', 'y'] + class FooBarError(Exception): pass + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -832,9 +844,10 @@ def test_external_read_sometimes_dont_compile_guard(self): jitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) - + class Frame(object): _virtualizable2_ = ['x', 'y'] + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -868,9 +881,10 @@ def test_external_read_sometimes_recursive(self): jitdriver = JitDriver(greens = [], reds = ['rec', 'frame'], virtualizables = ['frame']) - + class Frame(object): _virtualizable2_ = ['x', 'y'] + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -919,9 +933,10 @@ def test_external_write_sometimes(self): jitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) - + class Frame(object): _virtualizable2_ = ['x', 'y'] + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -955,9 +970,10 @@ def test_bridge_forces(self): jitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) - + class Frame(object): _virtualizable2_ = ['x', 'y'] + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -988,6 +1004,7 @@ def test_promote_index_in_virtualizable_list(self): jitdriver = JitDriver(greens = [], reds = ['n', 'frame'], virtualizables = ['frame']) + class Frame(object): _virtualizable2_ = ['stackpos', 'stack[*]'] @@ -1063,8 +1080,8 @@ assert direct_calls(f_graph) == ['__init__', 'force_virtualizable_if_necessary', 'll_portal_runner'] - assert direct_calls(portal_graph)==['force_virtualizable_if_necessary', - 'maybe_enter_jit'] + assert direct_calls(portal_graph) == ['force_virtualizable_if_necessary', + 'maybe_enter_jit'] assert direct_calls(init_graph) == [] def test_virtual_child_frame(self): @@ -1262,7 +1279,7 @@ somewhere_else = SomewhereElse() def jump_back(frame, fail): - myjitdriver.can_enter_jit(frame=frame, fail=fail) + myjitdriver.can_enter_jit(frame=frame, fail=fail) def f(n, fail): frame = Frame(n, 0) @@ -1315,8 +1332,10 @@ f.x -= 1 result += indirection(f) return result + def indirection(arg): return interp(arg) + def run_interp(n): f = hint(Frame(n), access_directly=True) return interp(f) @@ -1325,7 +1344,7 @@ assert res == run_interp(4) def test_guard_failure_in_inlined_function(self): - from rpython.rtyper.annlowlevel import hlstr + class Frame(object): _virtualizable2_ = ['n', 'next'] @@ -1368,11 +1387,12 @@ assert 0 pc += 1 return frame.n + def main(n): frame = Frame(n) return f("c-l", frame) - print main(100) res = self.meta_interp(main, [100], inline=True, enable_opts='') + assert res == main(100) def test_stuff_from_backend_test(self): class Thing(object): @@ -1385,6 +1405,7 @@ driver = JitDriver(greens = ['codeno'], reds = ['i', 'frame'], virtualizables = ['frame'], get_printable_location = lambda codeno: str(codeno)) + class SomewhereElse(object): pass @@ -1428,7 +1449,7 @@ OOJitMixin): pass - + class TestLLtype(ExplicitVirtualizableTests, ImplicitVirtualizableTests, LLJitMixin): From noreply at buildbot.pypy.org Sat Apr 13 19:53:36 2013 From: noreply at buildbot.pypy.org (fijal) Date: Sat, 13 Apr 2013 19:53:36 +0200 (CEST) Subject: [pypy-commit] pypy default: Backout the merge of virtual-raw-mallocs, it has more than one issue. Message-ID: <20130413175336.09C0E1C070B@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r63316:8c25722743f5 Date: 2013-04-13 19:53 +0200 http://bitbucket.org/pypy/pypy/changeset/8c25722743f5/ Log: Backout the merge of virtual-raw-mallocs, it has more than one issue. * the monkey-patching in tests is super-ugly, maybe instead the tests should exercise this feature * there are pervasive changes to resume.py, which is not an easy file to edit, with no tests * because of the above, it breaks stuff (e.g. the django test suite) diff too long, truncating to 2000 out of 2582 lines diff --git a/pypy/module/_cffi_backend/ccallback.py b/pypy/module/_cffi_backend/ccallback.py --- a/pypy/module/_cffi_backend/ccallback.py +++ b/pypy/module/_cffi_backend/ccallback.py @@ -134,7 +134,7 @@ # W_CTypePrimitiveSigned.convert_from_object() in order # to write a whole 'ffi_arg'. value = misc.as_long(space, w_res) - misc.write_raw_signed_data(ll_res, value, SIZE_OF_FFI_ARG) + misc.write_raw_integer_data(ll_res, value, SIZE_OF_FFI_ARG) return else: # zero extension: fill the '*result' with zeros, and (on big- diff --git a/pypy/module/_cffi_backend/cdataobj.py b/pypy/module/_cffi_backend/cdataobj.py --- a/pypy/module/_cffi_backend/cdataobj.py +++ b/pypy/module/_cffi_backend/cdataobj.py @@ -280,13 +280,8 @@ return self.ctype.iter(self) @specialize.argtype(1) - def write_raw_signed_data(self, source): - misc.write_raw_signed_data(self._cdata, source, self.ctype.size) - keepalive_until_here(self) - - @specialize.argtype(1) - def write_raw_unsigned_data(self, source): - misc.write_raw_unsigned_data(self._cdata, source, self.ctype.size) + def write_raw_integer_data(self, source): + misc.write_raw_integer_data(self._cdata, source, self.ctype.size) keepalive_until_here(self) def write_raw_float_data(self, source): diff --git a/pypy/module/_cffi_backend/ctypeprim.py b/pypy/module/_cffi_backend/ctypeprim.py --- a/pypy/module/_cffi_backend/ctypeprim.py +++ b/pypy/module/_cffi_backend/ctypeprim.py @@ -63,7 +63,7 @@ else: value = self._cast_generic(w_ob) w_cdata = cdataobj.W_CDataMem(space, self.size, self) - self.write_raw_integer_data(w_cdata, value) + w_cdata.write_raw_integer_data(value) return w_cdata def _cast_result(self, intvalue): @@ -94,9 +94,6 @@ from pypy.module._cffi_backend import newtype return newtype.new_primitive_type(self.space, "int") - def write_raw_integer_data(self, w_cdata, value): - w_cdata.write_raw_unsigned_data(value) - class W_CTypePrimitiveChar(W_CTypePrimitiveCharOrUniChar): _attrs_ = [] @@ -188,10 +185,10 @@ if self.size < rffi.sizeof(lltype.Signed): if r_uint(value) - self.vmin > self.vrangemax: self._overflow(w_ob) - misc.write_raw_signed_data(cdata, value, self.size) + misc.write_raw_integer_data(cdata, value, self.size) else: value = misc.as_long_long(self.space, w_ob) - misc.write_raw_signed_data(cdata, value, self.size) + misc.write_raw_integer_data(cdata, value, self.size) def get_vararg_type(self): if self.size < rffi.sizeof(rffi.INT): @@ -199,9 +196,6 @@ return newtype.new_primitive_type(self.space, "int") return self - def write_raw_integer_data(self, w_cdata, value): - w_cdata.write_raw_signed_data(value) - class W_CTypePrimitiveUnsigned(W_CTypePrimitive): _attrs_ = ['value_fits_long', 'value_fits_ulong', 'vrangemax'] @@ -228,10 +222,10 @@ if self.value_fits_long: if value > self.vrangemax: self._overflow(w_ob) - misc.write_raw_unsigned_data(cdata, value, self.size) + misc.write_raw_integer_data(cdata, value, self.size) else: value = misc.as_unsigned_long_long(self.space, w_ob, strict=True) - misc.write_raw_unsigned_data(cdata, value, self.size) + misc.write_raw_integer_data(cdata, value, self.size) def convert_to_object(self, cdata): if self.value_fits_ulong: @@ -250,9 +244,6 @@ return newtype.new_primitive_type(self.space, "int") return self - def write_raw_integer_data(self, w_cdata, value): - w_cdata.write_raw_unsigned_data(value) - class W_CTypePrimitiveBool(W_CTypePrimitiveUnsigned): _attrs_ = [] diff --git a/pypy/module/_cffi_backend/ctypestruct.py b/pypy/module/_cffi_backend/ctypestruct.py --- a/pypy/module/_cffi_backend/ctypestruct.py +++ b/pypy/module/_cffi_backend/ctypestruct.py @@ -242,13 +242,11 @@ # value = misc.as_long_long(space, w_ob) if isinstance(ctype, ctypeprim.W_CTypePrimitiveSigned): - is_signed = True fmin = -(r_longlong(1) << (self.bitsize - 1)) fmax = (r_longlong(1) << (self.bitsize - 1)) - 1 if fmax == 0: fmax = 1 # special case to let "int x:1" receive "1" else: - is_signed = False fmin = r_longlong(0) fmax = r_longlong((r_ulonglong(1) << self.bitsize) - 1) if value < fmin or value > fmax: @@ -260,10 +258,7 @@ rawvalue = r_ulonglong(value) << self.bitshift rawfielddata = misc.read_raw_unsigned_data(cdata, ctype.size) rawfielddata = (rawfielddata & ~rawmask) | (rawvalue & rawmask) - if is_signed: - misc.write_raw_signed_data(cdata, rawfielddata, ctype.size) - else: - misc.write_raw_unsigned_data(cdata, rawfielddata, ctype.size) + misc.write_raw_integer_data(cdata, rawfielddata, ctype.size) W_CField.typedef = TypeDef( diff --git a/pypy/module/_cffi_backend/misc.py b/pypy/module/_cffi_backend/misc.py --- a/pypy/module/_cffi_backend/misc.py +++ b/pypy/module/_cffi_backend/misc.py @@ -9,7 +9,6 @@ from rpython.rtyper.lltypesystem import lltype, llmemory, rffi from rpython.translator.tool.cbuild import ExternalCompilationInfo - # ____________________________________________________________ _prim_signed_types = unrolling_iterable([ @@ -66,22 +65,19 @@ return rffi.cast(rffi.LONGDOUBLEP, target)[0] @specialize.argtype(1) -def write_raw_unsigned_data(target, source, size): - for TP, TPP in _prim_unsigned_types: - if size == rffi.sizeof(TP): - rffi.cast(TPP, target)[0] = rffi.cast(TP, source) - return +def write_raw_integer_data(target, source, size): + if is_signed_integer_type(lltype.typeOf(source)): + for TP, TPP in _prim_signed_types: + if size == rffi.sizeof(TP): + rffi.cast(TPP, target)[0] = rffi.cast(TP, source) + return + else: + for TP, TPP in _prim_unsigned_types: + if size == rffi.sizeof(TP): + rffi.cast(TPP, target)[0] = rffi.cast(TP, source) + return raise NotImplementedError("bad integer size") - at specialize.argtype(1) -def write_raw_signed_data(target, source, size): - for TP, TPP in _prim_signed_types: - if size == rffi.sizeof(TP): - rffi.cast(TPP, target)[0] = rffi.cast(TP, source) - return - raise NotImplementedError("bad integer size") - - def write_raw_float_data(target, source, size): for TP, TPP in _prim_float_types: if size == rffi.sizeof(TP): diff --git a/pypy/module/pypyjit/test_pypy_c/test__ffi.py b/pypy/module/pypyjit/test_pypy_c/test__ffi.py new file mode 100644 --- /dev/null +++ b/pypy/module/pypyjit/test_pypy_c/test__ffi.py @@ -0,0 +1,272 @@ +import sys, py +from pypy.module.pypyjit.test_pypy_c.test_00_model import BaseTestPyPyC + +class Test__ffi(BaseTestPyPyC): + + def test__ffi_call(self): + from rpython.rlib.test.test_clibffi import get_libm_name + def main(libm_name): + try: + from _ffi import CDLL, types + except ImportError: + sys.stderr.write('SKIP: cannot import _ffi\n') + return 0 + + libm = CDLL(libm_name) + pow = libm.getfunc('pow', [types.double, types.double], + types.double) + i = 0 + res = 0 + while i < 300: + tmp = pow(2, 3) # ID: fficall + res += tmp + i += 1 + return pow.getaddr(), res + # + libm_name = get_libm_name(sys.platform) + log = self.run(main, [libm_name]) + pow_addr, res = log.result + assert res == 8.0 * 300 + py.test.xfail() # XXX re-optimize _ffi for the JIT? + loop, = log.loops_by_filename(self.filepath) + if 'ConstClass(pow)' in repr(loop): # e.g. OS/X + pow_addr = 'ConstClass(pow)' + assert loop.match_by_id('fficall', """ + guard_not_invalidated(descr=...) + i17 = force_token() + setfield_gc(p0, i17, descr=<.* .*PyFrame.vable_token .*>) + f21 = call_release_gil(%s, 2.000000, 3.000000, descr=) + guard_not_forced(descr=...) + guard_no_exception(descr=...) + """ % pow_addr) + + + def test__ffi_call_frame_does_not_escape(self): + from rpython.rlib.test.test_clibffi import get_libm_name + def main(libm_name): + try: + from _ffi import CDLL, types + except ImportError: + sys.stderr.write('SKIP: cannot import _ffi\n') + return 0 + + libm = CDLL(libm_name) + pow = libm.getfunc('pow', [types.double, types.double], + types.double) + + def mypow(a, b): + return pow(a, b) + + i = 0 + res = 0 + while i < 300: + tmp = mypow(2, 3) + res += tmp + i += 1 + return pow.getaddr(), res + # + libm_name = get_libm_name(sys.platform) + log = self.run(main, [libm_name]) + pow_addr, res = log.result + assert res == 8.0 * 300 + loop, = log.loops_by_filename(self.filepath) + opnames = log.opnames(loop.allops()) + # we only force the virtualref, not its content + assert opnames.count('new_with_vtable') == 1 + + def test__ffi_call_releases_gil(self): + from rpython.rlib.clibffi import get_libc_name + def main(libc_name, n): + import time + import os + from threading import Thread + # + if os.name == 'nt': + from _ffi import WinDLL, types + libc = WinDLL('Kernel32.dll') + sleep = libc.getfunc('Sleep', [types.uint], types.uint) + delays = [0]*n + [1000] + else: + from _ffi import CDLL, types + libc = CDLL(libc_name) + sleep = libc.getfunc('sleep', [types.uint], types.uint) + delays = [0]*n + [1] + # + def loop_of_sleeps(i, delays): + for delay in delays: + sleep(delay) # ID: sleep + # + threads = [Thread(target=loop_of_sleeps, args=[i, delays]) for i in range(5)] + start = time.time() + for i, thread in enumerate(threads): + thread.start() + for thread in threads: + thread.join() + end = time.time() + return end - start + log = self.run(main, [get_libc_name(), 200], threshold=150, + import_site=True) + assert 1 <= log.result <= 1.5 # at most 0.5 seconds of overhead + loops = log.loops_by_id('sleep') + assert len(loops) == 1 # make sure that we actually JITted the loop + + def test_ctypes_call(self): + from rpython.rlib.test.test_clibffi import get_libm_name + def main(libm_name): + import ctypes + libm = ctypes.CDLL(libm_name) + fabs = libm.fabs + fabs.argtypes = [ctypes.c_double] + fabs.restype = ctypes.c_double + x = -4 + i = 0 + while i < 300: + x = fabs(x) + x = x - 100 + i += 1 + return fabs._ptr.getaddr(), x + + libm_name = get_libm_name(sys.platform) + log = self.run(main, [libm_name], import_site=True) + fabs_addr, res = log.result + assert res == -4.0 + loop, = log.loops_by_filename(self.filepath) + ops = loop.allops() + opnames = log.opnames(ops) + assert opnames.count('new_with_vtable') == 1 # only the virtualref + py.test.xfail() # XXX re-optimize _ffi for the JIT? + assert opnames.count('call_release_gil') == 1 + idx = opnames.index('call_release_gil') + call = ops[idx] + assert (call.args[0] == 'ConstClass(fabs)' or # e.g. OS/X + int(call.args[0]) == fabs_addr) + + + def test__ffi_struct(self): + def main(): + from _ffi import _StructDescr, Field, types + fields = [ + Field('x', types.slong), + ] + descr = _StructDescr('foo', fields) + struct = descr.allocate() + i = 0 + while i < 300: + x = struct.getfield('x') # ID: getfield + x = x+1 + struct.setfield('x', x) # ID: setfield + i += 1 + return struct.getfield('x') + # + log = self.run(main, []) + py.test.xfail() # XXX re-optimize _ffi for the JIT? + loop, = log.loops_by_filename(self.filepath) + assert loop.match_by_id('getfield', """ + guard_not_invalidated(descr=...) + i57 = getfield_raw(i46, descr=) + """) + assert loop.match_by_id('setfield', """ + setfield_raw(i44, i57, descr=) + """) + + + def test__cffi_call(self): + from rpython.rlib.test.test_clibffi import get_libm_name + def main(libm_name): + try: + import _cffi_backend + except ImportError: + sys.stderr.write('SKIP: cannot import _cffi_backend\n') + return 0 + + libm = _cffi_backend.load_library(libm_name) + BDouble = _cffi_backend.new_primitive_type("double") + BPow = _cffi_backend.new_function_type([BDouble, BDouble], BDouble) + pow = libm.load_function(BPow, 'pow') + i = 0 + res = 0 + while i < 300: + tmp = pow(2, 3) # ID: cfficall + res += tmp + i += 1 + BLong = _cffi_backend.new_primitive_type("long") + pow_addr = int(_cffi_backend.cast(BLong, pow)) + return pow_addr, res + # + libm_name = get_libm_name(sys.platform) + log = self.run(main, [libm_name]) + pow_addr, res = log.result + assert res == 8.0 * 300 + loop, = log.loops_by_filename(self.filepath) + if 'ConstClass(pow)' in repr(loop): # e.g. OS/X + pow_addr = 'ConstClass(pow)' + assert loop.match_by_id('cfficall', """ + ... + f1 = call_release_gil(..., descr=) + ... + """) + # so far just check that call_release_gil() is produced. + # later, also check that the arguments to call_release_gil() + # are constants, and that the numerous raw_mallocs are removed + + def test_cffi_call_guard_not_forced_fails(self): + # this is the test_pypy_c equivalent of + # rpython/jit/metainterp/test/test_fficall::test_guard_not_forced_fails + # + # it requires cffi to be installed for pypy in order to run + def main(): + import sys + try: + import cffi + except ImportError: + sys.stderr.write('SKIP: cannot import cffi\n') + return 0 + + ffi = cffi.FFI() + + ffi.cdef(""" + typedef void (*functype)(int); + int foo(int n, functype func); + """) + + lib = ffi.verify(""" + #include + typedef void (*functype)(int); + + int foo(int n, functype func) { + if (n >= 2000) { + func(n); + } + return n*2; + } + """) + + @ffi.callback("functype") + def mycallback(n): + if n < 5000: + return + # make sure that guard_not_forced fails + d = {} + f = sys._getframe() + while f: + d.update(f.f_locals) + f = f.f_back + + n = 0 + while n < 10000: + res = lib.foo(n, mycallback) # ID: cfficall + # this is the real point of the test: before the + # refactor-call_release_gil branch, the assert failed when + # res == 5000 + assert res == n*2 + n += 1 + return n + + log = self.run(main, [], import_site=True) + assert log.result == 10000 + loop, = log.loops_by_id('cfficall') + assert loop.match_by_id('cfficall', """ + ... + f1 = call_release_gil(..., descr=) + ... + """) diff --git a/pypy/module/pypyjit/test_pypy_c/test_ffi.py b/pypy/module/pypyjit/test_pypy_c/test_ffi.py deleted file mode 100644 --- a/pypy/module/pypyjit/test_pypy_c/test_ffi.py +++ /dev/null @@ -1,279 +0,0 @@ -import sys, py -from pypy.module.pypyjit.test_pypy_c.test_00_model import BaseTestPyPyC - -class Test__ffi(BaseTestPyPyC): - - def test__ffi_call(self): - from rpython.rlib.test.test_clibffi import get_libm_name - def main(libm_name): - try: - from _ffi import CDLL, types - except ImportError: - sys.stderr.write('SKIP: cannot import _ffi\n') - return 0 - - libm = CDLL(libm_name) - pow = libm.getfunc('pow', [types.double, types.double], - types.double) - i = 0 - res = 0 - while i < 300: - tmp = pow(2, 3) # ID: fficall - res += tmp - i += 1 - return pow.getaddr(), res - # - libm_name = get_libm_name(sys.platform) - log = self.run(main, [libm_name]) - pow_addr, res = log.result - assert res == 8.0 * 300 - py.test.xfail() # XXX re-optimize _ffi for the JIT? - loop, = log.loops_by_filename(self.filepath) - if 'ConstClass(pow)' in repr(loop): # e.g. OS/X - pow_addr = 'ConstClass(pow)' - assert loop.match_by_id('fficall', """ - guard_not_invalidated(descr=...) - i17 = force_token() - setfield_gc(p0, i17, descr=<.* .*PyFrame.vable_token .*>) - f21 = call_release_gil(%s, 2.000000, 3.000000, descr=) - guard_not_forced(descr=...) - guard_no_exception(descr=...) - """ % pow_addr) - - - def test__ffi_call_frame_does_not_escape(self): - from rpython.rlib.test.test_clibffi import get_libm_name - def main(libm_name): - try: - from _ffi import CDLL, types - except ImportError: - sys.stderr.write('SKIP: cannot import _ffi\n') - return 0 - - libm = CDLL(libm_name) - pow = libm.getfunc('pow', [types.double, types.double], - types.double) - - def mypow(a, b): - return pow(a, b) - - i = 0 - res = 0 - while i < 300: - tmp = mypow(2, 3) - res += tmp - i += 1 - return pow.getaddr(), res - # - libm_name = get_libm_name(sys.platform) - log = self.run(main, [libm_name]) - pow_addr, res = log.result - assert res == 8.0 * 300 - loop, = log.loops_by_filename(self.filepath) - opnames = log.opnames(loop.allops()) - # we only force the virtualref, not its content - assert opnames.count('new_with_vtable') == 1 - - def test__ffi_call_releases_gil(self): - from rpython.rlib.clibffi import get_libc_name - def main(libc_name, n): - import time - import os - from threading import Thread - # - if os.name == 'nt': - from _ffi import WinDLL, types - libc = WinDLL('Kernel32.dll') - sleep = libc.getfunc('Sleep', [types.uint], types.uint) - delays = [0]*n + [1000] - else: - from _ffi import CDLL, types - libc = CDLL(libc_name) - sleep = libc.getfunc('sleep', [types.uint], types.uint) - delays = [0]*n + [1] - # - def loop_of_sleeps(i, delays): - for delay in delays: - sleep(delay) # ID: sleep - # - threads = [Thread(target=loop_of_sleeps, args=[i, delays]) for i in range(5)] - start = time.time() - for i, thread in enumerate(threads): - thread.start() - for thread in threads: - thread.join() - end = time.time() - return end - start - log = self.run(main, [get_libc_name(), 200], threshold=150, - import_site=True) - assert 1 <= log.result <= 1.5 # at most 0.5 seconds of overhead - loops = log.loops_by_id('sleep') - assert len(loops) == 1 # make sure that we actually JITted the loop - - def test_ctypes_call(self): - from rpython.rlib.test.test_clibffi import get_libm_name - def main(libm_name): - import ctypes - libm = ctypes.CDLL(libm_name) - fabs = libm.fabs - fabs.argtypes = [ctypes.c_double] - fabs.restype = ctypes.c_double - x = -4 - i = 0 - while i < 300: - x = fabs(x) - x = x - 100 - i += 1 - return fabs._ptr.getaddr(), x - - libm_name = get_libm_name(sys.platform) - log = self.run(main, [libm_name], import_site=True) - fabs_addr, res = log.result - assert res == -4.0 - loop, = log.loops_by_filename(self.filepath) - ops = loop.allops() - opnames = log.opnames(ops) - assert opnames.count('new_with_vtable') == 1 # only the virtualref - py.test.xfail() # XXX re-optimize _ffi for the JIT? - assert opnames.count('call_release_gil') == 1 - idx = opnames.index('call_release_gil') - call = ops[idx] - assert (call.args[0] == 'ConstClass(fabs)' or # e.g. OS/X - int(call.args[0]) == fabs_addr) - - - def test__ffi_struct(self): - def main(): - from _ffi import _StructDescr, Field, types - fields = [ - Field('x', types.slong), - ] - descr = _StructDescr('foo', fields) - struct = descr.allocate() - i = 0 - while i < 300: - x = struct.getfield('x') # ID: getfield - x = x+1 - struct.setfield('x', x) # ID: setfield - i += 1 - return struct.getfield('x') - # - log = self.run(main, []) - py.test.xfail() # XXX re-optimize _ffi for the JIT? - loop, = log.loops_by_filename(self.filepath) - assert loop.match_by_id('getfield', """ - guard_not_invalidated(descr=...) - i57 = getfield_raw(i46, descr=) - """) - assert loop.match_by_id('setfield', """ - setfield_raw(i44, i57, descr=) - """) - - - def test__cffi_call(self): - from rpython.rlib.test.test_clibffi import get_libm_name - def main(libm_name): - try: - import _cffi_backend - except ImportError: - sys.stderr.write('SKIP: cannot import _cffi_backend\n') - return 0 - - libm = _cffi_backend.load_library(libm_name) - BDouble = _cffi_backend.new_primitive_type("double") - BInt = _cffi_backend.new_primitive_type("int") - BPow = _cffi_backend.new_function_type([BDouble, BInt], BDouble) - ldexp = libm.load_function(BPow, 'ldexp') - i = 0 - res = 0 - while i < 300: - tmp = ldexp(1, 3) # ID: cfficall - res += tmp - i += 1 - BLong = _cffi_backend.new_primitive_type("long") - ldexp_addr = int(_cffi_backend.cast(BLong, ldexp)) - return ldexp_addr, res - # - libm_name = get_libm_name(sys.platform) - log = self.run(main, [libm_name]) - ldexp_addr, res = log.result - assert res == 8.0 * 300 - loop, = log.loops_by_filename(self.filepath) - if 'ConstClass(ldexp)' in repr(loop): # e.g. OS/X - ldexp_addr = 'ConstClass(ldexp)' - assert loop.match_by_id('cfficall', """ - ... - f1 = call_release_gil(..., descr=) - ... - """) - ops = loop.ops_by_id('cfficall') - assert 'raw_malloc' not in str(ops) - assert 'raw_free' not in str(ops) - assert 'getarrayitem_raw' not in log.opnames(ops) - assert 'setarrayitem_raw' not in log.opnames(ops) - # so far just check that call_release_gil() is produced. - # later, also check that the arguments to call_release_gil() - # are constants - # are constants, and that the numerous raw_mallocs are removed - - def test_cffi_call_guard_not_forced_fails(self): - # this is the test_pypy_c equivalent of - # rpython/jit/metainterp/test/test_fficall::test_guard_not_forced_fails - # - # it requires cffi to be installed for pypy in order to run - def main(): - import sys - try: - import cffi - except ImportError: - sys.stderr.write('SKIP: cannot import cffi\n') - return 0 - - ffi = cffi.FFI() - - ffi.cdef(""" - typedef void (*functype)(int); - int foo(int n, functype func); - """) - - lib = ffi.verify(""" - #include - typedef void (*functype)(int); - - int foo(int n, functype func) { - if (n >= 2000) { - func(n); - } - return n*2; - } - """) - - @ffi.callback("functype") - def mycallback(n): - if n < 5000: - return - # make sure that guard_not_forced fails - d = {} - f = sys._getframe() - while f: - d.update(f.f_locals) - f = f.f_back - - n = 0 - while n < 10000: - res = lib.foo(n, mycallback) # ID: cfficall - # this is the real point of the test: before the - # refactor-call_release_gil branch, the assert failed when - # res == 5000 - assert res == n*2 - n += 1 - return n - - log = self.run(main, [], import_site=True) - assert log.result == 10000 - loop, = log.loops_by_id('cfficall') - assert loop.match_by_id('cfficall', """ - ... - f1 = call_release_gil(..., descr=) - ... - """) diff --git a/rpython/jit/backend/llgraph/runner.py b/rpython/jit/backend/llgraph/runner.py --- a/rpython/jit/backend/llgraph/runner.py +++ b/rpython/jit/backend/llgraph/runner.py @@ -484,15 +484,6 @@ else: return self.bh_raw_load_i(struct, offset, descr) - def unpack_arraydescr_size(self, arraydescr): - from rpython.jit.backend.llsupport.symbolic import get_array_token - from rpython.jit.backend.llsupport.descr import get_type_flag, FLAG_SIGNED - assert isinstance(arraydescr, ArrayDescr) - basesize, itemsize, _ = get_array_token(arraydescr.A, False) - flag = get_type_flag(arraydescr.A.OF) - is_signed = (flag == FLAG_SIGNED) - return basesize, itemsize, is_signed - def bh_raw_store_i(self, struct, offset, newvalue, descr): ll_p = rffi.cast(rffi.CCHARP, struct) ll_p = rffi.cast(lltype.Ptr(descr.A), rffi.ptradd(ll_p, offset)) @@ -575,14 +566,10 @@ def bh_read_timestamp(self): return read_timestamp() - def bh_new_raw_buffer(self, size): - return lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') - def store_fail_descr(self, deadframe, descr): pass # I *think* - class LLDeadFrame(object): _TYPE = llmemory.GCREF diff --git a/rpython/jit/backend/llsupport/llmodel.py b/rpython/jit/backend/llsupport/llmodel.py --- a/rpython/jit/backend/llsupport/llmodel.py +++ b/rpython/jit/backend/llsupport/llmodel.py @@ -742,9 +742,6 @@ as_array[self.vtable_offset/WORD] = vtable return res - def bh_new_raw_buffer(self, size): - return lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') - def bh_classof(self, struct): struct = lltype.cast_opaque_ptr(rclass.OBJECTPTR, struct) result_adr = llmemory.cast_ptr_to_adr(struct.typeptr) diff --git a/rpython/jit/backend/llsupport/test/ztranslation_test.py b/rpython/jit/backend/llsupport/test/ztranslation_test.py --- a/rpython/jit/backend/llsupport/test/ztranslation_test.py +++ b/rpython/jit/backend/llsupport/test/ztranslation_test.py @@ -10,15 +10,7 @@ def fix_annotator_for_vrawbuffer(monkeypatch): - from rpython.rlib.nonconst import NonConstant - from rpython.jit.metainterp.optimizeopt.virtualize import VRawBufferValue - from rpython.jit.metainterp import warmspot - - def my_hook_for_tests(cpu): - # this is needed so that the annotator can see it - if NonConstant(False): - v = VRawBufferValue(cpu, None, -1, None, None) - monkeypatch.setattr(warmspot, 'hook_for_tests', my_hook_for_tests) + return class TranslationTest(CCompiledMixin): diff --git a/rpython/jit/backend/model.py b/rpython/jit/backend/model.py --- a/rpython/jit/backend/model.py +++ b/rpython/jit/backend/model.py @@ -194,18 +194,11 @@ def typedescrof(self, TYPE): raise NotImplementedError - def unpack_arraydescr_size(self, arraydescr): - """ - Return basesize, itemsize, is_signed - """ - raise NotImplementedError - @staticmethod def cast_int_to_ptr(x, TYPE): x = llmemory.cast_int_to_adr(x) return llmemory.cast_adr_to_ptr(x, TYPE) - # ---------- the backend-dependent operations ---------- # lltype specific operations @@ -242,8 +235,6 @@ raise NotImplementedError def bh_newunicode(self, length): raise NotImplementedError - def bh_new_raw_buffer(self, size): - raise NotImplementedError def bh_arraylen_gc(self, array, arraydescr): raise NotImplementedError diff --git a/rpython/jit/codewriter/effectinfo.py b/rpython/jit/codewriter/effectinfo.py --- a/rpython/jit/codewriter/effectinfo.py +++ b/rpython/jit/codewriter/effectinfo.py @@ -76,14 +76,14 @@ # OS_MATH_SQRT = 100 # - OS_RAW_MALLOC_VARSIZE_CHAR = 110 + OS_RAW_MALLOC_VARSIZE = 110 OS_RAW_FREE = 111 OS_JIT_FORCE_VIRTUAL = 120 # for debugging: _OS_CANRAISE = set([OS_NONE, OS_STR2UNICODE, OS_LIBFFI_CALL, - OS_RAW_MALLOC_VARSIZE_CHAR, OS_JIT_FORCE_VIRTUAL]) + OS_RAW_MALLOC_VARSIZE, OS_JIT_FORCE_VIRTUAL]) def __new__(cls, readonly_descrs_fields, readonly_descrs_arrays, write_descrs_fields, write_descrs_arrays, diff --git a/rpython/jit/codewriter/jtransform.py b/rpython/jit/codewriter/jtransform.py --- a/rpython/jit/codewriter/jtransform.py +++ b/rpython/jit/codewriter/jtransform.py @@ -539,11 +539,9 @@ name += '_no_track_allocation' op1 = self.prepare_builtin_call(op, name, args, (TYPE,), TYPE) if name == 'raw_malloc_varsize': - ITEMTYPE = op.args[0].value.OF - if ITEMTYPE == lltype.Char: - return self._handle_oopspec_call(op1, args, - EffectInfo.OS_RAW_MALLOC_VARSIZE_CHAR, - EffectInfo.EF_CAN_RAISE) + return self._handle_oopspec_call(op1, args, + EffectInfo.OS_RAW_MALLOC_VARSIZE, + EffectInfo.EF_CAN_RAISE) return self.rewrite_op_direct_call(op1) def rewrite_op_malloc_varsize(self, op): diff --git a/rpython/jit/codewriter/test/test_jtransform.py b/rpython/jit/codewriter/test/test_jtransform.py --- a/rpython/jit/codewriter/test/test_jtransform.py +++ b/rpython/jit/codewriter/test/test_jtransform.py @@ -126,7 +126,7 @@ INT = lltype.Signed UNICHAR = lltype.UniChar FLOAT = lltype.Float - ARRAYPTR = rffi.CArrayPtr(lltype.Char) + ARRAYPTR = rffi.CArrayPtr(lltype.Signed) argtypes = { EI.OS_MATH_SQRT: ([FLOAT], FLOAT), EI.OS_STR2UNICODE:([PSTR], PUNICODE), @@ -143,7 +143,7 @@ EI.OS_UNIEQ_NONNULL_CHAR: ([PUNICODE, UNICHAR], INT), EI.OS_UNIEQ_CHECKNULL_CHAR: ([PUNICODE, UNICHAR], INT), EI.OS_UNIEQ_LENGTHOK: ([PUNICODE, PUNICODE], INT), - EI.OS_RAW_MALLOC_VARSIZE_CHAR: ([INT], ARRAYPTR), + EI.OS_RAW_MALLOC_VARSIZE: ([INT], ARRAYPTR), EI.OS_RAW_FREE: ([ARRAYPTR], lltype.Void), } argtypes = argtypes[oopspecindex] @@ -151,7 +151,7 @@ assert argtypes[1] == op.result.concretetype if oopspecindex == EI.OS_STR2UNICODE: assert extraeffect == EI.EF_ELIDABLE_CAN_RAISE - elif oopspecindex == EI.OS_RAW_MALLOC_VARSIZE_CHAR: + elif oopspecindex == EI.OS_RAW_MALLOC_VARSIZE: assert extraeffect == EI.EF_CAN_RAISE elif oopspecindex == EI.OS_RAW_FREE: assert extraeffect == EI.EF_CANNOT_RAISE @@ -161,7 +161,7 @@ def calldescr_canraise(self, calldescr): EI = effectinfo.EffectInfo - if calldescr == 'calldescr-%d' % EI.OS_RAW_MALLOC_VARSIZE_CHAR: + if calldescr == 'calldescr-%d' % EI.OS_RAW_MALLOC_VARSIZE: return True return False @@ -555,7 +555,7 @@ assert op1.args == [] def test_raw_malloc(): - S = rffi.CArray(lltype.Char) + S = rffi.CArray(lltype.Signed) v1 = varoftype(lltype.Signed) v = varoftype(lltype.Ptr(S)) flags = Constant({'flavor': 'raw'}, lltype.Void) @@ -566,7 +566,7 @@ assert op0.opname == 'residual_call_ir_i' assert op0.args[0].value == 'raw_malloc_varsize' # pseudo-function as a str assert (op0.args[-1] == 'calldescr-%d' % - effectinfo.EffectInfo.OS_RAW_MALLOC_VARSIZE_CHAR) + effectinfo.EffectInfo.OS_RAW_MALLOC_VARSIZE) assert op1.opname == '-live-' assert op1.args == [] @@ -608,7 +608,7 @@ assert op1.args == [] def test_raw_free(): - S = rffi.CArray(lltype.Char) + S = rffi.CArray(lltype.Signed) flags = Constant({'flavor': 'raw', 'track_allocation': True}, lltype.Void) op = SpaceOperation('free', [varoftype(lltype.Ptr(S)), flags], diff --git a/rpython/jit/metainterp/compile.py b/rpython/jit/metainterp/compile.py --- a/rpython/jit/metainterp/compile.py +++ b/rpython/jit/metainterp/compile.py @@ -15,7 +15,7 @@ from rpython.jit.metainterp import history, resume from rpython.jit.metainterp.optimize import InvalidLoop from rpython.jit.metainterp.inliner import Inliner -from rpython.jit.metainterp.resume import NUMBERING, PENDINGFIELDSP, ResumeDataDirectReader +from rpython.jit.metainterp.resume import NUMBERING, PENDINGFIELDSP from rpython.jit.codewriter import heaptracker, longlong def giveup(): @@ -656,9 +656,9 @@ class AllVirtuals: llopaque = True - cache = None - def __init__(self, cache): - self.cache = cache + list = [resume.ResumeDataDirectReader.virtual_default] # annotation hack + def __init__(self, list): + self.list = list def hide(self, cpu): ptr = cpu.ts.cast_instance_to_base_ref(self) return cpu.ts.cast_to_ref(ptr) @@ -682,9 +682,9 @@ from rpython.jit.metainterp.blackhole import resume_in_blackhole hidden_all_virtuals = metainterp_sd.cpu.get_savedata_ref(deadframe) obj = AllVirtuals.show(metainterp_sd.cpu, hidden_all_virtuals) - all_virtuals = obj.cache + all_virtuals = obj.list if all_virtuals is None: - all_virtuals = ResumeDataDirectReader.VirtualCache([], []) + all_virtuals = [] assert jitdriver_sd is self.jitdriver_sd resume_in_blackhole(metainterp_sd, jitdriver_sd, self, deadframe, all_virtuals) diff --git a/rpython/jit/metainterp/history.py b/rpython/jit/metainterp/history.py --- a/rpython/jit/metainterp/history.py +++ b/rpython/jit/metainterp/history.py @@ -191,6 +191,7 @@ def get_jitcode_for_class(self, oocls): return self.jitcodes[oocls] + class Const(AbstractValue): __slots__ = () diff --git a/rpython/jit/metainterp/optimizeopt/earlyforce.py b/rpython/jit/metainterp/optimizeopt/earlyforce.py --- a/rpython/jit/metainterp/optimizeopt/earlyforce.py +++ b/rpython/jit/metainterp/optimizeopt/earlyforce.py @@ -1,26 +1,15 @@ -from rpython.jit.codewriter.effectinfo import EffectInfo from rpython.jit.metainterp.optimizeopt.optimizer import Optimization from rpython.jit.metainterp.optimizeopt.vstring import VAbstractStringValue from rpython.jit.metainterp.resoperation import rop, ResOperation -def is_raw_free(op, opnum): - if opnum != rop.CALL: - return False - einfo = op.getdescr().get_extra_info() - return einfo.oopspecindex == EffectInfo.OS_RAW_FREE - - class OptEarlyForce(Optimization): def propagate_forward(self, op): opnum = op.getopnum() - if (opnum != rop.SETFIELD_GC and opnum != rop.SETARRAYITEM_GC and - opnum != rop.SETARRAYITEM_RAW and opnum != rop.QUASIIMMUT_FIELD and opnum != rop.SAME_AS and - opnum != rop.MARK_OPAQUE_PTR and - not is_raw_free(op, opnum)): + opnum != rop.MARK_OPAQUE_PTR): for arg in op.getarglist(): if arg in self.optimizer.values: diff --git a/rpython/jit/metainterp/optimizeopt/optimizer.py b/rpython/jit/metainterp/optimizeopt/optimizer.py --- a/rpython/jit/metainterp/optimizeopt/optimizer.py +++ b/rpython/jit/metainterp/optimizeopt/optimizer.py @@ -231,12 +231,6 @@ def setitem(self, index, value): raise NotImplementedError - def getitem_raw(self, offset, length, descr): - raise NotImplementedError - - def setitem_raw(self, offset, length, descr, value): - raise NotImplementedError - def getinteriorfield(self, index, ofs, default): raise NotImplementedError diff --git a/rpython/jit/metainterp/optimizeopt/rawbuffer.py b/rpython/jit/metainterp/optimizeopt/rawbuffer.py deleted file mode 100644 --- a/rpython/jit/metainterp/optimizeopt/rawbuffer.py +++ /dev/null @@ -1,134 +0,0 @@ -from rpython.rlib.debug import debug_start, debug_stop, debug_print -from rpython.rlib.objectmodel import compute_unique_id, we_are_translated - -class InvalidRawOperation(Exception): - pass - -class InvalidRawWrite(InvalidRawOperation): - pass - -class InvalidRawRead(InvalidRawOperation): - pass - -class RawBuffer(object): - def __init__(self, cpu, logops=None): - # the following lists represents the writes in the buffer: values[i] - # is the value of length lengths[i] stored at offset[i]. - # - # the invariant is that they are ordered by offset, and that - # offset[i]+length[i] <= offset[i+1], i.e. that the writes never - # overlaps - self.cpu = cpu - self.logops = logops - self.offsets = [] - self.lengths = [] - self.descrs = [] - self.values = [] - - def _get_memory(self): - """ - NOT_RPYTHON - for testing only - """ - return zip(self.offsets, self.lengths, self.descrs, self.values) - - def _repr_of_descr(self, descr): - if self.logops: - s = self.logops.repr_of_descr(descr) - else: - s = str(descr) - s += " at %d" % compute_unique_id(descr) - return s - - def _repr_of_value(self, value): - if not we_are_translated() and isinstance(value, str): - return value # for tests - if self.logops: - s = self.logops.repr_of_arg(value.box) - else: - s = str(value.box) - s += " at %d" % compute_unique_id(value.box) - return s - - def _dump_to_log(self): - debug_print("RawBuffer state") - debug_print("offset, length, descr, box") - debug_print("(box == None means that the value is still virtual)") - for i in range(len(self.offsets)): - descr = self._repr_of_descr(self.descrs[i]) - box = self._repr_of_value(self.values[i]) - debug_print("%d, %d, %s, %s" % (self.offsets[i], self.lengths[i], descr, box)) - - def _invalid_write(self, message, offset, length, descr, value): - debug_start('jit-log-rawbuffer') - debug_print('Invalid write: %s' % message) - debug_print(" offset: %d" % offset) - debug_print(" length: %d" % length) - debug_print(" descr: %s" % self._repr_of_descr(descr)) - debug_print(" value: %s" % self._repr_of_value(value)) - self._dump_to_log() - debug_stop('jit-log-rawbuffer') - raise InvalidRawWrite - - def _invalid_read(self, message, offset, length, descr): - debug_start('jit-log-rawbuffer') - debug_print('Invalid read: %s' % message) - debug_print(" offset: %d" % offset) - debug_print(" length: %d" % length) - debug_print(" descr: %s" % self._repr_of_descr(descr)) - self._dump_to_log() - debug_stop('jit-log-rawbuffer') - raise InvalidRawRead - - def _descrs_are_compatible(self, d1, d2): - # two arraydescrs are compatible if they have the same basesize, - # itemsize and sign, even if they are not identical - unpack = self.cpu.unpack_arraydescr_size - return unpack(d1) == unpack(d2) - - def write_value(self, offset, length, descr, value): - i = 0 - N = len(self.offsets) - while i < N: - if self.offsets[i] == offset: - if (length != self.lengths[i] or not - self._descrs_are_compatible(descr, self.descrs[i])): - # in theory we could add support for the cases in which - # the length or descr is different, but I don't think we - # need it in practice - self._invalid_write('length or descr not compatible', - offset, length, descr, value) - # update the value at this offset - self.values[i] = value - return - elif self.offsets[i] > offset: - break - i += 1 - # - if i < len(self.offsets) and offset+length > self.offsets[i]: - self._invalid_write("overlap with next bytes", - offset, length, descr, value) - if i > 0 and self.offsets[i-1]+self.lengths[i-1] > offset: - self._invalid_write("overlap with previous bytes", - offset, length, descr, value) - # insert a new value at offset - self.offsets.insert(i, offset) - self.lengths.insert(i, length) - self.descrs.insert(i, descr) - self.values.insert(i, value) - - def read_value(self, offset, length, descr): - i = 0 - N = len(self.offsets) - while i < N: - if self.offsets[i] == offset: - if (length != self.lengths[i] or - not self._descrs_are_compatible(descr, self.descrs[i])): - self._invalid_read('length or descr not compatible', - offset, length, descr) - return self.values[i] - i += 1 - # memory location not found: this means we are reading from - # uninitialized memory, give up the optimization - self._invalid_read('uninitialized memory', - offset, length, descr) diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py --- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py @@ -770,6 +770,8 @@ """ self.optimize_loop(ops, expected) + + def test_p123_simple(self): ops = """ [i1, p2, p3] @@ -1728,175 +1730,6 @@ # We cannot track virtuals that survive for more than two iterations. self.optimize_loop(ops, expected, preamble) - def test_virtual_raw_malloc(self): - ops = """ - [i1] - i2 = call('malloc', 10, descr=raw_malloc_descr) - setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) - i3 = getarrayitem_raw(i2, 0, descr=rawarraydescr) - call('free', i2, descr=raw_free_descr) - jump(i3) - """ - expected = """ - [i1] - jump(i1) - """ - self.optimize_loop(ops, expected) - - def test_virtual_raw_malloc_force(self): - ops = """ - [i1] - i2 = call('malloc', 10, descr=raw_malloc_descr) - setarrayitem_raw(i2, 0, i1, descr=rawarraydescr_char) - setarrayitem_raw(i2, 2, 456, descr=rawarraydescr_char) - setarrayitem_raw(i2, 1, 123, descr=rawarraydescr_char) - label('foo') # we expect the buffer to be forced *after* the label - escape(i2) - call('free', i2, descr=raw_free_descr) - jump(i1) - """ - expected = """ - [i1] - label('foo') - i2 = call('malloc', 10, descr=raw_malloc_descr) - setarrayitem_raw(i2, 0, i1, descr=rawarraydescr_char) - i3 = int_add(i2, 1) - setarrayitem_raw(i3, 0, 123, descr=rawarraydescr_char) - i4 = int_add(i2, 2) - setarrayitem_raw(i4, 0, 456, descr=rawarraydescr_char) - escape(i2) - call('free', i2, descr=raw_free_descr) - jump(i1) - """ - self.optimize_loop(ops, expected) - - def test_virtual_raw_malloc_invalid_write_force(self): - ops = """ - [i1] - i2 = call('malloc', 10, descr=raw_malloc_descr) - setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) - label('foo') # we expect the buffer to be forced *after* the label - setarrayitem_raw(i2, 2, 456, descr=rawarraydescr_char) # overlap! - call('free', i2, descr=raw_free_descr) - jump(i1) - """ - expected = """ - [i1] - label('foo') - i2 = call('malloc', 10, descr=raw_malloc_descr) - setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) - setarrayitem_raw(i2, 2, 456, descr=rawarraydescr_char) - call('free', i2, descr=raw_free_descr) - jump(i1) - """ - self.optimize_loop(ops, expected) - - def test_virtual_raw_malloc_invalid_read_force(self): - ops = """ - [i1] - i2 = call('malloc', 10, descr=raw_malloc_descr) - setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) - label('foo') # we expect the buffer to be forced *after* the label - i3 = getarrayitem_raw(i2, 0, descr=rawarraydescr_char) - call('free', i2, descr=raw_free_descr) - jump(i1) - """ - expected = """ - [i1] - label('foo') - i2 = call('malloc', 10, descr=raw_malloc_descr) - setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) - i3 = getarrayitem_raw(i2, 0, descr=rawarraydescr_char) - call('free', i2, descr=raw_free_descr) - jump(i1) - """ - self.optimize_loop(ops, expected) - - def test_virtual_raw_slice(self): - ops = """ - [i0, i1] - i2 = call('malloc', 10, descr=raw_malloc_descr) - setarrayitem_raw(i2, 0, 42, descr=rawarraydescr_char) - i3 = int_add(i2, 1) # get a slice of the original buffer - setarrayitem_raw(i3, 0, 4242, descr=rawarraydescr) # write to the slice - i4 = getarrayitem_raw(i2, 0, descr=rawarraydescr_char) - i5 = int_add(i2, 1) - i6 = getarrayitem_raw(i5, 0, descr=rawarraydescr) - call('free', i2, descr=raw_free_descr) - jump(i0, i1) - """ - expected = """ - [i0, i1] - jump(i0, i1) - """ - self.optimize_loop(ops, expected) - - def test_virtual_raw_slice_of_a_raw_slice(self): - ops = """ - [i0, i1] - i2 = call('malloc', 10, descr=raw_malloc_descr) - i3 = int_add(i2, 1) # get a slice of the original buffer - i4 = int_add(i3, 1) # get a slice of a slice - setarrayitem_raw(i4, 0, i1, descr=rawarraydescr_char) # write to the slice - i5 = getarrayitem_raw(i2, 2, descr=rawarraydescr_char) - call('free', i2, descr=raw_free_descr) - jump(i0, i5) - """ - expected = """ - [i0, i1] - jump(i0, i1) - """ - self.optimize_loop(ops, expected) - - def test_virtual_raw_slice_force(self): - ops = """ - [i0, i1] - i2 = call('malloc', 10, descr=raw_malloc_descr) - setarrayitem_raw(i2, 0, 42, descr=rawarraydescr_char) - i3 = int_add(i2, 1) # get a slice of the original buffer - setarrayitem_raw(i3, 4, 4242, descr=rawarraydescr_char) # write to the slice - label('foo') - escape(i3) - jump(i0, i1) - """ - expected = """ - [i0, i1] - label('foo') - # these ops are generated by VirtualRawBufferValue._really_force - i2 = call('malloc', 10, descr=raw_malloc_descr) - setarrayitem_raw(i2, 0, 42, descr=rawarraydescr_char) - i3 = int_add(i2, 5) # 1+4*sizeof(char) - setarrayitem_raw(i3, 0, 4242, descr=rawarraydescr_char) - # this is generated by VirtualRawSliceValue._really_force - i4 = int_add(i2, 1) - escape(i4) - jump(i0, i1) - """ - self.optimize_loop(ops, expected) - - def test_virtual_raw_malloc_virtualstate(self): - ops = """ - [i0] - i1 = getarrayitem_raw(i0, 0, descr=rawarraydescr) - i2 = int_add(i1, 1) - call('free', i0, descr=raw_free_descr) - i3 = call('malloc', 10, descr=raw_malloc_descr) - setarrayitem_raw(i3, 0, i2, descr=rawarraydescr) - label('foo') - jump(i3) - """ - expected = """ - [i0] - i1 = getarrayitem_raw(i0, 0, descr=rawarraydescr) - i2 = int_add(i1, 1) - call('free', i0, descr=raw_free_descr) - label('foo') - i3 = call('malloc', 10, descr=raw_malloc_descr) - setarrayitem_raw(i3, 0, i2, descr=rawarraydescr) - jump(i3) - """ - self.optimize_loop(ops, expected) - def test_duplicate_getfield_1(self): ops = """ [p1, p2] diff --git a/rpython/jit/metainterp/optimizeopt/test/test_rawbuffer.py b/rpython/jit/metainterp/optimizeopt/test/test_rawbuffer.py deleted file mode 100644 --- a/rpython/jit/metainterp/optimizeopt/test/test_rawbuffer.py +++ /dev/null @@ -1,90 +0,0 @@ -import py -from rpython.jit.metainterp.optimizeopt.rawbuffer import (InvalidRawWrite, - InvalidRawRead, RawBuffer) - -class FakeCPU(object): - def unpack_arraydescr_size(self, descr): - return descr, 'foo', 'bar' - -def test_write_value(): - buf = RawBuffer(FakeCPU()) - buf.write_value(8, 4, 'descr3', 'three') - buf.write_value(0, 4, 'descr1', 'one') - buf.write_value(4, 2, 'descr2', 'two') - buf.write_value(12, 2, 'descr4', 'four') - assert buf._get_memory() == [ - ( 0, 4, 'descr1', 'one'), - ( 4, 2, 'descr2', 'two'), - ( 8, 4, 'descr3', 'three'), - (12, 2, 'descr4', 'four'), - ] - # - -def test_write_value_update(): - buf = RawBuffer(FakeCPU()) - buf.write_value(0, 4, 'descr', 'one') - buf.write_value(4, 2, 'descr', 'two') - buf.write_value(0, 4, 'descr', 'ONE') - assert buf._get_memory() == [ - ( 0, 4, 'descr', 'ONE'), - ( 4, 2, 'descr', 'two'), - ] - -def test_write_value_invalid_length(): - buf = RawBuffer(FakeCPU()) - buf.write_value(0, 4, 'descr1', 'one') - with py.test.raises(InvalidRawWrite): - buf.write_value(0, 5, 'descr1', 'two') - with py.test.raises(InvalidRawWrite): - buf.write_value(0, 4, 'descr2', 'two') - - -def test_write_value_overlapping_next(): - buf = RawBuffer(FakeCPU()) - buf.write_value(0, 4, 'descr', 'one') - buf.write_value(6, 4, 'descr', 'two') - with py.test.raises(InvalidRawWrite): - buf.write_value(4, 4, 'descr', 'three') - -def test_write_value_overlapping_prev(): - buf = RawBuffer(FakeCPU()) - buf.write_value(0, 4, 'descr', 'one') - with py.test.raises(InvalidRawWrite): - buf.write_value(2, 1, 'descr', 'two') - -def test_read_value(): - buf = RawBuffer(FakeCPU()) - buf.write_value(0, 4, 'descr', 'one') - buf.write_value(4, 4, 'descr', 'two') - assert buf.read_value(0, 4, 'descr') == 'one' - assert buf.read_value(4, 4, 'descr') == 'two' - with py.test.raises(InvalidRawRead): - buf.read_value(0, 2, 'descr') - with py.test.raises(InvalidRawRead): - buf.read_value(8, 2, 'descr') - with py.test.raises(InvalidRawRead): - buf.read_value(0, 4, 'another descr') - -def test_unpack_descrs(): - ArrayS_8_1 = object() - ArrayS_8_2 = object() - ArrayU_8 = object() - - class FakeCPU(object): - def unpack_arraydescr_size(self, descr): - if descr in (ArrayS_8_1, ArrayS_8_2): - return 0, 8, True - return 0, 8, False - - buf = RawBuffer(FakeCPU()) - buf.write_value(0, 4, ArrayS_8_1, 'one') - assert buf.read_value(0, 4, ArrayS_8_1) == 'one' - assert buf.read_value(0, 4, ArrayS_8_2) == 'one' # with a non-identical descr - # - buf.write_value(0, 4, ArrayS_8_2, 'two') # with a non-identical descr - assert buf.read_value(0, 4, ArrayS_8_1) == 'two' - # - with py.test.raises(InvalidRawRead): - buf.read_value(0, 4, ArrayU_8) - with py.test.raises(InvalidRawWrite): - buf.write_value(0, 4, ArrayU_8, 'three') diff --git a/rpython/jit/metainterp/optimizeopt/test/test_util.py b/rpython/jit/metainterp/optimizeopt/test/test_util.py --- a/rpython/jit/metainterp/optimizeopt/test/test_util.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_util.py @@ -196,15 +196,6 @@ EffectInfo.EF_CANNOT_RAISE, oopspecindex=EffectInfo.OS_ARRAYCOPY)) - raw_malloc_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, - EffectInfo([], [], [], [], - EffectInfo.EF_CAN_RAISE, - oopspecindex=EffectInfo.OS_RAW_MALLOC_VARSIZE_CHAR)) - raw_free_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, - EffectInfo([], [], [], [], - EffectInfo.EF_CANNOT_RAISE, - oopspecindex=EffectInfo.OS_RAW_FREE)) - # array of structs (complex data) complexarray = lltype.GcArray( @@ -217,12 +208,6 @@ complexrealdescr = cpu.interiorfielddescrof(complexarray, "real") compleximagdescr = cpu.interiorfielddescrof(complexarray, "imag") - rawarraydescr = cpu.arraydescrof(lltype.Array(lltype.Signed, - hints={'nolength': True})) - rawarraydescr_char = cpu.arraydescrof(lltype.Array(lltype.Char, - hints={'nolength': True})) - - for _name, _os in [ ('strconcatdescr', 'OS_STR_CONCAT'), ('strslicedescr', 'OS_STR_SLICE'), diff --git a/rpython/jit/metainterp/optimizeopt/virtualize.py b/rpython/jit/metainterp/optimizeopt/virtualize.py --- a/rpython/jit/metainterp/optimizeopt/virtualize.py +++ b/rpython/jit/metainterp/optimizeopt/virtualize.py @@ -6,9 +6,7 @@ from rpython.jit.metainterp.optimizeopt import optimizer from rpython.jit.metainterp.optimizeopt.optimizer import OptValue, REMOVED from rpython.jit.metainterp.optimizeopt.util import (make_dispatcher_method, - descrlist_dict, sort_descrs) - -from rpython.jit.metainterp.optimizeopt.rawbuffer import RawBuffer, InvalidRawOperation + descrlist_dict, sort_descrs) from rpython.jit.metainterp.resoperation import rop, ResOperation from rpython.rlib.objectmodel import we_are_translated @@ -238,36 +236,8 @@ def _get_descr(self): return self.structdescr -class AbstractVArrayValue(AbstractVirtualValue): - """ - Base class for VArrayValue (for normal GC arrays) and VRawBufferValue (for - malloc()ed memory) - """ - def getlength(self): - return len(self._items) - - def get_item_value(self, i): - raise NotImplementedError - - def set_item_value(self, i, newval): - raise NotImplementedError - - def get_args_for_fail(self, modifier): - if self.box is None and not modifier.already_seen_virtual(self.keybox): - # checks for recursion: it is False unless - # we have already seen the very same keybox - itemboxes = [] - for i in range(self.getlength()): - itemvalue = self.get_item_value(i) - itemboxes.append(itemvalue.get_key_box()) - modifier.register_virtual_fields(self.keybox, itemboxes) - for i in range(self.getlength()): - itemvalue = self.get_item_value(i) - itemvalue.get_args_for_fail(modifier) - - -class VArrayValue(AbstractVArrayValue): +class VArrayValue(AbstractVirtualValue): def __init__(self, arraydescr, constvalue, size, keybox, source_op=None): AbstractVirtualValue.__init__(self, keybox, source_op) @@ -278,12 +248,6 @@ def getlength(self): return len(self._items) - def get_item_value(self, i): - return self._items[i] - - def set_item_value(self, i, newval): - self._items[i] = newval - def getitem(self, index): res = self._items[index] return res @@ -293,16 +257,11 @@ self._items[index] = itemvalue def force_at_end_of_preamble(self, already_forced, optforce): - # note that this method is on VArrayValue instead of - # AbstractVArrayValue because we do not want to support virtualstate - # for rawbuffers for now if self in already_forced: return self already_forced[self] = self - for index in range(self.getlength()): - itemval = self.get_item_value(index) - itemval = itemval.force_at_end_of_preamble(already_forced, optforce) - self.set_item_value(index, itemval) + for index in range(len(self._items)): + self._items[index] = self._items[index].force_at_end_of_preamble(already_forced, optforce) return self def _really_force(self, optforce): @@ -322,16 +281,29 @@ descr=self.arraydescr) optforce.emit_operation(op) + def get_args_for_fail(self, modifier): + if self.box is None and not modifier.already_seen_virtual(self.keybox): + # checks for recursion: it is False unless + # we have already seen the very same keybox + itemboxes = [] + for itemvalue in self._items: + itemboxes.append(itemvalue.get_key_box()) + modifier.register_virtual_fields(self.keybox, itemboxes) + for itemvalue in self._items: + itemvalue.get_args_for_fail(modifier) + def _make_virtual(self, modifier): return modifier.make_varray(self.arraydescr) - class VArrayStructValue(AbstractVirtualValue): def __init__(self, arraydescr, size, keybox, source_op=None): AbstractVirtualValue.__init__(self, keybox, source_op) self.arraydescr = arraydescr self._items = [{} for _ in xrange(size)] + def getlength(self): + return len(self._items) + def getinteriorfield(self, index, ofs, default): return self._items[index].get(ofs, default) @@ -391,90 +363,6 @@ return modifier.make_varraystruct(self.arraydescr, self._get_list_of_descrs()) -class VRawBufferValue(AbstractVArrayValue): - - def __init__(self, cpu, logops, size, keybox, source_op): - AbstractVirtualValue.__init__(self, keybox, source_op) - # note that size is unused, because we assume that the buffer is big - # enough to write/read everything we need. If it's not, it's undefined - # behavior anyway, although in theory we could probably detect such - # cases here - self.size = size - self.buffer = RawBuffer(cpu, logops) - - def getlength(self): - return len(self.buffer.values) - - def get_item_value(self, i): - return self.buffer.values[i] - - def set_item_value(self, i, newval): - self.buffer.values[i] = newval - - def getitem_raw(self, offset, length, descr): - return self.buffer.read_value(offset, length, descr) - - def setitem_raw(self, offset, length, descr, value): - self.buffer.write_value(offset, length, descr, value) - - def _really_force(self, optforce): - op = self.source_op - assert op is not None - if not we_are_translated(): - op.name = 'FORCE ' + self.source_op.name - optforce.emit_operation(self.source_op) - self.box = box = self.source_op.result - for i in range(len(self.buffer.offsets)): - # get a pointer to self.box+offset - offset = self.buffer.offsets[i] - if offset == 0: - arraybox = self.box - else: - arraybox = BoxInt() - op = ResOperation(rop.INT_ADD, - [self.box, ConstInt(offset)], arraybox) - optforce.emit_operation(op) - # - # write the value - descr = self.buffer.descrs[i] - itemvalue = self.buffer.values[i] - itembox = itemvalue.force_box(optforce) - op = ResOperation(rop.SETARRAYITEM_RAW, - [arraybox, ConstInt(0), itembox], None, - descr=descr) - optforce.emit_operation(op) - - def _make_virtual(self, modifier): - # I *think* we need to make a copy of offsets and descrs because we - # want a snapshot of the virtual state right now: if we grow more - # elements later, we don't want them to go in this virtual state - return modifier.make_vrawbuffer(self.size, - self.buffer.offsets[:], - self.buffer.descrs[:]) - - -class VRawSliceValue(AbstractVirtualValue): - - def __init__(self, rawbuffer_value, offset, keybox, source_op): - AbstractVirtualValue.__init__(self, keybox, source_op) - self.rawbuffer_value = rawbuffer_value - self.offset = offset - - def _really_force(self, optforce): - op = self.source_op - assert op is not None - if not we_are_translated(): - op.name = 'FORCE ' + self.source_op.name - self.box = self.source_op.result - self.rawbuffer_value.force_box(optforce) - optforce.emit_operation(op) - - def setitem_raw(self, offset, length, descr, value): - self.rawbuffer_value.setitem_raw(self.offset+offset, length, descr, value) - - def getitem_raw(self, offset, length, descr): - return self.rawbuffer_value.getitem_raw(self.offset+offset, length, descr) - class OptVirtualize(optimizer.Optimization): "Virtualize objects until they escape." @@ -500,17 +388,6 @@ self.make_equal_to(box, vvalue) return vvalue - def make_virtual_raw_memory(self, size, box, source_op): - logops = self.optimizer.loop.logops - vvalue = VRawBufferValue(self.optimizer.cpu, logops, size, box, source_op) - self.make_equal_to(box, vvalue) - return vvalue - - def make_virtual_raw_slice(self, rawbuffer_value, offset, box, source_op): - vvalue = VRawSliceValue(rawbuffer_value, offset, box, source_op) - self.make_equal_to(box, vvalue) - return vvalue - def optimize_GUARD_NO_EXCEPTION(self, op): if self.last_emitted_operation is REMOVED: return @@ -647,43 +524,6 @@ self.getvalue(op.result).ensure_nonnull() self.emit_operation(op) - def optimize_CALL(self, op): - effectinfo = op.getdescr().get_extra_info() - if effectinfo.oopspecindex == EffectInfo.OS_RAW_MALLOC_VARSIZE_CHAR: - self.do_RAW_MALLOC_VARSIZE_CHAR(op) - elif effectinfo.oopspecindex == EffectInfo.OS_RAW_FREE: - self.do_RAW_FREE(op) - else: - self.emit_operation(op) - - def do_RAW_MALLOC_VARSIZE_CHAR(self, op): - sizebox = op.getarg(1) - if not isinstance(sizebox, ConstInt): - self.emit_operation(op) - return - size = sizebox.value - self.make_virtual_raw_memory(size, op.result, op) - - def do_RAW_FREE(self, op): - value = self.getvalue(op.getarg(1)) - if value.is_virtual(): - return - self.emit_operation(op) - - def optimize_INT_ADD(self, op): - value = self.getvalue(op.getarg(0)) - offsetbox = self.get_constant_box(op.getarg(1)) - if value.is_virtual() and offsetbox is not None: - offset = offsetbox.getint() - if isinstance(value, VRawBufferValue): - self.make_virtual_raw_slice(value, offset, op.result, op) - return - elif isinstance(value, VRawSliceValue): - offset = offset + value.offset - self.make_virtual_raw_slice(value.rawbuffer_value, offset, op.result, op) - return - self.emit_operation(op) - def optimize_ARRAYLEN_GC(self, op): value = self.getvalue(op.getarg(0)) if value.is_virtual(): @@ -718,48 +558,6 @@ value.ensure_nonnull() self.emit_operation(op) - def _unpack_arrayitem_raw_op(self, op, indexbox): - index = indexbox.getint() - cpu = self.optimizer.cpu - descr = op.getdescr() - basesize, itemsize, _ = cpu.unpack_arraydescr_size(descr) - offset = basesize + (itemsize*index) - return offset, itemsize, descr - - def optimize_GETARRAYITEM_RAW(self, op): - value = self.getvalue(op.getarg(0)) - if value.is_virtual(): - indexbox = self.get_constant_box(op.getarg(1)) - if indexbox is not None: - offset, itemsize, descr = self._unpack_arrayitem_raw_op(op, indexbox) - try: - itemvalue = value.getitem_raw(offset, itemsize, descr) - self.make_equal_to(op.result, itemvalue) - except InvalidRawOperation: - box = value.force_box(self) - op.setarg(0, box) - self.emit_operation(op) - return - value.ensure_nonnull() - self.emit_operation(op) - - def optimize_SETARRAYITEM_RAW(self, op): - value = self.getvalue(op.getarg(0)) - if value.is_virtual(): - indexbox = self.get_constant_box(op.getarg(1)) - if indexbox is not None: - offset, itemsize, descr = self._unpack_arrayitem_raw_op(op, indexbox) - itemvalue = self.getvalue(op.getarg(2)) - try: - value.setitem_raw(offset, itemsize, descr, itemvalue) - except InvalidRawOperation: - box = value.force_box(self) - op.setarg(0, box) - self.emit_operation(op) - return - value.ensure_nonnull() - self.emit_operation(op) - def optimize_GETINTERIORFIELD_GC(self, op): value = self.getvalue(op.getarg(0)) if value.is_virtual(): diff --git a/rpython/jit/metainterp/optimizeopt/virtualstate.py b/rpython/jit/metainterp/optimizeopt/virtualstate.py --- a/rpython/jit/metainterp/optimizeopt/virtualstate.py +++ b/rpython/jit/metainterp/optimizeopt/virtualstate.py @@ -158,16 +158,10 @@ def debug_header(self, indent): debug_print(indent + 'VStructStateInfo(%d):' % self.position) - class VArrayStateInfo(AbstractVirtualStateInfo): - def __init__(self, arraydescr): self.arraydescr = arraydescr - def _generalization_of(self, other): - return (isinstance(other, VArrayStateInfo) and - self.arraydescr is other.arraydescr) - def generalization_of(self, other, renum, bad): assert self.position != -1 if self.position in renum: @@ -193,6 +187,10 @@ return False return True + def _generalization_of(self, other): + return (isinstance(other, VArrayStateInfo) and + self.arraydescr is other.arraydescr) + def enum_forced_boxes(self, boxes, value, optimizer): if not isinstance(value, virtualize.VArrayValue): raise BadVirtualState @@ -200,7 +198,7 @@ raise BadVirtualState for i in range(len(self.fieldstate)): try: - v = value.get_item_value(i) + v = value._items[i] except IndexError: raise BadVirtualState s = self.fieldstate[i] @@ -214,8 +212,6 @@ def debug_header(self, indent): debug_print(indent + 'VArrayStateInfo(%d):' % self.position) - - class VArrayStructStateInfo(AbstractVirtualStateInfo): def __init__(self, arraydescr, fielddescrs): self.arraydescr = arraydescr @@ -291,7 +287,6 @@ debug_print(indent + 'VArrayStructStateInfo(%d):' % self.position) - class NotVirtualStateInfo(AbstractVirtualStateInfo): def __init__(self, value, is_opaque=False): self.is_opaque = is_opaque @@ -584,9 +579,6 @@ def make_varraystruct(self, arraydescr, fielddescrs): return VArrayStructStateInfo(arraydescr, fielddescrs) - def make_vrawbuffer(self, size, offsets, descrs): - raise NotImplementedError - class BoxNotProducable(Exception): pass diff --git a/rpython/jit/metainterp/pyjitpl.py b/rpython/jit/metainterp/pyjitpl.py --- a/rpython/jit/metainterp/pyjitpl.py +++ b/rpython/jit/metainterp/pyjitpl.py @@ -2595,7 +2595,6 @@ box_exchange_buffer = op.getarg(3) self.history.operations.pop() arg_boxes = [] - for i in range(cif_description.nargs): kind, descr, itemsize = get_arg_descr(self.cpu, cif_description.atypes[i]) diff --git a/rpython/jit/metainterp/resume.py b/rpython/jit/metainterp/resume.py --- a/rpython/jit/metainterp/resume.py +++ b/rpython/jit/metainterp/resume.py @@ -275,9 +275,6 @@ def make_varraystruct(self, arraydescr, fielddescrs): return VArrayStructInfo(arraydescr, fielddescrs) - def make_vrawbuffer(self, size, offsets, descrs): - return VRawBufferStateInfo(size, offsets, descrs) - def make_vstrplain(self, is_unicode=False): if is_unicode: return VUniPlainInfo() @@ -449,8 +446,8 @@ return self.liveboxes_from_env[box] return self.liveboxes[box] + class AbstractVirtualInfo(object): - kind = REF #def allocate(self, decoder, index): # raise NotImplementedError def equals(self, fieldnums): @@ -461,7 +458,6 @@ def debug_prints(self): raise NotImplementedError - class AbstractVirtualStructInfo(AbstractVirtualInfo): def __init__(self, fielddescrs): @@ -490,7 +486,7 @@ @specialize.argtype(1) def allocate(self, decoder, index): struct = decoder.allocate_with_vtable(self.known_class) - decoder.virtuals_cache.set_ptr(index, struct) + decoder.virtuals_cache[index] = struct return self.setfields(decoder, struct) def debug_prints(self): @@ -506,7 +502,7 @@ @specialize.argtype(1) def allocate(self, decoder, index): struct = decoder.allocate_struct(self.typedescr) - decoder.virtuals_cache.set_ptr(index, struct) + decoder.virtuals_cache[index] = struct return self.setfields(decoder, struct) def debug_prints(self): @@ -523,7 +519,7 @@ length = len(self.fieldnums) arraydescr = self.arraydescr array = decoder.allocate_array(length, arraydescr) - decoder.virtuals_cache.set_ptr(index, array) + decoder.virtuals_cache[index] = array # NB. the check for the kind of array elements is moved out of the loop if arraydescr.is_array_of_pointers(): for i in range(length): @@ -545,31 +541,6 @@ debug_print("\t\t", str(untag(i))) -class VRawBufferStateInfo(AbstractVirtualInfo): - kind = INT - - def __init__(self, size, offsets, descrs): - self.size = size - self.offsets = offsets - self.descrs = descrs - - @specialize.argtype(1) - def allocate_int(self, decoder, index): - length = len(self.fieldnums) - buffer = decoder.allocate_raw_buffer(self.size) - decoder.virtuals_cache.set_int(index, buffer) - for i in range(len(self.offsets)): - offset = self.offsets[i] - descr = self.descrs[i] - decoder.setrawbuffer_item(buffer, self.fieldnums[i], offset, descr) - return buffer - - def debug_prints(self): - debug_print("\tvrawbufferinfo", " at ", compute_unique_id(self)) - for i in self.fieldnums: - debug_print("\t\t", str(untag(i))) - - class VArrayStructInfo(AbstractVirtualInfo): def __init__(self, arraydescr, fielddescrs): self.arraydescr = arraydescr @@ -583,7 +554,7 @@ @specialize.argtype(1) def allocate(self, decoder, index): array = decoder.allocate_array(len(self.fielddescrs), self.arraydescr) - decoder.virtuals_cache.set_ptr(index, array) + decoder.virtuals_cache[index] = array p = 0 for i in range(len(self.fielddescrs)): for j in range(len(self.fielddescrs[i])): @@ -600,7 +571,7 @@ def allocate(self, decoder, index): length = len(self.fieldnums) string = decoder.allocate_string(length) - decoder.virtuals_cache.set_ptr(index, string) + decoder.virtuals_cache[index] = string for i in range(length): charnum = self.fieldnums[i] if not tagged_eq(charnum, UNINITIALIZED): @@ -622,7 +593,7 @@ # efficient. Not sure we care. left, right = self.fieldnums string = decoder.concat_strings(left, right) - decoder.virtuals_cache.set_ptr(index, string) + decoder.virtuals_cache[index] = string return string def debug_prints(self): @@ -638,7 +609,7 @@ def allocate(self, decoder, index): largerstr, start, length = self.fieldnums From noreply at buildbot.pypy.org Sat Apr 13 20:00:15 2013 From: noreply at buildbot.pypy.org (alex_gaynor) Date: Sat, 13 Apr 2013 20:00:15 +0200 (CEST) Subject: [pypy-commit] pypy virtualref-virtualizable: a failing test Message-ID: <20130413180015.17CDB1C070B@cobra.cs.uni-duesseldorf.de> Author: Alex Gaynor Branch: virtualref-virtualizable Changeset: r63317:b2c06f6cdbc7 Date: 2013-04-13 11:00 -0700 http://bitbucket.org/pypy/pypy/changeset/b2c06f6cdbc7/ Log: a failing test diff --git a/rpython/jit/metainterp/test/test_virtualizable.py b/rpython/jit/metainterp/test/test_virtualizable.py --- a/rpython/jit/metainterp/test/test_virtualizable.py +++ b/rpython/jit/metainterp/test/test_virtualizable.py @@ -5,7 +5,7 @@ from rpython.jit.metainterp.optimizeopt.test.test_util import LLtypeMixin from rpython.jit.metainterp.test.support import LLJitMixin, OOJitMixin from rpython.jit.metainterp.warmspot import get_translator -from rpython.rlib.jit import JitDriver, hint, dont_look_inside, promote +from rpython.rlib.jit import JitDriver, hint, dont_look_inside, promote, virtual_ref from rpython.rlib.rarithmetic import intmask from rpython.rtyper.annlowlevel import hlstr from rpython.rtyper.extregistry import ExtRegistryEntry @@ -434,8 +434,7 @@ # ------------------------------ -class ImplicitVirtualizableTests: - +class ImplicitVirtualizableTests(object): def test_simple_implicit(self): myjitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) @@ -1443,6 +1442,33 @@ print hex(res) assert res == main(0) + def test_force_virtualref_to_virtualizable(self): + jitdriver = JitDriver( + greens=[], + reds=['i', 'n', 'f', 'f_ref'], + virtualizables=['f'] + ) + + class Frame(object): + _virtualizable2_ = ['x'] + + def main(n): + f = Frame() + f.x = 1 + f_ref = virtual_ref(f) + i = 0 + while i < n: + jitdriver.jit_merge_point(f=f, i=i, f_ref=f_ref, n=n) + i += f_ref().x + return i + + res = self.meta_interp(main, [10]) + assert res == main(10) + self.check_resops({ + "int_lt": 1, "guard_true": 1, "int_add": 1, "jump": 1, + }) + + class TestOOtype(#ExplicitVirtualizableTests, ImplicitVirtualizableTests, From noreply at buildbot.pypy.org Sat Apr 13 20:14:01 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Sat, 13 Apr 2013 20:14:01 +0200 (CEST) Subject: [pypy-commit] pypy default: finish backing out virtual-raw-mallocs Message-ID: <20130413181401.DA6E61C05C8@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63318:6a7e52f55f0f Date: 2013-04-13 14:10 -0400 http://bitbucket.org/pypy/pypy/changeset/6a7e52f55f0f/ Log: finish backing out virtual-raw-mallocs diff --git a/rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py b/rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py --- a/rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py +++ b/rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py @@ -2,7 +2,6 @@ import weakref from rpython.rlib.jit import JitDriver, dont_look_inside from rpython.jit.backend.llsupport.test.zrpy_gc_test import run, get_entry, compile -from rpython.jit.backend.llsupport.test.ztranslation_test import fix_annotator_for_vrawbuffer class X(object): def __init__(self, x=0): @@ -32,8 +31,7 @@ g._dont_inline_ = True return g -def compile_boehm_test(monkeypatch): - fix_annotator_for_vrawbuffer(monkeypatch) +def compile_boehm_test(): myjitdriver = JitDriver(greens = [], reds = ['n', 'x']) @dont_look_inside def see(lst, n): diff --git a/rpython/jit/backend/llsupport/test/ztranslation_test.py b/rpython/jit/backend/llsupport/test/ztranslation_test.py --- a/rpython/jit/backend/llsupport/test/ztranslation_test.py +++ b/rpython/jit/backend/llsupport/test/ztranslation_test.py @@ -9,15 +9,10 @@ from rpython.jit.codewriter.policy import StopAtXPolicy -def fix_annotator_for_vrawbuffer(monkeypatch): - return - - class TranslationTest(CCompiledMixin): CPUClass = getcpuclass() - def test_stuff_translates(self, monkeypatch): - fix_annotator_for_vrawbuffer(monkeypatch) + def test_stuff_translates(self): # this is a basic test that tries to hit a number of features and their # translation: # - jitting of loops and bridges @@ -94,10 +89,9 @@ class TranslationTestCallAssembler(CCompiledMixin): CPUClass = getcpuclass() - def test_direct_assembler_call_translates(self, monkeypatch): + def test_direct_assembler_call_translates(self): """Test CALL_ASSEMBLER and the recursion limit""" from rpython.rlib.rstackovf import StackOverflow - fix_annotator_for_vrawbuffer(monkeypatch) class Thing(object): def __init__(self, val): @@ -175,8 +169,7 @@ class TranslationTestJITStats(CCompiledMixin): CPUClass = getcpuclass() - def test_jit_get_stats(self, monkeypatch): - fix_annotator_for_vrawbuffer(monkeypatch) + def test_jit_get_stats(self): driver = JitDriver(greens = [], reds = ['i']) def f(): @@ -199,8 +192,7 @@ class TranslationRemoveTypePtrTest(CCompiledMixin): CPUClass = getcpuclass() - def test_external_exception_handling_translates(self, monkeypatch): - fix_annotator_for_vrawbuffer(monkeypatch) + def test_external_exception_handling_translates(self): jitdriver = JitDriver(greens = [], reds = ['n', 'total']) class ImDone(Exception): From noreply at buildbot.pypy.org Sat Apr 13 20:14:04 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Sat, 13 Apr 2013 20:14:04 +0200 (CEST) Subject: [pypy-commit] pypy virtual-raw-mallocs: merge default up to 295a4447f6ba Message-ID: <20130413181404.C577A1C05C8@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: virtual-raw-mallocs Changeset: r63319:911714748878 Date: 2013-04-13 14:11 -0400 http://bitbucket.org/pypy/pypy/changeset/911714748878/ Log: merge default up to 295a4447f6ba diff too long, truncating to 2000 out of 5430 lines diff --git a/README.rst b/README.rst --- a/README.rst +++ b/README.rst @@ -13,9 +13,9 @@ http://pypy.org/ -The getting-started document will help guide you: +If you want to help developing PyPy, this document might help you: - http://doc.pypy.org/en/latest/getting-started.html + http://doc.pypy.org/ It will also point you to the rest of the documentation which is generated from files in the pypy/doc directory within the source repositories. Enjoy diff --git a/pypy/doc/dir-reference.rst b/pypy/doc/dir-reference.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/dir-reference.rst @@ -0,0 +1,140 @@ +PyPy directory cross-reference +------------------------------ + +Here is a fully referenced alphabetical two-level deep +directory overview of PyPy: + +================================= ============================================ +Directory explanation/links +================================= ============================================ +`pypy/bin/`_ command-line scripts, mainly + `pypy/bin/pyinteractive.py`_ + +`pypy/config/`_ handles the numerous options for building + and running PyPy + +`pypy/doc/`_ text versions of PyPy developer + documentation + +`pypy/doc/config/`_ documentation for the numerous translation + options + +`pypy/doc/discussion/`_ drafts of ideas and documentation + +``doc/*/`` other specific documentation topics or tools + +`pypy/interpreter/`_ `bytecode interpreter`_ and related objects + (frames, functions, modules,...) + +`pypy/interpreter/pyparser/`_ interpreter-level Python source parser + +`pypy/interpreter/astcompiler/`_ interpreter-level bytecode compiler, + via an AST representation + +`pypy/module/`_ contains `mixed modules`_ + implementing core modules with + both application and interpreter level code. + Not all are finished and working. Use + the ``--withmod-xxx`` + or ``--allworkingmodules`` translation + options. + +`pypy/objspace/`_ `object space`_ implementations + +`pypy/objspace/std/`_ the StdObjSpace_ implementing CPython's + objects and types + +`pypy/tool/`_ various utilities and hacks used + from various places + +`pypy/tool/algo/`_ general-purpose algorithmic and mathematic + tools + +`pypy/tool/pytest/`_ support code for our `testing methods`_ + + +`rpython/annotator/`_ `type inferencing code`_ for + `RPython`_ programs + +`rpython/config/`_ handles the numerous options for RPython + + +`rpython/flowspace/`_ the FlowObjSpace_ implementing + `abstract interpretation`_ + +`rpython/rlib/`_ a `"standard library"`_ for RPython_ + programs + +`rpython/rtyper/`_ the `RPython Typer`_ + +`rpython/rtyper/lltypesystem/`_ the `low-level type system`_ for + C-like backends + +`rpython/rtyper/ootypesystem/`_ the `object-oriented type system`_ + for OO backends + +`rpython/memory/`_ the `garbage collector`_ construction + framework + +`rpython/translator/`_ translation_ backends and support code + +`rpython/translator/backendopt/`_ general optimizations that run before a + backend generates code + +`rpython/translator/c/`_ the `GenC backend`_, producing C code + from an + RPython program (generally via the rtyper_) + +`rpython/translator/cli/`_ the `CLI backend`_ for `.NET`_ + (Microsoft CLR or Mono_) + +`pypy/goal/`_ our `main PyPy-translation scripts`_ + live here + +`rpython/translator/jvm/`_ the Java backend + +`rpython/translator/tool/`_ helper tools for translation + +`dotviewer/`_ `graph viewer`_ + +``*/test/`` many directories have a test subdirectory + containing test + modules (see `Testing in PyPy`_) + +``_cache/`` holds cache files from various purposes +================================= ============================================ + +.. _`bytecode interpreter`: interpreter.html +.. _`Testing in PyPy`: coding-guide.html#testing-in-pypy +.. _`mixed modules`: coding-guide.html#mixed-modules +.. _`modules`: coding-guide.html#modules +.. _`basil`: http://people.cs.uchicago.edu/~jriehl/BasilTalk.pdf +.. _`object space`: objspace.html +.. _FlowObjSpace: objspace.html#the-flow-object-space +.. _`transparent proxies`: objspace-proxies.html#tproxy +.. _`Differences between PyPy and CPython`: cpython_differences.html +.. _`What PyPy can do for your objects`: objspace-proxies.html +.. _`Continulets and greenlets`: stackless.html +.. _StdObjSpace: objspace.html#the-standard-object-space +.. _`abstract interpretation`: http://en.wikipedia.org/wiki/Abstract_interpretation +.. _`rpython`: coding-guide.html#rpython +.. _`type inferencing code`: translation.html#the-annotation-pass +.. _`RPython Typer`: translation.html#rpython-typer +.. _`testing methods`: coding-guide.html#testing-in-pypy +.. _`translation`: translation.html +.. _`GenC backend`: translation.html#genc +.. _`CLI backend`: cli-backend.html +.. _`py.py`: getting-started-python.html#the-py.py-interpreter +.. _`translatorshell.py`: getting-started-dev.html#try-out-the-translator +.. _JIT: jit/index.html +.. _`JIT Generation in PyPy`: jit/index.html +.. _`just-in-time compiler generator`: jit/index.html +.. _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 +.. _`main PyPy-translation scripts`: getting-started-python.html#translating-the-pypy-python-interpreter +.. _`.NET`: http://www.microsoft.com/net/ +.. _Mono: http://www.mono-project.com/ +.. _`"standard library"`: rlib.html +.. _`graph viewer`: getting-started-dev.html#try-out-the-translator diff --git a/pypy/doc/getting-started-dev.rst b/pypy/doc/getting-started-dev.rst --- a/pypy/doc/getting-started-dev.rst +++ b/pypy/doc/getting-started-dev.rst @@ -1,13 +1,58 @@ -=============================================================================== -Getting Started with the Translation Toolchain and Development Process -=============================================================================== +============================ +Getting Started with RPython +============================ .. contents:: +RPython is a subset of Python that can be statically compiled. The PyPy +interpreter is written mostly in RPython (with pieces in Python), while +the RPython compiler is written in Python. The hard to understand part +is that Python is a meta-programming language for RPython, that is, +RPython is considered from live objects **after** the imports are done. +This might require more explanation. You start writing RPython from +``entry_point``, a good starting point is +``rpython/translator/goal/targetnopstandalone.py``. This does not do all that +much, but is a start. Now if code analyzed (in this case ``entry_point``) +calls some functions, those calls will be followed. Those followed calls +have to be RPython themselves (and everything they call etc.), however not +entire module files. To show how you can use metaprogramming, we can do +a silly example (note that closures are not RPython):: + + def generator(operation): + if operation == 'add': + def f(a, b): + return a + b + else: + def f(a, b): + return a - b + return f + + add = generator('add') + sub = generator('sub') + + def entry_point(argv): + print add(sub(int(argv[1]), 3) 4) + return 0 + +In this example ``entry_point`` is RPython, ``add`` and ``sub`` are RPython, +however, ``generator`` is not. + +A good introductory level articles are available: + +* Laurence Tratt -- `Fast Enough VMs in Fast Enough Time`_. + +* `How to write interpreters in RPython`_ and `part 2`_ by Andrew Brown. + +.. _`Fast Enough VMs in Fast Enough Time`: http://tratt.net/laurie/tech_articles/articles/fast_enough_vms_in_fast_enough_time + +.. _`How to write interpreters in RPython`: http://morepypy.blogspot.com/2011/04/tutorial-writing-interpreter-with-pypy.html + +.. _`part 2`: http://morepypy.blogspot.com/2011/04/tutorial-part-2-adding-jit.html + .. _`try out the translator`: Trying out the translator -------------------------- +------------------------- The translator is a tool based on the PyPy interpreter which can translate sufficiently static RPython programs into low-level code (in particular it can @@ -28,7 +73,7 @@ >>> t = Translation(snippet.is_perfect_number, [int]) >>> t.view() - + After that, the graph viewer pops up, that lets you interactively inspect the flow graph. To move around, click on something that you want to inspect. To get help about how to use it, press 'H'. To close it again, press 'Q'. @@ -83,10 +128,10 @@ The object returned by ``compile_cli`` or ``compile_jvm`` is a wrapper around the real executable: the parameters are passed as command line arguments, and -the returned value is read from the standard output. +the returned value is read from the standard output. Once you have compiled the snippet, you can also try to launch the -executable directly from the shell. You will find the +executable directly from the shell. You will find the executable in one of the ``/tmp/usession-*`` directories:: # For CLI: diff --git a/pypy/doc/getting-started-python.rst b/pypy/doc/getting-started-python.rst --- a/pypy/doc/getting-started-python.rst +++ b/pypy/doc/getting-started-python.rst @@ -6,7 +6,7 @@ PyPy's Python interpreter is a very compliant Python -interpreter implemented in Python. When translated to C, it passes most of +interpreter implemented in RPython. When compiled, it passes most of `CPythons core language regression tests`_ and comes with many of the extension modules included in the standard library including ``ctypes``. It can run large libraries such as Django_ and Twisted_. There are some small behavioral @@ -147,6 +147,8 @@ Translating using the CLI backend +++++++++++++++++++++++++++++++++ +**Note: the CLI backend is no longer maintained** + To create a standalone .NET executable using the `CLI backend`_:: ./translate.py --backend=cli targetpypystandalone.py diff --git a/pypy/doc/how-to-contribute.rst b/pypy/doc/how-to-contribute.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/how-to-contribute.rst @@ -0,0 +1,78 @@ +How to contribute to PyPy +------------------------- + +This page describes how to contribute to the PyPy project. The first thing +to remember is that PyPy project is very different than most projects out there. +It's also different from a classic compiler project, so academic courses +about compilers often don't apply or lead in the wrong direction. + +Don't just hack +--------------- + +The first and most important rule how not to contribute to PyPy is +"just hacking". This won't work. There are two major reasons why not +-- build times are large and PyPy has very thick layer separation which +make it harder to "just hack a feature". + +Test driven development +----------------------- + +Instead, we practice a lot of test driven development. This is partly because +of very high quality requirements for compilers and partly because there is +simply no other way to get around such complex project, that will keep you sane. +There are probably people out there who are smart enough not to need it, we're +not one of those. You may consider familiarizing yourself with `pytest`_, +since this is a tool we use for tests. +This leads to the next issue: + +Layers +------ + +PyPy has layers. Those layers help us keep the respective parts separated enough +to be worked on independently and make the complexity manageable. This is, +again, just a sanity requirement for such a complex project. For example writing +a new optimization for the JIT usually does **not** involve touching a Python +interpreter at all or the JIT assembler backend or the garbage collector. +Instead it requires writing small tests in +``rpython/jit/metainterp/optimizeopt/test/test_*`` and fixing files there. +After that, you can just compile PyPy and things should just work. + +The short list of layers for further reading. For each of those layers, a good +entry point is a test subdirectory in respective directories. It usually +describes (better or worse) the interfaces between the submodules. For the +``pypy`` subdirectory, most tests are small snippets of python programs that +check for correctness (calls ``AppTestXxx``) that will call the appropriate +part of the interpreter. For the ``rpython`` directory, most tests are small +RPython interpreters that perform certain tasks. To see how they translate +to low-level graphs, run them with ``--view``. To see small interpreters +with a JIT compiler, use ``--viewloops`` option. + +* **python interpreter** - it's the part implemented in the ``pypy/`` directory. + It's implemented in RPython, which is a high level static language with + classes, garbage collection, just-in-time compiler generation and the ability + to call C. A cool part about it is that it can be run untranslated, so all + the tests are runnable without translating PyPy. + + **interpreter** contains the interpreter core + + **objspace** contains implementations of various objects exported to + the Python layer + + **module** directory contains extension modules written in RPython + +* **rpython compiler** that resides in ``rpython/annotator`` and + ``rpython/rtyper`` directories. Consult `introduction to RPython`_ for + further reading + +* **JIT generator** lives in ``rpython/jit`` directory. optimizations live + in ``rpython/jit/metainterp/optimizeopt``, the main JIT in + ``rpython/jit/metainterp`` (runtime part) and + ``rpython/jit/codewriter`` (translation-time part). Backends live in + ``rpython/jit/backend``. + +* **garbage collection** lives in ``rpython/memory`` + +The rest of directories serve specific niche goal and are unlikely a good +entry point. + +.. _`introduction to RPython`: getting-started-dev.rst diff --git a/pypy/doc/index.rst b/pypy/doc/index.rst --- a/pypy/doc/index.rst +++ b/pypy/doc/index.rst @@ -1,15 +1,40 @@ -Welcome to PyPy Development -============================================= +Welcome to PyPy +=============== -The PyPy project aims at producing a flexible and fast Python_ -implementation. The guiding idea is to translate a Python-level -description of the Python language itself to lower level languages. -Rumors have it that the secret goal is being faster-than-C which is -nonsense, isn't it? `more...`_ +The PyPy project aims to produce a flexible and fast Python_ +implementation. This page documents the development of the PyPy +project itself. If you don't know what PyPy is, consult the `PyPy +website`_. If you just want to use PyPy, consult the `download`_ page +and the `getting started with pypy`_ documents. If you want to help +develop PyPy -- keep reading! -Getting into PyPy ... -============================================= +PyPy is written in a language called `RPython`_, which is suitable for +writing dynamic language interpreters (and not much else). RPython is +a subset of Python and is itself written in Python. If you'd like to +learn more about RPython, `Starting with RPython`_ should provide a +reasonable overview. + +**If you would like to contribute to PyPy**, please read `how to +contribute`_ first. PyPy's development style is somewhat different to +that of many other software projects and it often surprises +newcomers. What is **not** necessary is an academic background from +university in writing compilers -- much of it does not apply to PyPy +any way. + +All of the documentation and source code is available under the MIT license, +unless otherwise specified. Consult `LICENSE`_ + +.. _`download`: http://pypy.org/download.html +.. _`getting started with pypy`: getting-started-python.html +.. _`RPython`: coding-guide.html#RPython +.. _`Starting with RPython`: getting-started-dev.html +.. _`how to contribute`: how-to-contribute.html +.. _`PyPy website`: http://pypy.org +.. _`LICENSE`: https://bitbucket.org/pypy/pypy/src/default/LICENSE + +Index of various topics: +======================== * `Getting started`_: how to install and run the PyPy Python interpreter @@ -25,20 +50,30 @@ * `potential project ideas`_: In case you want to get your feet wet... +* `more stuff`_: this is a collection of documentation that's there, but not + particularly organized + Documentation for the PyPy Python Interpreter -=============================================== +============================================= New features of PyPy's Python Interpreter and Translation Framework: * `Differences between PyPy and CPython`_ - * `What PyPy can do for your objects`_ - * `Continulets and greenlets`_ + * `What PyPy can do for your objects`_ - transparent proxy documentation + * `Continulets and greenlets`_ - documentation about stackless features * `JIT Generation in PyPy`_ + * `JIT hooks`_ * `Sandboxing Python code`_ + * `Garbage collection environment variables`_ -Status_ of the project. - +.. _`Differences between PyPy and CPython`: cpython_differences.html +.. _`What PyPy can do for your objects`: objspace-proxies.html +.. _`Continulets and greenlets`: stackless.html +.. _`JIT Generation in PyPy`: jit/index.html +.. _`JIT hooks`: jit-hooks.html +.. _`Sandboxing Python code`: sandbox.html +.. _`Garbage collection environment variables`: gc_info.html Mailing lists, bug tracker, IRC channel ============================================= @@ -79,354 +114,6 @@ .. _`speed.pypy.org`: http://speed.pypy.org .. _`RPython toolchain`: translation.html .. _`potential project ideas`: project-ideas.html - -Project Documentation -===================================== - -PyPy was funded by the EU for several years. See the `web site of the EU -project`_ for more details. - -.. _`web site of the EU project`: http://pypy.org - -architecture_ gives a complete view of PyPy's basic design. - -`coding guide`_ helps you to write code for PyPy (especially also describes -coding in RPython a bit). - -`sprint reports`_ lists reports written at most of our sprints, from -2003 to the present. - -`papers, talks and related projects`_ lists presentations -and related projects as well as our published papers. - -`PyPy video documentation`_ is a page linking to the videos (e.g. of talks and -introductions) that are available. - -`Technical reports`_ is a page that contains links to the -reports that we submitted to the European Union. - -`development methodology`_ describes our sprint-driven approach. - -`LICENSE`_ contains licensing details (basically a straight MIT-license). - -`Glossary`_ of PyPy words to help you align your inner self with -the PyPy universe. - - -Status -=================================== - -PyPy can be used to run Python programs on Linux, OS/X, -Windows, on top of .NET, and on top of Java. -To dig into PyPy it is recommended to try out the current -Mercurial default branch, which is always working or mostly working, -instead of the latest release, which is `2.0 beta1`__. - -.. __: release-2.0.0-beta1.html - -PyPy is mainly developed on Linux and Mac OS X. Windows is supported, -but platform-specific bugs tend to take longer before we notice and fix -them. Linux 64-bit machines are supported (though it may also take some -time before we notice and fix bugs). - -PyPy's own tests `summary`_, daily updated, run through BuildBot infrastructure. -You can also find CPython's compliance tests run with compiled ``pypy-c`` -executables there. - - -Source Code Documentation -=============================================== - -`object spaces`_ discusses the object space interface -and several implementations. - -`bytecode interpreter`_ explains the basic mechanisms -of the bytecode interpreter and virtual machine. - -`interpreter optimizations`_ describes our various strategies for -improving the performance of our interpreter, including alternative -object implementations (for strings, dictionaries and lists) in the -standard object space. - -`translation`_ is a detailed overview of our translation process. The -rtyper_ is the largest component of our translation process. - -`dynamic-language translation`_ is a paper that describes -the translation process, especially the flow object space -and the annotator in detail. (This document is one -of the `EU reports`_.) - -`low-level encapsulation`_ describes how our approach hides -away a lot of low level details. This document is also part -of the `EU reports`_. - -`translation aspects`_ describes how we weave different -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. - -`rlib`_ describes some modules that can be used when implementing programs in -RPython. - -`configuration documentation`_ describes the various configuration options that -allow you to customize PyPy. - -`CLI backend`_ describes the details of the .NET backend. - -`JIT Generation in PyPy`_ describes how we produce the Python Just-in-time Compiler -from our Python interpreter. - - - -.. _`FAQ`: faq.html -.. _Glossary: glossary.html -.. _`PyPy video documentation`: video-index.html -.. _parser: parser.html -.. _`development methodology`: dev_method.html -.. _`sprint reports`: sprint-reports.html -.. _`papers, talks and related projects`: extradoc.html -.. _`object spaces`: objspace.html -.. _`interpreter optimizations`: interpreter-optimizations.html -.. _`translation`: translation.html -.. _`dynamic-language translation`: https://bitbucket.org/pypy/extradoc/raw/tip/eu-report/D05.1_Publish_on_translating_a_very-high-level_description.pdf -.. _`low-level encapsulation`: low-level-encapsulation.html -.. _`translation aspects`: translation-aspects.html -.. _`configuration documentation`: config/ -.. _`coding guide`: coding-guide.html -.. _`architecture`: architecture.html -.. _`getting started`: getting-started.html -.. _`bytecode interpreter`: interpreter.html -.. _`EU reports`: index-report.html -.. _`Technical reports`: index-report.html -.. _`summary`: http://buildbot.pypy.org/summary -.. _`ideas for PyPy related projects`: project-ideas.html -.. _`Nightly builds and benchmarks`: http://tuatara.cs.uni-duesseldorf.de/benchmark.html -.. _`directory reference`: -.. _`rlib`: rlib.html -.. _`Sandboxing Python code`: sandbox.html -.. _`LICENSE`: https://bitbucket.org/pypy/pypy/src/default/LICENSE - -PyPy directory cross-reference ------------------------------- - -Here is a fully referenced alphabetical two-level deep -directory overview of PyPy: - -================================= ============================================ -Directory explanation/links -================================= ============================================ -`pypy/bin/`_ command-line scripts, mainly - `pypy/bin/pyinteractive.py`_ - -`pypy/config/`_ handles the numerous options for building - and running PyPy - -`pypy/doc/`_ text versions of PyPy developer - documentation - -`pypy/doc/config/`_ documentation for the numerous translation - options - -`pypy/doc/discussion/`_ drafts of ideas and documentation - -``doc/*/`` other specific documentation topics or tools - -`pypy/interpreter/`_ `bytecode interpreter`_ and related objects - (frames, functions, modules,...) - -`pypy/interpreter/pyparser/`_ interpreter-level Python source parser - -`pypy/interpreter/astcompiler/`_ interpreter-level bytecode compiler, - via an AST representation - -`pypy/module/`_ contains `mixed modules`_ - implementing core modules with - both application and interpreter level code. - Not all are finished and working. Use - the ``--withmod-xxx`` - or ``--allworkingmodules`` translation - options. - -`pypy/objspace/`_ `object space`_ implementations - -`pypy/objspace/std/`_ the StdObjSpace_ implementing CPython's - objects and types - -`pypy/tool/`_ various utilities and hacks used - from various places - -`pypy/tool/algo/`_ general-purpose algorithmic and mathematic - tools - -`pypy/tool/pytest/`_ support code for our `testing methods`_ - - -`rpython/annotator/`_ `type inferencing code`_ for - `RPython`_ programs - -`rpython/config/`_ handles the numerous options for RPython - - -`rpython/flowspace/`_ the FlowObjSpace_ implementing - `abstract interpretation`_ - -`rpython/rlib/`_ a `"standard library"`_ for RPython_ - programs - -`rpython/rtyper/`_ the `RPython Typer`_ - -`rpython/rtyper/lltypesystem/`_ the `low-level type system`_ for - C-like backends - -`rpython/rtyper/ootypesystem/`_ the `object-oriented type system`_ - for OO backends - -`rpython/memory/`_ the `garbage collector`_ construction - framework - -`rpython/translator/`_ translation_ backends and support code - -`rpython/translator/backendopt/`_ general optimizations that run before a - backend generates code - -`rpython/translator/c/`_ the `GenC backend`_, producing C code - from an - RPython program (generally via the rtyper_) - -`rpython/translator/cli/`_ the `CLI backend`_ for `.NET`_ - (Microsoft CLR or Mono_) - -`pypy/goal/`_ our `main PyPy-translation scripts`_ - live here - -`rpython/translator/jvm/`_ the Java backend - -`rpython/translator/tool/`_ helper tools for translation - -`dotviewer/`_ `graph viewer`_ - -``*/test/`` many directories have a test subdirectory - containing test - modules (see `Testing in PyPy`_) - -``_cache/`` holds cache files from various purposes -================================= ============================================ - -.. _`bytecode interpreter`: interpreter.html -.. _`Testing in PyPy`: coding-guide.html#testing-in-pypy -.. _`mixed modules`: coding-guide.html#mixed-modules -.. _`modules`: coding-guide.html#modules -.. _`basil`: http://people.cs.uchicago.edu/~jriehl/BasilTalk.pdf -.. _`object space`: objspace.html -.. _FlowObjSpace: objspace.html#the-flow-object-space -.. _`transparent proxies`: objspace-proxies.html#tproxy -.. _`Differences between PyPy and CPython`: cpython_differences.html -.. _`What PyPy can do for your objects`: objspace-proxies.html -.. _`Continulets and greenlets`: stackless.html -.. _StdObjSpace: objspace.html#the-standard-object-space -.. _`abstract interpretation`: http://en.wikipedia.org/wiki/Abstract_interpretation -.. _`rpython`: coding-guide.html#rpython -.. _`type inferencing code`: translation.html#the-annotation-pass -.. _`RPython Typer`: translation.html#rpython-typer -.. _`testing methods`: coding-guide.html#testing-in-pypy -.. _`translation`: translation.html -.. _`GenC backend`: translation.html#genc -.. _`CLI backend`: cli-backend.html -.. _`py.py`: getting-started-python.html#the-py.py-interpreter -.. _`translatorshell.py`: getting-started-dev.html#try-out-the-translator -.. _JIT: jit/index.html -.. _`JIT Generation in PyPy`: jit/index.html -.. _`just-in-time compiler generator`: jit/index.html -.. _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 -.. _`main PyPy-translation scripts`: getting-started-python.html#translating-the-pypy-python-interpreter -.. _`.NET`: http://www.microsoft.com/net/ -.. _Mono: http://www.mono-project.com/ -.. _`"standard library"`: rlib.html -.. _`graph viewer`: getting-started-dev.html#try-out-the-translator - - -.. The following documentation is important and reasonably up-to-date: - -.. extradoc: should this be integrated one level up: dcolish? - - -.. toctree:: - :maxdepth: 1 - :hidden: - - getting-started.rst - getting-started-python.rst - getting-started-dev.rst - windows.rst - faq.rst - commandline_ref.rst - architecture.rst - coding-guide.rst - cpython_differences.rst - garbage_collection.rst - gc_info.rst - interpreter.rst - objspace.rst - __pypy__-module.rst - objspace-proxies.rst - config/index.rst - - dev_method.rst - extending.rst - - extradoc.rst - video-index.rst - - glossary.rst - - contributor.rst - - interpreter-optimizations.rst - configuration.rst - parser.rst - rlib.rst - rtyper.rst - rffi.rst - - translation.rst - jit/index.rst - jit/overview.rst - jit/pyjitpl5.rst - - index-of-release-notes.rst - - ctypes-implementation.rst - - how-to-release.rst - - index-report.rst - - stackless.rst - sandbox.rst - - discussions.rst - - cleanup.rst - - sprint-reports.rst - - eventhistory.rst - statistic/index.rst - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`search` -* :ref:`glossary` - +.. _`more stuff`: project-documentation.html .. include:: _ref.txt diff --git a/pypy/doc/needswork.txt b/pypy/doc/needswork.txt deleted file mode 100644 --- a/pypy/doc/needswork.txt +++ /dev/null @@ -1,3 +0,0 @@ -.. warning:: - - This documentation needs work (as discussed during the Gothenburg sprint in 2011) diff --git a/pypy/doc/objspace-proxies.rst b/pypy/doc/objspace-proxies.rst --- a/pypy/doc/objspace-proxies.rst +++ b/pypy/doc/objspace-proxies.rst @@ -5,7 +5,6 @@ .. contents:: - Thanks to the `Object Space`_ architecture, any feature that is based on proxying, extending, changing or otherwise controlling the behavior of all objects in a running program is easy to implement on diff --git a/pypy/doc/project-documentation.rst b/pypy/doc/project-documentation.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/project-documentation.rst @@ -0,0 +1,177 @@ + +Project Documentation +===================================== + +`architecture`_ gives a complete view of PyPy's basic design. + +`coding guide`_ helps you to write code for PyPy (especially also describes +coding in RPython a bit). + +`sprint reports`_ lists reports written at most of our sprints, from +2003 to the present. + +`papers, talks and related projects`_ lists presentations +and related projects as well as our published papers. + +`PyPy video documentation`_ is a page linking to the videos (e.g. of talks and +introductions) that are available. + +`Technical reports`_ is a page that contains links to the +reports that we submitted to the European Union. + +`development methodology`_ describes our sprint-driven approach. + +`LICENSE`_ contains licensing details (basically a straight MIT-license). + +`Glossary`_ of PyPy words to help you align your inner self with +the PyPy universe. + +Source Code Documentation +=============================================== + +`object spaces`_ discusses the object space interface +and several implementations. + +`bytecode interpreter`_ explains the basic mechanisms +of the bytecode interpreter and virtual machine. + +`interpreter optimizations`_ describes our various strategies for +improving the performance of our interpreter, including alternative +object implementations (for strings, dictionaries and lists) in the +standard object space. + +`translation`_ is a detailed overview of our translation process. The +rtyper_ is the largest component of our translation process. + +`dynamic-language translation`_ is a paper that describes +the translation process, especially the flow object space +and the annotator in detail. (This document is one +of the `EU reports`_.) + +`low-level encapsulation`_ describes how our approach hides +away a lot of low level details. This document is also part +of the `EU reports`_. + +`translation aspects`_ describes how we weave different +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. + +`rlib`_ describes some modules that can be used when implementing programs in +RPython. + +`configuration documentation`_ describes the various configuration options that +allow you to customize PyPy. + +`pypy on windows`_ + +`command line reference`_ + +`CLI backend`_ describes the details of the .NET backend. + +`JIT Generation in PyPy`_ describes how we produce the Python Just-in-time Compiler +from our Python interpreter. + +`directory cross-reference`_ + +.. _`garbage collector`: garbage_collection.html +.. _`directory cross-reference`: dir-reference.html +.. _`pypy on windows`: windows.html +.. _`command line reference`: commandline_ref.html +.. _`FAQ`: faq.html +.. _Glossary: glossary.html +.. _`PyPy video documentation`: video-index.html +.. _parser: parser.html +.. _`development methodology`: dev_method.html +.. _`sprint reports`: sprint-reports.html +.. _`papers, talks and related projects`: extradoc.html +.. _`object spaces`: objspace.html +.. _`interpreter optimizations`: interpreter-optimizations.html +.. _`translation`: translation.html +.. _`dynamic-language translation`: https://bitbucket.org/pypy/extradoc/raw/tip/eu-report/D05.1_Publish_on_translating_a_very-high-level_description.pdf +.. _`low-level encapsulation`: low-level-encapsulation.html +.. _`translation aspects`: translation-aspects.html +.. _`configuration documentation`: config/ +.. _`coding guide`: coding-guide.html +.. _`Architecture`: architecture.html +.. _`getting started`: getting-started.html +.. _`bytecode interpreter`: interpreter.html +.. _`EU reports`: index-report.html +.. _`Technical reports`: index-report.html +.. _`summary`: http://buildbot.pypy.org/summary +.. _`ideas for PyPy related projects`: project-ideas.html +.. _`Nightly builds and benchmarks`: http://tuatara.cs.uni-duesseldorf.de/benchmark.html +.. _`directory reference`: +.. _`rlib`: rlib.html +.. _`Sandboxing Python code`: sandbox.html +.. _`LICENSE`: https://bitbucket.org/pypy/pypy/src/default/LICENSE + +.. The following documentation is important and reasonably up-to-date: + +.. extradoc: should this be integrated one level up: dcolish? + +.. toctree:: + :maxdepth: 1 + :hidden: + + interpreter.rst + objspace.rst + __pypy__-module.rst + objspace-proxies.rst + config/index.rst + + dev_method.rst + extending.rst + + extradoc.rst + video-index.rst + + glossary.rst + + contributor.rst + + interpreter-optimizations.rst + configuration.rst + parser.rst + rlib.rst + rtyper.rst + rffi.rst + + translation.rst + jit/index.rst + jit/overview.rst + jit/pyjitpl5.rst + + index-of-release-notes.rst + + ctypes-implementation.rst + + how-to-release.rst + + index-report.rst + + stackless.rst + sandbox.rst + + discussions.rst + + cleanup.rst + + sprint-reports.rst + + eventhistory.rst + statistic/index.rst + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`search` +* :ref:`glossary` + +.. include:: _ref.txt diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -46,6 +46,13 @@ Fix a bug which casused cffi to return the wrong result when calling a C function which calls a Python callback which forces the frames +.. branch: virtual-raw-mallocs +JIT optimizations which makes cffi calls even faster, by removing the need to +allocate a temporary buffer where to store the arguments. + +.. branch: improve-docs-2 +Improve documents and straighten out links + .. branches we don't care about .. branch: autoreds .. branch: reflex-support @@ -121,3 +128,4 @@ cffi implementation of sqlite3 .. branch: release-2.0-beta2 +.. branch: unbreak-freebsd diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py --- a/pypy/interpreter/pyopcode.py +++ b/pypy/interpreter/pyopcode.py @@ -255,19 +255,7 @@ "code=%d, name=%s" % (self.last_instr, opcode, methodname)) - try: - res = meth(oparg, next_instr) - except Exception: - if 0: - import dis, sys - print "*** %s at offset %d (%s)" % (sys.exc_info()[0], - self.last_instr, - methodname) - try: - dis.dis(co_code) - except: - pass - raise + res = meth(oparg, next_instr) if res is not None: next_instr = res diff --git a/pypy/module/_io/interp_bytesio.py b/pypy/module/_io/interp_bytesio.py --- a/pypy/module/_io/interp_bytesio.py +++ b/pypy/module/_io/interp_bytesio.py @@ -2,37 +2,26 @@ TypeDef, generic_new_descr, GetSetProperty) from pypy.interpreter.gateway import interp2app, unwrap_spec from pypy.interpreter.error import OperationError, operationerrfmt +from rpython.rlib.rStringIO import RStringIO from rpython.rlib.rarithmetic import r_longlong from pypy.module._io.interp_bufferedio import W_BufferedIOBase from pypy.module._io.interp_iobase import convert_size import sys -def buffer2string(buffer, start, end): - from rpython.rlib.rstring import StringBuilder - builder = StringBuilder(end - start) - for i in range(start, end): - builder.append(buffer[i]) - return builder.build() -class W_BytesIO(W_BufferedIOBase): +class W_BytesIO(RStringIO, W_BufferedIOBase): def __init__(self, space): W_BufferedIOBase.__init__(self, space) - self.pos = 0 - self.string_size = 0 - self.buf = None + self.init() def descr_init(self, space, w_initial_bytes=None): - # In case __init__ is called multiple times - self.buf = [] - self.string_size = 0 - self.pos = 0 - + self.init() if not space.is_none(w_initial_bytes): self.write_w(space, w_initial_bytes) - self.pos = 0 + self.seek(0) def _check_closed(self, space, message=None): - if self.buf is None: + if self.is_closed(): if message is None: message = "I/O operation on closed file" raise OperationError(space.w_ValueError, space.wrap(message)) @@ -40,36 +29,12 @@ def read_w(self, space, w_size=None): self._check_closed(space) size = convert_size(space, w_size) - - # adjust invalid sizes - available = self.string_size - self.pos - if not 0 <= size <= available: - size = available - if size < 0: - size = 0 - - output = buffer2string(self.buf, self.pos, self.pos + size) - self.pos += size - return space.wrap(output) + return space.wrap(self.read(size)) def readline_w(self, space, w_limit=None): self._check_closed(space) limit = convert_size(space, w_limit) - - cur_pos = self.pos - if limit < 0: - end_pos = self.string_size - else: - end_pos = min(cur_pos + limit, self.string_size) - while cur_pos != end_pos: - if self.buf[cur_pos] == '\n': - cur_pos += 1 - break - cur_pos += 1 - - output = buffer2string(self.buf, self.pos, cur_pos) - self.pos = cur_pos - return space.wrap(output) + return space.wrap(self.readline(limit)) def read1_w(self, space, w_size): return self.read_w(space, w_size) @@ -79,56 +44,28 @@ rwbuffer = space.rwbuffer_w(w_buffer) size = rwbuffer.getlength() - if self.pos + size > self.string_size: - size = self.string_size - self.pos - - output = buffer2string(self.buf, self.pos, self.pos + size) - length = len(output) + output = self.read(size) rwbuffer.setslice(0, output) - self.pos += length - return space.wrap(length) + return space.wrap(len(output)) def write_w(self, space, w_data): self._check_closed(space) if space.isinstance_w(w_data, space.w_unicode): raise OperationError(space.w_TypeError, space.wrap( "bytes string of buffer expected")) - buf = space.buffer_w(w_data) - length = buf.getlength() + buf = space.bufferstr_w(w_data) + length = len(buf) if length <= 0: - return - - if self.pos + length > len(self.buf): - self.buf.extend(['\0'] * (self.pos + length - len(self.buf))) - - if self.pos > self.string_size: - # In case of overseek, pad with null bytes the buffer region - # between the end of stream and the current position. - # - # 0 lo string_size hi - # | |<---used--->|<----------available----------->| - # | | <--to pad-->|<---to write---> | - # 0 buf position - for i in range(self.string_size, self.pos): - self.buf[i] = '\0' - - # Copy the data to the internal buffer, overwriting some of the - # existing data if self->pos < self->string_size. - for i in range(length): - self.buf[self.pos + i] = buf.getitem(i) - self.pos += length - - # Set the new length of the internal string if it has changed - if self.string_size < self.pos: - self.string_size = self.pos - + return space.wrap(0) + self.write(buf) return space.wrap(length) def truncate_w(self, space, w_size=None): self._check_closed(space) + pos = self.tell() if space.is_none(w_size): - size = self.pos + size = pos else: size = space.r_longlong_w(w_size) @@ -136,19 +73,20 @@ raise OperationError(space.w_ValueError, space.wrap( "negative size value")) - if size < self.string_size: - self.string_size = size - del self.buf[size:] - + self.truncate(size) + if size == pos: + self.seek(0, 2) + else: + self.seek(pos) return space.wrap(size) def getvalue_w(self, space): self._check_closed(space) - return space.wrap(buffer2string(self.buf, 0, self.string_size)) + return space.wrap(self.getvalue()) def tell_w(self, space): self._check_closed(space) - return space.wrap(self.pos) + return space.wrap(self.tell()) @unwrap_spec(pos=r_longlong, whence=int) def seek_w(self, space, pos, whence=0): @@ -159,24 +97,19 @@ raise OperationError(space.w_ValueError, space.wrap( "negative seek value")) elif whence == 1: - if pos > sys.maxint - self.pos: + if pos > sys.maxint - self.tell(): raise OperationError(space.w_OverflowError, space.wrap( "new position too large")) - pos += self.pos elif whence == 2: - if pos > sys.maxint - self.string_size: + if pos > sys.maxint - self.getsize(): raise OperationError(space.w_OverflowError, space.wrap( "new position too large")) - pos += self.string_size else: raise operationerrfmt(space.w_ValueError, "whence must be between 0 and 2, not %d", whence) - if pos >= 0: - self.pos = pos - else: - self.pos = 0 - return space.wrap(self.pos) + self.seek(pos, whence) + return space.wrap(self.tell()) def readable_w(self, space): return space.w_True @@ -188,17 +121,16 @@ return space.w_True def close_w(self, space): - self.buf = None + self.close() def closed_get_w(self, space): - return space.wrap(self.buf is None) + return space.wrap(self.is_closed()) def getstate_w(self, space): self._check_closed(space) - w_content = space.wrap(buffer2string(self.buf, 0, self.string_size)) return space.newtuple([ - w_content, - space.wrap(self.pos), + space.wrap(self.getvalue()), + space.wrap(self.tell()), self.getdict(space)]) def setstate_w(self, space, w_state): @@ -211,13 +143,13 @@ space.type(w_state).getname(space) ) w_content, w_pos, w_dict = space.unpackiterable(w_state, 3) + self.truncate(0) + self.write_w(space, w_content) pos = space.int_w(w_pos) - self.buf = [] - self.write_w(space, w_content) if pos < 0: raise OperationError(space.w_ValueError, space.wrap( "position value cannot be negative")) - self.pos = pos + self.seek(pos) if not space.is_w(w_dict, space.w_None): space.call_method(self.getdict(space), "update", w_dict) diff --git a/pypy/module/_io/interp_stringio.py b/pypy/module/_io/interp_stringio.py --- a/pypy/module/_io/interp_stringio.py +++ b/pypy/module/_io/interp_stringio.py @@ -169,9 +169,9 @@ self.pos = end return space.wrap(u''.join(self.buf[start:end])) - @unwrap_spec(limit=int) - def readline_w(self, space, limit=-1): + def readline_w(self, space, w_limit=None): self._check_closed(space) + limit = convert_size(space, w_limit) if self.pos >= len(self.buf): return space.wrap(u"") diff --git a/pypy/module/_io/test/test_bytesio.py b/pypy/module/_io/test/test_bytesio.py --- a/pypy/module/_io/test/test_bytesio.py +++ b/pypy/module/_io/test/test_bytesio.py @@ -4,6 +4,15 @@ def test_init(self): import _io raises(TypeError, _io.BytesIO, u"12345") + buf = "1234567890" + b = _io.BytesIO(buf) + assert b.getvalue() == buf + b = _io.BytesIO(None) + assert b.getvalue() == "" + b.__init__(buf * 2) + assert b.getvalue() == buf * 2 + b.__init__(buf) + assert b.getvalue() == buf def test_init_kwargs(self): import _io @@ -24,6 +33,7 @@ def test_write(self): import _io f = _io.BytesIO() + assert f.write("") == 0 assert f.write("hello") == 5 import gc; gc.collect() assert f.getvalue() == "hello" @@ -47,10 +57,17 @@ def test_truncate(self): import _io - f = _io.BytesIO("hello") + f = _io.BytesIO() + f.write("hello") + assert f.truncate(0) == 0 + assert f.tell() == 5 + f.seek(0) + f.write("hello") f.seek(3) assert f.truncate() == 3 assert f.getvalue() == "hel" + assert f.truncate(2) == 2 + assert f.tell() == 3 def test_setstate(self): # state is (content, position, __dict__) @@ -73,7 +90,13 @@ import _io b = _io.BytesIO("hello") + a1 = bytearray('t') + a2 = bytearray('testing') + assert b.readinto(a1) == 1 + assert b.readinto(a2) == 4 b.close() + assert a1 == "h" + assert a2 == "elloing" raises(ValueError, b.readinto, bytearray("hello")) def test_readline(self): diff --git a/pypy/module/_io/test/test_stringio.py b/pypy/module/_io/test/test_stringio.py --- a/pypy/module/_io/test/test_stringio.py +++ b/pypy/module/_io/test/test_stringio.py @@ -32,7 +32,7 @@ raises(ValueError, sio.read, 1) raises(ValueError, sio.write, u"text") - def testRead(self): + def test_read(self): import io buf = u"1234567890" sio = io.StringIO(buf) @@ -42,6 +42,13 @@ assert buf[5:] == sio.read(900) assert u"" == sio.read() + def test_readline(self): + import io + sio = io.StringIO(u'123\n456') + assert sio.readline(2) == '12' + assert sio.readline(None) == '3\n' + assert sio.readline() == '456' + def test_seek(self): import io diff --git a/pypy/module/_io/test/test_ztranslation.py b/pypy/module/_io/test/test_ztranslation.py new file mode 100644 --- /dev/null +++ b/pypy/module/_io/test/test_ztranslation.py @@ -0,0 +1,4 @@ +from pypy.objspace.fake.checkmodule import checkmodule + +def test_checkmodule(): + checkmodule('_io') diff --git a/pypy/module/_minimal_curses/__init__.py b/pypy/module/_minimal_curses/__init__.py --- a/pypy/module/_minimal_curses/__init__.py +++ b/pypy/module/_minimal_curses/__init__.py @@ -2,10 +2,12 @@ import _curses except ImportError: try: - import _minimal_curses as _curses # when running on top of pypy-c + # when running on top of pypy before it had _curses, settle for minimal + # we prefer _curses so any constants added make it into _minimal_curses + import _minimal_curses as _curses except ImportError: import py - py.test.skip("no _curses or _minimal_curses module") #no _curses at all + py.test.skip("no _curses or _minimal_curses module") # no _curses at all from pypy.interpreter.mixedmodule import MixedModule from pypy.module._minimal_curses import fficurses # for side effects diff --git a/pypy/module/cStringIO/interp_stringio.py b/pypy/module/cStringIO/interp_stringio.py --- a/pypy/module/cStringIO/interp_stringio.py +++ b/pypy/module/cStringIO/interp_stringio.py @@ -146,7 +146,7 @@ class W_OutputType(RStringIO, W_InputOutputType): def __init__(self, space): - RStringIO.__init__(self) + self.init() self.space = space def descr_truncate(self, w_size=None): @@ -159,6 +159,7 @@ if size < 0: raise OperationError(space.w_IOError, space.wrap("negative size")) self.truncate(size) + self.seek(0, 2) @unwrap_spec(buffer='bufferstr') def descr_write(self, buffer): diff --git a/pypy/module/cStringIO/test/test_interp_stringio.py b/pypy/module/cStringIO/test/test_interp_stringio.py --- a/pypy/module/cStringIO/test/test_interp_stringio.py +++ b/pypy/module/cStringIO/test/test_interp_stringio.py @@ -142,8 +142,11 @@ f.write(' world') f.truncate(30) assert f.getvalue() == '\x00' * 20 + 'hello worl' + assert f.tell() == 30 + f.seek(0) f.truncate(25) assert f.getvalue() == '\x00' * 20 + 'hello' + assert f.tell() == 25 f.write('baz') f.write('egg') f.truncate(3) diff --git a/pypy/module/cpyext/test/test_cpyext.py b/pypy/module/cpyext/test/test_cpyext.py --- a/pypy/module/cpyext/test/test_cpyext.py +++ b/pypy/module/cpyext/test/test_cpyext.py @@ -1,6 +1,6 @@ import sys import weakref -import os.path +import os import py @@ -19,6 +19,21 @@ from rpython.tool.identity_dict import identity_dict from rpython.tool import leakfinder +def setup_module(module): + if os.name == 'nt': + # Do not open dreaded dialog box on segfault + import ctypes + SEM_NOGPFAULTERRORBOX = 0x0002 # From MSDN + old_err_mode = ctypes.windll.kernel32.GetErrorMode() + new_err_mode = old_err_mode | SEM_NOGPFAULTERRORBOX + ctypes.windll.kernel32.SetErrorMode(new_err_mode) + module.old_err_mode = old_err_mode + +def teardown_module(module): + if os.name == 'nt': + import ctypes + ctypes.windll.kernel32.SetErrorMode(module.old_err_mode) + @api.cpython_api([], api.PyObject) def PyPy_Crash1(space): 1/0 diff --git a/pypy/module/thread/os_thread.py b/pypy/module/thread/os_thread.py --- a/pypy/module/thread/os_thread.py +++ b/pypy/module/thread/os_thread.py @@ -132,7 +132,7 @@ if not e.match(space, space.w_SystemExit): ident = rthread.get_ident() where = 'thread %d started by ' % ident - e.write_unraisable(space, where, w_callable) + e.write_unraisable(space, where, w_callable, with_traceback=True) e.clear(space) # clean up space.threadlocals to remove the ExecutionContext # entry corresponding to the current thread diff --git a/pypy/module/thread/test/test_thread.py b/pypy/module/thread/test/test_thread.py --- a/pypy/module/thread/test/test_thread.py +++ b/pypy/module/thread/test/test_thread.py @@ -129,10 +129,10 @@ sys.stderr = StringIO.StringIO() thread.start_new_thread(fn3, ()) self.waitfor(lambda: "ValueError" in sys.stderr.getvalue()) - result = sys.stderr.getvalue() - assert "ValueError" in result - assert "hello world" in result - assert len(result.splitlines()) == 1 + result = sys.stderr.getvalue().splitlines() + #assert result[0].startswith("Unhandled exception in thread ") + assert result[1].startswith("Traceback ") + assert result[-1] == "ValueError: hello world" finally: sys.stderr = prev diff --git a/pypy/objspace/fake/objspace.py b/pypy/objspace/fake/objspace.py --- a/pypy/objspace/fake/objspace.py +++ b/pypy/objspace/fake/objspace.py @@ -58,6 +58,10 @@ class W_MyType(W_MyObject): def __init__(self): self.mro_w = [w_some_obj(), w_some_obj()] + self.dict_w = {'__str__': w_some_obj()} + + def get_module(self): + return w_some_obj() def w_some_obj(): if NonConstant(False): @@ -318,7 +322,7 @@ ObjSpace.ExceptionTable + ['int', 'str', 'float', 'long', 'tuple', 'list', 'dict', 'unicode', 'complex', 'slice', 'bool', - 'basestring', 'object']): + 'basestring', 'object', 'bytearray']): setattr(FakeObjSpace, 'w_' + name, w_some_obj()) FakeObjSpace.w_type = w_some_type() # diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -47,14 +47,8 @@ self.stack_check_slowpath = 0 self._debug = False self.loop_run_counters = [] - self.debug_counter_descr = cpu.fielddescrof(DEBUG_COUNTER, 'i') self.gcrootmap_retaddr_forced = 0 - def set_debug(self, v): - r = self._debug - self._debug = v - return r - def setup(self, looptoken): assert self.memcpy_addr != 0, 'setup_once() not called?' if we_are_translated(): @@ -80,80 +74,6 @@ def setup_failure_recovery(self): self.failure_recovery_code = [0, 0, 0, 0] - def finish_once(self): - if self._debug: - debug_start('jit-backend-counts') - for i in range(len(self.loop_run_counters)): - struct = self.loop_run_counters[i] - if struct.type == 'l': - prefix = 'TargetToken(%d)' % struct.number - elif struct.type == 'b': - prefix = 'bridge ' + str(struct.number) - else: - prefix = 'entry ' + str(struct.number) - debug_print(prefix + ':' + str(struct.i)) - debug_stop('jit-backend-counts') - - # XXX: merge with x86 - def _register_counter(self, tp, number, token): - # YYY very minor leak -- we need the counters to stay alive - # forever, just because we want to report them at the end - # of the process - struct = lltype.malloc(DEBUG_COUNTER, flavor='raw', - track_allocation=False) - struct.i = 0 - struct.type = tp - if tp == 'b' or tp == 'e': - struct.number = number - else: - assert token - struct.number = compute_unique_id(token) - self.loop_run_counters.append(struct) - return struct - - @specialize.argtype(1) - def _inject_debugging_code(self, looptoken, operations, tp, number): - if self._debug: - # before doing anything, let's increase a counter - s = 0 - for op in operations: - s += op.getopnum() - looptoken._arm_debug_checksum = s - - newoperations = [] - self._append_debugging_code(newoperations, tp, number, - None) - for op in operations: - newoperations.append(op) - if op.getopnum() == rop.LABEL: - self._append_debugging_code(newoperations, 'l', number, - op.getdescr()) - operations = newoperations - return operations - - @staticmethod - def _release_gil_shadowstack(): - before = rffi.aroundstate.before - if before: - before() - - @staticmethod - def _reacquire_gil_shadowstack(): - after = rffi.aroundstate.after - if after: - after() - - _NOARG_FUNC = lltype.Ptr(lltype.FuncType([], lltype.Void)) - - def _build_release_gil(self, gcrootmap): - assert gcrootmap.is_shadow_stack - releasegil_func = llhelper(self._NOARG_FUNC, - self._release_gil_shadowstack) - reacqgil_func = llhelper(self._NOARG_FUNC, - self._reacquire_gil_shadowstack) - self.releasegil_addr = rffi.cast(lltype.Signed, releasegil_func) - self.reacqgil_addr = rffi.cast(lltype.Signed, reacqgil_func) - def _build_propagate_exception_path(self): if not self.cpu.propagate_exception_descr: return # not supported (for tests, or non-translated) @@ -594,7 +514,7 @@ clt.allgcrefs = [] clt.frame_info.clear() # for now - if False and log: + if log: operations = self._inject_debugging_code(looptoken, operations, 'e', looptoken.number) diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -630,7 +630,9 @@ # argument the address of the structure we are writing into # (the first argument to COND_CALL_GC_WB). helper_num = card_marking - if self._regalloc is not None and self._regalloc.vfprm.reg_bindings: + if is_frame: + helper_num = 4 + elif self._regalloc is not None and self._regalloc.vfprm.reg_bindings: helper_num += 2 if self.wb_slowpath[helper_num] == 0: # tests only assert not we_are_translated() @@ -1264,7 +1266,7 @@ resloc = arglocs[0] if gcrootmap: - self.call_release_gil(gcrootmap, arglocs, fcond) + self.call_release_gil(gcrootmap, arglocs, regalloc, fcond) # do the call self._store_force_index(guard_op) # @@ -1276,37 +1278,32 @@ resloc, (size, signed)) # then reopen the stack if gcrootmap: - self.call_reacquire_gil(gcrootmap, resloc, fcond) + self.call_reacquire_gil(gcrootmap, resloc, regalloc, fcond) self._emit_guard_may_force(guard_op, arglocs[numargs+1:], numargs) return fcond - def call_release_gil(self, gcrootmap, save_registers, fcond): - # First, we need to save away the registers listed in - # 'save_registers' that are not callee-save. + def call_release_gil(self, gcrootmap, save_registers, regalloc, fcond): + # Save caller saved registers and do the call # NOTE: We assume that the floating point registers won't be modified. - regs_to_save = [] - for reg in self._regalloc.rm.save_around_call_regs: - if reg in save_registers: - regs_to_save.append(reg) assert gcrootmap.is_shadow_stack - with saved_registers(self.mc, regs_to_save): + with saved_registers(self.mc, regalloc.rm.save_around_call_regs): self._emit_call(imm(self.releasegil_addr), [], fcond) - def call_reacquire_gil(self, gcrootmap, save_loc, fcond): - # save the previous result into the stack temporarily. + def call_reacquire_gil(self, gcrootmap, save_loc, regalloc, fcond): + # save the previous result into the stack temporarily, in case it is in + # a caller saved register. # NOTE: like with call_release_gil(), we assume that we don't need to # save vfp regs in this case. Besides the result location regs_to_save = [] vfp_regs_to_save = [] - if save_loc.is_reg(): + if save_loc and save_loc in regalloc.rm.save_around_call_regs: regs_to_save.append(save_loc) - if save_loc.is_vfp_reg(): + regs_to_save.append(r.ip) # for alingment + elif save_loc and save_loc in regalloc.vfprm.save_around_call_regs: vfp_regs_to_save.append(save_loc) + assert gcrootmap.is_shadow_stack # call the reopenstack() function (also reacquiring the GIL) - if len(regs_to_save) % 2 != 1: - regs_to_save.append(r.ip) # for alingment - assert gcrootmap.is_shadow_stack with saved_registers(self.mc, regs_to_save, vfp_regs_to_save): self._emit_call(imm(self.reacqgil_addr), [], fcond) diff --git a/rpython/jit/backend/arm/regalloc.py b/rpython/jit/backend/arm/regalloc.py --- a/rpython/jit/backend/arm/regalloc.py +++ b/rpython/jit/backend/arm/regalloc.py @@ -554,10 +554,9 @@ return self._prepare_call(op) def _prepare_call(self, op, force_store=[], save_all_regs=False): - args = [] - args.append(None) + args = [None] * (op.numargs()+1) for i in range(op.numargs()): - args.append(self.loc(op.getarg(i))) + args[i+1] = self.loc(op.getarg(i)) # spill variables that need to be saved around calls self.vfprm.before_call(save_all_regs=save_all_regs) if not save_all_regs: diff --git a/rpython/jit/backend/arm/test/test_zrpy_gc.py b/rpython/jit/backend/arm/test/test_zrpy_gc.py --- a/rpython/jit/backend/arm/test/test_zrpy_gc.py +++ b/rpython/jit/backend/arm/test/test_zrpy_gc.py @@ -1,798 +1,8 @@ -""" -This is a test that translates a complete JIT together with a GC and runs it. -It is testing that the GC-dependent aspects basically work, mostly the mallocs -and the various cases of write barrier. -""" - -import weakref -import py, os -from rpython.annotator import policy as annpolicy -from rpython.rlib import rgc -from rpython.rtyper.lltypesystem import lltype, llmemory, rffi -from rpython.rlib.jit import JitDriver, dont_look_inside -from rpython.rlib.jit import elidable, unroll_safe -from rpython.jit.backend.llsupport.gc import GcLLDescr_framework -from rpython.tool.udir import udir -from rpython.config.translationoption import DEFL_GC from rpython.jit.backend.arm.test.support import skip_unless_run_slow_tests skip_unless_run_slow_tests() - -class X(object): - def __init__(self, x=0): - self.x = x - - next = None - -class CheckError(Exception): - pass - -def check(flag): - if not flag: - raise CheckError - -def get_g(main): - main._dont_inline_ = True - def g(name, n): - x = X() - x.foo = 2 - main(n, x) - x.foo = 5 - return weakref.ref(x) - g._dont_inline_ = True - return g - - -def get_entry(g): - - def entrypoint(args): - name = '' - n = 2000 - argc = len(args) - if argc > 1: - name = args[1] - if argc > 2: - n = int(args[2]) - r_list = [] - for i in range(20): - r = g(name, n) - r_list.append(r) - rgc.collect() - rgc.collect(); rgc.collect() - freed = 0 - for r in r_list: - if r() is None: - freed += 1 - print freed - return 0 - - return entrypoint - - -def get_functions_to_patch(): - from rpython.jit.backend.llsupport import gc - # - can_use_nursery_malloc1 = gc.GcLLDescr_framework.can_use_nursery_malloc - def can_use_nursery_malloc2(*args): - try: - if os.environ['PYPY_NO_INLINE_MALLOC']: - return False - except KeyError: - pass - return can_use_nursery_malloc1(*args) - # - return {(gc.GcLLDescr_framework, 'can_use_nursery_malloc'): - can_use_nursery_malloc2} - -def compile(f, gc, enable_opts='', **kwds): - from rpython.annotator.listdef import s_list_of_strings - from rpython.translator.translator import TranslationContext - from rpython.jit.metainterp.warmspot import apply_jit - from rpython.translator.c import genc - # - t = TranslationContext() - t.config.translation.gc = gc - if gc != 'boehm': - t.config.translation.gcremovetypeptr = True - for name, value in kwds.items(): - setattr(t.config.translation, name, value) - ann = t.buildannotator() - ann.build_types(f, [s_list_of_strings], main_entry_point=True) - t.buildrtyper().specialize() - - if kwds['jit']: - patch = get_functions_to_patch() - old_value = {} - try: - for (obj, attr), value in patch.items(): - old_value[obj, attr] = getattr(obj, attr) - setattr(obj, attr, value) - # - apply_jit(t, enable_opts=enable_opts) - # - finally: - for (obj, attr), oldvalue in old_value.items(): - setattr(obj, attr, oldvalue) - - cbuilder = genc.CStandaloneBuilder(t, f, t.config) - cbuilder.generate_source(defines=cbuilder.DEBUG_DEFINES) - cbuilder.compile() - return cbuilder - -def run(cbuilder, args=''): - # - pypylog = udir.join('test_zrpy_gc.log') - data = cbuilder.cmdexec(args, env={'PYPYLOG': ':%s' % pypylog}) - return data.strip() - -def compile_and_run(f, gc, **kwds): - cbuilder = compile(f, gc, **kwds) - return run(cbuilder) - - - -def test_compile_boehm(): - myjitdriver = JitDriver(greens = [], reds = ['n', 'x']) - @dont_look_inside - def see(lst, n): - assert len(lst) == 3 - assert lst[0] == n+10 - assert lst[1] == n+20 - assert lst[2] == n+30 - def main(n, x): - while n > 0: - myjitdriver.can_enter_jit(n=n, x=x) - myjitdriver.jit_merge_point(n=n, x=x) - y = X() - y.foo = x.foo - n -= y.foo - see([n+10, n+20, n+30], n) - res = compile_and_run(get_entry(get_g(main)), "boehm", jit=True) - assert int(res) >= 16 - -# ______________________________________________________________________ - - -class BaseFrameworkTests(object): - compile_kwds = {} - - def setup_class(cls): - funcs = [] - name_to_func = {} - for fullname in dir(cls): - if not fullname.startswith('define'): - continue - definefunc = getattr(cls, fullname) - _, name = fullname.split('_', 1) - beforefunc, loopfunc, afterfunc = definefunc.im_func(cls) - if beforefunc is None: - def beforefunc(n, x): - return n, x, None, None, None, None, None, None, None, None, None, '' - if afterfunc is None: - def afterfunc(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s): - pass - beforefunc.func_name = 'before_'+name - loopfunc.func_name = 'loop_'+name - afterfunc.func_name = 'after_'+name - funcs.append((beforefunc, loopfunc, afterfunc)) - assert name not in name_to_func - name_to_func[name] = len(name_to_func) - print name_to_func - def allfuncs(name, n): - x = X() - x.foo = 2 - main_allfuncs(name, n, x) - x.foo = 5 - return weakref.ref(x) - def main_allfuncs(name, n, x): - num = name_to_func[name] - n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s = funcs[num][0](n, x) - while n > 0: - myjitdriver.can_enter_jit(num=num, n=n, x=x, x0=x0, x1=x1, - x2=x2, x3=x3, x4=x4, x5=x5, x6=x6, x7=x7, l=l, s=s) - myjitdriver.jit_merge_point(num=num, n=n, x=x, x0=x0, x1=x1, - x2=x2, x3=x3, x4=x4, x5=x5, x6=x6, x7=x7, l=l, s=s) - - n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s = funcs[num][1]( - n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s) - funcs[num][2](n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s) - myjitdriver = JitDriver(greens = ['num'], - reds = ['n', 'x', 'x0', 'x1', 'x2', 'x3', 'x4', - 'x5', 'x6', 'x7', 'l', 's']) - cls.main_allfuncs = staticmethod(main_allfuncs) - cls.name_to_func = name_to_func - OLD_DEBUG = GcLLDescr_framework.DEBUG - try: - GcLLDescr_framework.DEBUG = True - cls.cbuilder = compile(get_entry(allfuncs), DEFL_GC, - gcrootfinder=cls.gcrootfinder, jit=True, - **cls.compile_kwds) - finally: - GcLLDescr_framework.DEBUG = OLD_DEBUG - - def _run(self, name, n, env): - res = self.cbuilder.cmdexec("%s %d" %(name, n), env=env) - assert int(res) == 20 - - def run(self, name, n=2000): - pypylog = udir.join('TestCompileFramework.log') - env = {'PYPYLOG': ':%s' % pypylog, - 'PYPY_NO_INLINE_MALLOC': '1'} - self._run(name, n, env) - env['PYPY_NO_INLINE_MALLOC'] = '' - self._run(name, n, env) - - def run_orig(self, name, n, x): - self.main_allfuncs(name, n, x) - - -class CompileFrameworkTests(BaseFrameworkTests): - # Test suite using (so far) the minimark GC. - -## def define_libffi_workaround(cls): -## # XXX: this is a workaround for a bug in database.py. It seems that -## # the problem is triggered by optimizeopt/fficall.py, and in -## # particular by the ``cast_base_ptr_to_instance(Func, llfunc)``: in -## # these tests, that line is the only place where libffi.Func is -## # referenced. -## # -## # The problem occurs because the gctransformer tries to annotate a -## # low-level helper to call the __del__ of libffi.Func when it's too -## # late. -## # -## # This workaround works by forcing the annotator (and all the rest of -## # the toolchain) to see libffi.Func in a "proper" context, not just as -## # the target of cast_base_ptr_to_instance. Note that the function -## # below is *never* called by any actual test, it's just annotated. -## # -## from rpython.rlib.libffi import get_libc_name, CDLL, types, ArgChain -## libc_name = get_libc_name() -## def f(n, x, *args): -## libc = CDLL(libc_name) -## ptr = libc.getpointer('labs', [types.slong], types.slong) -## chain = ArgChain() -## chain.arg(n) -## n = ptr.call(chain, lltype.Signed) -## return (n, x) + args -## return None, f, None - - def define_compile_framework_1(cls): - # a moving GC. Supports malloc_varsize_nonmovable. Simple test, works - # without write_barriers and root stack enumeration. From noreply at buildbot.pypy.org Sat Apr 13 20:14:05 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Sat, 13 Apr 2013 20:14:05 +0200 (CEST) Subject: [pypy-commit] pypy virtual-raw-mallocs: null merge default past the backout of this branch Message-ID: <20130413181405.E84061C05C8@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: virtual-raw-mallocs Changeset: r63320:6dc1753f3a76 Date: 2013-04-13 14:12 -0400 http://bitbucket.org/pypy/pypy/changeset/6dc1753f3a76/ Log: null merge default past the backout of this branch From noreply at buildbot.pypy.org Sat Apr 13 20:17:05 2013 From: noreply at buildbot.pypy.org (alex_gaynor) Date: Sat, 13 Apr 2013 20:17:05 +0200 (CEST) Subject: [pypy-commit] pypy virtualref-virtualizable: Insert a place for our special logic Message-ID: <20130413181705.9132E1C0250@cobra.cs.uni-duesseldorf.de> Author: Alex Gaynor Branch: virtualref-virtualizable Changeset: r63321:684fdbbfb9c7 Date: 2013-04-13 11:16 -0700 http://bitbucket.org/pypy/pypy/changeset/684fdbbfb9c7/ Log: Insert a place for our special logic diff --git a/rpython/jit/metainterp/pyjitpl.py b/rpython/jit/metainterp/pyjitpl.py --- a/rpython/jit/metainterp/pyjitpl.py +++ b/rpython/jit/metainterp/pyjitpl.py @@ -1,25 +1,27 @@ -import py, sys +import sys + +import py + +from rpython.jit.codewriter import heaptracker +from rpython.jit.codewriter.effectinfo import EffectInfo +from rpython.jit.codewriter.jitcode import JitCode, SwitchDictDescr +from rpython.jit.metainterp import history, compile, resume, executor +from rpython.jit.metainterp.heapcache import HeapCache +from rpython.jit.metainterp.history import (Const, ConstInt, ConstPtr, + ConstFloat, Box, TargetToken) +from rpython.jit.metainterp.jitexc import JitException, get_llexception +from rpython.jit.metainterp.jitprof import EmptyProfiler +from rpython.jit.metainterp.logger import Logger +from rpython.jit.metainterp.optimizeopt.util import args_dict_box +from rpython.jit.metainterp.resoperation import rop +from rpython.rlib import nonconst, rstack +from rpython.rlib.debug import debug_start, debug_stop, debug_print, make_sure_not_resized +from rpython.rlib.jit import Counters +from rpython.rlib.objectmodel import we_are_translated, specialize +from rpython.rlib.unroll import unrolling_iterable from rpython.rtyper.lltypesystem import lltype, rclass -from rpython.rlib.objectmodel import we_are_translated -from rpython.rlib.unroll import unrolling_iterable -from rpython.rlib.debug import debug_start, debug_stop, debug_print -from rpython.rlib.debug import make_sure_not_resized -from rpython.rlib import nonconst, rstack -from rpython.jit.metainterp import history, compile, resume -from rpython.jit.metainterp.history import Const, ConstInt, ConstPtr, ConstFloat -from rpython.jit.metainterp.history import Box, TargetToken -from rpython.jit.metainterp.resoperation import rop -from rpython.jit.metainterp import executor -from rpython.jit.metainterp.logger import Logger -from rpython.jit.metainterp.jitprof import EmptyProfiler -from rpython.rlib.jit import Counters -from rpython.jit.metainterp.jitexc import JitException, get_llexception -from rpython.jit.metainterp.heapcache import HeapCache -from rpython.rlib.objectmodel import specialize -from rpython.jit.codewriter.jitcode import JitCode, SwitchDictDescr -from rpython.jit.codewriter import heaptracker -from rpython.jit.metainterp.optimizeopt.util import args_dict_box + # ____________________________________________________________ @@ -1370,6 +1372,8 @@ # residual calls require attention to keep virtualizables in-sync self.metainterp.clear_exception() self.metainterp.vable_and_vrefs_before_residual_call() + if effectinfo.oopspecindex == EffectInfo.OS_JIT_FORCE_VIRTUAL: + return self._do_jit_force_virtual(allboxes, descr) resbox = self.metainterp.execute_and_record_varargs( rop.CALL_MAY_FORCE, allboxes, descr=descr) if effectinfo.is_call_release_gil(): From noreply at buildbot.pypy.org Sat Apr 13 20:40:58 2013 From: noreply at buildbot.pypy.org (alex_gaynor) Date: Sat, 13 Apr 2013 20:40:58 +0200 (CEST) Subject: [pypy-commit] pypy virtualref-virtualizable: Seems to be working implementation. Let's try tests. Message-ID: <20130413184058.3C2CF1C1495@cobra.cs.uni-duesseldorf.de> Author: Alex Gaynor Branch: virtualref-virtualizable Changeset: r63322:71339841870c Date: 2013-04-13 11:40 -0700 http://bitbucket.org/pypy/pypy/changeset/71339841870c/ Log: Seems to be working implementation. Let's try tests. diff --git a/rpython/jit/metainterp/pyjitpl.py b/rpython/jit/metainterp/pyjitpl.py --- a/rpython/jit/metainterp/pyjitpl.py +++ b/rpython/jit/metainterp/pyjitpl.py @@ -833,15 +833,17 @@ opimpl_inline_call_irf_f = _opimpl_inline_call3 opimpl_inline_call_irf_v = _opimpl_inline_call3 - @arguments("box", "boxes", "descr") - def _opimpl_residual_call1(self, funcbox, argboxes, calldescr): - return self.do_residual_or_indirect_call(funcbox, argboxes, calldescr) - @arguments("box", "boxes2", "descr") - def _opimpl_residual_call2(self, funcbox, argboxes, calldescr): - return self.do_residual_or_indirect_call(funcbox, argboxes, calldescr) - @arguments("box", "boxes3", "descr") - def _opimpl_residual_call3(self, funcbox, argboxes, calldescr): - return self.do_residual_or_indirect_call(funcbox, argboxes, calldescr) + @arguments("box", "boxes", "descr", "orgpc") + def _opimpl_residual_call1(self, funcbox, argboxes, calldescr, pc): + return self.do_residual_or_indirect_call(funcbox, argboxes, calldescr, pc) + + @arguments("box", "boxes2", "descr", "orgpc") + def _opimpl_residual_call2(self, funcbox, argboxes, calldescr, pc): + return self.do_residual_or_indirect_call(funcbox, argboxes, calldescr, pc) + + @arguments("box", "boxes3", "descr", "orgpc") + def _opimpl_residual_call3(self, funcbox, argboxes, calldescr, pc): + return self.do_residual_or_indirect_call(funcbox, argboxes, calldescr, pc) opimpl_residual_call_r_i = _opimpl_residual_call1 opimpl_residual_call_r_r = _opimpl_residual_call1 @@ -854,8 +856,8 @@ opimpl_residual_call_irf_f = _opimpl_residual_call3 opimpl_residual_call_irf_v = _opimpl_residual_call3 - @arguments("int", "boxes3", "boxes3") - def _opimpl_recursive_call(self, jdindex, greenboxes, redboxes): + @arguments("int", "boxes3", "boxes3", "orgpc") + def _opimpl_recursive_call(self, jdindex, greenboxes, redboxes, pc): targetjitdriver_sd = self.metainterp.staticdata.jitdrivers_sd[jdindex] allboxes = greenboxes + redboxes warmrunnerstate = targetjitdriver_sd.warmstate @@ -870,15 +872,15 @@ # that assembler that we call is still correct self.verify_green_args(targetjitdriver_sd, greenboxes) # - return self.do_recursive_call(targetjitdriver_sd, allboxes, + return self.do_recursive_call(targetjitdriver_sd, allboxes, pc, assembler_call) - def do_recursive_call(self, targetjitdriver_sd, allboxes, + def do_recursive_call(self, targetjitdriver_sd, allboxes, pc, assembler_call=False): portal_code = targetjitdriver_sd.mainjitcode k = targetjitdriver_sd.portal_runner_adr funcbox = ConstInt(heaptracker.adr2int(k)) - return self.do_residual_call(funcbox, allboxes, portal_code.calldescr, + return self.do_residual_call(funcbox, allboxes, portal_code.calldescr, pc, assembler_call=assembler_call, assembler_call_jd=targetjitdriver_sd) @@ -1029,7 +1031,7 @@ except ChangeFrame: pass frame = self.metainterp.framestack[-1] - frame.do_recursive_call(jitdriver_sd, greenboxes + redboxes, + frame.do_recursive_call(jitdriver_sd, greenboxes + redboxes, orgpc, assembler_call=True) raise ChangeFrame @@ -1331,7 +1333,7 @@ self.metainterp.assert_no_exception() return resbox - def do_residual_call(self, funcbox, argboxes, descr, + def do_residual_call(self, funcbox, argboxes, descr, pc, assembler_call=False, assembler_call_jd=None): # First build allboxes: it may need some reordering from the @@ -1371,9 +1373,11 @@ effectinfo.check_forces_virtual_or_virtualizable()): # residual calls require attention to keep virtualizables in-sync self.metainterp.clear_exception() + if effectinfo.oopspecindex == EffectInfo.OS_JIT_FORCE_VIRTUAL: + handled, resbox = self._do_jit_force_virtual(allboxes, descr, pc) + if handled: + return resbox self.metainterp.vable_and_vrefs_before_residual_call() - if effectinfo.oopspecindex == EffectInfo.OS_JIT_FORCE_VIRTUAL: - return self._do_jit_force_virtual(allboxes, descr) resbox = self.metainterp.execute_and_record_varargs( rop.CALL_MAY_FORCE, allboxes, descr=descr) if effectinfo.is_call_release_gil(): @@ -1403,7 +1407,27 @@ pure = effectinfo.check_is_elidable() return self.execute_varargs(rop.CALL, allboxes, descr, exc, pure) - def do_residual_or_indirect_call(self, funcbox, argboxes, calldescr): + def _do_jit_force_virtual(self, allboxes, descr, pc): + assert len(allboxes) == 2 + if (self.metainterp.jitdriver_sd.virtualizable_info is None and + self.metainterp.jitdriver_sd.greenfield_info is None): + # can occur in case of multiple JITs + return False, None + vref_box = allboxes[1] + standard_box = self.metainterp.virtualizable_boxes[-1] + if standard_box is vref_box: + return True, vref_box + if self.metainterp.heapcache.is_nonstandard_virtualizable(vref_box): + return False, None + eqbox = self.metainterp.execute_and_record(rop.PTR_EQ, None, vref_box, standard_box) + eqbox = self.implement_guard_value(eqbox, pc) + isstandard = eqbox.getint() + if isstandard: + return True, standard_box + else: + return False, None + + def do_residual_or_indirect_call(self, funcbox, argboxes, calldescr, pc): """The 'residual_call' operation is emitted in two cases: when we have to generate a residual CALL operation, but also to handle an indirect_call that may need to be inlined.""" @@ -1415,7 +1439,7 @@ # we should follow calls to this graph return self.metainterp.perform_call(jitcode, argboxes) # but we should not follow calls to that graph - return self.do_residual_call(funcbox, argboxes, calldescr) + return self.do_residual_call(funcbox, argboxes, calldescr, pc) # ____________________________________________________________ diff --git a/rpython/jit/metainterp/test/test_virtualizable.py b/rpython/jit/metainterp/test/test_virtualizable.py --- a/rpython/jit/metainterp/test/test_virtualizable.py +++ b/rpython/jit/metainterp/test/test_virtualizable.py @@ -1465,11 +1465,11 @@ res = self.meta_interp(main, [10]) assert res == main(10) self.check_resops({ - "int_lt": 1, "guard_true": 1, "int_add": 1, "jump": 1, + "getfield_gc": 1, "int_lt": 2, "ptr_eq": 1, "guard_true": 3, + "int_add": 2, "jump": 1 }) - class TestOOtype(#ExplicitVirtualizableTests, ImplicitVirtualizableTests, OOJitMixin): From noreply at buildbot.pypy.org Sat Apr 13 20:50:37 2013 From: noreply at buildbot.pypy.org (alex_gaynor) Date: Sat, 13 Apr 2013 20:50:37 +0200 (CEST) Subject: [pypy-commit] pypy virtualref-virtualizable: fix guard_str_value Message-ID: <20130413185037.0F2101C1495@cobra.cs.uni-duesseldorf.de> Author: Alex Gaynor Branch: virtualref-virtualizable Changeset: r63323:dfce75a3baa0 Date: 2013-04-13 11:50 -0700 http://bitbucket.org/pypy/pypy/changeset/dfce75a3baa0/ Log: fix guard_str_value diff --git a/rpython/jit/metainterp/pyjitpl.py b/rpython/jit/metainterp/pyjitpl.py --- a/rpython/jit/metainterp/pyjitpl.py +++ b/rpython/jit/metainterp/pyjitpl.py @@ -939,7 +939,7 @@ return box # no promotion needed, already a Const else: constbox = box.constbox() - resbox = self.do_residual_call(funcbox, [box, constbox], descr) + resbox = self.do_residual_call(funcbox, [box, constbox], descr, orgpc) promoted_box = resbox.constbox() # This is GUARD_VALUE because GUARD_TRUE assumes the existance # of a label when computing resumepc From noreply at buildbot.pypy.org Sat Apr 13 23:23:03 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Sat, 13 Apr 2013 23:23:03 +0200 (CEST) Subject: [pypy-commit] pypy default: close these sockets so test passes on pypy Message-ID: <20130413212303.0EDE51C05C8@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63324:7beff1053ecc Date: 2013-04-13 17:22 -0400 http://bitbucket.org/pypy/pypy/changeset/7beff1053ecc/ Log: close these sockets so test passes on pypy diff --git a/rpython/rlib/test/test_rsocket.py b/rpython/rlib/test/test_rsocket.py --- a/rpython/rlib/test/test_rsocket.py +++ b/rpython/rlib/test/test_rsocket.py @@ -375,6 +375,8 @@ s2 = s.dup() assert s.fd != s2.fd assert s.getsockname().eq(s2.getsockname()) + s.close() + s2.close() def test_c_dup(): # rsocket.dup() duplicates fd, it also works on Windows @@ -384,6 +386,8 @@ s2 = RSocket(fd=dup(s.fd)) assert s.fd != s2.fd assert s.getsockname().eq(s2.getsockname()) + s.close() + s2.close() def test_inet_aton(): assert inet_aton('1.2.3.4') == '\x01\x02\x03\x04' From noreply at buildbot.pypy.org Sun Apr 14 01:16:47 2013 From: noreply at buildbot.pypy.org (alex_gaynor) Date: Sun, 14 Apr 2013 01:16:47 +0200 (CEST) Subject: [pypy-commit] pypy virtualref-virtualizable: if we put a guard here, we need liveness data Message-ID: <20130413231647.C5A841C1495@cobra.cs.uni-duesseldorf.de> Author: Alex Gaynor Branch: virtualref-virtualizable Changeset: r63325:16e33c75718e Date: 2013-04-13 15:29 -0700 http://bitbucket.org/pypy/pypy/changeset/16e33c75718e/ Log: if we put a guard here, we need liveness data diff --git a/rpython/jit/codewriter/jtransform.py b/rpython/jit/codewriter/jtransform.py --- a/rpython/jit/codewriter/jtransform.py +++ b/rpython/jit/codewriter/jtransform.py @@ -1755,7 +1755,7 @@ return SpaceOperation('libffi_save_result_%s' % kind, op.args[1:], None) def rewrite_op_jit_force_virtual(self, op): - return self._do_builtin_call(op) + return [SpaceOperation('-live-', [], None), self._do_builtin_call(op)] def rewrite_op_jit_is_virtual(self, op): raise Exception, ( From noreply at buildbot.pypy.org Sun Apr 14 01:16:49 2013 From: noreply at buildbot.pypy.org (alex_gaynor) Date: Sun, 14 Apr 2013 01:16:49 +0200 (CEST) Subject: [pypy-commit] pypy virtualref-virtualizable: merged default in Message-ID: <20130413231649.CFDB21C1495@cobra.cs.uni-duesseldorf.de> Author: Alex Gaynor Branch: virtualref-virtualizable Changeset: r63326:e9fc31627328 Date: 2013-04-13 15:29 -0700 http://bitbucket.org/pypy/pypy/changeset/e9fc31627328/ Log: merged default in diff too long, truncating to 2000 out of 2964 lines diff --git a/pypy/module/_cffi_backend/ccallback.py b/pypy/module/_cffi_backend/ccallback.py --- a/pypy/module/_cffi_backend/ccallback.py +++ b/pypy/module/_cffi_backend/ccallback.py @@ -134,7 +134,7 @@ # W_CTypePrimitiveSigned.convert_from_object() in order # to write a whole 'ffi_arg'. value = misc.as_long(space, w_res) - misc.write_raw_signed_data(ll_res, value, SIZE_OF_FFI_ARG) + misc.write_raw_integer_data(ll_res, value, SIZE_OF_FFI_ARG) return else: # zero extension: fill the '*result' with zeros, and (on big- diff --git a/pypy/module/_cffi_backend/cdataobj.py b/pypy/module/_cffi_backend/cdataobj.py --- a/pypy/module/_cffi_backend/cdataobj.py +++ b/pypy/module/_cffi_backend/cdataobj.py @@ -280,13 +280,8 @@ return self.ctype.iter(self) @specialize.argtype(1) - def write_raw_signed_data(self, source): - misc.write_raw_signed_data(self._cdata, source, self.ctype.size) - keepalive_until_here(self) - - @specialize.argtype(1) - def write_raw_unsigned_data(self, source): - misc.write_raw_unsigned_data(self._cdata, source, self.ctype.size) + def write_raw_integer_data(self, source): + misc.write_raw_integer_data(self._cdata, source, self.ctype.size) keepalive_until_here(self) def write_raw_float_data(self, source): diff --git a/pypy/module/_cffi_backend/ctypeprim.py b/pypy/module/_cffi_backend/ctypeprim.py --- a/pypy/module/_cffi_backend/ctypeprim.py +++ b/pypy/module/_cffi_backend/ctypeprim.py @@ -63,7 +63,7 @@ else: value = self._cast_generic(w_ob) w_cdata = cdataobj.W_CDataMem(space, self.size, self) - self.write_raw_integer_data(w_cdata, value) + w_cdata.write_raw_integer_data(value) return w_cdata def _cast_result(self, intvalue): @@ -94,9 +94,6 @@ from pypy.module._cffi_backend import newtype return newtype.new_primitive_type(self.space, "int") - def write_raw_integer_data(self, w_cdata, value): - w_cdata.write_raw_unsigned_data(value) - class W_CTypePrimitiveChar(W_CTypePrimitiveCharOrUniChar): _attrs_ = [] @@ -188,10 +185,10 @@ if self.size < rffi.sizeof(lltype.Signed): if r_uint(value) - self.vmin > self.vrangemax: self._overflow(w_ob) - misc.write_raw_signed_data(cdata, value, self.size) + misc.write_raw_integer_data(cdata, value, self.size) else: value = misc.as_long_long(self.space, w_ob) - misc.write_raw_signed_data(cdata, value, self.size) + misc.write_raw_integer_data(cdata, value, self.size) def get_vararg_type(self): if self.size < rffi.sizeof(rffi.INT): @@ -199,9 +196,6 @@ return newtype.new_primitive_type(self.space, "int") return self - def write_raw_integer_data(self, w_cdata, value): - w_cdata.write_raw_signed_data(value) - class W_CTypePrimitiveUnsigned(W_CTypePrimitive): _attrs_ = ['value_fits_long', 'value_fits_ulong', 'vrangemax'] @@ -228,10 +222,10 @@ if self.value_fits_long: if value > self.vrangemax: self._overflow(w_ob) - misc.write_raw_unsigned_data(cdata, value, self.size) + misc.write_raw_integer_data(cdata, value, self.size) else: value = misc.as_unsigned_long_long(self.space, w_ob, strict=True) - misc.write_raw_unsigned_data(cdata, value, self.size) + misc.write_raw_integer_data(cdata, value, self.size) def convert_to_object(self, cdata): if self.value_fits_ulong: @@ -250,9 +244,6 @@ return newtype.new_primitive_type(self.space, "int") return self - def write_raw_integer_data(self, w_cdata, value): - w_cdata.write_raw_unsigned_data(value) - class W_CTypePrimitiveBool(W_CTypePrimitiveUnsigned): _attrs_ = [] diff --git a/pypy/module/_cffi_backend/ctypestruct.py b/pypy/module/_cffi_backend/ctypestruct.py --- a/pypy/module/_cffi_backend/ctypestruct.py +++ b/pypy/module/_cffi_backend/ctypestruct.py @@ -242,13 +242,11 @@ # value = misc.as_long_long(space, w_ob) if isinstance(ctype, ctypeprim.W_CTypePrimitiveSigned): - is_signed = True fmin = -(r_longlong(1) << (self.bitsize - 1)) fmax = (r_longlong(1) << (self.bitsize - 1)) - 1 if fmax == 0: fmax = 1 # special case to let "int x:1" receive "1" else: - is_signed = False fmin = r_longlong(0) fmax = r_longlong((r_ulonglong(1) << self.bitsize) - 1) if value < fmin or value > fmax: @@ -260,10 +258,7 @@ rawvalue = r_ulonglong(value) << self.bitshift rawfielddata = misc.read_raw_unsigned_data(cdata, ctype.size) rawfielddata = (rawfielddata & ~rawmask) | (rawvalue & rawmask) - if is_signed: - misc.write_raw_signed_data(cdata, rawfielddata, ctype.size) - else: - misc.write_raw_unsigned_data(cdata, rawfielddata, ctype.size) + misc.write_raw_integer_data(cdata, rawfielddata, ctype.size) W_CField.typedef = TypeDef( diff --git a/pypy/module/_cffi_backend/misc.py b/pypy/module/_cffi_backend/misc.py --- a/pypy/module/_cffi_backend/misc.py +++ b/pypy/module/_cffi_backend/misc.py @@ -9,7 +9,6 @@ from rpython.rtyper.lltypesystem import lltype, llmemory, rffi from rpython.translator.tool.cbuild import ExternalCompilationInfo - # ____________________________________________________________ _prim_signed_types = unrolling_iterable([ @@ -66,22 +65,19 @@ return rffi.cast(rffi.LONGDOUBLEP, target)[0] @specialize.argtype(1) -def write_raw_unsigned_data(target, source, size): - for TP, TPP in _prim_unsigned_types: - if size == rffi.sizeof(TP): - rffi.cast(TPP, target)[0] = rffi.cast(TP, source) - return +def write_raw_integer_data(target, source, size): + if is_signed_integer_type(lltype.typeOf(source)): + for TP, TPP in _prim_signed_types: + if size == rffi.sizeof(TP): + rffi.cast(TPP, target)[0] = rffi.cast(TP, source) + return + else: + for TP, TPP in _prim_unsigned_types: + if size == rffi.sizeof(TP): + rffi.cast(TPP, target)[0] = rffi.cast(TP, source) + return raise NotImplementedError("bad integer size") - at specialize.argtype(1) -def write_raw_signed_data(target, source, size): - for TP, TPP in _prim_signed_types: - if size == rffi.sizeof(TP): - rffi.cast(TPP, target)[0] = rffi.cast(TP, source) - return - raise NotImplementedError("bad integer size") - - def write_raw_float_data(target, source, size): for TP, TPP in _prim_float_types: if size == rffi.sizeof(TP): diff --git a/pypy/module/pypyjit/test_pypy_c/test__ffi.py b/pypy/module/pypyjit/test_pypy_c/test__ffi.py new file mode 100644 --- /dev/null +++ b/pypy/module/pypyjit/test_pypy_c/test__ffi.py @@ -0,0 +1,272 @@ +import sys, py +from pypy.module.pypyjit.test_pypy_c.test_00_model import BaseTestPyPyC + +class Test__ffi(BaseTestPyPyC): + + def test__ffi_call(self): + from rpython.rlib.test.test_clibffi import get_libm_name + def main(libm_name): + try: + from _ffi import CDLL, types + except ImportError: + sys.stderr.write('SKIP: cannot import _ffi\n') + return 0 + + libm = CDLL(libm_name) + pow = libm.getfunc('pow', [types.double, types.double], + types.double) + i = 0 + res = 0 + while i < 300: + tmp = pow(2, 3) # ID: fficall + res += tmp + i += 1 + return pow.getaddr(), res + # + libm_name = get_libm_name(sys.platform) + log = self.run(main, [libm_name]) + pow_addr, res = log.result + assert res == 8.0 * 300 + py.test.xfail() # XXX re-optimize _ffi for the JIT? + loop, = log.loops_by_filename(self.filepath) + if 'ConstClass(pow)' in repr(loop): # e.g. OS/X + pow_addr = 'ConstClass(pow)' + assert loop.match_by_id('fficall', """ + guard_not_invalidated(descr=...) + i17 = force_token() + setfield_gc(p0, i17, descr=<.* .*PyFrame.vable_token .*>) + f21 = call_release_gil(%s, 2.000000, 3.000000, descr=) + guard_not_forced(descr=...) + guard_no_exception(descr=...) + """ % pow_addr) + + + def test__ffi_call_frame_does_not_escape(self): + from rpython.rlib.test.test_clibffi import get_libm_name + def main(libm_name): + try: + from _ffi import CDLL, types + except ImportError: + sys.stderr.write('SKIP: cannot import _ffi\n') + return 0 + + libm = CDLL(libm_name) + pow = libm.getfunc('pow', [types.double, types.double], + types.double) + + def mypow(a, b): + return pow(a, b) + + i = 0 + res = 0 + while i < 300: + tmp = mypow(2, 3) + res += tmp + i += 1 + return pow.getaddr(), res + # + libm_name = get_libm_name(sys.platform) + log = self.run(main, [libm_name]) + pow_addr, res = log.result + assert res == 8.0 * 300 + loop, = log.loops_by_filename(self.filepath) + opnames = log.opnames(loop.allops()) + # we only force the virtualref, not its content + assert opnames.count('new_with_vtable') == 1 + + def test__ffi_call_releases_gil(self): + from rpython.rlib.clibffi import get_libc_name + def main(libc_name, n): + import time + import os + from threading import Thread + # + if os.name == 'nt': + from _ffi import WinDLL, types + libc = WinDLL('Kernel32.dll') + sleep = libc.getfunc('Sleep', [types.uint], types.uint) + delays = [0]*n + [1000] + else: + from _ffi import CDLL, types + libc = CDLL(libc_name) + sleep = libc.getfunc('sleep', [types.uint], types.uint) + delays = [0]*n + [1] + # + def loop_of_sleeps(i, delays): + for delay in delays: + sleep(delay) # ID: sleep + # + threads = [Thread(target=loop_of_sleeps, args=[i, delays]) for i in range(5)] + start = time.time() + for i, thread in enumerate(threads): + thread.start() + for thread in threads: + thread.join() + end = time.time() + return end - start + log = self.run(main, [get_libc_name(), 200], threshold=150, + import_site=True) + assert 1 <= log.result <= 1.5 # at most 0.5 seconds of overhead + loops = log.loops_by_id('sleep') + assert len(loops) == 1 # make sure that we actually JITted the loop + + def test_ctypes_call(self): + from rpython.rlib.test.test_clibffi import get_libm_name + def main(libm_name): + import ctypes + libm = ctypes.CDLL(libm_name) + fabs = libm.fabs + fabs.argtypes = [ctypes.c_double] + fabs.restype = ctypes.c_double + x = -4 + i = 0 + while i < 300: + x = fabs(x) + x = x - 100 + i += 1 + return fabs._ptr.getaddr(), x + + libm_name = get_libm_name(sys.platform) + log = self.run(main, [libm_name], import_site=True) + fabs_addr, res = log.result + assert res == -4.0 + loop, = log.loops_by_filename(self.filepath) + ops = loop.allops() + opnames = log.opnames(ops) + assert opnames.count('new_with_vtable') == 1 # only the virtualref + py.test.xfail() # XXX re-optimize _ffi for the JIT? + assert opnames.count('call_release_gil') == 1 + idx = opnames.index('call_release_gil') + call = ops[idx] + assert (call.args[0] == 'ConstClass(fabs)' or # e.g. OS/X + int(call.args[0]) == fabs_addr) + + + def test__ffi_struct(self): + def main(): + from _ffi import _StructDescr, Field, types + fields = [ + Field('x', types.slong), + ] + descr = _StructDescr('foo', fields) + struct = descr.allocate() + i = 0 + while i < 300: + x = struct.getfield('x') # ID: getfield + x = x+1 + struct.setfield('x', x) # ID: setfield + i += 1 + return struct.getfield('x') + # + log = self.run(main, []) + py.test.xfail() # XXX re-optimize _ffi for the JIT? + loop, = log.loops_by_filename(self.filepath) + assert loop.match_by_id('getfield', """ + guard_not_invalidated(descr=...) + i57 = getfield_raw(i46, descr=) + """) + assert loop.match_by_id('setfield', """ + setfield_raw(i44, i57, descr=) + """) + + + def test__cffi_call(self): + from rpython.rlib.test.test_clibffi import get_libm_name + def main(libm_name): + try: + import _cffi_backend + except ImportError: + sys.stderr.write('SKIP: cannot import _cffi_backend\n') + return 0 + + libm = _cffi_backend.load_library(libm_name) + BDouble = _cffi_backend.new_primitive_type("double") + BPow = _cffi_backend.new_function_type([BDouble, BDouble], BDouble) + pow = libm.load_function(BPow, 'pow') + i = 0 + res = 0 + while i < 300: + tmp = pow(2, 3) # ID: cfficall + res += tmp + i += 1 + BLong = _cffi_backend.new_primitive_type("long") + pow_addr = int(_cffi_backend.cast(BLong, pow)) + return pow_addr, res + # + libm_name = get_libm_name(sys.platform) + log = self.run(main, [libm_name]) + pow_addr, res = log.result + assert res == 8.0 * 300 + loop, = log.loops_by_filename(self.filepath) + if 'ConstClass(pow)' in repr(loop): # e.g. OS/X + pow_addr = 'ConstClass(pow)' + assert loop.match_by_id('cfficall', """ + ... + f1 = call_release_gil(..., descr=) + ... + """) + # so far just check that call_release_gil() is produced. + # later, also check that the arguments to call_release_gil() + # are constants, and that the numerous raw_mallocs are removed + + def test_cffi_call_guard_not_forced_fails(self): + # this is the test_pypy_c equivalent of + # rpython/jit/metainterp/test/test_fficall::test_guard_not_forced_fails + # + # it requires cffi to be installed for pypy in order to run + def main(): + import sys + try: + import cffi + except ImportError: + sys.stderr.write('SKIP: cannot import cffi\n') + return 0 + + ffi = cffi.FFI() + + ffi.cdef(""" + typedef void (*functype)(int); + int foo(int n, functype func); + """) + + lib = ffi.verify(""" + #include + typedef void (*functype)(int); + + int foo(int n, functype func) { + if (n >= 2000) { + func(n); + } + return n*2; + } + """) + + @ffi.callback("functype") + def mycallback(n): + if n < 5000: + return + # make sure that guard_not_forced fails + d = {} + f = sys._getframe() + while f: + d.update(f.f_locals) + f = f.f_back + + n = 0 + while n < 10000: + res = lib.foo(n, mycallback) # ID: cfficall + # this is the real point of the test: before the + # refactor-call_release_gil branch, the assert failed when + # res == 5000 + assert res == n*2 + n += 1 + return n + + log = self.run(main, [], import_site=True) + assert log.result == 10000 + loop, = log.loops_by_id('cfficall') + assert loop.match_by_id('cfficall', """ + ... + f1 = call_release_gil(..., descr=) + ... + """) diff --git a/pypy/module/pypyjit/test_pypy_c/test_ffi.py b/pypy/module/pypyjit/test_pypy_c/test_ffi.py deleted file mode 100644 --- a/pypy/module/pypyjit/test_pypy_c/test_ffi.py +++ /dev/null @@ -1,279 +0,0 @@ -import sys, py -from pypy.module.pypyjit.test_pypy_c.test_00_model import BaseTestPyPyC - -class Test__ffi(BaseTestPyPyC): - - def test__ffi_call(self): - from rpython.rlib.test.test_clibffi import get_libm_name - def main(libm_name): - try: - from _ffi import CDLL, types - except ImportError: - sys.stderr.write('SKIP: cannot import _ffi\n') - return 0 - - libm = CDLL(libm_name) - pow = libm.getfunc('pow', [types.double, types.double], - types.double) - i = 0 - res = 0 - while i < 300: - tmp = pow(2, 3) # ID: fficall - res += tmp - i += 1 - return pow.getaddr(), res - # - libm_name = get_libm_name(sys.platform) - log = self.run(main, [libm_name]) - pow_addr, res = log.result - assert res == 8.0 * 300 - py.test.xfail() # XXX re-optimize _ffi for the JIT? - loop, = log.loops_by_filename(self.filepath) - if 'ConstClass(pow)' in repr(loop): # e.g. OS/X - pow_addr = 'ConstClass(pow)' - assert loop.match_by_id('fficall', """ - guard_not_invalidated(descr=...) - i17 = force_token() - setfield_gc(p0, i17, descr=<.* .*PyFrame.vable_token .*>) - f21 = call_release_gil(%s, 2.000000, 3.000000, descr=) - guard_not_forced(descr=...) - guard_no_exception(descr=...) - """ % pow_addr) - - - def test__ffi_call_frame_does_not_escape(self): - from rpython.rlib.test.test_clibffi import get_libm_name - def main(libm_name): - try: - from _ffi import CDLL, types - except ImportError: - sys.stderr.write('SKIP: cannot import _ffi\n') - return 0 - - libm = CDLL(libm_name) - pow = libm.getfunc('pow', [types.double, types.double], - types.double) - - def mypow(a, b): - return pow(a, b) - - i = 0 - res = 0 - while i < 300: - tmp = mypow(2, 3) - res += tmp - i += 1 - return pow.getaddr(), res - # - libm_name = get_libm_name(sys.platform) - log = self.run(main, [libm_name]) - pow_addr, res = log.result - assert res == 8.0 * 300 - loop, = log.loops_by_filename(self.filepath) - opnames = log.opnames(loop.allops()) - # we only force the virtualref, not its content - assert opnames.count('new_with_vtable') == 1 - - def test__ffi_call_releases_gil(self): - from rpython.rlib.clibffi import get_libc_name - def main(libc_name, n): - import time - import os - from threading import Thread - # - if os.name == 'nt': - from _ffi import WinDLL, types - libc = WinDLL('Kernel32.dll') - sleep = libc.getfunc('Sleep', [types.uint], types.uint) - delays = [0]*n + [1000] - else: - from _ffi import CDLL, types - libc = CDLL(libc_name) - sleep = libc.getfunc('sleep', [types.uint], types.uint) - delays = [0]*n + [1] - # - def loop_of_sleeps(i, delays): - for delay in delays: - sleep(delay) # ID: sleep - # - threads = [Thread(target=loop_of_sleeps, args=[i, delays]) for i in range(5)] - start = time.time() - for i, thread in enumerate(threads): - thread.start() - for thread in threads: - thread.join() - end = time.time() - return end - start - log = self.run(main, [get_libc_name(), 200], threshold=150, - import_site=True) - assert 1 <= log.result <= 1.5 # at most 0.5 seconds of overhead - loops = log.loops_by_id('sleep') - assert len(loops) == 1 # make sure that we actually JITted the loop - - def test_ctypes_call(self): - from rpython.rlib.test.test_clibffi import get_libm_name - def main(libm_name): - import ctypes - libm = ctypes.CDLL(libm_name) - fabs = libm.fabs - fabs.argtypes = [ctypes.c_double] - fabs.restype = ctypes.c_double - x = -4 - i = 0 - while i < 300: - x = fabs(x) - x = x - 100 - i += 1 - return fabs._ptr.getaddr(), x - - libm_name = get_libm_name(sys.platform) - log = self.run(main, [libm_name], import_site=True) - fabs_addr, res = log.result - assert res == -4.0 - loop, = log.loops_by_filename(self.filepath) - ops = loop.allops() - opnames = log.opnames(ops) - assert opnames.count('new_with_vtable') == 1 # only the virtualref - py.test.xfail() # XXX re-optimize _ffi for the JIT? - assert opnames.count('call_release_gil') == 1 - idx = opnames.index('call_release_gil') - call = ops[idx] - assert (call.args[0] == 'ConstClass(fabs)' or # e.g. OS/X - int(call.args[0]) == fabs_addr) - - - def test__ffi_struct(self): - def main(): - from _ffi import _StructDescr, Field, types - fields = [ - Field('x', types.slong), - ] - descr = _StructDescr('foo', fields) - struct = descr.allocate() - i = 0 - while i < 300: - x = struct.getfield('x') # ID: getfield - x = x+1 - struct.setfield('x', x) # ID: setfield - i += 1 - return struct.getfield('x') - # - log = self.run(main, []) - py.test.xfail() # XXX re-optimize _ffi for the JIT? - loop, = log.loops_by_filename(self.filepath) - assert loop.match_by_id('getfield', """ - guard_not_invalidated(descr=...) - i57 = getfield_raw(i46, descr=) - """) - assert loop.match_by_id('setfield', """ - setfield_raw(i44, i57, descr=) - """) - - - def test__cffi_call(self): - from rpython.rlib.test.test_clibffi import get_libm_name - def main(libm_name): - try: - import _cffi_backend - except ImportError: - sys.stderr.write('SKIP: cannot import _cffi_backend\n') - return 0 - - libm = _cffi_backend.load_library(libm_name) - BDouble = _cffi_backend.new_primitive_type("double") - BInt = _cffi_backend.new_primitive_type("int") - BPow = _cffi_backend.new_function_type([BDouble, BInt], BDouble) - ldexp = libm.load_function(BPow, 'ldexp') - i = 0 - res = 0 - while i < 300: - tmp = ldexp(1, 3) # ID: cfficall - res += tmp - i += 1 - BLong = _cffi_backend.new_primitive_type("long") - ldexp_addr = int(_cffi_backend.cast(BLong, ldexp)) - return ldexp_addr, res - # - libm_name = get_libm_name(sys.platform) - log = self.run(main, [libm_name]) - ldexp_addr, res = log.result - assert res == 8.0 * 300 - loop, = log.loops_by_filename(self.filepath) - if 'ConstClass(ldexp)' in repr(loop): # e.g. OS/X - ldexp_addr = 'ConstClass(ldexp)' - assert loop.match_by_id('cfficall', """ - ... - f1 = call_release_gil(..., descr=) - ... - """) - ops = loop.ops_by_id('cfficall') - assert 'raw_malloc' not in str(ops) - assert 'raw_free' not in str(ops) - assert 'getarrayitem_raw' not in log.opnames(ops) - assert 'setarrayitem_raw' not in log.opnames(ops) - # so far just check that call_release_gil() is produced. - # later, also check that the arguments to call_release_gil() - # are constants - # are constants, and that the numerous raw_mallocs are removed - - def test_cffi_call_guard_not_forced_fails(self): - # this is the test_pypy_c equivalent of - # rpython/jit/metainterp/test/test_fficall::test_guard_not_forced_fails - # - # it requires cffi to be installed for pypy in order to run - def main(): - import sys - try: - import cffi - except ImportError: - sys.stderr.write('SKIP: cannot import cffi\n') - return 0 - - ffi = cffi.FFI() - - ffi.cdef(""" - typedef void (*functype)(int); - int foo(int n, functype func); - """) - - lib = ffi.verify(""" - #include - typedef void (*functype)(int); - - int foo(int n, functype func) { - if (n >= 2000) { - func(n); - } - return n*2; - } - """) - - @ffi.callback("functype") - def mycallback(n): - if n < 5000: - return - # make sure that guard_not_forced fails - d = {} - f = sys._getframe() - while f: - d.update(f.f_locals) - f = f.f_back - - n = 0 - while n < 10000: - res = lib.foo(n, mycallback) # ID: cfficall - # this is the real point of the test: before the - # refactor-call_release_gil branch, the assert failed when - # res == 5000 - assert res == n*2 - n += 1 - return n - - log = self.run(main, [], import_site=True) - assert log.result == 10000 - loop, = log.loops_by_id('cfficall') - assert loop.match_by_id('cfficall', """ - ... - f1 = call_release_gil(..., descr=) - ... - """) diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -74,29 +74,6 @@ def setup_failure_recovery(self): self.failure_recovery_code = [0, 0, 0, 0] - @staticmethod - def _release_gil_shadowstack(): - before = rffi.aroundstate.before - if before: - before() - - @staticmethod - def _reacquire_gil_shadowstack(): - after = rffi.aroundstate.after - if after: - after() - - _NOARG_FUNC = lltype.Ptr(lltype.FuncType([], lltype.Void)) - - def _build_release_gil(self, gcrootmap): - assert gcrootmap.is_shadow_stack - releasegil_func = llhelper(self._NOARG_FUNC, - self._release_gil_shadowstack) - reacqgil_func = llhelper(self._NOARG_FUNC, - self._reacquire_gil_shadowstack) - self.releasegil_addr = rffi.cast(lltype.Signed, releasegil_func) - self.reacqgil_addr = rffi.cast(lltype.Signed, reacqgil_func) - def _build_propagate_exception_path(self): if not self.cpu.propagate_exception_descr: return # not supported (for tests, or non-translated) @@ -537,7 +514,7 @@ clt.allgcrefs = [] clt.frame_info.clear() # for now - if False and log: + if log: operations = self._inject_debugging_code(looptoken, operations, 'e', looptoken.number) diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -630,7 +630,9 @@ # argument the address of the structure we are writing into # (the first argument to COND_CALL_GC_WB). helper_num = card_marking - if self._regalloc is not None and self._regalloc.vfprm.reg_bindings: + if is_frame: + helper_num = 4 + elif self._regalloc is not None and self._regalloc.vfprm.reg_bindings: helper_num += 2 if self.wb_slowpath[helper_num] == 0: # tests only assert not we_are_translated() @@ -1264,7 +1266,7 @@ resloc = arglocs[0] if gcrootmap: - self.call_release_gil(gcrootmap, arglocs, fcond) + self.call_release_gil(gcrootmap, arglocs, regalloc, fcond) # do the call self._store_force_index(guard_op) # @@ -1276,37 +1278,32 @@ resloc, (size, signed)) # then reopen the stack if gcrootmap: - self.call_reacquire_gil(gcrootmap, resloc, fcond) + self.call_reacquire_gil(gcrootmap, resloc, regalloc, fcond) self._emit_guard_may_force(guard_op, arglocs[numargs+1:], numargs) return fcond - def call_release_gil(self, gcrootmap, save_registers, fcond): - # First, we need to save away the registers listed in - # 'save_registers' that are not callee-save. + def call_release_gil(self, gcrootmap, save_registers, regalloc, fcond): + # Save caller saved registers and do the call # NOTE: We assume that the floating point registers won't be modified. - regs_to_save = [] - for reg in self._regalloc.rm.save_around_call_regs: - if reg in save_registers: - regs_to_save.append(reg) assert gcrootmap.is_shadow_stack - with saved_registers(self.mc, regs_to_save): + with saved_registers(self.mc, regalloc.rm.save_around_call_regs): self._emit_call(imm(self.releasegil_addr), [], fcond) - def call_reacquire_gil(self, gcrootmap, save_loc, fcond): - # save the previous result into the stack temporarily. + def call_reacquire_gil(self, gcrootmap, save_loc, regalloc, fcond): + # save the previous result into the stack temporarily, in case it is in + # a caller saved register. # NOTE: like with call_release_gil(), we assume that we don't need to # save vfp regs in this case. Besides the result location regs_to_save = [] vfp_regs_to_save = [] - if save_loc.is_reg(): + if save_loc and save_loc in regalloc.rm.save_around_call_regs: regs_to_save.append(save_loc) - if save_loc.is_vfp_reg(): + regs_to_save.append(r.ip) # for alingment + elif save_loc and save_loc in regalloc.vfprm.save_around_call_regs: vfp_regs_to_save.append(save_loc) + assert gcrootmap.is_shadow_stack # call the reopenstack() function (also reacquiring the GIL) - if len(regs_to_save) % 2 != 1: - regs_to_save.append(r.ip) # for alingment - assert gcrootmap.is_shadow_stack with saved_registers(self.mc, regs_to_save, vfp_regs_to_save): self._emit_call(imm(self.reacqgil_addr), [], fcond) diff --git a/rpython/jit/backend/arm/regalloc.py b/rpython/jit/backend/arm/regalloc.py --- a/rpython/jit/backend/arm/regalloc.py +++ b/rpython/jit/backend/arm/regalloc.py @@ -554,10 +554,9 @@ return self._prepare_call(op) def _prepare_call(self, op, force_store=[], save_all_regs=False): - args = [] - args.append(None) + args = [None] * (op.numargs()+1) for i in range(op.numargs()): - args.append(self.loc(op.getarg(i))) + args[i+1] = self.loc(op.getarg(i)) # spill variables that need to be saved around calls self.vfprm.before_call(save_all_regs=save_all_regs) if not save_all_regs: diff --git a/rpython/jit/backend/llgraph/runner.py b/rpython/jit/backend/llgraph/runner.py --- a/rpython/jit/backend/llgraph/runner.py +++ b/rpython/jit/backend/llgraph/runner.py @@ -484,15 +484,6 @@ else: return self.bh_raw_load_i(struct, offset, descr) - def unpack_arraydescr_size(self, arraydescr): - from rpython.jit.backend.llsupport.symbolic import get_array_token - from rpython.jit.backend.llsupport.descr import get_type_flag, FLAG_SIGNED - assert isinstance(arraydescr, ArrayDescr) - basesize, itemsize, _ = get_array_token(arraydescr.A, False) - flag = get_type_flag(arraydescr.A.OF) - is_signed = (flag == FLAG_SIGNED) - return basesize, itemsize, is_signed - def bh_raw_store_i(self, struct, offset, newvalue, descr): ll_p = rffi.cast(rffi.CCHARP, struct) ll_p = rffi.cast(lltype.Ptr(descr.A), rffi.ptradd(ll_p, offset)) @@ -575,14 +566,10 @@ def bh_read_timestamp(self): return read_timestamp() - def bh_new_raw_buffer(self, size): - return lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') - def store_fail_descr(self, deadframe, descr): pass # I *think* - class LLDeadFrame(object): _TYPE = llmemory.GCREF diff --git a/rpython/jit/backend/llsupport/assembler.py b/rpython/jit/backend/llsupport/assembler.py --- a/rpython/jit/backend/llsupport/assembler.py +++ b/rpython/jit/backend/llsupport/assembler.py @@ -9,7 +9,7 @@ debug_print) from rpython.rlib.rarithmetic import r_uint from rpython.rlib.objectmodel import specialize, compute_unique_id -from rpython.rtyper.annlowlevel import cast_instance_to_gcref +from rpython.rtyper.annlowlevel import cast_instance_to_gcref, llhelper from rpython.rtyper.lltypesystem import rffi, lltype @@ -282,6 +282,69 @@ debug_print(prefix + ':' + str(struct.i)) debug_stop('jit-backend-counts') + @staticmethod + @rgc.no_collect + def _release_gil_asmgcc(css): + # similar to trackgcroot.py:pypy_asm_stackwalk, first part + from rpython.memory.gctransform import asmgcroot + new = rffi.cast(asmgcroot.ASM_FRAMEDATA_HEAD_PTR, css) + next = asmgcroot.gcrootanchor.next + new.next = next + new.prev = asmgcroot.gcrootanchor + asmgcroot.gcrootanchor.next = new + next.prev = new + # and now release the GIL + before = rffi.aroundstate.before + if before: + before() + + @staticmethod + @rgc.no_collect + def _reacquire_gil_asmgcc(css): + # first reacquire the GIL + after = rffi.aroundstate.after + if after: + after() + # similar to trackgcroot.py:pypy_asm_stackwalk, second part + from rpython.memory.gctransform import asmgcroot + old = rffi.cast(asmgcroot.ASM_FRAMEDATA_HEAD_PTR, css) + prev = old.prev + next = old.next + prev.next = next + next.prev = prev + + @staticmethod + @rgc.no_collect + def _release_gil_shadowstack(): + before = rffi.aroundstate.before + if before: + before() + + @staticmethod + @rgc.no_collect + def _reacquire_gil_shadowstack(): + after = rffi.aroundstate.after + if after: + after() + + _NOARG_FUNC = lltype.Ptr(lltype.FuncType([], lltype.Void)) + _CLOSESTACK_FUNC = lltype.Ptr(lltype.FuncType([rffi.LONGP], + lltype.Void)) + + def _build_release_gil(self, gcrootmap): + if gcrootmap.is_shadow_stack: + releasegil_func = llhelper(self._NOARG_FUNC, + self._release_gil_shadowstack) + reacqgil_func = llhelper(self._NOARG_FUNC, + self._reacquire_gil_shadowstack) + else: + releasegil_func = llhelper(self._CLOSESTACK_FUNC, + self._release_gil_asmgcc) + reacqgil_func = llhelper(self._CLOSESTACK_FUNC, + self._reacquire_gil_asmgcc) + self.releasegil_addr = self.cpu.cast_ptr_to_int(releasegil_func) + self.reacqgil_addr = self.cpu.cast_ptr_to_int(reacqgil_func) + def debug_bridge(descr_number, rawstart, codeendpos): diff --git a/rpython/jit/backend/llsupport/llmodel.py b/rpython/jit/backend/llsupport/llmodel.py --- a/rpython/jit/backend/llsupport/llmodel.py +++ b/rpython/jit/backend/llsupport/llmodel.py @@ -742,9 +742,6 @@ as_array[self.vtable_offset/WORD] = vtable return res - def bh_new_raw_buffer(self, size): - return lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') - def bh_classof(self, struct): struct = lltype.cast_opaque_ptr(rclass.OBJECTPTR, struct) result_adr = llmemory.cast_ptr_to_adr(struct.typeptr) diff --git a/rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py b/rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py --- a/rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py +++ b/rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py @@ -2,7 +2,6 @@ import weakref from rpython.rlib.jit import JitDriver, dont_look_inside from rpython.jit.backend.llsupport.test.zrpy_gc_test import run, get_entry, compile -from rpython.jit.backend.llsupport.test.ztranslation_test import fix_annotator_for_vrawbuffer class X(object): def __init__(self, x=0): @@ -32,8 +31,7 @@ g._dont_inline_ = True return g -def compile_boehm_test(monkeypatch): - fix_annotator_for_vrawbuffer(monkeypatch) +def compile_boehm_test(): myjitdriver = JitDriver(greens = [], reds = ['n', 'x']) @dont_look_inside def see(lst, n): diff --git a/rpython/jit/backend/llsupport/test/ztranslation_test.py b/rpython/jit/backend/llsupport/test/ztranslation_test.py --- a/rpython/jit/backend/llsupport/test/ztranslation_test.py +++ b/rpython/jit/backend/llsupport/test/ztranslation_test.py @@ -9,23 +9,10 @@ from rpython.jit.codewriter.policy import StopAtXPolicy -def fix_annotator_for_vrawbuffer(monkeypatch): - from rpython.rlib.nonconst import NonConstant - from rpython.jit.metainterp.optimizeopt.virtualize import VRawBufferValue - from rpython.jit.metainterp import warmspot - - def my_hook_for_tests(cpu): - # this is needed so that the annotator can see it - if NonConstant(False): - v = VRawBufferValue(cpu, None, -1, None, None) - monkeypatch.setattr(warmspot, 'hook_for_tests', my_hook_for_tests) - - class TranslationTest(CCompiledMixin): CPUClass = getcpuclass() - def test_stuff_translates(self, monkeypatch): - fix_annotator_for_vrawbuffer(monkeypatch) + def test_stuff_translates(self): # this is a basic test that tries to hit a number of features and their # translation: # - jitting of loops and bridges @@ -102,10 +89,9 @@ class TranslationTestCallAssembler(CCompiledMixin): CPUClass = getcpuclass() - def test_direct_assembler_call_translates(self, monkeypatch): + def test_direct_assembler_call_translates(self): """Test CALL_ASSEMBLER and the recursion limit""" from rpython.rlib.rstackovf import StackOverflow - fix_annotator_for_vrawbuffer(monkeypatch) class Thing(object): def __init__(self, val): @@ -183,8 +169,7 @@ class TranslationTestJITStats(CCompiledMixin): CPUClass = getcpuclass() - def test_jit_get_stats(self, monkeypatch): - fix_annotator_for_vrawbuffer(monkeypatch) + def test_jit_get_stats(self): driver = JitDriver(greens = [], reds = ['i']) def f(): @@ -207,8 +192,7 @@ class TranslationRemoveTypePtrTest(CCompiledMixin): CPUClass = getcpuclass() - def test_external_exception_handling_translates(self, monkeypatch): - fix_annotator_for_vrawbuffer(monkeypatch) + def test_external_exception_handling_translates(self): jitdriver = JitDriver(greens = [], reds = ['n', 'total']) class ImDone(Exception): diff --git a/rpython/jit/backend/model.py b/rpython/jit/backend/model.py --- a/rpython/jit/backend/model.py +++ b/rpython/jit/backend/model.py @@ -194,18 +194,11 @@ def typedescrof(self, TYPE): raise NotImplementedError - def unpack_arraydescr_size(self, arraydescr): - """ - Return basesize, itemsize, is_signed - """ - raise NotImplementedError - @staticmethod def cast_int_to_ptr(x, TYPE): x = llmemory.cast_int_to_adr(x) return llmemory.cast_adr_to_ptr(x, TYPE) - # ---------- the backend-dependent operations ---------- # lltype specific operations @@ -242,8 +235,6 @@ raise NotImplementedError def bh_newunicode(self, length): raise NotImplementedError - def bh_new_raw_buffer(self, size): - raise NotImplementedError def bh_arraylen_gc(self, array, arraydescr): raise NotImplementedError diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -367,69 +367,6 @@ else: self.wb_slowpath[withcards + 2 * withfloats] = rawstart - @staticmethod - @rgc.no_collect - def _release_gil_asmgcc(css): - # similar to trackgcroot.py:pypy_asm_stackwalk, first part - from rpython.memory.gctransform import asmgcroot - new = rffi.cast(asmgcroot.ASM_FRAMEDATA_HEAD_PTR, css) - next = asmgcroot.gcrootanchor.next - new.next = next - new.prev = asmgcroot.gcrootanchor - asmgcroot.gcrootanchor.next = new - next.prev = new - # and now release the GIL - before = rffi.aroundstate.before - if before: - before() - - @staticmethod - @rgc.no_collect - def _reacquire_gil_asmgcc(css): - # first reacquire the GIL - after = rffi.aroundstate.after - if after: - after() - # similar to trackgcroot.py:pypy_asm_stackwalk, second part - from rpython.memory.gctransform import asmgcroot - old = rffi.cast(asmgcroot.ASM_FRAMEDATA_HEAD_PTR, css) - prev = old.prev - next = old.next - prev.next = next - next.prev = prev - - @staticmethod - @rgc.no_collect - def _release_gil_shadowstack(): - before = rffi.aroundstate.before - if before: - before() - - @staticmethod - @rgc.no_collect - def _reacquire_gil_shadowstack(): - after = rffi.aroundstate.after - if after: - after() - - _NOARG_FUNC = lltype.Ptr(lltype.FuncType([], lltype.Void)) - _CLOSESTACK_FUNC = lltype.Ptr(lltype.FuncType([rffi.LONGP], - lltype.Void)) - - def _build_release_gil(self, gcrootmap): - if gcrootmap.is_shadow_stack: - releasegil_func = llhelper(self._NOARG_FUNC, - self._release_gil_shadowstack) - reacqgil_func = llhelper(self._NOARG_FUNC, - self._reacquire_gil_shadowstack) - else: - releasegil_func = llhelper(self._CLOSESTACK_FUNC, - self._release_gil_asmgcc) - reacqgil_func = llhelper(self._CLOSESTACK_FUNC, - self._reacquire_gil_asmgcc) - self.releasegil_addr = self.cpu.cast_ptr_to_int(releasegil_func) - self.reacqgil_addr = self.cpu.cast_ptr_to_int(reacqgil_func) - def assemble_loop(self, loopname, inputargs, operations, looptoken, log): '''adds the following attributes to looptoken: _ll_function_addr (address of the generated func, as an int) diff --git a/rpython/jit/codewriter/effectinfo.py b/rpython/jit/codewriter/effectinfo.py --- a/rpython/jit/codewriter/effectinfo.py +++ b/rpython/jit/codewriter/effectinfo.py @@ -76,14 +76,14 @@ # OS_MATH_SQRT = 100 # - OS_RAW_MALLOC_VARSIZE_CHAR = 110 + OS_RAW_MALLOC_VARSIZE = 110 OS_RAW_FREE = 111 OS_JIT_FORCE_VIRTUAL = 120 # for debugging: _OS_CANRAISE = set([OS_NONE, OS_STR2UNICODE, OS_LIBFFI_CALL, - OS_RAW_MALLOC_VARSIZE_CHAR, OS_JIT_FORCE_VIRTUAL]) + OS_RAW_MALLOC_VARSIZE, OS_JIT_FORCE_VIRTUAL]) def __new__(cls, readonly_descrs_fields, readonly_descrs_arrays, write_descrs_fields, write_descrs_arrays, diff --git a/rpython/jit/codewriter/jtransform.py b/rpython/jit/codewriter/jtransform.py --- a/rpython/jit/codewriter/jtransform.py +++ b/rpython/jit/codewriter/jtransform.py @@ -539,11 +539,9 @@ name += '_no_track_allocation' op1 = self.prepare_builtin_call(op, name, args, (TYPE,), TYPE) if name == 'raw_malloc_varsize': - ITEMTYPE = op.args[0].value.OF - if ITEMTYPE == lltype.Char: - return self._handle_oopspec_call(op1, args, - EffectInfo.OS_RAW_MALLOC_VARSIZE_CHAR, - EffectInfo.EF_CAN_RAISE) + return self._handle_oopspec_call(op1, args, + EffectInfo.OS_RAW_MALLOC_VARSIZE, + EffectInfo.EF_CAN_RAISE) return self.rewrite_op_direct_call(op1) def rewrite_op_malloc_varsize(self, op): diff --git a/rpython/jit/codewriter/test/test_jtransform.py b/rpython/jit/codewriter/test/test_jtransform.py --- a/rpython/jit/codewriter/test/test_jtransform.py +++ b/rpython/jit/codewriter/test/test_jtransform.py @@ -126,7 +126,7 @@ INT = lltype.Signed UNICHAR = lltype.UniChar FLOAT = lltype.Float - ARRAYPTR = rffi.CArrayPtr(lltype.Char) + ARRAYPTR = rffi.CArrayPtr(lltype.Signed) argtypes = { EI.OS_MATH_SQRT: ([FLOAT], FLOAT), EI.OS_STR2UNICODE:([PSTR], PUNICODE), @@ -143,7 +143,7 @@ EI.OS_UNIEQ_NONNULL_CHAR: ([PUNICODE, UNICHAR], INT), EI.OS_UNIEQ_CHECKNULL_CHAR: ([PUNICODE, UNICHAR], INT), EI.OS_UNIEQ_LENGTHOK: ([PUNICODE, PUNICODE], INT), - EI.OS_RAW_MALLOC_VARSIZE_CHAR: ([INT], ARRAYPTR), + EI.OS_RAW_MALLOC_VARSIZE: ([INT], ARRAYPTR), EI.OS_RAW_FREE: ([ARRAYPTR], lltype.Void), } argtypes = argtypes[oopspecindex] @@ -151,7 +151,7 @@ assert argtypes[1] == op.result.concretetype if oopspecindex == EI.OS_STR2UNICODE: assert extraeffect == EI.EF_ELIDABLE_CAN_RAISE - elif oopspecindex == EI.OS_RAW_MALLOC_VARSIZE_CHAR: + elif oopspecindex == EI.OS_RAW_MALLOC_VARSIZE: assert extraeffect == EI.EF_CAN_RAISE elif oopspecindex == EI.OS_RAW_FREE: assert extraeffect == EI.EF_CANNOT_RAISE @@ -161,7 +161,7 @@ def calldescr_canraise(self, calldescr): EI = effectinfo.EffectInfo - if calldescr == 'calldescr-%d' % EI.OS_RAW_MALLOC_VARSIZE_CHAR: + if calldescr == 'calldescr-%d' % EI.OS_RAW_MALLOC_VARSIZE: return True return False @@ -555,7 +555,7 @@ assert op1.args == [] def test_raw_malloc(): - S = rffi.CArray(lltype.Char) + S = rffi.CArray(lltype.Signed) v1 = varoftype(lltype.Signed) v = varoftype(lltype.Ptr(S)) flags = Constant({'flavor': 'raw'}, lltype.Void) @@ -566,7 +566,7 @@ assert op0.opname == 'residual_call_ir_i' assert op0.args[0].value == 'raw_malloc_varsize' # pseudo-function as a str assert (op0.args[-1] == 'calldescr-%d' % - effectinfo.EffectInfo.OS_RAW_MALLOC_VARSIZE_CHAR) + effectinfo.EffectInfo.OS_RAW_MALLOC_VARSIZE) assert op1.opname == '-live-' assert op1.args == [] @@ -608,7 +608,7 @@ assert op1.args == [] def test_raw_free(): - S = rffi.CArray(lltype.Char) + S = rffi.CArray(lltype.Signed) flags = Constant({'flavor': 'raw', 'track_allocation': True}, lltype.Void) op = SpaceOperation('free', [varoftype(lltype.Ptr(S)), flags], diff --git a/rpython/jit/metainterp/compile.py b/rpython/jit/metainterp/compile.py --- a/rpython/jit/metainterp/compile.py +++ b/rpython/jit/metainterp/compile.py @@ -15,7 +15,7 @@ from rpython.jit.metainterp import history, resume from rpython.jit.metainterp.optimize import InvalidLoop from rpython.jit.metainterp.inliner import Inliner -from rpython.jit.metainterp.resume import NUMBERING, PENDINGFIELDSP, ResumeDataDirectReader +from rpython.jit.metainterp.resume import NUMBERING, PENDINGFIELDSP from rpython.jit.codewriter import heaptracker, longlong def giveup(): @@ -656,9 +656,9 @@ class AllVirtuals: llopaque = True - cache = None - def __init__(self, cache): - self.cache = cache + list = [resume.ResumeDataDirectReader.virtual_default] # annotation hack + def __init__(self, list): + self.list = list def hide(self, cpu): ptr = cpu.ts.cast_instance_to_base_ref(self) return cpu.ts.cast_to_ref(ptr) @@ -682,9 +682,9 @@ from rpython.jit.metainterp.blackhole import resume_in_blackhole hidden_all_virtuals = metainterp_sd.cpu.get_savedata_ref(deadframe) obj = AllVirtuals.show(metainterp_sd.cpu, hidden_all_virtuals) - all_virtuals = obj.cache + all_virtuals = obj.list if all_virtuals is None: - all_virtuals = ResumeDataDirectReader.VirtualCache([], []) + all_virtuals = [] assert jitdriver_sd is self.jitdriver_sd resume_in_blackhole(metainterp_sd, jitdriver_sd, self, deadframe, all_virtuals) diff --git a/rpython/jit/metainterp/history.py b/rpython/jit/metainterp/history.py --- a/rpython/jit/metainterp/history.py +++ b/rpython/jit/metainterp/history.py @@ -191,6 +191,7 @@ def get_jitcode_for_class(self, oocls): return self.jitcodes[oocls] + class Const(AbstractValue): __slots__ = () diff --git a/rpython/jit/metainterp/optimizeopt/earlyforce.py b/rpython/jit/metainterp/optimizeopt/earlyforce.py --- a/rpython/jit/metainterp/optimizeopt/earlyforce.py +++ b/rpython/jit/metainterp/optimizeopt/earlyforce.py @@ -1,26 +1,15 @@ -from rpython.jit.codewriter.effectinfo import EffectInfo from rpython.jit.metainterp.optimizeopt.optimizer import Optimization from rpython.jit.metainterp.optimizeopt.vstring import VAbstractStringValue from rpython.jit.metainterp.resoperation import rop, ResOperation -def is_raw_free(op, opnum): - if opnum != rop.CALL: - return False - einfo = op.getdescr().get_extra_info() - return einfo.oopspecindex == EffectInfo.OS_RAW_FREE - - class OptEarlyForce(Optimization): def propagate_forward(self, op): opnum = op.getopnum() - if (opnum != rop.SETFIELD_GC and opnum != rop.SETARRAYITEM_GC and - opnum != rop.SETARRAYITEM_RAW and opnum != rop.QUASIIMMUT_FIELD and opnum != rop.SAME_AS and - opnum != rop.MARK_OPAQUE_PTR and - not is_raw_free(op, opnum)): + opnum != rop.MARK_OPAQUE_PTR): for arg in op.getarglist(): if arg in self.optimizer.values: diff --git a/rpython/jit/metainterp/optimizeopt/optimizer.py b/rpython/jit/metainterp/optimizeopt/optimizer.py --- a/rpython/jit/metainterp/optimizeopt/optimizer.py +++ b/rpython/jit/metainterp/optimizeopt/optimizer.py @@ -231,12 +231,6 @@ def setitem(self, index, value): raise NotImplementedError - def getitem_raw(self, offset, length, descr): - raise NotImplementedError - - def setitem_raw(self, offset, length, descr, value): - raise NotImplementedError - def getinteriorfield(self, index, ofs, default): raise NotImplementedError diff --git a/rpython/jit/metainterp/optimizeopt/rawbuffer.py b/rpython/jit/metainterp/optimizeopt/rawbuffer.py deleted file mode 100644 --- a/rpython/jit/metainterp/optimizeopt/rawbuffer.py +++ /dev/null @@ -1,134 +0,0 @@ -from rpython.rlib.debug import debug_start, debug_stop, debug_print -from rpython.rlib.objectmodel import compute_unique_id, we_are_translated - -class InvalidRawOperation(Exception): - pass - -class InvalidRawWrite(InvalidRawOperation): - pass - -class InvalidRawRead(InvalidRawOperation): - pass - -class RawBuffer(object): - def __init__(self, cpu, logops=None): - # the following lists represents the writes in the buffer: values[i] - # is the value of length lengths[i] stored at offset[i]. - # - # the invariant is that they are ordered by offset, and that - # offset[i]+length[i] <= offset[i+1], i.e. that the writes never - # overlaps - self.cpu = cpu - self.logops = logops - self.offsets = [] - self.lengths = [] - self.descrs = [] - self.values = [] - - def _get_memory(self): - """ - NOT_RPYTHON - for testing only - """ - return zip(self.offsets, self.lengths, self.descrs, self.values) - - def _repr_of_descr(self, descr): - if self.logops: - s = self.logops.repr_of_descr(descr) - else: - s = str(descr) - s += " at %d" % compute_unique_id(descr) - return s - - def _repr_of_value(self, value): - if not we_are_translated() and isinstance(value, str): - return value # for tests - if self.logops: - s = self.logops.repr_of_arg(value.box) - else: - s = str(value.box) - s += " at %d" % compute_unique_id(value.box) - return s - - def _dump_to_log(self): - debug_print("RawBuffer state") - debug_print("offset, length, descr, box") - debug_print("(box == None means that the value is still virtual)") - for i in range(len(self.offsets)): - descr = self._repr_of_descr(self.descrs[i]) - box = self._repr_of_value(self.values[i]) - debug_print("%d, %d, %s, %s" % (self.offsets[i], self.lengths[i], descr, box)) - - def _invalid_write(self, message, offset, length, descr, value): - debug_start('jit-log-rawbuffer') - debug_print('Invalid write: %s' % message) - debug_print(" offset: %d" % offset) - debug_print(" length: %d" % length) - debug_print(" descr: %s" % self._repr_of_descr(descr)) - debug_print(" value: %s" % self._repr_of_value(value)) - self._dump_to_log() - debug_stop('jit-log-rawbuffer') - raise InvalidRawWrite - - def _invalid_read(self, message, offset, length, descr): - debug_start('jit-log-rawbuffer') - debug_print('Invalid read: %s' % message) - debug_print(" offset: %d" % offset) - debug_print(" length: %d" % length) - debug_print(" descr: %s" % self._repr_of_descr(descr)) - self._dump_to_log() - debug_stop('jit-log-rawbuffer') - raise InvalidRawRead - - def _descrs_are_compatible(self, d1, d2): - # two arraydescrs are compatible if they have the same basesize, - # itemsize and sign, even if they are not identical - unpack = self.cpu.unpack_arraydescr_size - return unpack(d1) == unpack(d2) - - def write_value(self, offset, length, descr, value): - i = 0 - N = len(self.offsets) - while i < N: - if self.offsets[i] == offset: - if (length != self.lengths[i] or not - self._descrs_are_compatible(descr, self.descrs[i])): - # in theory we could add support for the cases in which - # the length or descr is different, but I don't think we - # need it in practice - self._invalid_write('length or descr not compatible', - offset, length, descr, value) - # update the value at this offset - self.values[i] = value - return - elif self.offsets[i] > offset: - break - i += 1 - # - if i < len(self.offsets) and offset+length > self.offsets[i]: - self._invalid_write("overlap with next bytes", - offset, length, descr, value) - if i > 0 and self.offsets[i-1]+self.lengths[i-1] > offset: - self._invalid_write("overlap with previous bytes", - offset, length, descr, value) - # insert a new value at offset - self.offsets.insert(i, offset) - self.lengths.insert(i, length) - self.descrs.insert(i, descr) - self.values.insert(i, value) - - def read_value(self, offset, length, descr): - i = 0 - N = len(self.offsets) - while i < N: - if self.offsets[i] == offset: - if (length != self.lengths[i] or - not self._descrs_are_compatible(descr, self.descrs[i])): - self._invalid_read('length or descr not compatible', - offset, length, descr) - return self.values[i] - i += 1 - # memory location not found: this means we are reading from - # uninitialized memory, give up the optimization - self._invalid_read('uninitialized memory', - offset, length, descr) diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py --- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py @@ -770,6 +770,8 @@ """ self.optimize_loop(ops, expected) + + def test_p123_simple(self): ops = """ [i1, p2, p3] @@ -1728,175 +1730,6 @@ # We cannot track virtuals that survive for more than two iterations. self.optimize_loop(ops, expected, preamble) - def test_virtual_raw_malloc(self): - ops = """ - [i1] - i2 = call('malloc', 10, descr=raw_malloc_descr) - setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) - i3 = getarrayitem_raw(i2, 0, descr=rawarraydescr) - call('free', i2, descr=raw_free_descr) - jump(i3) - """ - expected = """ - [i1] - jump(i1) - """ - self.optimize_loop(ops, expected) - - def test_virtual_raw_malloc_force(self): - ops = """ - [i1] - i2 = call('malloc', 10, descr=raw_malloc_descr) - setarrayitem_raw(i2, 0, i1, descr=rawarraydescr_char) - setarrayitem_raw(i2, 2, 456, descr=rawarraydescr_char) - setarrayitem_raw(i2, 1, 123, descr=rawarraydescr_char) - label('foo') # we expect the buffer to be forced *after* the label - escape(i2) - call('free', i2, descr=raw_free_descr) - jump(i1) - """ - expected = """ - [i1] - label('foo') - i2 = call('malloc', 10, descr=raw_malloc_descr) - setarrayitem_raw(i2, 0, i1, descr=rawarraydescr_char) - i3 = int_add(i2, 1) - setarrayitem_raw(i3, 0, 123, descr=rawarraydescr_char) - i4 = int_add(i2, 2) - setarrayitem_raw(i4, 0, 456, descr=rawarraydescr_char) - escape(i2) - call('free', i2, descr=raw_free_descr) - jump(i1) - """ - self.optimize_loop(ops, expected) - - def test_virtual_raw_malloc_invalid_write_force(self): - ops = """ - [i1] - i2 = call('malloc', 10, descr=raw_malloc_descr) - setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) - label('foo') # we expect the buffer to be forced *after* the label - setarrayitem_raw(i2, 2, 456, descr=rawarraydescr_char) # overlap! - call('free', i2, descr=raw_free_descr) - jump(i1) - """ - expected = """ - [i1] - label('foo') - i2 = call('malloc', 10, descr=raw_malloc_descr) - setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) - setarrayitem_raw(i2, 2, 456, descr=rawarraydescr_char) - call('free', i2, descr=raw_free_descr) - jump(i1) - """ - self.optimize_loop(ops, expected) - - def test_virtual_raw_malloc_invalid_read_force(self): - ops = """ - [i1] - i2 = call('malloc', 10, descr=raw_malloc_descr) - setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) - label('foo') # we expect the buffer to be forced *after* the label - i3 = getarrayitem_raw(i2, 0, descr=rawarraydescr_char) - call('free', i2, descr=raw_free_descr) - jump(i1) - """ - expected = """ - [i1] - label('foo') - i2 = call('malloc', 10, descr=raw_malloc_descr) - setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) - i3 = getarrayitem_raw(i2, 0, descr=rawarraydescr_char) - call('free', i2, descr=raw_free_descr) - jump(i1) - """ - self.optimize_loop(ops, expected) - - def test_virtual_raw_slice(self): - ops = """ - [i0, i1] - i2 = call('malloc', 10, descr=raw_malloc_descr) - setarrayitem_raw(i2, 0, 42, descr=rawarraydescr_char) - i3 = int_add(i2, 1) # get a slice of the original buffer - setarrayitem_raw(i3, 0, 4242, descr=rawarraydescr) # write to the slice - i4 = getarrayitem_raw(i2, 0, descr=rawarraydescr_char) - i5 = int_add(i2, 1) - i6 = getarrayitem_raw(i5, 0, descr=rawarraydescr) - call('free', i2, descr=raw_free_descr) - jump(i0, i1) - """ - expected = """ - [i0, i1] - jump(i0, i1) - """ - self.optimize_loop(ops, expected) - - def test_virtual_raw_slice_of_a_raw_slice(self): - ops = """ - [i0, i1] - i2 = call('malloc', 10, descr=raw_malloc_descr) - i3 = int_add(i2, 1) # get a slice of the original buffer - i4 = int_add(i3, 1) # get a slice of a slice - setarrayitem_raw(i4, 0, i1, descr=rawarraydescr_char) # write to the slice - i5 = getarrayitem_raw(i2, 2, descr=rawarraydescr_char) - call('free', i2, descr=raw_free_descr) - jump(i0, i5) - """ - expected = """ - [i0, i1] - jump(i0, i1) - """ - self.optimize_loop(ops, expected) - - def test_virtual_raw_slice_force(self): - ops = """ - [i0, i1] - i2 = call('malloc', 10, descr=raw_malloc_descr) - setarrayitem_raw(i2, 0, 42, descr=rawarraydescr_char) - i3 = int_add(i2, 1) # get a slice of the original buffer - setarrayitem_raw(i3, 4, 4242, descr=rawarraydescr_char) # write to the slice - label('foo') - escape(i3) - jump(i0, i1) - """ - expected = """ - [i0, i1] - label('foo') - # these ops are generated by VirtualRawBufferValue._really_force - i2 = call('malloc', 10, descr=raw_malloc_descr) - setarrayitem_raw(i2, 0, 42, descr=rawarraydescr_char) - i3 = int_add(i2, 5) # 1+4*sizeof(char) - setarrayitem_raw(i3, 0, 4242, descr=rawarraydescr_char) - # this is generated by VirtualRawSliceValue._really_force - i4 = int_add(i2, 1) - escape(i4) - jump(i0, i1) - """ - self.optimize_loop(ops, expected) - - def test_virtual_raw_malloc_virtualstate(self): - ops = """ - [i0] - i1 = getarrayitem_raw(i0, 0, descr=rawarraydescr) - i2 = int_add(i1, 1) - call('free', i0, descr=raw_free_descr) - i3 = call('malloc', 10, descr=raw_malloc_descr) - setarrayitem_raw(i3, 0, i2, descr=rawarraydescr) - label('foo') - jump(i3) - """ - expected = """ - [i0] - i1 = getarrayitem_raw(i0, 0, descr=rawarraydescr) - i2 = int_add(i1, 1) - call('free', i0, descr=raw_free_descr) - label('foo') - i3 = call('malloc', 10, descr=raw_malloc_descr) - setarrayitem_raw(i3, 0, i2, descr=rawarraydescr) - jump(i3) - """ - self.optimize_loop(ops, expected) - def test_duplicate_getfield_1(self): ops = """ [p1, p2] diff --git a/rpython/jit/metainterp/optimizeopt/test/test_rawbuffer.py b/rpython/jit/metainterp/optimizeopt/test/test_rawbuffer.py deleted file mode 100644 --- a/rpython/jit/metainterp/optimizeopt/test/test_rawbuffer.py +++ /dev/null @@ -1,90 +0,0 @@ -import py -from rpython.jit.metainterp.optimizeopt.rawbuffer import (InvalidRawWrite, - InvalidRawRead, RawBuffer) - -class FakeCPU(object): - def unpack_arraydescr_size(self, descr): - return descr, 'foo', 'bar' - -def test_write_value(): - buf = RawBuffer(FakeCPU()) - buf.write_value(8, 4, 'descr3', 'three') - buf.write_value(0, 4, 'descr1', 'one') - buf.write_value(4, 2, 'descr2', 'two') - buf.write_value(12, 2, 'descr4', 'four') - assert buf._get_memory() == [ - ( 0, 4, 'descr1', 'one'), - ( 4, 2, 'descr2', 'two'), - ( 8, 4, 'descr3', 'three'), - (12, 2, 'descr4', 'four'), - ] - # - -def test_write_value_update(): - buf = RawBuffer(FakeCPU()) - buf.write_value(0, 4, 'descr', 'one') - buf.write_value(4, 2, 'descr', 'two') - buf.write_value(0, 4, 'descr', 'ONE') - assert buf._get_memory() == [ - ( 0, 4, 'descr', 'ONE'), - ( 4, 2, 'descr', 'two'), - ] - -def test_write_value_invalid_length(): - buf = RawBuffer(FakeCPU()) - buf.write_value(0, 4, 'descr1', 'one') - with py.test.raises(InvalidRawWrite): - buf.write_value(0, 5, 'descr1', 'two') - with py.test.raises(InvalidRawWrite): - buf.write_value(0, 4, 'descr2', 'two') - - -def test_write_value_overlapping_next(): - buf = RawBuffer(FakeCPU()) - buf.write_value(0, 4, 'descr', 'one') - buf.write_value(6, 4, 'descr', 'two') - with py.test.raises(InvalidRawWrite): - buf.write_value(4, 4, 'descr', 'three') - -def test_write_value_overlapping_prev(): - buf = RawBuffer(FakeCPU()) - buf.write_value(0, 4, 'descr', 'one') - with py.test.raises(InvalidRawWrite): - buf.write_value(2, 1, 'descr', 'two') - -def test_read_value(): - buf = RawBuffer(FakeCPU()) - buf.write_value(0, 4, 'descr', 'one') - buf.write_value(4, 4, 'descr', 'two') - assert buf.read_value(0, 4, 'descr') == 'one' - assert buf.read_value(4, 4, 'descr') == 'two' - with py.test.raises(InvalidRawRead): - buf.read_value(0, 2, 'descr') - with py.test.raises(InvalidRawRead): - buf.read_value(8, 2, 'descr') - with py.test.raises(InvalidRawRead): - buf.read_value(0, 4, 'another descr') - -def test_unpack_descrs(): - ArrayS_8_1 = object() - ArrayS_8_2 = object() - ArrayU_8 = object() - - class FakeCPU(object): - def unpack_arraydescr_size(self, descr): - if descr in (ArrayS_8_1, ArrayS_8_2): - return 0, 8, True - return 0, 8, False - - buf = RawBuffer(FakeCPU()) - buf.write_value(0, 4, ArrayS_8_1, 'one') - assert buf.read_value(0, 4, ArrayS_8_1) == 'one' - assert buf.read_value(0, 4, ArrayS_8_2) == 'one' # with a non-identical descr - # - buf.write_value(0, 4, ArrayS_8_2, 'two') # with a non-identical descr - assert buf.read_value(0, 4, ArrayS_8_1) == 'two' - # - with py.test.raises(InvalidRawRead): - buf.read_value(0, 4, ArrayU_8) - with py.test.raises(InvalidRawWrite): - buf.write_value(0, 4, ArrayU_8, 'three') diff --git a/rpython/jit/metainterp/optimizeopt/test/test_util.py b/rpython/jit/metainterp/optimizeopt/test/test_util.py --- a/rpython/jit/metainterp/optimizeopt/test/test_util.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_util.py @@ -196,15 +196,6 @@ EffectInfo.EF_CANNOT_RAISE, oopspecindex=EffectInfo.OS_ARRAYCOPY)) - raw_malloc_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, - EffectInfo([], [], [], [], - EffectInfo.EF_CAN_RAISE, - oopspecindex=EffectInfo.OS_RAW_MALLOC_VARSIZE_CHAR)) - raw_free_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, - EffectInfo([], [], [], [], - EffectInfo.EF_CANNOT_RAISE, - oopspecindex=EffectInfo.OS_RAW_FREE)) - # array of structs (complex data) complexarray = lltype.GcArray( @@ -217,12 +208,6 @@ complexrealdescr = cpu.interiorfielddescrof(complexarray, "real") compleximagdescr = cpu.interiorfielddescrof(complexarray, "imag") - rawarraydescr = cpu.arraydescrof(lltype.Array(lltype.Signed, - hints={'nolength': True})) - rawarraydescr_char = cpu.arraydescrof(lltype.Array(lltype.Char, - hints={'nolength': True})) - - for _name, _os in [ ('strconcatdescr', 'OS_STR_CONCAT'), ('strslicedescr', 'OS_STR_SLICE'), diff --git a/rpython/jit/metainterp/optimizeopt/virtualize.py b/rpython/jit/metainterp/optimizeopt/virtualize.py --- a/rpython/jit/metainterp/optimizeopt/virtualize.py +++ b/rpython/jit/metainterp/optimizeopt/virtualize.py @@ -6,9 +6,7 @@ from rpython.jit.metainterp.optimizeopt import optimizer from rpython.jit.metainterp.optimizeopt.optimizer import OptValue, REMOVED from rpython.jit.metainterp.optimizeopt.util import (make_dispatcher_method, - descrlist_dict, sort_descrs) - -from rpython.jit.metainterp.optimizeopt.rawbuffer import RawBuffer, InvalidRawOperation + descrlist_dict, sort_descrs) from rpython.jit.metainterp.resoperation import rop, ResOperation from rpython.rlib.objectmodel import we_are_translated @@ -238,36 +236,8 @@ def _get_descr(self): return self.structdescr -class AbstractVArrayValue(AbstractVirtualValue): - """ - Base class for VArrayValue (for normal GC arrays) and VRawBufferValue (for - malloc()ed memory) - """ - def getlength(self): - return len(self._items) - - def get_item_value(self, i): - raise NotImplementedError - - def set_item_value(self, i, newval): - raise NotImplementedError - - def get_args_for_fail(self, modifier): - if self.box is None and not modifier.already_seen_virtual(self.keybox): - # checks for recursion: it is False unless - # we have already seen the very same keybox - itemboxes = [] - for i in range(self.getlength()): - itemvalue = self.get_item_value(i) - itemboxes.append(itemvalue.get_key_box()) - modifier.register_virtual_fields(self.keybox, itemboxes) - for i in range(self.getlength()): - itemvalue = self.get_item_value(i) - itemvalue.get_args_for_fail(modifier) - - -class VArrayValue(AbstractVArrayValue): +class VArrayValue(AbstractVirtualValue): def __init__(self, arraydescr, constvalue, size, keybox, source_op=None): AbstractVirtualValue.__init__(self, keybox, source_op) @@ -278,12 +248,6 @@ def getlength(self): return len(self._items) - def get_item_value(self, i): - return self._items[i] - - def set_item_value(self, i, newval): - self._items[i] = newval - def getitem(self, index): res = self._items[index] return res @@ -293,16 +257,11 @@ self._items[index] = itemvalue def force_at_end_of_preamble(self, already_forced, optforce): - # note that this method is on VArrayValue instead of - # AbstractVArrayValue because we do not want to support virtualstate - # for rawbuffers for now if self in already_forced: return self already_forced[self] = self - for index in range(self.getlength()): - itemval = self.get_item_value(index) - itemval = itemval.force_at_end_of_preamble(already_forced, optforce) - self.set_item_value(index, itemval) + for index in range(len(self._items)): + self._items[index] = self._items[index].force_at_end_of_preamble(already_forced, optforce) return self def _really_force(self, optforce): @@ -322,16 +281,29 @@ descr=self.arraydescr) optforce.emit_operation(op) + def get_args_for_fail(self, modifier): + if self.box is None and not modifier.already_seen_virtual(self.keybox): + # checks for recursion: it is False unless + # we have already seen the very same keybox + itemboxes = [] + for itemvalue in self._items: + itemboxes.append(itemvalue.get_key_box()) + modifier.register_virtual_fields(self.keybox, itemboxes) + for itemvalue in self._items: + itemvalue.get_args_for_fail(modifier) + def _make_virtual(self, modifier): return modifier.make_varray(self.arraydescr) - class VArrayStructValue(AbstractVirtualValue): def __init__(self, arraydescr, size, keybox, source_op=None): AbstractVirtualValue.__init__(self, keybox, source_op) self.arraydescr = arraydescr self._items = [{} for _ in xrange(size)] + def getlength(self): + return len(self._items) + def getinteriorfield(self, index, ofs, default): return self._items[index].get(ofs, default) @@ -391,90 +363,6 @@ return modifier.make_varraystruct(self.arraydescr, self._get_list_of_descrs()) -class VRawBufferValue(AbstractVArrayValue): - - def __init__(self, cpu, logops, size, keybox, source_op): - AbstractVirtualValue.__init__(self, keybox, source_op) - # note that size is unused, because we assume that the buffer is big - # enough to write/read everything we need. If it's not, it's undefined - # behavior anyway, although in theory we could probably detect such - # cases here - self.size = size - self.buffer = RawBuffer(cpu, logops) - - def getlength(self): - return len(self.buffer.values) - - def get_item_value(self, i): - return self.buffer.values[i] - - def set_item_value(self, i, newval): - self.buffer.values[i] = newval - - def getitem_raw(self, offset, length, descr): - return self.buffer.read_value(offset, length, descr) - - def setitem_raw(self, offset, length, descr, value): - self.buffer.write_value(offset, length, descr, value) - - def _really_force(self, optforce): - op = self.source_op - assert op is not None - if not we_are_translated(): - op.name = 'FORCE ' + self.source_op.name - optforce.emit_operation(self.source_op) - self.box = box = self.source_op.result - for i in range(len(self.buffer.offsets)): - # get a pointer to self.box+offset - offset = self.buffer.offsets[i] - if offset == 0: - arraybox = self.box - else: - arraybox = BoxInt() - op = ResOperation(rop.INT_ADD, - [self.box, ConstInt(offset)], arraybox) - optforce.emit_operation(op) - # - # write the value - descr = self.buffer.descrs[i] - itemvalue = self.buffer.values[i] - itembox = itemvalue.force_box(optforce) - op = ResOperation(rop.SETARRAYITEM_RAW, - [arraybox, ConstInt(0), itembox], None, From noreply at buildbot.pypy.org Sun Apr 14 01:16:51 2013 From: noreply at buildbot.pypy.org (alex_gaynor) Date: Sun, 14 Apr 2013 01:16:51 +0200 (CEST) Subject: [pypy-commit] pypy virtualref-virtualizable: fix types Message-ID: <20130413231651.0D4051C1495@cobra.cs.uni-duesseldorf.de> Author: Alex Gaynor Branch: virtualref-virtualizable Changeset: r63327:1f25f6e40624 Date: 2013-04-13 16:00 -0700 http://bitbucket.org/pypy/pypy/changeset/1f25f6e40624/ Log: fix types diff --git a/rpython/jit/codewriter/jtransform.py b/rpython/jit/codewriter/jtransform.py --- a/rpython/jit/codewriter/jtransform.py +++ b/rpython/jit/codewriter/jtransform.py @@ -1753,11 +1753,10 @@ return SpaceOperation('libffi_save_result_%s' % kind, op.args[1:], None) def rewrite_op_jit_force_virtual(self, op): - return [SpaceOperation('-live-', [], None), self._do_builtin_call(op)] + return [SpaceOperation('-live-', [], None)] + self._do_builtin_call(op) def rewrite_op_jit_is_virtual(self, op): - raise Exception, ( - "'vref.virtual' should not be used from jit-visible code") + raise Exception("'vref.virtual' should not be used from jit-visible code") def rewrite_op_jit_force_virtualizable(self, op): # this one is for virtualizables From noreply at buildbot.pypy.org Sun Apr 14 01:25:43 2013 From: noreply at buildbot.pypy.org (bivab) Date: Sun, 14 Apr 2013 01:25:43 +0200 (CEST) Subject: [pypy-commit] pypy default: kill tabs Message-ID: <20130413232543.3D3B61C1495@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63328:f2e960fec852 Date: 2013-04-14 01:25 +0200 http://bitbucket.org/pypy/pypy/changeset/f2e960fec852/ Log: kill tabs diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -1291,8 +1291,8 @@ self._emit_call(imm(self.releasegil_addr), [], fcond) def call_reacquire_gil(self, gcrootmap, save_loc, regalloc, fcond): - # save the previous result into the stack temporarily, in case it is in - # a caller saved register. + # save the previous result into the stack temporarily, in case it is in + # a caller saved register. # NOTE: like with call_release_gil(), we assume that we don't need to # save vfp regs in this case. Besides the result location regs_to_save = [] diff --git a/rpython/jit/backend/arm/regalloc.py b/rpython/jit/backend/arm/regalloc.py --- a/rpython/jit/backend/arm/regalloc.py +++ b/rpython/jit/backend/arm/regalloc.py @@ -554,9 +554,9 @@ return self._prepare_call(op) def _prepare_call(self, op, force_store=[], save_all_regs=False): - args = [None] * (op.numargs()+1) + args = [None] * (op.numargs() + 1) for i in range(op.numargs()): - args[i+1] = self.loc(op.getarg(i)) + args[i + 1] = self.loc(op.getarg(i)) # spill variables that need to be saved around calls self.vfprm.before_call(save_all_regs=save_all_regs) if not save_all_regs: From noreply at buildbot.pypy.org Sun Apr 14 01:40:08 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Sun, 14 Apr 2013 01:40:08 +0200 (CEST) Subject: [pypy-commit] pypy py3k: test_capi expects a fatal error when PyThreadState_Get would have been NULL Message-ID: <20130413234008.8B0DA1C0250@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63329:0ac0a778e15b Date: 2013-04-13 16:36 -0700 http://bitbucket.org/pypy/pypy/changeset/0ac0a778e15b/ Log: test_capi expects a fatal error when PyThreadState_Get would have been NULL diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py --- a/pypy/module/cpyext/api.py +++ b/pypy/module/cpyext/api.py @@ -651,12 +651,13 @@ lambda space: init_capsule(), ]) from pypy.module.posix.interp_posix import add_fork_hook - if translating: - reinit_tls = rffi.llexternal('PyThread_ReInitTLS', [], lltype.Void, - compilation_info=eci) - else: - reinit_tls = rffi.llexternal('PyPyThread_ReInitTLS', [], lltype.Void, - compilation_info=eci) + prefix = 'Py' if translating else 'PyPy' + reinit_tls = rffi.llexternal(prefix + 'Thread_ReInitTLS', [], lltype.Void, + compilation_info=eci) + global py_fatalerror + py_fatalerror = rffi.llexternal(prefix + '_FatalError', + [CONST_STRING], lltype.Void, + compilation_info=eci) add_fork_hook('child', reinit_tls) def init_function(func): diff --git a/pypy/module/cpyext/include/pythonrun.h b/pypy/module/cpyext/include/pythonrun.h --- a/pypy/module/cpyext/include/pythonrun.h +++ b/pypy/module/cpyext/include/pythonrun.h @@ -6,7 +6,7 @@ extern "C" { #endif - void Py_FatalError(const char *msg); +PyAPI_FUNC(void) Py_FatalError(const char *message); /* the -3 option will probably not be implemented */ #define Py_Py3kWarningFlag 0 diff --git a/pypy/module/cpyext/pystate.py b/pypy/module/cpyext/pystate.py --- a/pypy/module/cpyext/pystate.py +++ b/pypy/module/cpyext/pystate.py @@ -161,7 +161,11 @@ @cpython_api([], PyThreadState, error=CANNOT_FAIL) def PyThreadState_Get(space): state = space.fromcache(InterpreterState) - return state.get_thread_state(space) + ts = state.get_thread_state(space) + if not ts: + from pypy.module.cpyext.api import py_fatalerror + py_fatalerror("PyThreadState_Get: no current thread") + return ts @cpython_api([], PyObject, error=CANNOT_FAIL) def PyThreadState_GetDict(space): From noreply at buildbot.pypy.org Sun Apr 14 01:40:09 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Sun, 14 Apr 2013 01:40:09 +0200 (CEST) Subject: [pypy-commit] pypy py3k: o bring over the rest of the _testcapi skips from default Message-ID: <20130413234009.ED86F1C0250@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63330:16f053aecc5d Date: 2013-04-13 16:38 -0700 http://bitbucket.org/pypy/pypy/changeset/16f053aecc5d/ Log: o bring over the rest of the _testcapi skips from default o skip test_{Z,u}_code too as we currently lack PY_SSIZE_T_CLEAN support diff --git a/lib-python/3/test/test_capi.py b/lib-python/3/test/test_capi.py --- a/lib-python/3/test/test_capi.py +++ b/lib-python/3/test/test_capi.py @@ -16,6 +16,17 @@ threading = None import _testcapi +skips = [] +if support.check_impl_detail(pypy=True): + skips += [ + 'test_Z_code', # test_{Z,u}_code require PY_SSIZE_T_CLEAN support + 'test_u_code', + 'test_broken_memoryview', + 'test_capsule', + 'test_lazy_hash_inheritance', + 'test_widechar', + 'TestThreadState' + ] def testfunction(self): """some doc""" @@ -198,7 +209,7 @@ support.run_unittest(CAPITest, TestPendingCalls, Test6012, EmbeddingTest) for name in dir(_testcapi): - if name.startswith('test_'): + if name.startswith('test_') and name not in skips: test = getattr(_testcapi, name) if support.verbose: print("internal", name) @@ -222,7 +233,7 @@ raise support.TestFailed( "Couldn't find main thread correctly in the list") - if threading: + if threading and 'TestThreadState' not in skips: import _thread import time TestThreadState() From noreply at buildbot.pypy.org Sun Apr 14 03:24:27 2013 From: noreply at buildbot.pypy.org (alex_gaynor) Date: Sun, 14 Apr 2013 03:24:27 +0200 (CEST) Subject: [pypy-commit] pypy virtualref-virtualizable: merged default in Message-ID: <20130414012427.ED9B91C1559@cobra.cs.uni-duesseldorf.de> Author: Alex Gaynor Branch: virtualref-virtualizable Changeset: r63331:927411444d44 Date: 2013-04-13 18:21 -0700 http://bitbucket.org/pypy/pypy/changeset/927411444d44/ Log: merged default in diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -1291,8 +1291,8 @@ self._emit_call(imm(self.releasegil_addr), [], fcond) def call_reacquire_gil(self, gcrootmap, save_loc, regalloc, fcond): - # save the previous result into the stack temporarily, in case it is in - # a caller saved register. + # save the previous result into the stack temporarily, in case it is in + # a caller saved register. # NOTE: like with call_release_gil(), we assume that we don't need to # save vfp regs in this case. Besides the result location regs_to_save = [] diff --git a/rpython/jit/backend/arm/regalloc.py b/rpython/jit/backend/arm/regalloc.py --- a/rpython/jit/backend/arm/regalloc.py +++ b/rpython/jit/backend/arm/regalloc.py @@ -554,9 +554,9 @@ return self._prepare_call(op) def _prepare_call(self, op, force_store=[], save_all_regs=False): - args = [None] * (op.numargs()+1) + args = [None] * (op.numargs() + 1) for i in range(op.numargs()): - args[i+1] = self.loc(op.getarg(i)) + args[i + 1] = self.loc(op.getarg(i)) # spill variables that need to be saved around calls self.vfprm.before_call(save_all_regs=save_all_regs) if not save_all_regs: From noreply at buildbot.pypy.org Sun Apr 14 03:24:29 2013 From: noreply at buildbot.pypy.org (alex_gaynor) Date: Sun, 14 Apr 2013 03:24:29 +0200 (CEST) Subject: [pypy-commit] pypy virtualref-virtualizable: fix test Message-ID: <20130414012429.4F1611C23C8@cobra.cs.uni-duesseldorf.de> Author: Alex Gaynor Branch: virtualref-virtualizable Changeset: r63332:bf771453745d Date: 2013-04-13 18:24 -0700 http://bitbucket.org/pypy/pypy/changeset/bf771453745d/ Log: fix test diff --git a/rpython/jit/codewriter/jtransform.py b/rpython/jit/codewriter/jtransform.py --- a/rpython/jit/codewriter/jtransform.py +++ b/rpython/jit/codewriter/jtransform.py @@ -1753,7 +1753,12 @@ return SpaceOperation('libffi_save_result_%s' % kind, op.args[1:], None) def rewrite_op_jit_force_virtual(self, op): - return [SpaceOperation('-live-', [], None)] + self._do_builtin_call(op) + op0 = SpaceOperation('-live-', [], None) + op1 = self._do_builtin_call(op) + if isinstance(op, list): + return [op0] + op1 + else: + return [op0, op1] def rewrite_op_jit_is_virtual(self, op): raise Exception("'vref.virtual' should not be used from jit-visible code") diff --git a/rpython/jit/codewriter/test/test_flatten.py b/rpython/jit/codewriter/test/test_flatten.py --- a/rpython/jit/codewriter/test/test_flatten.py +++ b/rpython/jit/codewriter/test/test_flatten.py @@ -689,6 +689,7 @@ self.encoding_test(f, [], """ new_with_vtable -> %r0 virtual_ref %r0 -> %r1 + -live- residual_call_r_r $<* fn jit_force_virtual>, R[%r1], -> %r2 ref_return %r2 """, transform=True, cc=FakeCallControlWithVRefInfo()) From noreply at buildbot.pypy.org Sun Apr 14 03:58:16 2013 From: noreply at buildbot.pypy.org (alex_gaynor) Date: Sun, 14 Apr 2013 03:58:16 +0200 (CEST) Subject: [pypy-commit] pypy virtualref-virtualizable: really fix tests Message-ID: <20130414015816.C3C991C070B@cobra.cs.uni-duesseldorf.de> Author: Alex Gaynor Branch: virtualref-virtualizable Changeset: r63333:f2257f212284 Date: 2013-04-13 18:58 -0700 http://bitbucket.org/pypy/pypy/changeset/f2257f212284/ Log: really fix tests diff --git a/rpython/jit/codewriter/jtransform.py b/rpython/jit/codewriter/jtransform.py --- a/rpython/jit/codewriter/jtransform.py +++ b/rpython/jit/codewriter/jtransform.py @@ -1755,7 +1755,7 @@ def rewrite_op_jit_force_virtual(self, op): op0 = SpaceOperation('-live-', [], None) op1 = self._do_builtin_call(op) - if isinstance(op, list): + if isinstance(op1, list): return [op0] + op1 else: return [op0, op1] From noreply at buildbot.pypy.org Sun Apr 14 17:44:22 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sun, 14 Apr 2013 17:44:22 +0200 (CEST) Subject: [pypy-commit] pypy stm-gc-2: in-progress Message-ID: <20130414154422.E040E1C05C8@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: stm-gc-2 Changeset: r63334:064ecad6af6b Date: 2013-04-13 16:01 +0200 http://bitbucket.org/pypy/pypy/changeset/064ecad6af6b/ Log: in-progress diff --git a/rpython/memory/gc/stmtls.py b/rpython/memory/gc/stmtls.py --- a/rpython/memory/gc/stmtls.py +++ b/rpython/memory/gc/stmtls.py @@ -29,7 +29,7 @@ nontranslated_dict = {} - def __init__(self, gc): + def __init__(self, gc, StmGCThreadLocalAllocator=None): debug_start("gc-init") self.gc = gc self.stm_operations = self.gc.stm_operations @@ -41,6 +41,9 @@ llmemory.Address) self.adr_of_stack_top = llop.gc_adr_of_root_stack_top( llmemory.Address) + if StmGCThreadLocalAllocator is None: + from rpython.memory.gc.stmshared import StmGCThreadLocalAllocator + self.StmGCThreadLocalAllocator = StmGCThreadLocalAllocator # # --- current position, or NULL when mallocs are forbidden self.nursery_free = NULL @@ -59,8 +62,8 @@ self.nursery_top = self.nursery_stop # # --- a thread-local allocator for the shared area - from rpython.memory.gc.stmshared import StmGCThreadLocalAllocator - self.sharedarea_tls = StmGCThreadLocalAllocator(self.gc.sharedarea) + self.sharedarea_tls = self.StmGCThreadLocalAllocator( + self.gc.sharedarea) # --- the LOCAL objects which are weakrefs. They are also listed # in the appropriate place, like sharedarea_tls, if needed. self.local_weakrefs = self.AddressStack() @@ -196,9 +199,9 @@ self.detect_flag_combination = -1 # # Move away the previous sharedarea_tls and start a new one. - from rpython.memory.gc.stmshared import StmGCThreadLocalAllocator previous_sharedarea_tls = self.sharedarea_tls - self.sharedarea_tls = StmGCThreadLocalAllocator(self.gc.sharedarea) + self.sharedarea_tls = self.StmGCThreadLocalAllocator( + self.gc.sharedarea) # # List of LOCAL objects pending a visit. Note that no GLOBAL # object can at any point contain a reference to a LOCAL object. @@ -268,16 +271,17 @@ if not self.nursery_free: fatalerror("malloc in a non-main thread but outside a transaction") if llmemory.raw_malloc_usage(size) > self.nursery_size // 8 * 7: - fatalerror("object too large to ever fit in the nursery") - self.local_collection() - free = self.nursery_free - top = self.nursery_top - if (top - free) < llmemory.raw_malloc_usage(size): - # try again - self.local_collection(run_finalizers=False) - ll_assert(self.local_nursery_is_empty(), "nursery must be empty [0]") + fatalerror("XXX object too large to ever fit in the nursery") + self.stm_operations.should_break_transaction() + step = 0 + while True: free = self.nursery_free - return free + top = self.nursery_top + if (top - free) >= llmemory.raw_malloc_usage(size): + return free + ll_assert(step < 2, "nursery must be empty [0]") + self.local_collection(run_finalizers=(step==0)) + step += 1 def is_in_nursery(self, addr): ll_assert(llmemory.cast_adr_to_int(addr) & 1 == 0, diff --git a/rpython/memory/gc/test/test_stmshared.py b/rpython/memory/gc/test/test_stmshared.py --- a/rpython/memory/gc/test/test_stmshared.py +++ b/rpython/memory/gc/test/test_stmshared.py @@ -55,3 +55,21 @@ gc.set_size(obj, 3*WORD) thl1.free_object(obj) thl1.delete() + +def test_allocation_is_thread_local(): + gc = FakeGC() + shared = StmGCSharedArea(gc, 10*WORD, 2*WORD) + shared.setup() + thl1 = StmGCThreadLocalAllocator(shared) + thl2 = StmGCThreadLocalAllocator(shared) + # + assert len(thl1._seen_pages) == 0 + thl1.malloc_object(2*WORD) + assert len(thl1._seen_pages) == 1 + # + assert len(thl2._seen_pages) == 0 + thl2.malloc_object(2*WORD) + assert len(thl2._seen_pages) == 1 + # + thl1.delete() + thl2.delete() diff --git a/rpython/memory/gc/test/test_stmtls.py b/rpython/memory/gc/test/test_stmtls.py --- a/rpython/memory/gc/test/test_stmtls.py +++ b/rpython/memory/gc/test/test_stmtls.py @@ -20,10 +20,45 @@ pass def del_tls(self, tlsaddr): pass + def should_break_transaction(self): + return False class FakeSharedArea: pass +class FakeStmGCTL: + def __init__(self, stmshared): + assert isinstance(stmshared, FakeSharedArea) + self.gc = stmshared.gc + self.chained_list = NULL + + def malloc_object_addr(self, totalsize): + return llarena.arena_malloc(llmemory.raw_malloc_usage(totalsize), 0) + + def add_regular(self, obj): + self.gc.set_obj_revision(obj, self.chained_list) + self.chained_list = obj + + def free_object(self, adr2): + adr1 = adr2 - self.gc.gcheaderbuilder.size_gc_header + llarena.arena_free(llarena.getfakearenaaddress(adr1)) + + def free_and_clear(self): + obj = self.chained_list + self.chained_list = NULL + while obj: + next = self.gc.obj_revision(obj) + self.free_object(obj) + obj = next + + def free_and_clear_list(self, lst): + while lst.non_empty(): + self.free_object(lst.pop()) + + def delete(self): + del self.gc + del self.chained_list + class FakeRootWalker: STACK_DEPTH = 200 prebuilt_nongc = () @@ -111,8 +146,8 @@ def setup_method(self, meth): self.gc = FakeGC() self.gc.sharedarea.gc = self.gc - self.gctls_main = StmGCTLS(self.gc) - self.gctls_thrd = StmGCTLS(self.gc) + self.gctls_main = StmGCTLS(self.gc, FakeStmGCTL) + self.gctls_thrd = StmGCTLS(self.gc, FakeStmGCTL) self.gc.main_thread_tls = self.gctls_main self.gctls_main.start_transaction() From noreply at buildbot.pypy.org Sun Apr 14 17:44:24 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sun, 14 Apr 2013 17:44:24 +0200 (CEST) Subject: [pypy-commit] pypy default: Bah? Another version of gcc 4.8 writes "rep; ret" instead of "rep ret". Message-ID: <20130414154424.347371C131F@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63335:8463b9cbe114 Date: 2013-04-14 17:46 +0200 http://bitbucket.org/pypy/pypy/changeset/8463b9cbe114/ Log: Bah? Another version of gcc 4.8 writes "rep; ret" instead of "rep ret". diff --git a/rpython/translator/c/gcc/trackgcroot.py b/rpython/translator/c/gcc/trackgcroot.py --- a/rpython/translator/c/gcc/trackgcroot.py +++ b/rpython/translator/c/gcc/trackgcroot.py @@ -184,6 +184,8 @@ continue self.currentlineno = lineno insn = [] + if line.startswith('\trep;'): + line = '\t'+line[5:].lstrip() match = self.r_insn.match(line) if self.r_bottom_marker.match(line): @@ -665,7 +667,7 @@ return InsnRet(self.CALLEE_SAVE_REGISTERS) def visit_rep(self, line): - # 'rep ret': bad reasons for this bogus 'rep' here + # 'rep ret' or 'rep; ret': bad reasons for this bogus 'rep' here if line.split()[:2] == ['rep', 'ret']: return self.visit_ret(line) return [] From noreply at buildbot.pypy.org Sun Apr 14 20:48:40 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Sun, 14 Apr 2013 20:48:40 +0200 (CEST) Subject: [pypy-commit] pypy stdlib-2.7.4: test and fix for FileIO(fd) overflow behavior Message-ID: <20130414184840.275301C10AF@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: stdlib-2.7.4 Changeset: r63336:6528f2c2dd65 Date: 2013-04-14 14:47 -0400 http://bitbucket.org/pypy/pypy/changeset/6528f2c2dd65/ Log: test and fix for FileIO(fd) overflow behavior diff --git a/pypy/module/_io/interp_fileio.py b/pypy/module/_io/interp_fileio.py --- a/pypy/module/_io/interp_fileio.py +++ b/pypy/module/_io/interp_fileio.py @@ -140,7 +140,7 @@ fd = -1 try: - fd = space.int_w(w_name) + fd = space.c_int_w(w_name) except OperationError, e: pass else: diff --git a/pypy/module/_io/interp_io.py b/pypy/module/_io/interp_io.py --- a/pypy/module/_io/interp_io.py +++ b/pypy/module/_io/interp_io.py @@ -119,7 +119,7 @@ buffering = DEFAULT_BUFFER_SIZE if space.config.translation.type_system == 'lltype' and 'st_blksize' in STAT_FIELD_TYPES: - fileno = space.int_w(space.call_method(w_raw, "fileno")) + fileno = space.c_int_w(space.call_method(w_raw, "fileno")) try: st = os.fstat(fileno) except OSError: diff --git a/pypy/module/_io/test/test_fileio.py b/pypy/module/_io/test/test_fileio.py --- a/pypy/module/_io/test/test_fileio.py +++ b/pypy/module/_io/test/test_fileio.py @@ -21,6 +21,12 @@ assert f.closefd is True f.close() + def test_invalid_fd(self): + import _io + raises(ValueError, _io.FileIO, -10) + raises(TypeError, _io.FileIO, 2 ** 31) + raises(TypeError, _io.FileIO, -2 ** 31 - 1) + def test_weakrefable(self): import _io from weakref import proxy From noreply at buildbot.pypy.org Sun Apr 14 20:48:42 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Sun, 14 Apr 2013 20:48:42 +0200 (CEST) Subject: [pypy-commit] pypy stdlib-2.7.4: merge default Message-ID: <20130414184842.6FA1A1C10AF@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: stdlib-2.7.4 Changeset: r63337:39e2b357b2cb Date: 2013-04-14 14:48 -0400 http://bitbucket.org/pypy/pypy/changeset/39e2b357b2cb/ Log: merge default diff too long, truncating to 2000 out of 3015 lines diff --git a/pypy/module/_cffi_backend/ccallback.py b/pypy/module/_cffi_backend/ccallback.py --- a/pypy/module/_cffi_backend/ccallback.py +++ b/pypy/module/_cffi_backend/ccallback.py @@ -134,7 +134,7 @@ # W_CTypePrimitiveSigned.convert_from_object() in order # to write a whole 'ffi_arg'. value = misc.as_long(space, w_res) - misc.write_raw_signed_data(ll_res, value, SIZE_OF_FFI_ARG) + misc.write_raw_integer_data(ll_res, value, SIZE_OF_FFI_ARG) return else: # zero extension: fill the '*result' with zeros, and (on big- diff --git a/pypy/module/_cffi_backend/cdataobj.py b/pypy/module/_cffi_backend/cdataobj.py --- a/pypy/module/_cffi_backend/cdataobj.py +++ b/pypy/module/_cffi_backend/cdataobj.py @@ -280,13 +280,8 @@ return self.ctype.iter(self) @specialize.argtype(1) - def write_raw_signed_data(self, source): - misc.write_raw_signed_data(self._cdata, source, self.ctype.size) - keepalive_until_here(self) - - @specialize.argtype(1) - def write_raw_unsigned_data(self, source): - misc.write_raw_unsigned_data(self._cdata, source, self.ctype.size) + def write_raw_integer_data(self, source): + misc.write_raw_integer_data(self._cdata, source, self.ctype.size) keepalive_until_here(self) def write_raw_float_data(self, source): diff --git a/pypy/module/_cffi_backend/ctypeprim.py b/pypy/module/_cffi_backend/ctypeprim.py --- a/pypy/module/_cffi_backend/ctypeprim.py +++ b/pypy/module/_cffi_backend/ctypeprim.py @@ -63,7 +63,7 @@ else: value = self._cast_generic(w_ob) w_cdata = cdataobj.W_CDataMem(space, self.size, self) - self.write_raw_integer_data(w_cdata, value) + w_cdata.write_raw_integer_data(value) return w_cdata def _cast_result(self, intvalue): @@ -94,9 +94,6 @@ from pypy.module._cffi_backend import newtype return newtype.new_primitive_type(self.space, "int") - def write_raw_integer_data(self, w_cdata, value): - w_cdata.write_raw_unsigned_data(value) - class W_CTypePrimitiveChar(W_CTypePrimitiveCharOrUniChar): _attrs_ = [] @@ -188,10 +185,10 @@ if self.size < rffi.sizeof(lltype.Signed): if r_uint(value) - self.vmin > self.vrangemax: self._overflow(w_ob) - misc.write_raw_signed_data(cdata, value, self.size) + misc.write_raw_integer_data(cdata, value, self.size) else: value = misc.as_long_long(self.space, w_ob) - misc.write_raw_signed_data(cdata, value, self.size) + misc.write_raw_integer_data(cdata, value, self.size) def get_vararg_type(self): if self.size < rffi.sizeof(rffi.INT): @@ -199,9 +196,6 @@ return newtype.new_primitive_type(self.space, "int") return self - def write_raw_integer_data(self, w_cdata, value): - w_cdata.write_raw_signed_data(value) - class W_CTypePrimitiveUnsigned(W_CTypePrimitive): _attrs_ = ['value_fits_long', 'value_fits_ulong', 'vrangemax'] @@ -228,10 +222,10 @@ if self.value_fits_long: if value > self.vrangemax: self._overflow(w_ob) - misc.write_raw_unsigned_data(cdata, value, self.size) + misc.write_raw_integer_data(cdata, value, self.size) else: value = misc.as_unsigned_long_long(self.space, w_ob, strict=True) - misc.write_raw_unsigned_data(cdata, value, self.size) + misc.write_raw_integer_data(cdata, value, self.size) def convert_to_object(self, cdata): if self.value_fits_ulong: @@ -250,9 +244,6 @@ return newtype.new_primitive_type(self.space, "int") return self - def write_raw_integer_data(self, w_cdata, value): - w_cdata.write_raw_unsigned_data(value) - class W_CTypePrimitiveBool(W_CTypePrimitiveUnsigned): _attrs_ = [] diff --git a/pypy/module/_cffi_backend/ctypestruct.py b/pypy/module/_cffi_backend/ctypestruct.py --- a/pypy/module/_cffi_backend/ctypestruct.py +++ b/pypy/module/_cffi_backend/ctypestruct.py @@ -242,13 +242,11 @@ # value = misc.as_long_long(space, w_ob) if isinstance(ctype, ctypeprim.W_CTypePrimitiveSigned): - is_signed = True fmin = -(r_longlong(1) << (self.bitsize - 1)) fmax = (r_longlong(1) << (self.bitsize - 1)) - 1 if fmax == 0: fmax = 1 # special case to let "int x:1" receive "1" else: - is_signed = False fmin = r_longlong(0) fmax = r_longlong((r_ulonglong(1) << self.bitsize) - 1) if value < fmin or value > fmax: @@ -260,10 +258,7 @@ rawvalue = r_ulonglong(value) << self.bitshift rawfielddata = misc.read_raw_unsigned_data(cdata, ctype.size) rawfielddata = (rawfielddata & ~rawmask) | (rawvalue & rawmask) - if is_signed: - misc.write_raw_signed_data(cdata, rawfielddata, ctype.size) - else: - misc.write_raw_unsigned_data(cdata, rawfielddata, ctype.size) + misc.write_raw_integer_data(cdata, rawfielddata, ctype.size) W_CField.typedef = TypeDef( diff --git a/pypy/module/_cffi_backend/misc.py b/pypy/module/_cffi_backend/misc.py --- a/pypy/module/_cffi_backend/misc.py +++ b/pypy/module/_cffi_backend/misc.py @@ -9,7 +9,6 @@ from rpython.rtyper.lltypesystem import lltype, llmemory, rffi from rpython.translator.tool.cbuild import ExternalCompilationInfo - # ____________________________________________________________ _prim_signed_types = unrolling_iterable([ @@ -66,22 +65,19 @@ return rffi.cast(rffi.LONGDOUBLEP, target)[0] @specialize.argtype(1) -def write_raw_unsigned_data(target, source, size): - for TP, TPP in _prim_unsigned_types: - if size == rffi.sizeof(TP): - rffi.cast(TPP, target)[0] = rffi.cast(TP, source) - return +def write_raw_integer_data(target, source, size): + if is_signed_integer_type(lltype.typeOf(source)): + for TP, TPP in _prim_signed_types: + if size == rffi.sizeof(TP): + rffi.cast(TPP, target)[0] = rffi.cast(TP, source) + return + else: + for TP, TPP in _prim_unsigned_types: + if size == rffi.sizeof(TP): + rffi.cast(TPP, target)[0] = rffi.cast(TP, source) + return raise NotImplementedError("bad integer size") - at specialize.argtype(1) -def write_raw_signed_data(target, source, size): - for TP, TPP in _prim_signed_types: - if size == rffi.sizeof(TP): - rffi.cast(TPP, target)[0] = rffi.cast(TP, source) - return - raise NotImplementedError("bad integer size") - - def write_raw_float_data(target, source, size): for TP, TPP in _prim_float_types: if size == rffi.sizeof(TP): diff --git a/pypy/module/pypyjit/test_pypy_c/test__ffi.py b/pypy/module/pypyjit/test_pypy_c/test__ffi.py new file mode 100644 --- /dev/null +++ b/pypy/module/pypyjit/test_pypy_c/test__ffi.py @@ -0,0 +1,272 @@ +import sys, py +from pypy.module.pypyjit.test_pypy_c.test_00_model import BaseTestPyPyC + +class Test__ffi(BaseTestPyPyC): + + def test__ffi_call(self): + from rpython.rlib.test.test_clibffi import get_libm_name + def main(libm_name): + try: + from _ffi import CDLL, types + except ImportError: + sys.stderr.write('SKIP: cannot import _ffi\n') + return 0 + + libm = CDLL(libm_name) + pow = libm.getfunc('pow', [types.double, types.double], + types.double) + i = 0 + res = 0 + while i < 300: + tmp = pow(2, 3) # ID: fficall + res += tmp + i += 1 + return pow.getaddr(), res + # + libm_name = get_libm_name(sys.platform) + log = self.run(main, [libm_name]) + pow_addr, res = log.result + assert res == 8.0 * 300 + py.test.xfail() # XXX re-optimize _ffi for the JIT? + loop, = log.loops_by_filename(self.filepath) + if 'ConstClass(pow)' in repr(loop): # e.g. OS/X + pow_addr = 'ConstClass(pow)' + assert loop.match_by_id('fficall', """ + guard_not_invalidated(descr=...) + i17 = force_token() + setfield_gc(p0, i17, descr=<.* .*PyFrame.vable_token .*>) + f21 = call_release_gil(%s, 2.000000, 3.000000, descr=) + guard_not_forced(descr=...) + guard_no_exception(descr=...) + """ % pow_addr) + + + def test__ffi_call_frame_does_not_escape(self): + from rpython.rlib.test.test_clibffi import get_libm_name + def main(libm_name): + try: + from _ffi import CDLL, types + except ImportError: + sys.stderr.write('SKIP: cannot import _ffi\n') + return 0 + + libm = CDLL(libm_name) + pow = libm.getfunc('pow', [types.double, types.double], + types.double) + + def mypow(a, b): + return pow(a, b) + + i = 0 + res = 0 + while i < 300: + tmp = mypow(2, 3) + res += tmp + i += 1 + return pow.getaddr(), res + # + libm_name = get_libm_name(sys.platform) + log = self.run(main, [libm_name]) + pow_addr, res = log.result + assert res == 8.0 * 300 + loop, = log.loops_by_filename(self.filepath) + opnames = log.opnames(loop.allops()) + # we only force the virtualref, not its content + assert opnames.count('new_with_vtable') == 1 + + def test__ffi_call_releases_gil(self): + from rpython.rlib.clibffi import get_libc_name + def main(libc_name, n): + import time + import os + from threading import Thread + # + if os.name == 'nt': + from _ffi import WinDLL, types + libc = WinDLL('Kernel32.dll') + sleep = libc.getfunc('Sleep', [types.uint], types.uint) + delays = [0]*n + [1000] + else: + from _ffi import CDLL, types + libc = CDLL(libc_name) + sleep = libc.getfunc('sleep', [types.uint], types.uint) + delays = [0]*n + [1] + # + def loop_of_sleeps(i, delays): + for delay in delays: + sleep(delay) # ID: sleep + # + threads = [Thread(target=loop_of_sleeps, args=[i, delays]) for i in range(5)] + start = time.time() + for i, thread in enumerate(threads): + thread.start() + for thread in threads: + thread.join() + end = time.time() + return end - start + log = self.run(main, [get_libc_name(), 200], threshold=150, + import_site=True) + assert 1 <= log.result <= 1.5 # at most 0.5 seconds of overhead + loops = log.loops_by_id('sleep') + assert len(loops) == 1 # make sure that we actually JITted the loop + + def test_ctypes_call(self): + from rpython.rlib.test.test_clibffi import get_libm_name + def main(libm_name): + import ctypes + libm = ctypes.CDLL(libm_name) + fabs = libm.fabs + fabs.argtypes = [ctypes.c_double] + fabs.restype = ctypes.c_double + x = -4 + i = 0 + while i < 300: + x = fabs(x) + x = x - 100 + i += 1 + return fabs._ptr.getaddr(), x + + libm_name = get_libm_name(sys.platform) + log = self.run(main, [libm_name], import_site=True) + fabs_addr, res = log.result + assert res == -4.0 + loop, = log.loops_by_filename(self.filepath) + ops = loop.allops() + opnames = log.opnames(ops) + assert opnames.count('new_with_vtable') == 1 # only the virtualref + py.test.xfail() # XXX re-optimize _ffi for the JIT? + assert opnames.count('call_release_gil') == 1 + idx = opnames.index('call_release_gil') + call = ops[idx] + assert (call.args[0] == 'ConstClass(fabs)' or # e.g. OS/X + int(call.args[0]) == fabs_addr) + + + def test__ffi_struct(self): + def main(): + from _ffi import _StructDescr, Field, types + fields = [ + Field('x', types.slong), + ] + descr = _StructDescr('foo', fields) + struct = descr.allocate() + i = 0 + while i < 300: + x = struct.getfield('x') # ID: getfield + x = x+1 + struct.setfield('x', x) # ID: setfield + i += 1 + return struct.getfield('x') + # + log = self.run(main, []) + py.test.xfail() # XXX re-optimize _ffi for the JIT? + loop, = log.loops_by_filename(self.filepath) + assert loop.match_by_id('getfield', """ + guard_not_invalidated(descr=...) + i57 = getfield_raw(i46, descr=) + """) + assert loop.match_by_id('setfield', """ + setfield_raw(i44, i57, descr=) + """) + + + def test__cffi_call(self): + from rpython.rlib.test.test_clibffi import get_libm_name + def main(libm_name): + try: + import _cffi_backend + except ImportError: + sys.stderr.write('SKIP: cannot import _cffi_backend\n') + return 0 + + libm = _cffi_backend.load_library(libm_name) + BDouble = _cffi_backend.new_primitive_type("double") + BPow = _cffi_backend.new_function_type([BDouble, BDouble], BDouble) + pow = libm.load_function(BPow, 'pow') + i = 0 + res = 0 + while i < 300: + tmp = pow(2, 3) # ID: cfficall + res += tmp + i += 1 + BLong = _cffi_backend.new_primitive_type("long") + pow_addr = int(_cffi_backend.cast(BLong, pow)) + return pow_addr, res + # + libm_name = get_libm_name(sys.platform) + log = self.run(main, [libm_name]) + pow_addr, res = log.result + assert res == 8.0 * 300 + loop, = log.loops_by_filename(self.filepath) + if 'ConstClass(pow)' in repr(loop): # e.g. OS/X + pow_addr = 'ConstClass(pow)' + assert loop.match_by_id('cfficall', """ + ... + f1 = call_release_gil(..., descr=) + ... + """) + # so far just check that call_release_gil() is produced. + # later, also check that the arguments to call_release_gil() + # are constants, and that the numerous raw_mallocs are removed + + def test_cffi_call_guard_not_forced_fails(self): + # this is the test_pypy_c equivalent of + # rpython/jit/metainterp/test/test_fficall::test_guard_not_forced_fails + # + # it requires cffi to be installed for pypy in order to run + def main(): + import sys + try: + import cffi + except ImportError: + sys.stderr.write('SKIP: cannot import cffi\n') + return 0 + + ffi = cffi.FFI() + + ffi.cdef(""" + typedef void (*functype)(int); + int foo(int n, functype func); + """) + + lib = ffi.verify(""" + #include + typedef void (*functype)(int); + + int foo(int n, functype func) { + if (n >= 2000) { + func(n); + } + return n*2; + } + """) + + @ffi.callback("functype") + def mycallback(n): + if n < 5000: + return + # make sure that guard_not_forced fails + d = {} + f = sys._getframe() + while f: + d.update(f.f_locals) + f = f.f_back + + n = 0 + while n < 10000: + res = lib.foo(n, mycallback) # ID: cfficall + # this is the real point of the test: before the + # refactor-call_release_gil branch, the assert failed when + # res == 5000 + assert res == n*2 + n += 1 + return n + + log = self.run(main, [], import_site=True) + assert log.result == 10000 + loop, = log.loops_by_id('cfficall') + assert loop.match_by_id('cfficall', """ + ... + f1 = call_release_gil(..., descr=) + ... + """) diff --git a/pypy/module/pypyjit/test_pypy_c/test_ffi.py b/pypy/module/pypyjit/test_pypy_c/test_ffi.py deleted file mode 100644 --- a/pypy/module/pypyjit/test_pypy_c/test_ffi.py +++ /dev/null @@ -1,279 +0,0 @@ -import sys, py -from pypy.module.pypyjit.test_pypy_c.test_00_model import BaseTestPyPyC - -class Test__ffi(BaseTestPyPyC): - - def test__ffi_call(self): - from rpython.rlib.test.test_clibffi import get_libm_name - def main(libm_name): - try: - from _ffi import CDLL, types - except ImportError: - sys.stderr.write('SKIP: cannot import _ffi\n') - return 0 - - libm = CDLL(libm_name) - pow = libm.getfunc('pow', [types.double, types.double], - types.double) - i = 0 - res = 0 - while i < 300: - tmp = pow(2, 3) # ID: fficall - res += tmp - i += 1 - return pow.getaddr(), res - # - libm_name = get_libm_name(sys.platform) - log = self.run(main, [libm_name]) - pow_addr, res = log.result - assert res == 8.0 * 300 - py.test.xfail() # XXX re-optimize _ffi for the JIT? - loop, = log.loops_by_filename(self.filepath) - if 'ConstClass(pow)' in repr(loop): # e.g. OS/X - pow_addr = 'ConstClass(pow)' - assert loop.match_by_id('fficall', """ - guard_not_invalidated(descr=...) - i17 = force_token() - setfield_gc(p0, i17, descr=<.* .*PyFrame.vable_token .*>) - f21 = call_release_gil(%s, 2.000000, 3.000000, descr=) - guard_not_forced(descr=...) - guard_no_exception(descr=...) - """ % pow_addr) - - - def test__ffi_call_frame_does_not_escape(self): - from rpython.rlib.test.test_clibffi import get_libm_name - def main(libm_name): - try: - from _ffi import CDLL, types - except ImportError: - sys.stderr.write('SKIP: cannot import _ffi\n') - return 0 - - libm = CDLL(libm_name) - pow = libm.getfunc('pow', [types.double, types.double], - types.double) - - def mypow(a, b): - return pow(a, b) - - i = 0 - res = 0 - while i < 300: - tmp = mypow(2, 3) - res += tmp - i += 1 - return pow.getaddr(), res - # - libm_name = get_libm_name(sys.platform) - log = self.run(main, [libm_name]) - pow_addr, res = log.result - assert res == 8.0 * 300 - loop, = log.loops_by_filename(self.filepath) - opnames = log.opnames(loop.allops()) - # we only force the virtualref, not its content - assert opnames.count('new_with_vtable') == 1 - - def test__ffi_call_releases_gil(self): - from rpython.rlib.clibffi import get_libc_name - def main(libc_name, n): - import time - import os - from threading import Thread - # - if os.name == 'nt': - from _ffi import WinDLL, types - libc = WinDLL('Kernel32.dll') - sleep = libc.getfunc('Sleep', [types.uint], types.uint) - delays = [0]*n + [1000] - else: - from _ffi import CDLL, types - libc = CDLL(libc_name) - sleep = libc.getfunc('sleep', [types.uint], types.uint) - delays = [0]*n + [1] - # - def loop_of_sleeps(i, delays): - for delay in delays: - sleep(delay) # ID: sleep - # - threads = [Thread(target=loop_of_sleeps, args=[i, delays]) for i in range(5)] - start = time.time() - for i, thread in enumerate(threads): - thread.start() - for thread in threads: - thread.join() - end = time.time() - return end - start - log = self.run(main, [get_libc_name(), 200], threshold=150, - import_site=True) - assert 1 <= log.result <= 1.5 # at most 0.5 seconds of overhead - loops = log.loops_by_id('sleep') - assert len(loops) == 1 # make sure that we actually JITted the loop - - def test_ctypes_call(self): - from rpython.rlib.test.test_clibffi import get_libm_name - def main(libm_name): - import ctypes - libm = ctypes.CDLL(libm_name) - fabs = libm.fabs - fabs.argtypes = [ctypes.c_double] - fabs.restype = ctypes.c_double - x = -4 - i = 0 - while i < 300: - x = fabs(x) - x = x - 100 - i += 1 - return fabs._ptr.getaddr(), x - - libm_name = get_libm_name(sys.platform) - log = self.run(main, [libm_name], import_site=True) - fabs_addr, res = log.result - assert res == -4.0 - loop, = log.loops_by_filename(self.filepath) - ops = loop.allops() - opnames = log.opnames(ops) - assert opnames.count('new_with_vtable') == 1 # only the virtualref - py.test.xfail() # XXX re-optimize _ffi for the JIT? - assert opnames.count('call_release_gil') == 1 - idx = opnames.index('call_release_gil') - call = ops[idx] - assert (call.args[0] == 'ConstClass(fabs)' or # e.g. OS/X - int(call.args[0]) == fabs_addr) - - - def test__ffi_struct(self): - def main(): - from _ffi import _StructDescr, Field, types - fields = [ - Field('x', types.slong), - ] - descr = _StructDescr('foo', fields) - struct = descr.allocate() - i = 0 - while i < 300: - x = struct.getfield('x') # ID: getfield - x = x+1 - struct.setfield('x', x) # ID: setfield - i += 1 - return struct.getfield('x') - # - log = self.run(main, []) - py.test.xfail() # XXX re-optimize _ffi for the JIT? - loop, = log.loops_by_filename(self.filepath) - assert loop.match_by_id('getfield', """ - guard_not_invalidated(descr=...) - i57 = getfield_raw(i46, descr=) - """) - assert loop.match_by_id('setfield', """ - setfield_raw(i44, i57, descr=) - """) - - - def test__cffi_call(self): - from rpython.rlib.test.test_clibffi import get_libm_name - def main(libm_name): - try: - import _cffi_backend - except ImportError: - sys.stderr.write('SKIP: cannot import _cffi_backend\n') - return 0 - - libm = _cffi_backend.load_library(libm_name) - BDouble = _cffi_backend.new_primitive_type("double") - BInt = _cffi_backend.new_primitive_type("int") - BPow = _cffi_backend.new_function_type([BDouble, BInt], BDouble) - ldexp = libm.load_function(BPow, 'ldexp') - i = 0 - res = 0 - while i < 300: - tmp = ldexp(1, 3) # ID: cfficall - res += tmp - i += 1 - BLong = _cffi_backend.new_primitive_type("long") - ldexp_addr = int(_cffi_backend.cast(BLong, ldexp)) - return ldexp_addr, res - # - libm_name = get_libm_name(sys.platform) - log = self.run(main, [libm_name]) - ldexp_addr, res = log.result - assert res == 8.0 * 300 - loop, = log.loops_by_filename(self.filepath) - if 'ConstClass(ldexp)' in repr(loop): # e.g. OS/X - ldexp_addr = 'ConstClass(ldexp)' - assert loop.match_by_id('cfficall', """ - ... - f1 = call_release_gil(..., descr=) - ... - """) - ops = loop.ops_by_id('cfficall') - assert 'raw_malloc' not in str(ops) - assert 'raw_free' not in str(ops) - assert 'getarrayitem_raw' not in log.opnames(ops) - assert 'setarrayitem_raw' not in log.opnames(ops) - # so far just check that call_release_gil() is produced. - # later, also check that the arguments to call_release_gil() - # are constants - # are constants, and that the numerous raw_mallocs are removed - - def test_cffi_call_guard_not_forced_fails(self): - # this is the test_pypy_c equivalent of - # rpython/jit/metainterp/test/test_fficall::test_guard_not_forced_fails - # - # it requires cffi to be installed for pypy in order to run - def main(): - import sys - try: - import cffi - except ImportError: - sys.stderr.write('SKIP: cannot import cffi\n') - return 0 - - ffi = cffi.FFI() - - ffi.cdef(""" - typedef void (*functype)(int); - int foo(int n, functype func); - """) - - lib = ffi.verify(""" - #include - typedef void (*functype)(int); - - int foo(int n, functype func) { - if (n >= 2000) { - func(n); - } - return n*2; - } - """) - - @ffi.callback("functype") - def mycallback(n): - if n < 5000: - return - # make sure that guard_not_forced fails - d = {} - f = sys._getframe() - while f: - d.update(f.f_locals) - f = f.f_back - - n = 0 - while n < 10000: - res = lib.foo(n, mycallback) # ID: cfficall - # this is the real point of the test: before the - # refactor-call_release_gil branch, the assert failed when - # res == 5000 - assert res == n*2 - n += 1 - return n - - log = self.run(main, [], import_site=True) - assert log.result == 10000 - loop, = log.loops_by_id('cfficall') - assert loop.match_by_id('cfficall', """ - ... - f1 = call_release_gil(..., descr=) - ... - """) diff --git a/pypy/module/thread/os_thread.py b/pypy/module/thread/os_thread.py --- a/pypy/module/thread/os_thread.py +++ b/pypy/module/thread/os_thread.py @@ -132,7 +132,7 @@ if not e.match(space, space.w_SystemExit): ident = rthread.get_ident() where = 'thread %d started by ' % ident - e.write_unraisable(space, where, w_callable) + e.write_unraisable(space, where, w_callable, with_traceback=True) e.clear(space) # clean up space.threadlocals to remove the ExecutionContext # entry corresponding to the current thread diff --git a/pypy/module/thread/test/test_thread.py b/pypy/module/thread/test/test_thread.py --- a/pypy/module/thread/test/test_thread.py +++ b/pypy/module/thread/test/test_thread.py @@ -129,10 +129,10 @@ sys.stderr = StringIO.StringIO() thread.start_new_thread(fn3, ()) self.waitfor(lambda: "ValueError" in sys.stderr.getvalue()) - result = sys.stderr.getvalue() - assert "ValueError" in result - assert "hello world" in result - assert len(result.splitlines()) == 1 + result = sys.stderr.getvalue().splitlines() + #assert result[0].startswith("Unhandled exception in thread ") + assert result[1].startswith("Traceback ") + assert result[-1] == "ValueError: hello world" finally: sys.stderr = prev diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -74,29 +74,6 @@ def setup_failure_recovery(self): self.failure_recovery_code = [0, 0, 0, 0] - @staticmethod - def _release_gil_shadowstack(): - before = rffi.aroundstate.before - if before: - before() - - @staticmethod - def _reacquire_gil_shadowstack(): - after = rffi.aroundstate.after - if after: - after() - - _NOARG_FUNC = lltype.Ptr(lltype.FuncType([], lltype.Void)) - - def _build_release_gil(self, gcrootmap): - assert gcrootmap.is_shadow_stack - releasegil_func = llhelper(self._NOARG_FUNC, - self._release_gil_shadowstack) - reacqgil_func = llhelper(self._NOARG_FUNC, - self._reacquire_gil_shadowstack) - self.releasegil_addr = rffi.cast(lltype.Signed, releasegil_func) - self.reacqgil_addr = rffi.cast(lltype.Signed, reacqgil_func) - def _build_propagate_exception_path(self): if not self.cpu.propagate_exception_descr: return # not supported (for tests, or non-translated) @@ -537,7 +514,7 @@ clt.allgcrefs = [] clt.frame_info.clear() # for now - if False and log: + if log: operations = self._inject_debugging_code(looptoken, operations, 'e', looptoken.number) diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -630,7 +630,9 @@ # argument the address of the structure we are writing into # (the first argument to COND_CALL_GC_WB). helper_num = card_marking - if self._regalloc is not None and self._regalloc.vfprm.reg_bindings: + if is_frame: + helper_num = 4 + elif self._regalloc is not None and self._regalloc.vfprm.reg_bindings: helper_num += 2 if self.wb_slowpath[helper_num] == 0: # tests only assert not we_are_translated() @@ -1264,7 +1266,7 @@ resloc = arglocs[0] if gcrootmap: - self.call_release_gil(gcrootmap, arglocs, fcond) + self.call_release_gil(gcrootmap, arglocs, regalloc, fcond) # do the call self._store_force_index(guard_op) # @@ -1276,37 +1278,32 @@ resloc, (size, signed)) # then reopen the stack if gcrootmap: - self.call_reacquire_gil(gcrootmap, resloc, fcond) + self.call_reacquire_gil(gcrootmap, resloc, regalloc, fcond) self._emit_guard_may_force(guard_op, arglocs[numargs+1:], numargs) return fcond - def call_release_gil(self, gcrootmap, save_registers, fcond): - # First, we need to save away the registers listed in - # 'save_registers' that are not callee-save. + def call_release_gil(self, gcrootmap, save_registers, regalloc, fcond): + # Save caller saved registers and do the call # NOTE: We assume that the floating point registers won't be modified. - regs_to_save = [] - for reg in self._regalloc.rm.save_around_call_regs: - if reg in save_registers: - regs_to_save.append(reg) assert gcrootmap.is_shadow_stack - with saved_registers(self.mc, regs_to_save): + with saved_registers(self.mc, regalloc.rm.save_around_call_regs): self._emit_call(imm(self.releasegil_addr), [], fcond) - def call_reacquire_gil(self, gcrootmap, save_loc, fcond): - # save the previous result into the stack temporarily. + def call_reacquire_gil(self, gcrootmap, save_loc, regalloc, fcond): + # save the previous result into the stack temporarily, in case it is in + # a caller saved register. # NOTE: like with call_release_gil(), we assume that we don't need to # save vfp regs in this case. Besides the result location regs_to_save = [] vfp_regs_to_save = [] - if save_loc.is_reg(): + if save_loc and save_loc in regalloc.rm.save_around_call_regs: regs_to_save.append(save_loc) - if save_loc.is_vfp_reg(): + regs_to_save.append(r.ip) # for alingment + elif save_loc and save_loc in regalloc.vfprm.save_around_call_regs: vfp_regs_to_save.append(save_loc) + assert gcrootmap.is_shadow_stack # call the reopenstack() function (also reacquiring the GIL) - if len(regs_to_save) % 2 != 1: - regs_to_save.append(r.ip) # for alingment - assert gcrootmap.is_shadow_stack with saved_registers(self.mc, regs_to_save, vfp_regs_to_save): self._emit_call(imm(self.reacqgil_addr), [], fcond) diff --git a/rpython/jit/backend/arm/regalloc.py b/rpython/jit/backend/arm/regalloc.py --- a/rpython/jit/backend/arm/regalloc.py +++ b/rpython/jit/backend/arm/regalloc.py @@ -554,10 +554,9 @@ return self._prepare_call(op) def _prepare_call(self, op, force_store=[], save_all_regs=False): - args = [] - args.append(None) + args = [None] * (op.numargs() + 1) for i in range(op.numargs()): - args.append(self.loc(op.getarg(i))) + args[i + 1] = self.loc(op.getarg(i)) # spill variables that need to be saved around calls self.vfprm.before_call(save_all_regs=save_all_regs) if not save_all_regs: diff --git a/rpython/jit/backend/llgraph/runner.py b/rpython/jit/backend/llgraph/runner.py --- a/rpython/jit/backend/llgraph/runner.py +++ b/rpython/jit/backend/llgraph/runner.py @@ -484,15 +484,6 @@ else: return self.bh_raw_load_i(struct, offset, descr) - def unpack_arraydescr_size(self, arraydescr): - from rpython.jit.backend.llsupport.symbolic import get_array_token - from rpython.jit.backend.llsupport.descr import get_type_flag, FLAG_SIGNED - assert isinstance(arraydescr, ArrayDescr) - basesize, itemsize, _ = get_array_token(arraydescr.A, False) - flag = get_type_flag(arraydescr.A.OF) - is_signed = (flag == FLAG_SIGNED) - return basesize, itemsize, is_signed - def bh_raw_store_i(self, struct, offset, newvalue, descr): ll_p = rffi.cast(rffi.CCHARP, struct) ll_p = rffi.cast(lltype.Ptr(descr.A), rffi.ptradd(ll_p, offset)) @@ -575,14 +566,10 @@ def bh_read_timestamp(self): return read_timestamp() - def bh_new_raw_buffer(self, size): - return lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') - def store_fail_descr(self, deadframe, descr): pass # I *think* - class LLDeadFrame(object): _TYPE = llmemory.GCREF diff --git a/rpython/jit/backend/llsupport/assembler.py b/rpython/jit/backend/llsupport/assembler.py --- a/rpython/jit/backend/llsupport/assembler.py +++ b/rpython/jit/backend/llsupport/assembler.py @@ -9,7 +9,7 @@ debug_print) from rpython.rlib.rarithmetic import r_uint from rpython.rlib.objectmodel import specialize, compute_unique_id -from rpython.rtyper.annlowlevel import cast_instance_to_gcref +from rpython.rtyper.annlowlevel import cast_instance_to_gcref, llhelper from rpython.rtyper.lltypesystem import rffi, lltype @@ -282,6 +282,69 @@ debug_print(prefix + ':' + str(struct.i)) debug_stop('jit-backend-counts') + @staticmethod + @rgc.no_collect + def _release_gil_asmgcc(css): + # similar to trackgcroot.py:pypy_asm_stackwalk, first part + from rpython.memory.gctransform import asmgcroot + new = rffi.cast(asmgcroot.ASM_FRAMEDATA_HEAD_PTR, css) + next = asmgcroot.gcrootanchor.next + new.next = next + new.prev = asmgcroot.gcrootanchor + asmgcroot.gcrootanchor.next = new + next.prev = new + # and now release the GIL + before = rffi.aroundstate.before + if before: + before() + + @staticmethod + @rgc.no_collect + def _reacquire_gil_asmgcc(css): + # first reacquire the GIL + after = rffi.aroundstate.after + if after: + after() + # similar to trackgcroot.py:pypy_asm_stackwalk, second part + from rpython.memory.gctransform import asmgcroot + old = rffi.cast(asmgcroot.ASM_FRAMEDATA_HEAD_PTR, css) + prev = old.prev + next = old.next + prev.next = next + next.prev = prev + + @staticmethod + @rgc.no_collect + def _release_gil_shadowstack(): + before = rffi.aroundstate.before + if before: + before() + + @staticmethod + @rgc.no_collect + def _reacquire_gil_shadowstack(): + after = rffi.aroundstate.after + if after: + after() + + _NOARG_FUNC = lltype.Ptr(lltype.FuncType([], lltype.Void)) + _CLOSESTACK_FUNC = lltype.Ptr(lltype.FuncType([rffi.LONGP], + lltype.Void)) + + def _build_release_gil(self, gcrootmap): + if gcrootmap.is_shadow_stack: + releasegil_func = llhelper(self._NOARG_FUNC, + self._release_gil_shadowstack) + reacqgil_func = llhelper(self._NOARG_FUNC, + self._reacquire_gil_shadowstack) + else: + releasegil_func = llhelper(self._CLOSESTACK_FUNC, + self._release_gil_asmgcc) + reacqgil_func = llhelper(self._CLOSESTACK_FUNC, + self._reacquire_gil_asmgcc) + self.releasegil_addr = self.cpu.cast_ptr_to_int(releasegil_func) + self.reacqgil_addr = self.cpu.cast_ptr_to_int(reacqgil_func) + def debug_bridge(descr_number, rawstart, codeendpos): diff --git a/rpython/jit/backend/llsupport/llmodel.py b/rpython/jit/backend/llsupport/llmodel.py --- a/rpython/jit/backend/llsupport/llmodel.py +++ b/rpython/jit/backend/llsupport/llmodel.py @@ -742,9 +742,6 @@ as_array[self.vtable_offset/WORD] = vtable return res - def bh_new_raw_buffer(self, size): - return lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') - def bh_classof(self, struct): struct = lltype.cast_opaque_ptr(rclass.OBJECTPTR, struct) result_adr = llmemory.cast_ptr_to_adr(struct.typeptr) diff --git a/rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py b/rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py --- a/rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py +++ b/rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py @@ -2,7 +2,6 @@ import weakref from rpython.rlib.jit import JitDriver, dont_look_inside from rpython.jit.backend.llsupport.test.zrpy_gc_test import run, get_entry, compile -from rpython.jit.backend.llsupport.test.ztranslation_test import fix_annotator_for_vrawbuffer class X(object): def __init__(self, x=0): @@ -32,8 +31,7 @@ g._dont_inline_ = True return g -def compile_boehm_test(monkeypatch): - fix_annotator_for_vrawbuffer(monkeypatch) +def compile_boehm_test(): myjitdriver = JitDriver(greens = [], reds = ['n', 'x']) @dont_look_inside def see(lst, n): diff --git a/rpython/jit/backend/llsupport/test/ztranslation_test.py b/rpython/jit/backend/llsupport/test/ztranslation_test.py --- a/rpython/jit/backend/llsupport/test/ztranslation_test.py +++ b/rpython/jit/backend/llsupport/test/ztranslation_test.py @@ -9,23 +9,10 @@ from rpython.jit.codewriter.policy import StopAtXPolicy -def fix_annotator_for_vrawbuffer(monkeypatch): - from rpython.rlib.nonconst import NonConstant - from rpython.jit.metainterp.optimizeopt.virtualize import VRawBufferValue - from rpython.jit.metainterp import warmspot - - def my_hook_for_tests(cpu): - # this is needed so that the annotator can see it - if NonConstant(False): - v = VRawBufferValue(cpu, None, -1, None, None) - monkeypatch.setattr(warmspot, 'hook_for_tests', my_hook_for_tests) - - class TranslationTest(CCompiledMixin): CPUClass = getcpuclass() - def test_stuff_translates(self, monkeypatch): - fix_annotator_for_vrawbuffer(monkeypatch) + def test_stuff_translates(self): # this is a basic test that tries to hit a number of features and their # translation: # - jitting of loops and bridges @@ -102,10 +89,9 @@ class TranslationTestCallAssembler(CCompiledMixin): CPUClass = getcpuclass() - def test_direct_assembler_call_translates(self, monkeypatch): + def test_direct_assembler_call_translates(self): """Test CALL_ASSEMBLER and the recursion limit""" from rpython.rlib.rstackovf import StackOverflow - fix_annotator_for_vrawbuffer(monkeypatch) class Thing(object): def __init__(self, val): @@ -183,8 +169,7 @@ class TranslationTestJITStats(CCompiledMixin): CPUClass = getcpuclass() - def test_jit_get_stats(self, monkeypatch): - fix_annotator_for_vrawbuffer(monkeypatch) + def test_jit_get_stats(self): driver = JitDriver(greens = [], reds = ['i']) def f(): @@ -207,8 +192,7 @@ class TranslationRemoveTypePtrTest(CCompiledMixin): CPUClass = getcpuclass() - def test_external_exception_handling_translates(self, monkeypatch): - fix_annotator_for_vrawbuffer(monkeypatch) + def test_external_exception_handling_translates(self): jitdriver = JitDriver(greens = [], reds = ['n', 'total']) class ImDone(Exception): diff --git a/rpython/jit/backend/model.py b/rpython/jit/backend/model.py --- a/rpython/jit/backend/model.py +++ b/rpython/jit/backend/model.py @@ -194,18 +194,11 @@ def typedescrof(self, TYPE): raise NotImplementedError - def unpack_arraydescr_size(self, arraydescr): - """ - Return basesize, itemsize, is_signed - """ - raise NotImplementedError - @staticmethod def cast_int_to_ptr(x, TYPE): x = llmemory.cast_int_to_adr(x) return llmemory.cast_adr_to_ptr(x, TYPE) - # ---------- the backend-dependent operations ---------- # lltype specific operations @@ -242,8 +235,6 @@ raise NotImplementedError def bh_newunicode(self, length): raise NotImplementedError - def bh_new_raw_buffer(self, size): - raise NotImplementedError def bh_arraylen_gc(self, array, arraydescr): raise NotImplementedError diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -367,69 +367,6 @@ else: self.wb_slowpath[withcards + 2 * withfloats] = rawstart - @staticmethod - @rgc.no_collect - def _release_gil_asmgcc(css): - # similar to trackgcroot.py:pypy_asm_stackwalk, first part - from rpython.memory.gctransform import asmgcroot - new = rffi.cast(asmgcroot.ASM_FRAMEDATA_HEAD_PTR, css) - next = asmgcroot.gcrootanchor.next - new.next = next - new.prev = asmgcroot.gcrootanchor - asmgcroot.gcrootanchor.next = new - next.prev = new - # and now release the GIL - before = rffi.aroundstate.before - if before: - before() - - @staticmethod - @rgc.no_collect - def _reacquire_gil_asmgcc(css): - # first reacquire the GIL - after = rffi.aroundstate.after - if after: - after() - # similar to trackgcroot.py:pypy_asm_stackwalk, second part - from rpython.memory.gctransform import asmgcroot - old = rffi.cast(asmgcroot.ASM_FRAMEDATA_HEAD_PTR, css) - prev = old.prev - next = old.next - prev.next = next - next.prev = prev - - @staticmethod - @rgc.no_collect - def _release_gil_shadowstack(): - before = rffi.aroundstate.before - if before: - before() - - @staticmethod - @rgc.no_collect - def _reacquire_gil_shadowstack(): - after = rffi.aroundstate.after - if after: - after() - - _NOARG_FUNC = lltype.Ptr(lltype.FuncType([], lltype.Void)) - _CLOSESTACK_FUNC = lltype.Ptr(lltype.FuncType([rffi.LONGP], - lltype.Void)) - - def _build_release_gil(self, gcrootmap): - if gcrootmap.is_shadow_stack: - releasegil_func = llhelper(self._NOARG_FUNC, - self._release_gil_shadowstack) - reacqgil_func = llhelper(self._NOARG_FUNC, - self._reacquire_gil_shadowstack) - else: - releasegil_func = llhelper(self._CLOSESTACK_FUNC, - self._release_gil_asmgcc) - reacqgil_func = llhelper(self._CLOSESTACK_FUNC, - self._reacquire_gil_asmgcc) - self.releasegil_addr = self.cpu.cast_ptr_to_int(releasegil_func) - self.reacqgil_addr = self.cpu.cast_ptr_to_int(reacqgil_func) - def assemble_loop(self, loopname, inputargs, operations, looptoken, log): '''adds the following attributes to looptoken: _ll_function_addr (address of the generated func, as an int) diff --git a/rpython/jit/codewriter/effectinfo.py b/rpython/jit/codewriter/effectinfo.py --- a/rpython/jit/codewriter/effectinfo.py +++ b/rpython/jit/codewriter/effectinfo.py @@ -76,14 +76,14 @@ # OS_MATH_SQRT = 100 # - OS_RAW_MALLOC_VARSIZE_CHAR = 110 + OS_RAW_MALLOC_VARSIZE = 110 OS_RAW_FREE = 111 OS_JIT_FORCE_VIRTUAL = 120 # for debugging: _OS_CANRAISE = set([OS_NONE, OS_STR2UNICODE, OS_LIBFFI_CALL, - OS_RAW_MALLOC_VARSIZE_CHAR, OS_JIT_FORCE_VIRTUAL]) + OS_RAW_MALLOC_VARSIZE, OS_JIT_FORCE_VIRTUAL]) def __new__(cls, readonly_descrs_fields, readonly_descrs_arrays, write_descrs_fields, write_descrs_arrays, diff --git a/rpython/jit/codewriter/jtransform.py b/rpython/jit/codewriter/jtransform.py --- a/rpython/jit/codewriter/jtransform.py +++ b/rpython/jit/codewriter/jtransform.py @@ -539,11 +539,9 @@ name += '_no_track_allocation' op1 = self.prepare_builtin_call(op, name, args, (TYPE,), TYPE) if name == 'raw_malloc_varsize': - ITEMTYPE = op.args[0].value.OF - if ITEMTYPE == lltype.Char: - return self._handle_oopspec_call(op1, args, - EffectInfo.OS_RAW_MALLOC_VARSIZE_CHAR, - EffectInfo.EF_CAN_RAISE) + return self._handle_oopspec_call(op1, args, + EffectInfo.OS_RAW_MALLOC_VARSIZE, + EffectInfo.EF_CAN_RAISE) return self.rewrite_op_direct_call(op1) def rewrite_op_malloc_varsize(self, op): diff --git a/rpython/jit/codewriter/test/test_jtransform.py b/rpython/jit/codewriter/test/test_jtransform.py --- a/rpython/jit/codewriter/test/test_jtransform.py +++ b/rpython/jit/codewriter/test/test_jtransform.py @@ -126,7 +126,7 @@ INT = lltype.Signed UNICHAR = lltype.UniChar FLOAT = lltype.Float - ARRAYPTR = rffi.CArrayPtr(lltype.Char) + ARRAYPTR = rffi.CArrayPtr(lltype.Signed) argtypes = { EI.OS_MATH_SQRT: ([FLOAT], FLOAT), EI.OS_STR2UNICODE:([PSTR], PUNICODE), @@ -143,7 +143,7 @@ EI.OS_UNIEQ_NONNULL_CHAR: ([PUNICODE, UNICHAR], INT), EI.OS_UNIEQ_CHECKNULL_CHAR: ([PUNICODE, UNICHAR], INT), EI.OS_UNIEQ_LENGTHOK: ([PUNICODE, PUNICODE], INT), - EI.OS_RAW_MALLOC_VARSIZE_CHAR: ([INT], ARRAYPTR), + EI.OS_RAW_MALLOC_VARSIZE: ([INT], ARRAYPTR), EI.OS_RAW_FREE: ([ARRAYPTR], lltype.Void), } argtypes = argtypes[oopspecindex] @@ -151,7 +151,7 @@ assert argtypes[1] == op.result.concretetype if oopspecindex == EI.OS_STR2UNICODE: assert extraeffect == EI.EF_ELIDABLE_CAN_RAISE - elif oopspecindex == EI.OS_RAW_MALLOC_VARSIZE_CHAR: + elif oopspecindex == EI.OS_RAW_MALLOC_VARSIZE: assert extraeffect == EI.EF_CAN_RAISE elif oopspecindex == EI.OS_RAW_FREE: assert extraeffect == EI.EF_CANNOT_RAISE @@ -161,7 +161,7 @@ def calldescr_canraise(self, calldescr): EI = effectinfo.EffectInfo - if calldescr == 'calldescr-%d' % EI.OS_RAW_MALLOC_VARSIZE_CHAR: + if calldescr == 'calldescr-%d' % EI.OS_RAW_MALLOC_VARSIZE: return True return False @@ -555,7 +555,7 @@ assert op1.args == [] def test_raw_malloc(): - S = rffi.CArray(lltype.Char) + S = rffi.CArray(lltype.Signed) v1 = varoftype(lltype.Signed) v = varoftype(lltype.Ptr(S)) flags = Constant({'flavor': 'raw'}, lltype.Void) @@ -566,7 +566,7 @@ assert op0.opname == 'residual_call_ir_i' assert op0.args[0].value == 'raw_malloc_varsize' # pseudo-function as a str assert (op0.args[-1] == 'calldescr-%d' % - effectinfo.EffectInfo.OS_RAW_MALLOC_VARSIZE_CHAR) + effectinfo.EffectInfo.OS_RAW_MALLOC_VARSIZE) assert op1.opname == '-live-' assert op1.args == [] @@ -608,7 +608,7 @@ assert op1.args == [] def test_raw_free(): - S = rffi.CArray(lltype.Char) + S = rffi.CArray(lltype.Signed) flags = Constant({'flavor': 'raw', 'track_allocation': True}, lltype.Void) op = SpaceOperation('free', [varoftype(lltype.Ptr(S)), flags], diff --git a/rpython/jit/metainterp/compile.py b/rpython/jit/metainterp/compile.py --- a/rpython/jit/metainterp/compile.py +++ b/rpython/jit/metainterp/compile.py @@ -15,7 +15,7 @@ from rpython.jit.metainterp import history, resume from rpython.jit.metainterp.optimize import InvalidLoop from rpython.jit.metainterp.inliner import Inliner -from rpython.jit.metainterp.resume import NUMBERING, PENDINGFIELDSP, ResumeDataDirectReader +from rpython.jit.metainterp.resume import NUMBERING, PENDINGFIELDSP from rpython.jit.codewriter import heaptracker, longlong def giveup(): @@ -656,9 +656,9 @@ class AllVirtuals: llopaque = True - cache = None - def __init__(self, cache): - self.cache = cache + list = [resume.ResumeDataDirectReader.virtual_default] # annotation hack + def __init__(self, list): + self.list = list def hide(self, cpu): ptr = cpu.ts.cast_instance_to_base_ref(self) return cpu.ts.cast_to_ref(ptr) @@ -682,9 +682,9 @@ from rpython.jit.metainterp.blackhole import resume_in_blackhole hidden_all_virtuals = metainterp_sd.cpu.get_savedata_ref(deadframe) obj = AllVirtuals.show(metainterp_sd.cpu, hidden_all_virtuals) - all_virtuals = obj.cache + all_virtuals = obj.list if all_virtuals is None: - all_virtuals = ResumeDataDirectReader.VirtualCache([], []) + all_virtuals = [] assert jitdriver_sd is self.jitdriver_sd resume_in_blackhole(metainterp_sd, jitdriver_sd, self, deadframe, all_virtuals) diff --git a/rpython/jit/metainterp/history.py b/rpython/jit/metainterp/history.py --- a/rpython/jit/metainterp/history.py +++ b/rpython/jit/metainterp/history.py @@ -191,6 +191,7 @@ def get_jitcode_for_class(self, oocls): return self.jitcodes[oocls] + class Const(AbstractValue): __slots__ = () diff --git a/rpython/jit/metainterp/optimizeopt/earlyforce.py b/rpython/jit/metainterp/optimizeopt/earlyforce.py --- a/rpython/jit/metainterp/optimizeopt/earlyforce.py +++ b/rpython/jit/metainterp/optimizeopt/earlyforce.py @@ -1,26 +1,15 @@ -from rpython.jit.codewriter.effectinfo import EffectInfo from rpython.jit.metainterp.optimizeopt.optimizer import Optimization from rpython.jit.metainterp.optimizeopt.vstring import VAbstractStringValue from rpython.jit.metainterp.resoperation import rop, ResOperation -def is_raw_free(op, opnum): - if opnum != rop.CALL: - return False - einfo = op.getdescr().get_extra_info() - return einfo.oopspecindex == EffectInfo.OS_RAW_FREE - - class OptEarlyForce(Optimization): def propagate_forward(self, op): opnum = op.getopnum() - if (opnum != rop.SETFIELD_GC and opnum != rop.SETARRAYITEM_GC and - opnum != rop.SETARRAYITEM_RAW and opnum != rop.QUASIIMMUT_FIELD and opnum != rop.SAME_AS and - opnum != rop.MARK_OPAQUE_PTR and - not is_raw_free(op, opnum)): + opnum != rop.MARK_OPAQUE_PTR): for arg in op.getarglist(): if arg in self.optimizer.values: diff --git a/rpython/jit/metainterp/optimizeopt/optimizer.py b/rpython/jit/metainterp/optimizeopt/optimizer.py --- a/rpython/jit/metainterp/optimizeopt/optimizer.py +++ b/rpython/jit/metainterp/optimizeopt/optimizer.py @@ -231,12 +231,6 @@ def setitem(self, index, value): raise NotImplementedError - def getitem_raw(self, offset, length, descr): - raise NotImplementedError - - def setitem_raw(self, offset, length, descr, value): - raise NotImplementedError - def getinteriorfield(self, index, ofs, default): raise NotImplementedError diff --git a/rpython/jit/metainterp/optimizeopt/rawbuffer.py b/rpython/jit/metainterp/optimizeopt/rawbuffer.py deleted file mode 100644 --- a/rpython/jit/metainterp/optimizeopt/rawbuffer.py +++ /dev/null @@ -1,134 +0,0 @@ -from rpython.rlib.debug import debug_start, debug_stop, debug_print -from rpython.rlib.objectmodel import compute_unique_id, we_are_translated - -class InvalidRawOperation(Exception): - pass - -class InvalidRawWrite(InvalidRawOperation): - pass - -class InvalidRawRead(InvalidRawOperation): - pass - -class RawBuffer(object): - def __init__(self, cpu, logops=None): - # the following lists represents the writes in the buffer: values[i] - # is the value of length lengths[i] stored at offset[i]. - # - # the invariant is that they are ordered by offset, and that - # offset[i]+length[i] <= offset[i+1], i.e. that the writes never - # overlaps - self.cpu = cpu - self.logops = logops - self.offsets = [] - self.lengths = [] - self.descrs = [] - self.values = [] - - def _get_memory(self): - """ - NOT_RPYTHON - for testing only - """ - return zip(self.offsets, self.lengths, self.descrs, self.values) - - def _repr_of_descr(self, descr): - if self.logops: - s = self.logops.repr_of_descr(descr) - else: - s = str(descr) - s += " at %d" % compute_unique_id(descr) - return s - - def _repr_of_value(self, value): - if not we_are_translated() and isinstance(value, str): - return value # for tests - if self.logops: - s = self.logops.repr_of_arg(value.box) - else: - s = str(value.box) - s += " at %d" % compute_unique_id(value.box) - return s - - def _dump_to_log(self): - debug_print("RawBuffer state") - debug_print("offset, length, descr, box") - debug_print("(box == None means that the value is still virtual)") - for i in range(len(self.offsets)): - descr = self._repr_of_descr(self.descrs[i]) - box = self._repr_of_value(self.values[i]) - debug_print("%d, %d, %s, %s" % (self.offsets[i], self.lengths[i], descr, box)) - - def _invalid_write(self, message, offset, length, descr, value): - debug_start('jit-log-rawbuffer') - debug_print('Invalid write: %s' % message) - debug_print(" offset: %d" % offset) - debug_print(" length: %d" % length) - debug_print(" descr: %s" % self._repr_of_descr(descr)) - debug_print(" value: %s" % self._repr_of_value(value)) - self._dump_to_log() - debug_stop('jit-log-rawbuffer') - raise InvalidRawWrite - - def _invalid_read(self, message, offset, length, descr): - debug_start('jit-log-rawbuffer') - debug_print('Invalid read: %s' % message) - debug_print(" offset: %d" % offset) - debug_print(" length: %d" % length) - debug_print(" descr: %s" % self._repr_of_descr(descr)) - self._dump_to_log() - debug_stop('jit-log-rawbuffer') - raise InvalidRawRead - - def _descrs_are_compatible(self, d1, d2): - # two arraydescrs are compatible if they have the same basesize, - # itemsize and sign, even if they are not identical - unpack = self.cpu.unpack_arraydescr_size - return unpack(d1) == unpack(d2) - - def write_value(self, offset, length, descr, value): - i = 0 - N = len(self.offsets) - while i < N: - if self.offsets[i] == offset: - if (length != self.lengths[i] or not - self._descrs_are_compatible(descr, self.descrs[i])): - # in theory we could add support for the cases in which - # the length or descr is different, but I don't think we - # need it in practice - self._invalid_write('length or descr not compatible', - offset, length, descr, value) - # update the value at this offset - self.values[i] = value - return - elif self.offsets[i] > offset: - break - i += 1 - # - if i < len(self.offsets) and offset+length > self.offsets[i]: - self._invalid_write("overlap with next bytes", - offset, length, descr, value) - if i > 0 and self.offsets[i-1]+self.lengths[i-1] > offset: - self._invalid_write("overlap with previous bytes", - offset, length, descr, value) - # insert a new value at offset - self.offsets.insert(i, offset) - self.lengths.insert(i, length) - self.descrs.insert(i, descr) - self.values.insert(i, value) - - def read_value(self, offset, length, descr): - i = 0 - N = len(self.offsets) - while i < N: - if self.offsets[i] == offset: - if (length != self.lengths[i] or - not self._descrs_are_compatible(descr, self.descrs[i])): - self._invalid_read('length or descr not compatible', - offset, length, descr) - return self.values[i] - i += 1 - # memory location not found: this means we are reading from - # uninitialized memory, give up the optimization - self._invalid_read('uninitialized memory', - offset, length, descr) diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py --- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py @@ -770,6 +770,8 @@ """ self.optimize_loop(ops, expected) + + def test_p123_simple(self): ops = """ [i1, p2, p3] @@ -1728,175 +1730,6 @@ # We cannot track virtuals that survive for more than two iterations. self.optimize_loop(ops, expected, preamble) - def test_virtual_raw_malloc(self): - ops = """ - [i1] - i2 = call('malloc', 10, descr=raw_malloc_descr) - setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) - i3 = getarrayitem_raw(i2, 0, descr=rawarraydescr) - call('free', i2, descr=raw_free_descr) - jump(i3) - """ - expected = """ - [i1] - jump(i1) - """ - self.optimize_loop(ops, expected) - - def test_virtual_raw_malloc_force(self): - ops = """ - [i1] - i2 = call('malloc', 10, descr=raw_malloc_descr) - setarrayitem_raw(i2, 0, i1, descr=rawarraydescr_char) - setarrayitem_raw(i2, 2, 456, descr=rawarraydescr_char) - setarrayitem_raw(i2, 1, 123, descr=rawarraydescr_char) - label('foo') # we expect the buffer to be forced *after* the label - escape(i2) - call('free', i2, descr=raw_free_descr) - jump(i1) - """ - expected = """ - [i1] - label('foo') - i2 = call('malloc', 10, descr=raw_malloc_descr) - setarrayitem_raw(i2, 0, i1, descr=rawarraydescr_char) - i3 = int_add(i2, 1) - setarrayitem_raw(i3, 0, 123, descr=rawarraydescr_char) - i4 = int_add(i2, 2) - setarrayitem_raw(i4, 0, 456, descr=rawarraydescr_char) - escape(i2) - call('free', i2, descr=raw_free_descr) - jump(i1) - """ - self.optimize_loop(ops, expected) - - def test_virtual_raw_malloc_invalid_write_force(self): - ops = """ - [i1] - i2 = call('malloc', 10, descr=raw_malloc_descr) - setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) - label('foo') # we expect the buffer to be forced *after* the label - setarrayitem_raw(i2, 2, 456, descr=rawarraydescr_char) # overlap! - call('free', i2, descr=raw_free_descr) - jump(i1) - """ - expected = """ - [i1] - label('foo') - i2 = call('malloc', 10, descr=raw_malloc_descr) - setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) - setarrayitem_raw(i2, 2, 456, descr=rawarraydescr_char) - call('free', i2, descr=raw_free_descr) - jump(i1) - """ - self.optimize_loop(ops, expected) - - def test_virtual_raw_malloc_invalid_read_force(self): - ops = """ - [i1] - i2 = call('malloc', 10, descr=raw_malloc_descr) - setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) - label('foo') # we expect the buffer to be forced *after* the label - i3 = getarrayitem_raw(i2, 0, descr=rawarraydescr_char) - call('free', i2, descr=raw_free_descr) - jump(i1) - """ - expected = """ - [i1] - label('foo') - i2 = call('malloc', 10, descr=raw_malloc_descr) - setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) - i3 = getarrayitem_raw(i2, 0, descr=rawarraydescr_char) - call('free', i2, descr=raw_free_descr) - jump(i1) - """ - self.optimize_loop(ops, expected) - - def test_virtual_raw_slice(self): - ops = """ - [i0, i1] - i2 = call('malloc', 10, descr=raw_malloc_descr) - setarrayitem_raw(i2, 0, 42, descr=rawarraydescr_char) - i3 = int_add(i2, 1) # get a slice of the original buffer - setarrayitem_raw(i3, 0, 4242, descr=rawarraydescr) # write to the slice - i4 = getarrayitem_raw(i2, 0, descr=rawarraydescr_char) - i5 = int_add(i2, 1) - i6 = getarrayitem_raw(i5, 0, descr=rawarraydescr) - call('free', i2, descr=raw_free_descr) - jump(i0, i1) - """ - expected = """ - [i0, i1] - jump(i0, i1) - """ - self.optimize_loop(ops, expected) - - def test_virtual_raw_slice_of_a_raw_slice(self): - ops = """ - [i0, i1] - i2 = call('malloc', 10, descr=raw_malloc_descr) - i3 = int_add(i2, 1) # get a slice of the original buffer - i4 = int_add(i3, 1) # get a slice of a slice - setarrayitem_raw(i4, 0, i1, descr=rawarraydescr_char) # write to the slice - i5 = getarrayitem_raw(i2, 2, descr=rawarraydescr_char) - call('free', i2, descr=raw_free_descr) - jump(i0, i5) - """ - expected = """ - [i0, i1] - jump(i0, i1) - """ - self.optimize_loop(ops, expected) - - def test_virtual_raw_slice_force(self): - ops = """ - [i0, i1] - i2 = call('malloc', 10, descr=raw_malloc_descr) - setarrayitem_raw(i2, 0, 42, descr=rawarraydescr_char) - i3 = int_add(i2, 1) # get a slice of the original buffer - setarrayitem_raw(i3, 4, 4242, descr=rawarraydescr_char) # write to the slice - label('foo') - escape(i3) - jump(i0, i1) - """ - expected = """ - [i0, i1] - label('foo') - # these ops are generated by VirtualRawBufferValue._really_force - i2 = call('malloc', 10, descr=raw_malloc_descr) - setarrayitem_raw(i2, 0, 42, descr=rawarraydescr_char) - i3 = int_add(i2, 5) # 1+4*sizeof(char) - setarrayitem_raw(i3, 0, 4242, descr=rawarraydescr_char) - # this is generated by VirtualRawSliceValue._really_force - i4 = int_add(i2, 1) - escape(i4) - jump(i0, i1) - """ - self.optimize_loop(ops, expected) - - def test_virtual_raw_malloc_virtualstate(self): - ops = """ - [i0] - i1 = getarrayitem_raw(i0, 0, descr=rawarraydescr) - i2 = int_add(i1, 1) - call('free', i0, descr=raw_free_descr) - i3 = call('malloc', 10, descr=raw_malloc_descr) - setarrayitem_raw(i3, 0, i2, descr=rawarraydescr) - label('foo') - jump(i3) - """ - expected = """ - [i0] - i1 = getarrayitem_raw(i0, 0, descr=rawarraydescr) - i2 = int_add(i1, 1) - call('free', i0, descr=raw_free_descr) - label('foo') - i3 = call('malloc', 10, descr=raw_malloc_descr) - setarrayitem_raw(i3, 0, i2, descr=rawarraydescr) - jump(i3) - """ - self.optimize_loop(ops, expected) - def test_duplicate_getfield_1(self): ops = """ [p1, p2] diff --git a/rpython/jit/metainterp/optimizeopt/test/test_rawbuffer.py b/rpython/jit/metainterp/optimizeopt/test/test_rawbuffer.py deleted file mode 100644 --- a/rpython/jit/metainterp/optimizeopt/test/test_rawbuffer.py +++ /dev/null @@ -1,90 +0,0 @@ -import py -from rpython.jit.metainterp.optimizeopt.rawbuffer import (InvalidRawWrite, - InvalidRawRead, RawBuffer) - -class FakeCPU(object): - def unpack_arraydescr_size(self, descr): - return descr, 'foo', 'bar' - -def test_write_value(): - buf = RawBuffer(FakeCPU()) - buf.write_value(8, 4, 'descr3', 'three') - buf.write_value(0, 4, 'descr1', 'one') - buf.write_value(4, 2, 'descr2', 'two') - buf.write_value(12, 2, 'descr4', 'four') - assert buf._get_memory() == [ - ( 0, 4, 'descr1', 'one'), - ( 4, 2, 'descr2', 'two'), - ( 8, 4, 'descr3', 'three'), - (12, 2, 'descr4', 'four'), - ] - # - -def test_write_value_update(): - buf = RawBuffer(FakeCPU()) - buf.write_value(0, 4, 'descr', 'one') - buf.write_value(4, 2, 'descr', 'two') - buf.write_value(0, 4, 'descr', 'ONE') - assert buf._get_memory() == [ - ( 0, 4, 'descr', 'ONE'), - ( 4, 2, 'descr', 'two'), - ] - -def test_write_value_invalid_length(): - buf = RawBuffer(FakeCPU()) - buf.write_value(0, 4, 'descr1', 'one') - with py.test.raises(InvalidRawWrite): - buf.write_value(0, 5, 'descr1', 'two') - with py.test.raises(InvalidRawWrite): - buf.write_value(0, 4, 'descr2', 'two') - - -def test_write_value_overlapping_next(): - buf = RawBuffer(FakeCPU()) - buf.write_value(0, 4, 'descr', 'one') - buf.write_value(6, 4, 'descr', 'two') - with py.test.raises(InvalidRawWrite): - buf.write_value(4, 4, 'descr', 'three') - -def test_write_value_overlapping_prev(): - buf = RawBuffer(FakeCPU()) - buf.write_value(0, 4, 'descr', 'one') - with py.test.raises(InvalidRawWrite): - buf.write_value(2, 1, 'descr', 'two') - -def test_read_value(): - buf = RawBuffer(FakeCPU()) - buf.write_value(0, 4, 'descr', 'one') - buf.write_value(4, 4, 'descr', 'two') - assert buf.read_value(0, 4, 'descr') == 'one' - assert buf.read_value(4, 4, 'descr') == 'two' - with py.test.raises(InvalidRawRead): - buf.read_value(0, 2, 'descr') - with py.test.raises(InvalidRawRead): - buf.read_value(8, 2, 'descr') - with py.test.raises(InvalidRawRead): - buf.read_value(0, 4, 'another descr') - -def test_unpack_descrs(): - ArrayS_8_1 = object() - ArrayS_8_2 = object() - ArrayU_8 = object() - - class FakeCPU(object): - def unpack_arraydescr_size(self, descr): - if descr in (ArrayS_8_1, ArrayS_8_2): - return 0, 8, True - return 0, 8, False - - buf = RawBuffer(FakeCPU()) - buf.write_value(0, 4, ArrayS_8_1, 'one') - assert buf.read_value(0, 4, ArrayS_8_1) == 'one' - assert buf.read_value(0, 4, ArrayS_8_2) == 'one' # with a non-identical descr - # - buf.write_value(0, 4, ArrayS_8_2, 'two') # with a non-identical descr - assert buf.read_value(0, 4, ArrayS_8_1) == 'two' - # - with py.test.raises(InvalidRawRead): - buf.read_value(0, 4, ArrayU_8) - with py.test.raises(InvalidRawWrite): - buf.write_value(0, 4, ArrayU_8, 'three') diff --git a/rpython/jit/metainterp/optimizeopt/test/test_util.py b/rpython/jit/metainterp/optimizeopt/test/test_util.py --- a/rpython/jit/metainterp/optimizeopt/test/test_util.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_util.py @@ -196,15 +196,6 @@ EffectInfo.EF_CANNOT_RAISE, oopspecindex=EffectInfo.OS_ARRAYCOPY)) - raw_malloc_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, - EffectInfo([], [], [], [], - EffectInfo.EF_CAN_RAISE, - oopspecindex=EffectInfo.OS_RAW_MALLOC_VARSIZE_CHAR)) - raw_free_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, - EffectInfo([], [], [], [], - EffectInfo.EF_CANNOT_RAISE, - oopspecindex=EffectInfo.OS_RAW_FREE)) - # array of structs (complex data) complexarray = lltype.GcArray( @@ -217,12 +208,6 @@ complexrealdescr = cpu.interiorfielddescrof(complexarray, "real") compleximagdescr = cpu.interiorfielddescrof(complexarray, "imag") - rawarraydescr = cpu.arraydescrof(lltype.Array(lltype.Signed, - hints={'nolength': True})) - rawarraydescr_char = cpu.arraydescrof(lltype.Array(lltype.Char, - hints={'nolength': True})) - - for _name, _os in [ ('strconcatdescr', 'OS_STR_CONCAT'), ('strslicedescr', 'OS_STR_SLICE'), diff --git a/rpython/jit/metainterp/optimizeopt/virtualize.py b/rpython/jit/metainterp/optimizeopt/virtualize.py --- a/rpython/jit/metainterp/optimizeopt/virtualize.py +++ b/rpython/jit/metainterp/optimizeopt/virtualize.py @@ -6,9 +6,7 @@ from rpython.jit.metainterp.optimizeopt import optimizer from rpython.jit.metainterp.optimizeopt.optimizer import OptValue, REMOVED from rpython.jit.metainterp.optimizeopt.util import (make_dispatcher_method, - descrlist_dict, sort_descrs) - -from rpython.jit.metainterp.optimizeopt.rawbuffer import RawBuffer, InvalidRawOperation + descrlist_dict, sort_descrs) from rpython.jit.metainterp.resoperation import rop, ResOperation from rpython.rlib.objectmodel import we_are_translated @@ -238,36 +236,8 @@ def _get_descr(self): return self.structdescr -class AbstractVArrayValue(AbstractVirtualValue): - """ - Base class for VArrayValue (for normal GC arrays) and VRawBufferValue (for - malloc()ed memory) - """ - def getlength(self): - return len(self._items) - - def get_item_value(self, i): - raise NotImplementedError - - def set_item_value(self, i, newval): - raise NotImplementedError - - def get_args_for_fail(self, modifier): - if self.box is None and not modifier.already_seen_virtual(self.keybox): - # checks for recursion: it is False unless - # we have already seen the very same keybox - itemboxes = [] - for i in range(self.getlength()): - itemvalue = self.get_item_value(i) - itemboxes.append(itemvalue.get_key_box()) - modifier.register_virtual_fields(self.keybox, itemboxes) - for i in range(self.getlength()): - itemvalue = self.get_item_value(i) - itemvalue.get_args_for_fail(modifier) - - -class VArrayValue(AbstractVArrayValue): +class VArrayValue(AbstractVirtualValue): def __init__(self, arraydescr, constvalue, size, keybox, source_op=None): AbstractVirtualValue.__init__(self, keybox, source_op) @@ -278,12 +248,6 @@ def getlength(self): return len(self._items) - def get_item_value(self, i): - return self._items[i] - - def set_item_value(self, i, newval): - self._items[i] = newval - def getitem(self, index): res = self._items[index] return res @@ -293,16 +257,11 @@ self._items[index] = itemvalue def force_at_end_of_preamble(self, already_forced, optforce): - # note that this method is on VArrayValue instead of - # AbstractVArrayValue because we do not want to support virtualstate - # for rawbuffers for now if self in already_forced: return self already_forced[self] = self - for index in range(self.getlength()): - itemval = self.get_item_value(index) - itemval = itemval.force_at_end_of_preamble(already_forced, optforce) - self.set_item_value(index, itemval) + for index in range(len(self._items)): + self._items[index] = self._items[index].force_at_end_of_preamble(already_forced, optforce) return self def _really_force(self, optforce): @@ -322,16 +281,29 @@ descr=self.arraydescr) optforce.emit_operation(op) + def get_args_for_fail(self, modifier): + if self.box is None and not modifier.already_seen_virtual(self.keybox): + # checks for recursion: it is False unless + # we have already seen the very same keybox + itemboxes = [] + for itemvalue in self._items: + itemboxes.append(itemvalue.get_key_box()) + modifier.register_virtual_fields(self.keybox, itemboxes) + for itemvalue in self._items: + itemvalue.get_args_for_fail(modifier) + def _make_virtual(self, modifier): return modifier.make_varray(self.arraydescr) - class VArrayStructValue(AbstractVirtualValue): def __init__(self, arraydescr, size, keybox, source_op=None): AbstractVirtualValue.__init__(self, keybox, source_op) self.arraydescr = arraydescr self._items = [{} for _ in xrange(size)] + def getlength(self): + return len(self._items) + def getinteriorfield(self, index, ofs, default): return self._items[index].get(ofs, default) @@ -391,90 +363,6 @@ return modifier.make_varraystruct(self.arraydescr, self._get_list_of_descrs()) -class VRawBufferValue(AbstractVArrayValue): - - def __init__(self, cpu, logops, size, keybox, source_op): - AbstractVirtualValue.__init__(self, keybox, source_op) - # note that size is unused, because we assume that the buffer is big - # enough to write/read everything we need. If it's not, it's undefined - # behavior anyway, although in theory we could probably detect such - # cases here - self.size = size - self.buffer = RawBuffer(cpu, logops) - - def getlength(self): - return len(self.buffer.values) - - def get_item_value(self, i): - return self.buffer.values[i] - - def set_item_value(self, i, newval): - self.buffer.values[i] = newval - From noreply at buildbot.pypy.org Sun Apr 14 21:34:36 2013 From: noreply at buildbot.pypy.org (fijal) Date: Sun, 14 Apr 2013 21:34:36 +0200 (CEST) Subject: [pypy-commit] pypy default: (agaynor, fijal) write a passing test Message-ID: <20130414193436.75F071C1258@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r63338:a63bd427ed98 Date: 2013-04-14 21:36 +0200 http://bitbucket.org/pypy/pypy/changeset/a63bd427ed98/ Log: (agaynor, fijal) write a passing test diff --git a/rpython/jit/backend/test/runner_test.py b/rpython/jit/backend/test/runner_test.py --- a/rpython/jit/backend/test/runner_test.py +++ b/rpython/jit/backend/test/runner_test.py @@ -2831,6 +2831,51 @@ assert self.cpu.get_int_value(deadframe, 0) == 97 assert not called + def test_assembler_call_propagate_exc(self): + excdescr = BasicFailDescr(666) + self.cpu.propagate_exception_descr = excdescr + self.cpu.setup_once() # xxx redo it, because we added + # propagate_exception + + def assembler_helper(deadframe, virtualizable): + assert self.cpu.get_latest_descr(deadframe) is excdescr + # let's assume we handled that + return 3 + + FUNCPTR = lltype.Ptr(lltype.FuncType([llmemory.GCREF, + llmemory.GCREF], + lltype.Signed)) + class FakeJitDriverSD: + index_of_virtualizable = -1 + _assembler_helper_ptr = llhelper(FUNCPTR, assembler_helper) + assembler_helper_adr = llmemory.cast_ptr_to_adr( + _assembler_helper_ptr) + + ops = ''' + [i0] + p0 = newunicode(i0) + finish(p0)''' + loop = parse(ops) + looptoken = JitCellToken() + looptoken.outermost_jitdriver_sd = FakeJitDriverSD() + self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken) + ARGS = [lltype.Signed] * 10 + RES = lltype.Signed + FakeJitDriverSD.portal_calldescr = self.cpu.calldescrof( + lltype.Ptr(lltype.FuncType(ARGS, RES)), ARGS, RES, + EffectInfo.MOST_GENERAL) + ops = ''' + [i0] + i11 = call_assembler(i0, descr=looptoken) + guard_not_forced()[] + finish(i11) + ''' + loop = parse(ops, namespace=locals()) + othertoken = JitCellToken() + self.cpu.compile_loop(loop.inputargs, loop.operations, othertoken) + deadframe = self.cpu.execute_token(othertoken, sys.maxint - 1) + assert self.cpu.get_int_value(deadframe, 0) == 3 + def test_assembler_call_float(self): if not self.cpu.supports_floats: py.test.skip("requires floats") @@ -3341,7 +3386,7 @@ excdescr = BasicFailDescr(666) self.cpu.propagate_exception_descr = excdescr self.cpu.setup_once() # xxx redo it, because we added - # propagate_exception_v + # propagate_exception i0 = BoxInt() p0 = BoxPtr() operations = [ From noreply at buildbot.pypy.org Sun Apr 14 22:02:57 2013 From: noreply at buildbot.pypy.org (fijal) Date: Sun, 14 Apr 2013 22:02:57 +0200 (CEST) Subject: [pypy-commit] pypy default: An attempt to fix a race condition between reloading the frame and reacquiring Message-ID: <20130414200257.975A31C05C8@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r63339:66659a64a11b Date: 2013-04-14 22:02 +0200 http://bitbucket.org/pypy/pypy/changeset/66659a64a11b/ Log: An attempt to fix a race condition between reloading the frame and reacquiring the GIL. Not sure how to test it :/ diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -563,7 +563,7 @@ if expected_size == -1: mc.MOV_si(WORD, 0xffffff) else: - mc.MOV_si(WORD, expected_size) + mc.MOV_si(WORD, expected_size) ofs2 = mc.get_relative_pos() - 4 self.push_gcmap(mc, gcmap, mov=True) mc.CALL(imm(self._frame_realloc_slowpath)) @@ -601,7 +601,7 @@ mc = codebuf.MachineCodeBlockWrapper() mc.writeimm32(allocated_depth) mc.copy_to_raw_memory(adr) - + def get_asmmemmgr_blocks(self, looptoken): clt = looptoken.compiled_loop_token if clt.asmmemmgr_blocks is None: @@ -614,7 +614,7 @@ allblocks = self.get_asmmemmgr_blocks(looptoken) return self.mc.materialize(self.cpu.asmmemmgr, allblocks, self.cpu.gc_ll_descr.gcrootmap) - + def patch_jump_for_descr(self, faildescr, adr_new_target): adr_jump_offset = faildescr._x86_adr_jump_offset assert adr_jump_offset != 0 @@ -812,7 +812,7 @@ else: assert isinstance(to_loc, RawEspLoc) self.mc.MOV32_si(to_loc.value, low_part) - self.mc.MOV32_si(to_loc.value + 4, high_part) + self.mc.MOV32_si(to_loc.value + 4, high_part) def regalloc_perform(self, op, arglocs, resloc): genop_list[op.getopnum()](self, op, arglocs, resloc) @@ -974,12 +974,13 @@ def _emit_call(self, x, arglocs, start=0, tmp=eax, argtypes=None, callconv=FFI_DEFAULT_ABI, can_collect=1, - stack_max=PASS_ON_MY_FRAME): + stack_max=PASS_ON_MY_FRAME, reload_frame=False): if can_collect == 1 and not self._is_asmgcc(): can_collect = 2 # don't bother with jf_extra_stack_depth if IS_X86_64: return self._emit_call_64(x, arglocs, start, argtypes, - can_collect, stack_max) + can_collect, stack_max, + reload_frame=reload_frame) stack_depth = 0 n = len(arglocs) for i in range(start, n): @@ -1029,6 +1030,8 @@ ofs = self.cpu.get_ofs_of_frame_field('jf_extra_stack_depth') self.mc.MOV_bi(ofs, 0) self.pop_gcmap(self.mc) + elif reload_frame: + self._reload_frame_if_necessary(self.mc) # def _fix_stdcall(self, callconv, p): @@ -1039,7 +1042,7 @@ self.mc.SUB_ri(esp.value, p) def _emit_call_64(self, x, arglocs, start, argtypes, - can_collect, stack_max): + can_collect, stack_max, reload_frame=False): src_locs = [] dst_locs = [] xmm_src_locs = [] @@ -1129,6 +1132,8 @@ if align and can_collect == 1: ofs = self.cpu.get_ofs_of_frame_field('jf_extra_stack_depth') self.mc.MOV_bi(ofs, 0) + elif reload_frame: + self._reload_frame_if_necessary(self.mc) if align: self.mc.ADD_ri(esp.value, align * WORD) if can_collect: @@ -1658,7 +1663,7 @@ if exctploc is not None: assert exctploc.is_reg() mc.MOV(exctploc, heap(self.cpu.pos_exception())) - + mc.MOV(heap(self.cpu.pos_exception()), imm0) mc.MOV(heap(self.cpu.pos_exc_value()), imm0) @@ -2072,7 +2077,8 @@ reg = edi self.mc.LEA_rs(reg.value, css) args = [reg] - self._emit_call(imm(self.reacqgil_addr), args, can_collect=False) + self._emit_call(imm(self.reacqgil_addr), args, can_collect=False, + reload_frame=True) # restore the result from the stack if isinstance(save_loc, RegLoc) and not save_loc.is_xmm: self.mc.MOV_rs(save_loc.value, WORD) From noreply at buildbot.pypy.org Sun Apr 14 22:13:29 2013 From: noreply at buildbot.pypy.org (alex_gaynor) Date: Sun, 14 Apr 2013 22:13:29 +0200 (CEST) Subject: [pypy-commit] pypy virtualref-virtualizable: (alex, fijal): switch to using box-or-None instead ofa product type Message-ID: <20130414201329.140E51C05C8@cobra.cs.uni-duesseldorf.de> Author: Alex Gaynor Branch: virtualref-virtualizable Changeset: r63340:7d76beea8964 Date: 2013-04-14 13:13 -0700 http://bitbucket.org/pypy/pypy/changeset/7d76beea8964/ Log: (alex, fijal): switch to using box-or-None instead ofa product type diff --git a/rpython/jit/metainterp/pyjitpl.py b/rpython/jit/metainterp/pyjitpl.py --- a/rpython/jit/metainterp/pyjitpl.py +++ b/rpython/jit/metainterp/pyjitpl.py @@ -1374,8 +1374,8 @@ # residual calls require attention to keep virtualizables in-sync self.metainterp.clear_exception() if effectinfo.oopspecindex == EffectInfo.OS_JIT_FORCE_VIRTUAL: - handled, resbox = self._do_jit_force_virtual(allboxes, descr, pc) - if handled: + resbox = self._do_jit_force_virtual(allboxes, descr, pc) + if resbox is not None: return resbox self.metainterp.vable_and_vrefs_before_residual_call() resbox = self.metainterp.execute_and_record_varargs( @@ -1412,20 +1412,20 @@ if (self.metainterp.jitdriver_sd.virtualizable_info is None and self.metainterp.jitdriver_sd.greenfield_info is None): # can occur in case of multiple JITs - return False, None + return None vref_box = allboxes[1] standard_box = self.metainterp.virtualizable_boxes[-1] if standard_box is vref_box: - return True, vref_box + return vref_box if self.metainterp.heapcache.is_nonstandard_virtualizable(vref_box): - return False, None + return None eqbox = self.metainterp.execute_and_record(rop.PTR_EQ, None, vref_box, standard_box) eqbox = self.implement_guard_value(eqbox, pc) isstandard = eqbox.getint() if isstandard: - return True, standard_box + return standard_box else: - return False, None + return None def do_residual_or_indirect_call(self, funcbox, argboxes, calldescr, pc): """The 'residual_call' operation is emitted in two cases: From noreply at buildbot.pypy.org Sun Apr 14 22:14:51 2013 From: noreply at buildbot.pypy.org (alex_gaynor) Date: Sun, 14 Apr 2013 22:14:51 +0200 (CEST) Subject: [pypy-commit] pypy virtualref-virtualizable: Close to be merged branch. Message-ID: <20130414201451.600511C01FD@cobra.cs.uni-duesseldorf.de> Author: Alex Gaynor Branch: virtualref-virtualizable Changeset: r63341:f2541557213e Date: 2013-04-14 13:13 -0700 http://bitbucket.org/pypy/pypy/changeset/f2541557213e/ Log: Close to be merged branch. From noreply at buildbot.pypy.org Sun Apr 14 22:14:52 2013 From: noreply at buildbot.pypy.org (alex_gaynor) Date: Sun, 14 Apr 2013 22:14:52 +0200 (CEST) Subject: [pypy-commit] pypy default: Merged virtualref-virtualizable Message-ID: <20130414201452.C01DF1C01FD@cobra.cs.uni-duesseldorf.de> Author: Alex Gaynor Branch: Changeset: r63342:7dd24d6d73e4 Date: 2013-04-14 13:14 -0700 http://bitbucket.org/pypy/pypy/changeset/7dd24d6d73e4/ Log: Merged virtualref-virtualizable This improves the generated code in cases where a virtualref points to the standard virtualizable and we force it. diff --git a/rpython/jit/codewriter/jtransform.py b/rpython/jit/codewriter/jtransform.py --- a/rpython/jit/codewriter/jtransform.py +++ b/rpython/jit/codewriter/jtransform.py @@ -1753,11 +1753,15 @@ return SpaceOperation('libffi_save_result_%s' % kind, op.args[1:], None) def rewrite_op_jit_force_virtual(self, op): - return self._do_builtin_call(op) + op0 = SpaceOperation('-live-', [], None) + op1 = self._do_builtin_call(op) + if isinstance(op1, list): + return [op0] + op1 + else: + return [op0, op1] def rewrite_op_jit_is_virtual(self, op): - raise Exception, ( - "'vref.virtual' should not be used from jit-visible code") + raise Exception("'vref.virtual' should not be used from jit-visible code") def rewrite_op_jit_force_virtualizable(self, op): # this one is for virtualizables diff --git a/rpython/jit/codewriter/test/test_flatten.py b/rpython/jit/codewriter/test/test_flatten.py --- a/rpython/jit/codewriter/test/test_flatten.py +++ b/rpython/jit/codewriter/test/test_flatten.py @@ -689,6 +689,7 @@ self.encoding_test(f, [], """ new_with_vtable -> %r0 virtual_ref %r0 -> %r1 + -live- residual_call_r_r $<* fn jit_force_virtual>, R[%r1], -> %r2 ref_return %r2 """, transform=True, cc=FakeCallControlWithVRefInfo()) diff --git a/rpython/jit/metainterp/pyjitpl.py b/rpython/jit/metainterp/pyjitpl.py --- a/rpython/jit/metainterp/pyjitpl.py +++ b/rpython/jit/metainterp/pyjitpl.py @@ -1,25 +1,27 @@ -import py, sys +import sys + +import py + +from rpython.jit.codewriter import heaptracker +from rpython.jit.codewriter.effectinfo import EffectInfo +from rpython.jit.codewriter.jitcode import JitCode, SwitchDictDescr +from rpython.jit.metainterp import history, compile, resume, executor +from rpython.jit.metainterp.heapcache import HeapCache +from rpython.jit.metainterp.history import (Const, ConstInt, ConstPtr, + ConstFloat, Box, TargetToken) +from rpython.jit.metainterp.jitexc import JitException, get_llexception +from rpython.jit.metainterp.jitprof import EmptyProfiler +from rpython.jit.metainterp.logger import Logger +from rpython.jit.metainterp.optimizeopt.util import args_dict_box +from rpython.jit.metainterp.resoperation import rop +from rpython.rlib import nonconst, rstack +from rpython.rlib.debug import debug_start, debug_stop, debug_print, make_sure_not_resized +from rpython.rlib.jit import Counters +from rpython.rlib.objectmodel import we_are_translated, specialize +from rpython.rlib.unroll import unrolling_iterable from rpython.rtyper.lltypesystem import lltype, rclass -from rpython.rlib.objectmodel import we_are_translated -from rpython.rlib.unroll import unrolling_iterable -from rpython.rlib.debug import debug_start, debug_stop, debug_print -from rpython.rlib.debug import make_sure_not_resized -from rpython.rlib import nonconst, rstack -from rpython.jit.metainterp import history, compile, resume -from rpython.jit.metainterp.history import Const, ConstInt, ConstPtr, ConstFloat -from rpython.jit.metainterp.history import Box, TargetToken -from rpython.jit.metainterp.resoperation import rop -from rpython.jit.metainterp import executor -from rpython.jit.metainterp.logger import Logger -from rpython.jit.metainterp.jitprof import EmptyProfiler -from rpython.rlib.jit import Counters -from rpython.jit.metainterp.jitexc import JitException, get_llexception -from rpython.jit.metainterp.heapcache import HeapCache -from rpython.rlib.objectmodel import specialize -from rpython.jit.codewriter.jitcode import JitCode, SwitchDictDescr -from rpython.jit.codewriter import heaptracker -from rpython.jit.metainterp.optimizeopt.util import args_dict_box + # ____________________________________________________________ @@ -831,15 +833,17 @@ opimpl_inline_call_irf_f = _opimpl_inline_call3 opimpl_inline_call_irf_v = _opimpl_inline_call3 - @arguments("box", "boxes", "descr") - def _opimpl_residual_call1(self, funcbox, argboxes, calldescr): - return self.do_residual_or_indirect_call(funcbox, argboxes, calldescr) - @arguments("box", "boxes2", "descr") - def _opimpl_residual_call2(self, funcbox, argboxes, calldescr): - return self.do_residual_or_indirect_call(funcbox, argboxes, calldescr) - @arguments("box", "boxes3", "descr") - def _opimpl_residual_call3(self, funcbox, argboxes, calldescr): - return self.do_residual_or_indirect_call(funcbox, argboxes, calldescr) + @arguments("box", "boxes", "descr", "orgpc") + def _opimpl_residual_call1(self, funcbox, argboxes, calldescr, pc): + return self.do_residual_or_indirect_call(funcbox, argboxes, calldescr, pc) + + @arguments("box", "boxes2", "descr", "orgpc") + def _opimpl_residual_call2(self, funcbox, argboxes, calldescr, pc): + return self.do_residual_or_indirect_call(funcbox, argboxes, calldescr, pc) + + @arguments("box", "boxes3", "descr", "orgpc") + def _opimpl_residual_call3(self, funcbox, argboxes, calldescr, pc): + return self.do_residual_or_indirect_call(funcbox, argboxes, calldescr, pc) opimpl_residual_call_r_i = _opimpl_residual_call1 opimpl_residual_call_r_r = _opimpl_residual_call1 @@ -852,8 +856,8 @@ opimpl_residual_call_irf_f = _opimpl_residual_call3 opimpl_residual_call_irf_v = _opimpl_residual_call3 - @arguments("int", "boxes3", "boxes3") - def _opimpl_recursive_call(self, jdindex, greenboxes, redboxes): + @arguments("int", "boxes3", "boxes3", "orgpc") + def _opimpl_recursive_call(self, jdindex, greenboxes, redboxes, pc): targetjitdriver_sd = self.metainterp.staticdata.jitdrivers_sd[jdindex] allboxes = greenboxes + redboxes warmrunnerstate = targetjitdriver_sd.warmstate @@ -868,15 +872,15 @@ # that assembler that we call is still correct self.verify_green_args(targetjitdriver_sd, greenboxes) # - return self.do_recursive_call(targetjitdriver_sd, allboxes, + return self.do_recursive_call(targetjitdriver_sd, allboxes, pc, assembler_call) - def do_recursive_call(self, targetjitdriver_sd, allboxes, + def do_recursive_call(self, targetjitdriver_sd, allboxes, pc, assembler_call=False): portal_code = targetjitdriver_sd.mainjitcode k = targetjitdriver_sd.portal_runner_adr funcbox = ConstInt(heaptracker.adr2int(k)) - return self.do_residual_call(funcbox, allboxes, portal_code.calldescr, + return self.do_residual_call(funcbox, allboxes, portal_code.calldescr, pc, assembler_call=assembler_call, assembler_call_jd=targetjitdriver_sd) @@ -935,7 +939,7 @@ return box # no promotion needed, already a Const else: constbox = box.constbox() - resbox = self.do_residual_call(funcbox, [box, constbox], descr) + resbox = self.do_residual_call(funcbox, [box, constbox], descr, orgpc) promoted_box = resbox.constbox() # This is GUARD_VALUE because GUARD_TRUE assumes the existance # of a label when computing resumepc @@ -1027,7 +1031,7 @@ except ChangeFrame: pass frame = self.metainterp.framestack[-1] - frame.do_recursive_call(jitdriver_sd, greenboxes + redboxes, + frame.do_recursive_call(jitdriver_sd, greenboxes + redboxes, orgpc, assembler_call=True) raise ChangeFrame @@ -1329,7 +1333,7 @@ self.metainterp.assert_no_exception() return resbox - def do_residual_call(self, funcbox, argboxes, descr, + def do_residual_call(self, funcbox, argboxes, descr, pc, assembler_call=False, assembler_call_jd=None): # First build allboxes: it may need some reordering from the @@ -1369,6 +1373,10 @@ effectinfo.check_forces_virtual_or_virtualizable()): # residual calls require attention to keep virtualizables in-sync self.metainterp.clear_exception() + if effectinfo.oopspecindex == EffectInfo.OS_JIT_FORCE_VIRTUAL: + resbox = self._do_jit_force_virtual(allboxes, descr, pc) + if resbox is not None: + return resbox self.metainterp.vable_and_vrefs_before_residual_call() resbox = self.metainterp.execute_and_record_varargs( rop.CALL_MAY_FORCE, allboxes, descr=descr) @@ -1399,7 +1407,27 @@ pure = effectinfo.check_is_elidable() return self.execute_varargs(rop.CALL, allboxes, descr, exc, pure) - def do_residual_or_indirect_call(self, funcbox, argboxes, calldescr): + def _do_jit_force_virtual(self, allboxes, descr, pc): + assert len(allboxes) == 2 + if (self.metainterp.jitdriver_sd.virtualizable_info is None and + self.metainterp.jitdriver_sd.greenfield_info is None): + # can occur in case of multiple JITs + return None + vref_box = allboxes[1] + standard_box = self.metainterp.virtualizable_boxes[-1] + if standard_box is vref_box: + return vref_box + if self.metainterp.heapcache.is_nonstandard_virtualizable(vref_box): + return None + eqbox = self.metainterp.execute_and_record(rop.PTR_EQ, None, vref_box, standard_box) + eqbox = self.implement_guard_value(eqbox, pc) + isstandard = eqbox.getint() + if isstandard: + return standard_box + else: + return None + + def do_residual_or_indirect_call(self, funcbox, argboxes, calldescr, pc): """The 'residual_call' operation is emitted in two cases: when we have to generate a residual CALL operation, but also to handle an indirect_call that may need to be inlined.""" @@ -1411,7 +1439,7 @@ # we should follow calls to this graph return self.metainterp.perform_call(jitcode, argboxes) # but we should not follow calls to that graph - return self.do_residual_call(funcbox, argboxes, calldescr) + return self.do_residual_call(funcbox, argboxes, calldescr, pc) # ____________________________________________________________ diff --git a/rpython/jit/metainterp/test/test_virtualizable.py b/rpython/jit/metainterp/test/test_virtualizable.py --- a/rpython/jit/metainterp/test/test_virtualizable.py +++ b/rpython/jit/metainterp/test/test_virtualizable.py @@ -1,20 +1,22 @@ import py + +from rpython.jit.codewriter import heaptracker +from rpython.jit.codewriter.policy import StopAtXPolicy +from rpython.jit.metainterp.optimizeopt.test.test_util import LLtypeMixin +from rpython.jit.metainterp.test.support import LLJitMixin, OOJitMixin +from rpython.jit.metainterp.warmspot import get_translator +from rpython.rlib.jit import JitDriver, hint, dont_look_inside, promote, virtual_ref +from rpython.rlib.rarithmetic import intmask +from rpython.rtyper.annlowlevel import hlstr from rpython.rtyper.extregistry import ExtRegistryEntry from rpython.rtyper.lltypesystem import lltype, lloperation, rclass, llmemory -from rpython.rtyper.annlowlevel import llhelper -from rpython.rtyper.rclass import IR_IMMUTABLE, IR_IMMUTABLE_ARRAY -from rpython.jit.codewriter.policy import StopAtXPolicy -from rpython.jit.codewriter import heaptracker -from rpython.rlib.jit import JitDriver, hint, dont_look_inside, promote -from rpython.rlib.rarithmetic import intmask -from rpython.jit.metainterp.test.support import LLJitMixin, OOJitMixin -from rpython.rtyper.rclass import FieldListAccessor -from rpython.jit.metainterp.warmspot import get_stats, get_translator -from rpython.jit.metainterp import history -from rpython.jit.metainterp.optimizeopt.test.test_util import LLtypeMixin +from rpython.rtyper.rclass import IR_IMMUTABLE, IR_IMMUTABLE_ARRAY, FieldListAccessor + def promote_virtualizable(*args): pass + + class Entry(ExtRegistryEntry): "Annotation and rtyping of LLOp instances, which are callable." _about_ = promote_virtualizable @@ -46,7 +48,7 @@ ('inst_node', lltype.Ptr(LLtypeMixin.NODE)), hints = {'virtualizable2_accessor': FieldListAccessor()}) XY._hints['virtualizable2_accessor'].initialize( - XY, {'inst_x' : IR_IMMUTABLE, 'inst_node' : IR_IMMUTABLE}) + XY, {'inst_x': IR_IMMUTABLE, 'inst_node': IR_IMMUTABLE}) xy_vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) heaptracker.set_testing_vtable_for_gcstruct(XY, xy_vtable, 'XY') @@ -73,7 +75,7 @@ x = xy.inst_x xy.inst_x = x + 1 n -= 1 - promote_virtualizable(xy, 'inst_x') + promote_virtualizable(xy, 'inst_x') return xy.inst_x res = self.meta_interp(f, [20]) assert res == 30 @@ -97,7 +99,7 @@ x = xy.inst_x xy.inst_x = x + 10 n -= 1 - promote_virtualizable(xy, 'inst_x') + promote_virtualizable(xy, 'inst_x') return xy.inst_x assert f(5) == 185 res = self.meta_interp(f, [5]) @@ -118,10 +120,10 @@ x = xy.inst_x if n <= 10: x += 1000 - promote_virtualizable(xy, 'inst_x') + promote_virtualizable(xy, 'inst_x') xy.inst_x = x + 1 n -= 1 - promote_virtualizable(xy, 'inst_x') + promote_virtualizable(xy, 'inst_x') return xy.inst_x res = self.meta_interp(f, [18]) assert res == 10118 @@ -164,7 +166,7 @@ xy.inst_x = x + 1 m = (m+1) & 3 # the loop gets unrolled 4 times n -= 1 - promote_virtualizable(xy, 'inst_x') + promote_virtualizable(xy, 'inst_x') return xy.inst_x def f(n): res = 0 @@ -194,7 +196,7 @@ promote_virtualizable(xy, 'inst_x') xy.inst_x = value + 100 # virtualized away n -= 1 - promote_virtualizable(xy, 'inst_x') + promote_virtualizable(xy, 'inst_x') return xy.inst_x res = self.meta_interp(f, [20]) assert res == 134 @@ -212,8 +214,8 @@ ('inst_l2', lltype.Ptr(lltype.GcArray(lltype.Signed))), hints = {'virtualizable2_accessor': FieldListAccessor()}) XY2._hints['virtualizable2_accessor'].initialize( - XY2, {'inst_x' : IR_IMMUTABLE, - 'inst_l1' : IR_IMMUTABLE_ARRAY, 'inst_l2' : IR_IMMUTABLE_ARRAY}) + XY2, {'inst_x': IR_IMMUTABLE, + 'inst_l1': IR_IMMUTABLE_ARRAY, 'inst_l2': IR_IMMUTABLE_ARRAY}) xy2_vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) heaptracker.set_testing_vtable_for_gcstruct(XY2, xy2_vtable, 'XY2') @@ -241,11 +243,11 @@ while n > 0: myjitdriver.can_enter_jit(xy2=xy2, n=n) myjitdriver.jit_merge_point(xy2=xy2, n=n) - promote_virtualizable(xy2, 'inst_l1') + promote_virtualizable(xy2, 'inst_l1') promote_virtualizable(xy2, 'inst_l2') xy2.inst_l1[2] += xy2.inst_l2[0] n -= 1 - promote_virtualizable(xy2, 'inst_l1') + promote_virtualizable(xy2, 'inst_l1') return xy2.inst_l1[2] res = self.meta_interp(f, [16]) assert res == 3001 + 16 * 80 @@ -292,7 +294,7 @@ myjitdriver.can_enter_jit(xy2=xy2, n=n) myjitdriver.jit_merge_point(xy2=xy2, n=n) promote_virtualizable(xy2, 'inst_l1') - promote_virtualizable(xy2, 'inst_l2') + promote_virtualizable(xy2, 'inst_l2') xy2.inst_l1[1] += len(xy2.inst_l2) n -= 1 def f(n): @@ -373,7 +375,7 @@ promote_virtualizable(xy2, 'inst_l2') xy2.inst_l2[0] = value + 100 # virtualized away n -= 1 - promote_virtualizable(xy2, 'inst_l2') + promote_virtualizable(xy2, 'inst_l2') return xy2.inst_l2[0] expected = f(20) res = self.meta_interp(f, [20], enable_opts='') @@ -406,8 +408,8 @@ myjitdriver.can_enter_jit(xy2=xy2, n=n) myjitdriver.jit_merge_point(xy2=xy2, n=n) parent = xy2.parent - promote_virtualizable(parent, 'inst_x') - promote_virtualizable(parent, 'inst_l2') + promote_virtualizable(parent, 'inst_x') + promote_virtualizable(parent, 'inst_l2') parent.inst_l2[0] += parent.inst_x n -= 1 def f(n): @@ -432,8 +434,7 @@ # ------------------------------ -class ImplicitVirtualizableTests: - +class ImplicitVirtualizableTests(object): def test_simple_implicit(self): myjitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) @@ -473,9 +474,9 @@ def __init__(self, l, s): self.l = l self.s = s - + def f(n, a): - frame = Frame([a,a+1,a+2,a+3], 0) + frame = Frame([a, a+1, a+2, a+3], 0) x = 0 while n > 0: myjitdriver.can_enter_jit(frame=frame, n=n, x=x) @@ -544,7 +545,7 @@ def f(n): BaseFrame([]) # hack to force 'x' to be in BaseFrame - frame = Frame([1,2,3]) + frame = Frame([1, 2, 3]) z = 0 while n > 0: jitdriver.can_enter_jit(frame=frame, n=n, z=z) @@ -560,9 +561,10 @@ def test_external_read(self): jitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) - + class Frame(object): _virtualizable2_ = ['x', 'y'] + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -592,9 +594,10 @@ def test_external_read_with_exception(self): jitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) - + class Frame(object): _virtualizable2_ = ['x', 'y'] + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -634,6 +637,7 @@ class Frame(object): _virtualizable2_ = ['x', 'y'] + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -663,9 +667,10 @@ def test_external_read_sometimes(self): jitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) - + class Frame(object): _virtualizable2_ = ['x', 'y'] + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -699,11 +704,13 @@ def test_external_read_sometimes_with_virtuals(self): jitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) - + class Frame(object): _virtualizable2_ = ['x', 'y'] + class Y: pass + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -742,11 +749,13 @@ def test_external_read_sometimes_changing_virtuals(self): jitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) - + class Frame(object): _virtualizable2_ = ['x', 'y'] + class Y: pass + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -790,11 +799,13 @@ def test_external_read_sometimes_with_exception(self): jitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) - + class Frame(object): _virtualizable2_ = ['x', 'y'] + class FooBarError(Exception): pass + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -832,9 +843,10 @@ def test_external_read_sometimes_dont_compile_guard(self): jitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) - + class Frame(object): _virtualizable2_ = ['x', 'y'] + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -868,9 +880,10 @@ def test_external_read_sometimes_recursive(self): jitdriver = JitDriver(greens = [], reds = ['rec', 'frame'], virtualizables = ['frame']) - + class Frame(object): _virtualizable2_ = ['x', 'y'] + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -919,9 +932,10 @@ def test_external_write_sometimes(self): jitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) - + class Frame(object): _virtualizable2_ = ['x', 'y'] + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -955,9 +969,10 @@ def test_bridge_forces(self): jitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) - + class Frame(object): _virtualizable2_ = ['x', 'y'] + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -988,6 +1003,7 @@ def test_promote_index_in_virtualizable_list(self): jitdriver = JitDriver(greens = [], reds = ['n', 'frame'], virtualizables = ['frame']) + class Frame(object): _virtualizable2_ = ['stackpos', 'stack[*]'] @@ -1063,8 +1079,8 @@ assert direct_calls(f_graph) == ['__init__', 'force_virtualizable_if_necessary', 'll_portal_runner'] - assert direct_calls(portal_graph)==['force_virtualizable_if_necessary', - 'maybe_enter_jit'] + assert direct_calls(portal_graph) == ['force_virtualizable_if_necessary', + 'maybe_enter_jit'] assert direct_calls(init_graph) == [] def test_virtual_child_frame(self): @@ -1262,7 +1278,7 @@ somewhere_else = SomewhereElse() def jump_back(frame, fail): - myjitdriver.can_enter_jit(frame=frame, fail=fail) + myjitdriver.can_enter_jit(frame=frame, fail=fail) def f(n, fail): frame = Frame(n, 0) @@ -1315,8 +1331,10 @@ f.x -= 1 result += indirection(f) return result + def indirection(arg): return interp(arg) + def run_interp(n): f = hint(Frame(n), access_directly=True) return interp(f) @@ -1325,7 +1343,7 @@ assert res == run_interp(4) def test_guard_failure_in_inlined_function(self): - from rpython.rtyper.annlowlevel import hlstr + class Frame(object): _virtualizable2_ = ['n', 'next'] @@ -1368,11 +1386,12 @@ assert 0 pc += 1 return frame.n + def main(n): frame = Frame(n) return f("c-l", frame) - print main(100) res = self.meta_interp(main, [100], inline=True, enable_opts='') + assert res == main(100) def test_stuff_from_backend_test(self): class Thing(object): @@ -1385,6 +1404,7 @@ driver = JitDriver(greens = ['codeno'], reds = ['i', 'frame'], virtualizables = ['frame'], get_printable_location = lambda codeno: str(codeno)) + class SomewhereElse(object): pass @@ -1422,13 +1442,40 @@ print hex(res) assert res == main(0) + def test_force_virtualref_to_virtualizable(self): + jitdriver = JitDriver( + greens=[], + reds=['i', 'n', 'f', 'f_ref'], + virtualizables=['f'] + ) + + class Frame(object): + _virtualizable2_ = ['x'] + + def main(n): + f = Frame() + f.x = 1 + f_ref = virtual_ref(f) + i = 0 + while i < n: + jitdriver.jit_merge_point(f=f, i=i, f_ref=f_ref, n=n) + i += f_ref().x + return i + + res = self.meta_interp(main, [10]) + assert res == main(10) + self.check_resops({ + "getfield_gc": 1, "int_lt": 2, "ptr_eq": 1, "guard_true": 3, + "int_add": 2, "jump": 1 + }) + class TestOOtype(#ExplicitVirtualizableTests, ImplicitVirtualizableTests, OOJitMixin): pass - + class TestLLtype(ExplicitVirtualizableTests, ImplicitVirtualizableTests, LLJitMixin): From noreply at buildbot.pypy.org Sun Apr 14 22:14:54 2013 From: noreply at buildbot.pypy.org (alex_gaynor) Date: Sun, 14 Apr 2013 22:14:54 +0200 (CEST) Subject: [pypy-commit] pypy default: merged upstream Message-ID: <20130414201454.0DDE31C01FD@cobra.cs.uni-duesseldorf.de> Author: Alex Gaynor Branch: Changeset: r63343:0e80ff8260ae Date: 2013-04-14 13:14 -0700 http://bitbucket.org/pypy/pypy/changeset/0e80ff8260ae/ Log: merged upstream diff --git a/rpython/jit/backend/test/runner_test.py b/rpython/jit/backend/test/runner_test.py --- a/rpython/jit/backend/test/runner_test.py +++ b/rpython/jit/backend/test/runner_test.py @@ -2831,6 +2831,51 @@ assert self.cpu.get_int_value(deadframe, 0) == 97 assert not called + def test_assembler_call_propagate_exc(self): + excdescr = BasicFailDescr(666) + self.cpu.propagate_exception_descr = excdescr + self.cpu.setup_once() # xxx redo it, because we added + # propagate_exception + + def assembler_helper(deadframe, virtualizable): + assert self.cpu.get_latest_descr(deadframe) is excdescr + # let's assume we handled that + return 3 + + FUNCPTR = lltype.Ptr(lltype.FuncType([llmemory.GCREF, + llmemory.GCREF], + lltype.Signed)) + class FakeJitDriverSD: + index_of_virtualizable = -1 + _assembler_helper_ptr = llhelper(FUNCPTR, assembler_helper) + assembler_helper_adr = llmemory.cast_ptr_to_adr( + _assembler_helper_ptr) + + ops = ''' + [i0] + p0 = newunicode(i0) + finish(p0)''' + loop = parse(ops) + looptoken = JitCellToken() + looptoken.outermost_jitdriver_sd = FakeJitDriverSD() + self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken) + ARGS = [lltype.Signed] * 10 + RES = lltype.Signed + FakeJitDriverSD.portal_calldescr = self.cpu.calldescrof( + lltype.Ptr(lltype.FuncType(ARGS, RES)), ARGS, RES, + EffectInfo.MOST_GENERAL) + ops = ''' + [i0] + i11 = call_assembler(i0, descr=looptoken) + guard_not_forced()[] + finish(i11) + ''' + loop = parse(ops, namespace=locals()) + othertoken = JitCellToken() + self.cpu.compile_loop(loop.inputargs, loop.operations, othertoken) + deadframe = self.cpu.execute_token(othertoken, sys.maxint - 1) + assert self.cpu.get_int_value(deadframe, 0) == 3 + def test_assembler_call_float(self): if not self.cpu.supports_floats: py.test.skip("requires floats") @@ -3341,7 +3386,7 @@ excdescr = BasicFailDescr(666) self.cpu.propagate_exception_descr = excdescr self.cpu.setup_once() # xxx redo it, because we added - # propagate_exception_v + # propagate_exception i0 = BoxInt() p0 = BoxPtr() operations = [ diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -563,7 +563,7 @@ if expected_size == -1: mc.MOV_si(WORD, 0xffffff) else: - mc.MOV_si(WORD, expected_size) + mc.MOV_si(WORD, expected_size) ofs2 = mc.get_relative_pos() - 4 self.push_gcmap(mc, gcmap, mov=True) mc.CALL(imm(self._frame_realloc_slowpath)) @@ -601,7 +601,7 @@ mc = codebuf.MachineCodeBlockWrapper() mc.writeimm32(allocated_depth) mc.copy_to_raw_memory(adr) - + def get_asmmemmgr_blocks(self, looptoken): clt = looptoken.compiled_loop_token if clt.asmmemmgr_blocks is None: @@ -614,7 +614,7 @@ allblocks = self.get_asmmemmgr_blocks(looptoken) return self.mc.materialize(self.cpu.asmmemmgr, allblocks, self.cpu.gc_ll_descr.gcrootmap) - + def patch_jump_for_descr(self, faildescr, adr_new_target): adr_jump_offset = faildescr._x86_adr_jump_offset assert adr_jump_offset != 0 @@ -812,7 +812,7 @@ else: assert isinstance(to_loc, RawEspLoc) self.mc.MOV32_si(to_loc.value, low_part) - self.mc.MOV32_si(to_loc.value + 4, high_part) + self.mc.MOV32_si(to_loc.value + 4, high_part) def regalloc_perform(self, op, arglocs, resloc): genop_list[op.getopnum()](self, op, arglocs, resloc) @@ -974,12 +974,13 @@ def _emit_call(self, x, arglocs, start=0, tmp=eax, argtypes=None, callconv=FFI_DEFAULT_ABI, can_collect=1, - stack_max=PASS_ON_MY_FRAME): + stack_max=PASS_ON_MY_FRAME, reload_frame=False): if can_collect == 1 and not self._is_asmgcc(): can_collect = 2 # don't bother with jf_extra_stack_depth if IS_X86_64: return self._emit_call_64(x, arglocs, start, argtypes, - can_collect, stack_max) + can_collect, stack_max, + reload_frame=reload_frame) stack_depth = 0 n = len(arglocs) for i in range(start, n): @@ -1029,6 +1030,8 @@ ofs = self.cpu.get_ofs_of_frame_field('jf_extra_stack_depth') self.mc.MOV_bi(ofs, 0) self.pop_gcmap(self.mc) + elif reload_frame: + self._reload_frame_if_necessary(self.mc) # def _fix_stdcall(self, callconv, p): @@ -1039,7 +1042,7 @@ self.mc.SUB_ri(esp.value, p) def _emit_call_64(self, x, arglocs, start, argtypes, - can_collect, stack_max): + can_collect, stack_max, reload_frame=False): src_locs = [] dst_locs = [] xmm_src_locs = [] @@ -1129,6 +1132,8 @@ if align and can_collect == 1: ofs = self.cpu.get_ofs_of_frame_field('jf_extra_stack_depth') self.mc.MOV_bi(ofs, 0) + elif reload_frame: + self._reload_frame_if_necessary(self.mc) if align: self.mc.ADD_ri(esp.value, align * WORD) if can_collect: @@ -1658,7 +1663,7 @@ if exctploc is not None: assert exctploc.is_reg() mc.MOV(exctploc, heap(self.cpu.pos_exception())) - + mc.MOV(heap(self.cpu.pos_exception()), imm0) mc.MOV(heap(self.cpu.pos_exc_value()), imm0) @@ -2072,7 +2077,8 @@ reg = edi self.mc.LEA_rs(reg.value, css) args = [reg] - self._emit_call(imm(self.reacqgil_addr), args, can_collect=False) + self._emit_call(imm(self.reacqgil_addr), args, can_collect=False, + reload_frame=True) # restore the result from the stack if isinstance(save_loc, RegLoc) and not save_loc.is_xmm: self.mc.MOV_rs(save_loc.value, WORD) From noreply at buildbot.pypy.org Sun Apr 14 23:35:02 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Sun, 14 Apr 2013 23:35:02 +0200 (CEST) Subject: [pypy-commit] pypy default: be consistent w/ the console's filename: '', to match cpython Message-ID: <20130414213502.B028E1C01FD@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: Changeset: r63344:8302503ef566 Date: 2013-04-14 14:33 -0700 http://bitbucket.org/pypy/pypy/changeset/8302503ef566/ Log: be consistent w/ the console's filename: '', to match cpython diff --git a/lib_pypy/_pypy_interact.py b/lib_pypy/_pypy_interact.py --- a/lib_pypy/_pypy_interact.py +++ b/lib_pypy/_pypy_interact.py @@ -44,7 +44,7 @@ import code if mainmodule is None: import __main__ as mainmodule - console = code.InteractiveConsole(mainmodule.__dict__) + console = code.InteractiveConsole(mainmodule.__dict__, filename='') # some parts of code.py are copied here because it seems to be impossible # to start an interactive console without printing at least one line # of banner diff --git a/lib_pypy/pyrepl/python_reader.py b/lib_pypy/pyrepl/python_reader.py --- a/lib_pypy/pyrepl/python_reader.py +++ b/lib_pypy/pyrepl/python_reader.py @@ -171,11 +171,11 @@ def execute(self, text): try: - # ooh, look at the hack: + # ooh, look at the hack: code = self.compile("# coding:utf8\n"+text.encode('utf-8'), - '', 'single') + '', 'single') except (OverflowError, SyntaxError, ValueError): - self.showsyntaxerror("") + self.showsyntaxerror('') else: self.runcode(code) if sys.stdout and not sys.stdout.closed: diff --git a/lib_pypy/pyrepl/simple_interact.py b/lib_pypy/pyrepl/simple_interact.py --- a/lib_pypy/pyrepl/simple_interact.py +++ b/lib_pypy/pyrepl/simple_interact.py @@ -37,13 +37,13 @@ import code if mainmodule is None: import __main__ as mainmodule - console = code.InteractiveConsole(mainmodule.__dict__) + console = code.InteractiveConsole(mainmodule.__dict__, filename='') def more_lines(unicodetext): # ooh, look at the hack: src = "#coding:utf-8\n"+unicodetext.encode('utf-8') try: - code = console.compile(src, '', 'single') + code = console.compile(src, '', 'single') except (OverflowError, SyntaxError, ValueError): return False else: From noreply at buildbot.pypy.org Sun Apr 14 23:40:56 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Sun, 14 Apr 2013 23:40:56 +0200 (CEST) Subject: [pypy-commit] pypy py3k: PyThreadState_Get now abort()s here so skip the check Message-ID: <20130414214056.BD4431C05C8@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63345:42d34fd157c8 Date: 2013-04-14 14:38 -0700 http://bitbucket.org/pypy/pypy/changeset/42d34fd157c8/ Log: PyThreadState_Get now abort()s here so skip the check diff --git a/pypy/module/cpyext/test/test_pystate.py b/pypy/module/cpyext/test/test_pystate.py --- a/pypy/module/cpyext/test/test_pystate.py +++ b/pypy/module/cpyext/test/test_pystate.py @@ -56,11 +56,6 @@ return PyLong_FromLong(0); } - new_tstate = PyThreadState_Get(); - if (new_tstate != NULL) { - return PyLong_FromLong(1); - } - new_tstate = PyThreadState_Swap(old_tstate); if (new_tstate != NULL) { return PyLong_FromLong(2); From noreply at buildbot.pypy.org Sun Apr 14 23:40:58 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Sun, 14 Apr 2013 23:40:58 +0200 (CEST) Subject: [pypy-commit] pypy py3k: refactor Message-ID: <20130414214058.04B8D1C05C8@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63346:6b0adc9c8e8f Date: 2013-04-14 14:38 -0700 http://bitbucket.org/pypy/pypy/changeset/6b0adc9c8e8f/ Log: refactor diff --git a/pypy/interpreter/app_main.py b/pypy/interpreter/app_main.py --- a/pypy/interpreter/app_main.py +++ b/pypy/interpreter/app_main.py @@ -260,48 +260,26 @@ def create_stdio(fd, writing, name, encoding, errors, unbuffered): import io - - if writing: - mode = "wb" - else: - mode= "rb" # stdin is always opened in buffered mode, first because it # shouldn't make a difference in common use cases, second because # TextIOWrapper depends on the presence of a read1() method which # only exists on buffered streams. - if writing: - buffering = 0 - else: - buffering = -1 - if sys.platform == 'win32' and not writing: - # translate \r\n to \n for sys.stdin on Windows - newline = None - else: - newline = '\n' + buffering = 0 if writing else -1 + mode = 'w' if writing else 'r' try: - buf = io.open(fd, mode, buffering, closefd=False) + buf = io.open(fd, mode + 'b', buffering, closefd=False) except OSError as e: if e.errno != errno.EBADF: raise return None - if buffering: - raw = buf.raw - else: - raw = buf + raw = buf.raw if buffering else buf raw.name = name - if unbuffered or raw.isatty(): - line_buffering = True - else: - line_buffering = False - - stream = io.TextIOWrapper(buf, encoding, errors, - newline=newline, - line_buffering=line_buffering) - if writing: - stream.mode = 'w' - else: - stream.mode = 'r' + # translate \r\n to \n for sys.stdin on Windows + newline = None if sys.platform == 'win32' and not writing else '\n' + stream = io.TextIOWrapper(buf, encoding, errors, newline=newline, + line_buffering=unbuffered or raw.isatty()) + stream.mode = mode return stream From noreply at buildbot.pypy.org Sun Apr 14 23:40:59 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Sun, 14 Apr 2013 23:40:59 +0200 (CEST) Subject: [pypy-commit] pypy py3k: stdout/err should default to buffered Message-ID: <20130414214059.4AFD11C05C8@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63347:5131e9ae9bec Date: 2013-04-14 14:40 -0700 http://bitbucket.org/pypy/pypy/changeset/5131e9ae9bec/ Log: stdout/err should default to buffered diff --git a/pypy/interpreter/app_main.py b/pypy/interpreter/app_main.py --- a/pypy/interpreter/app_main.py +++ b/pypy/interpreter/app_main.py @@ -264,7 +264,7 @@ # shouldn't make a difference in common use cases, second because # TextIOWrapper depends on the presence of a read1() method which # only exists on buffered streams. - buffering = 0 if writing else -1 + buffering = 0 if unbuffered and writing else -1 mode = 'w' if writing else 'r' try: buf = io.open(fd, mode + 'b', buffering, closefd=False) diff --git a/pypy/interpreter/test2/test_app_main.py b/pypy/interpreter/test2/test_app_main.py --- a/pypy/interpreter/test2/test_app_main.py +++ b/pypy/interpreter/test2/test_app_main.py @@ -460,6 +460,11 @@ finally: os.environ['PYTHONPATH'] = old + def test_buffered(self): + line = 'import sys;print(type(sys.stdout.buffer).__name__)' + child = self.spawn(['-c', line]) + child.expect('BufferedWriter') + def test_unbuffered(self): # In Python3, -u affects the "binary layer" of sys.stdout. line = 'import os,sys;sys.stdout.buffer.write(str(789).encode());os.read(0,1)' From noreply at buildbot.pypy.org Sun Apr 14 23:41:00 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Sun, 14 Apr 2013 23:41:00 +0200 (CEST) Subject: [pypy-commit] pypy py3k: docs Message-ID: <20130414214100.8D1D51C05C8@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63348:ae60a59d5573 Date: 2013-04-14 14:40 -0700 http://bitbucket.org/pypy/pypy/changeset/ae60a59d5573/ Log: docs diff --git a/pypy/doc/config/objspace.usemodules._posixsubprocess.txt b/pypy/doc/config/objspace.usemodules._posixsubprocess.txt new file mode 100644 --- /dev/null +++ b/pypy/doc/config/objspace.usemodules._posixsubprocess.txt @@ -0,0 +1,2 @@ +Use the '_posixsubprocess' module. +Used by the 'subprocess' standard lib module. This module is expected to be working and is included by default. From noreply at buildbot.pypy.org Sun Apr 14 23:41:21 2013 From: noreply at buildbot.pypy.org (mattip) Date: Sun, 14 Apr 2013 23:41:21 +0200 (CEST) Subject: [pypy-commit] pypy default: fix wrong type in error message (amaury, arigato) Message-ID: <20130414214121.D43101C05C8@cobra.cs.uni-duesseldorf.de> Author: mattip Branch: Changeset: r63349:30d046ac6116 Date: 2013-04-15 00:35 +0300 http://bitbucket.org/pypy/pypy/changeset/30d046ac6116/ Log: fix wrong type in error message (amaury, arigato) diff --git a/pypy/module/micronumpy/interp_dtype.py b/pypy/module/micronumpy/interp_dtype.py --- a/pypy/module/micronumpy/interp_dtype.py +++ b/pypy/module/micronumpy/interp_dtype.py @@ -282,7 +282,10 @@ return dtype if w_dtype is dtype.w_box_type: return dtype - raise OperationError(space.w_TypeError, space.wrap("data type %r not understood" % w_dtype)) + typename = space.type(w_dtype).getname(space) + raise OperationError(space.w_TypeError, space.wrap( + "data type not understood (value of type " + + "%s not expected here)" % typename)) W_Dtype.typedef = TypeDef("dtype", __module__ = "numpypy", diff --git a/pypy/module/micronumpy/test/test_dtypes.py b/pypy/module/micronumpy/test/test_dtypes.py --- a/pypy/module/micronumpy/test/test_dtypes.py +++ b/pypy/module/micronumpy/test/test_dtypes.py @@ -32,7 +32,8 @@ assert dtype(None) is dtype(float) - raises(TypeError, dtype, 1042) + exc = raises(TypeError, dtype, (1, 2)) + assert 'data type not understood' in str(exc.value) raises(KeyError, 'dtype(int)["asdasd"]') def test_dtype_eq(self): From noreply at buildbot.pypy.org Sun Apr 14 23:41:23 2013 From: noreply at buildbot.pypy.org (mattip) Date: Sun, 14 Apr 2013 23:41:23 +0200 (CEST) Subject: [pypy-commit] pypy default: merge heads Message-ID: <20130414214123.0FF5B1C05C8@cobra.cs.uni-duesseldorf.de> Author: mattip Branch: Changeset: r63350:3c141c06dda8 Date: 2013-04-15 00:41 +0300 http://bitbucket.org/pypy/pypy/changeset/3c141c06dda8/ Log: merge heads diff --git a/lib_pypy/_pypy_interact.py b/lib_pypy/_pypy_interact.py --- a/lib_pypy/_pypy_interact.py +++ b/lib_pypy/_pypy_interact.py @@ -44,7 +44,7 @@ import code if mainmodule is None: import __main__ as mainmodule - console = code.InteractiveConsole(mainmodule.__dict__) + console = code.InteractiveConsole(mainmodule.__dict__, filename='') # some parts of code.py are copied here because it seems to be impossible # to start an interactive console without printing at least one line # of banner diff --git a/lib_pypy/pyrepl/python_reader.py b/lib_pypy/pyrepl/python_reader.py --- a/lib_pypy/pyrepl/python_reader.py +++ b/lib_pypy/pyrepl/python_reader.py @@ -171,11 +171,11 @@ def execute(self, text): try: - # ooh, look at the hack: + # ooh, look at the hack: code = self.compile("# coding:utf8\n"+text.encode('utf-8'), - '', 'single') + '', 'single') except (OverflowError, SyntaxError, ValueError): - self.showsyntaxerror("") + self.showsyntaxerror('') else: self.runcode(code) if sys.stdout and not sys.stdout.closed: diff --git a/lib_pypy/pyrepl/simple_interact.py b/lib_pypy/pyrepl/simple_interact.py --- a/lib_pypy/pyrepl/simple_interact.py +++ b/lib_pypy/pyrepl/simple_interact.py @@ -37,13 +37,13 @@ import code if mainmodule is None: import __main__ as mainmodule - console = code.InteractiveConsole(mainmodule.__dict__) + console = code.InteractiveConsole(mainmodule.__dict__, filename='') def more_lines(unicodetext): # ooh, look at the hack: src = "#coding:utf-8\n"+unicodetext.encode('utf-8') try: - code = console.compile(src, '', 'single') + code = console.compile(src, '', 'single') except (OverflowError, SyntaxError, ValueError): return False else: From noreply at buildbot.pypy.org Sun Apr 14 23:47:14 2013 From: noreply at buildbot.pypy.org (mattip) Date: Sun, 14 Apr 2013 23:47:14 +0200 (CEST) Subject: [pypy-commit] pypy default: skip hanging SIGINT test on windows Message-ID: <20130414214714.6C7131C10AF@cobra.cs.uni-duesseldorf.de> Author: mattip Branch: Changeset: r63351:30cad223b92c Date: 2013-04-15 00:43 +0300 http://bitbucket.org/pypy/pypy/changeset/30cad223b92c/ Log: skip hanging SIGINT test on windows diff --git a/pypy/module/__pypy__/test/test_signal.py b/pypy/module/__pypy__/test/test_signal.py --- a/pypy/module/__pypy__/test/test_signal.py +++ b/pypy/module/__pypy__/test/test_signal.py @@ -25,6 +25,9 @@ __pypy__.thread._signals_enter() def test_enable_signals(self): + import sys + if sys.platform.startswith('win'): + skip('signals not operable on windows') import __pypy__, thread, signal, time def subthread(): From noreply at buildbot.pypy.org Sun Apr 14 23:47:15 2013 From: noreply at buildbot.pypy.org (mattip) Date: Sun, 14 Apr 2013 23:47:15 +0200 (CEST) Subject: [pypy-commit] pypy default: begin to fix for this windows test whose failure now exposes missing abi consideration in llgraph/runner calldescrof_dynamic() Message-ID: <20130414214715.AE5B61C10AF@cobra.cs.uni-duesseldorf.de> Author: mattip Branch: Changeset: r63352:c547e2d2e237 Date: 2013-04-15 00:46 +0300 http://bitbucket.org/pypy/pypy/changeset/c547e2d2e237/ Log: begin to fix for this windows test whose failure now exposes missing abi consideration in llgraph/runner calldescrof_dynamic() diff --git a/rpython/jit/backend/test/runner_test.py b/rpython/jit/backend/test/runner_test.py --- a/rpython/jit/backend/test/runner_test.py +++ b/rpython/jit/backend/test/runner_test.py @@ -2455,12 +2455,12 @@ lltype.free(raw, flavor='raw') def test_call_to_winapi_function(self): - from rpython.rlib.clibffi import _WIN32, FUNCFLAG_STDCALL + from rpython.rlib.clibffi import _WIN32 if not _WIN32: py.test.skip("Windows test only") - from rpython.rlib.libffi import CDLL, types, ArgChain + from rpython.rlib.libffi import WinDLL, types, ArgChain from rpython.rlib.rwin32 import DWORD - libc = CDLL('KERNEL32') + libc = WinDLL('KERNEL32') c_GetCurrentDir = libc.getpointer('GetCurrentDirectoryA', [types.ulong, types.pointer], types.ulong) From noreply at buildbot.pypy.org Mon Apr 15 01:15:03 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Mon, 15 Apr 2013 01:15:03 +0200 (CEST) Subject: [pypy-commit] pypy py3k: explicitly flush stderr (it's potentially buffered), fix import Message-ID: <20130414231503.D67501C01FD@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63353:89c6b8b4121b Date: 2013-04-14 16:10 -0700 http://bitbucket.org/pypy/pypy/changeset/89c6b8b4121b/ Log: explicitly flush stderr (it's potentially buffered), fix import diff --git a/pypy/module/cpyext/test/test_pyerrors.py b/pypy/module/cpyext/test/test_pyerrors.py --- a/pypy/module/cpyext/test/test_pyerrors.py +++ b/pypy/module/cpyext/test/test_pyerrors.py @@ -69,6 +69,7 @@ def test_Warning(self, space, api, capfd): message = rffi.str2charp("this is a warning") api.PyErr_WarnEx(None, message, 1) + space.call_method(space.sys.get('stderr'), "flush") out, err = capfd.readouterr() assert ": UserWarning: this is a warning" in err rffi.free_charp(message) @@ -76,6 +77,7 @@ def test_print_err(self, space, api, capfd): api.PyErr_SetObject(space.w_Exception, space.wrap("cpyext is cool")) api.PyErr_Print() + space.call_method(space.sys.get('stderr'), "flush") out, err = capfd.readouterr() assert "cpyext is cool" in err assert not api.PyErr_Occurred() @@ -84,6 +86,7 @@ api.PyErr_SetObject(space.w_ValueError, space.wrap("message")) w_where = space.wrap("location") api.PyErr_WriteUnraisable(w_where) + space.call_method(space.sys.get('stderr'), "flush") out, err = capfd.readouterr() assert "Exception ValueError: 'message' in 'location' ignored" == err.strip() @@ -219,8 +222,8 @@ Py_RETURN_NONE; '''), ]) - import sys, StringIO - sys.stderr = StringIO.StringIO() + import io, sys + sys.stderr = io.StringIO() try: 1 / 0 except ZeroDivisionError: From noreply at buildbot.pypy.org Mon Apr 15 01:15:05 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Mon, 15 Apr 2013 01:15:05 +0200 (CEST) Subject: [pypy-commit] pypy py3k: ensure the exception is normalized before printing it Message-ID: <20130414231505.4F2051C01FD@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63354:c194bbd3ad95 Date: 2013-04-14 16:14 -0700 http://bitbucket.org/pypy/pypy/changeset/c194bbd3ad95/ Log: ensure the exception is normalized before printing it diff --git a/pypy/module/cpyext/pyerrors.py b/pypy/module/cpyext/pyerrors.py --- a/pypy/module/cpyext/pyerrors.py +++ b/pypy/module/cpyext/pyerrors.py @@ -262,9 +262,9 @@ type, value and traceback of the printed exception, respectively.""" if not PyErr_Occurred(space): PyErr_BadInternalCall(space) - state = space.fromcache(State) - operror = state.clear_exception() + operror = space.fromcache(State).clear_exception() + operror.normalize_exception(space) w_type = operror.w_type w_value = operror.get_w_value(space) w_tb = space.wrap(operror.get_traceback()) From noreply at buildbot.pypy.org Mon Apr 15 01:22:53 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Mon, 15 Apr 2013 01:22:53 +0200 (CEST) Subject: [pypy-commit] pypy default: use the correct 'i', not the one leaked from the list comp (which happened to Message-ID: <20130414232253.9773A1C10AF@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: Changeset: r63355:17df5567c9a0 Date: 2013-04-14 16:22 -0700 http://bitbucket.org/pypy/pypy/changeset/17df5567c9a0/ Log: use the correct 'i', not the one leaked from the list comp (which happened to be the same value) diff --git a/pypy/objspace/std/test/test_listobject.py b/pypy/objspace/std/test/test_listobject.py --- a/pypy/objspace/std/test/test_listobject.py +++ b/pypy/objspace/std/test/test_listobject.py @@ -1109,7 +1109,7 @@ self.i = i def __eq__(self, other): if self.i == 9: - del l[i - 1] + del l[self.i - 1] return True else: return False From noreply at buildbot.pypy.org Mon Apr 15 01:24:43 2013 From: noreply at buildbot.pypy.org (arigo) Date: Mon, 15 Apr 2013 01:24:43 +0200 (CEST) Subject: [pypy-commit] pypy.org extradoc: Add a warning: don't use gcc 4.8 for now Message-ID: <20130414232443.73A691C10AF@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: extradoc Changeset: r400:b61326da6fea Date: 2013-04-15 01:24 +0200 http://bitbucket.org/pypy/pypy.org/changeset/b61326da6fea/ Log: Add a warning: don't use gcc 4.8 for now diff --git a/download.html b/download.html --- a/download.html +++ b/download.html @@ -134,6 +134,8 @@

      Building from source

      +

      Warning: the new gcc 4.8 doesn't compile PyPy correctly. +We are investigating.

      1. Get the source code. The following packages contain the source at the same revision as the above binaries:

        diff --git a/source/download.txt b/source/download.txt --- a/source/download.txt +++ b/source/download.txt @@ -134,6 +134,9 @@ Building from source ------------------------------- +**Warning:** the new gcc 4.8 doesn't compile PyPy correctly. +We are investigating. + 1. Get the source code. The following packages contain the source at the same revision as the above binaries: From noreply at buildbot.pypy.org Mon Apr 15 01:33:59 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Mon, 15 Apr 2013 01:33:59 +0200 (CEST) Subject: [pypy-commit] pypy py3k: special case an appdirect difference Message-ID: <20130414233359.96F881C10AF@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63356:79963e004359 Date: 2013-04-14 16:33 -0700 http://bitbucket.org/pypy/pypy/changeset/79963e004359/ Log: special case an appdirect difference diff --git a/pypy/module/signal/test/test_signal.py b/pypy/module/signal/test/test_signal.py --- a/pypy/module/signal/test/test_signal.py +++ b/pypy/module/signal/test/test_signal.py @@ -41,6 +41,7 @@ def setup_class(cls): cls.w_signal = cls.space.getbuiltinmodule('signal') + cls.w_appdirect = cls.space.wrap(cls.runappdirect) def test_exported_names(self): import os @@ -137,7 +138,8 @@ pass try: - assert getsignal(SIGINT) == SIG_DFL + if not self.appdirect: + assert getsignal(SIGINT) == SIG_DFL signal(SIGINT, SIG_DFL) assert getsignal(SIGINT) == SIG_DFL signal(SIGINT, SIG_IGN) From noreply at buildbot.pypy.org Mon Apr 15 01:49:02 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Mon, 15 Apr 2013 01:49:02 +0200 (CEST) Subject: [pypy-commit] pypy py3k: better simulate the collection wrapping rules under appdirect tests Message-ID: <20130414234902.944FC1C131F@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63357:3243312f9f03 Date: 2013-04-14 16:48 -0700 http://bitbucket.org/pypy/pypy/changeset/3243312f9f03/ Log: better simulate the collection wrapping rules under appdirect tests diff --git a/pypy/tool/pytest/objspace.py b/pypy/tool/pytest/objspace.py --- a/pypy/tool/pytest/objspace.py +++ b/pypy/tool/pytest/objspace.py @@ -88,6 +88,13 @@ def wrap(self, obj): if isinstance(obj, str): return obj.decode('utf-8') + if isinstance(obj, dict): + return dict((self.wrap(k), self.wrap(v)) + for k, v in obj.iteritems()) + if isinstance(obj, tuple): + return tuple(self.wrap(item) for item in obj) + if isinstance(obj, list): + return list(self.wrap(item) for item in obj) return obj def wrapbytes(self, obj): From noreply at buildbot.pypy.org Mon Apr 15 01:59:35 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Mon, 15 Apr 2013 01:59:35 +0200 (CEST) Subject: [pypy-commit] pypy py3k: propagate None attributes down into the appdirect tests too Message-ID: <20130414235935.EFB161C131F@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63358:2353031aa8b8 Date: 2013-04-14 16:59 -0700 http://bitbucket.org/pypy/pypy/changeset/2353031aa8b8/ Log: propagate None attributes down into the appdirect tests too diff --git a/pypy/tool/pytest/apptest.py b/pypy/tool/pytest/apptest.py --- a/pypy/tool/pytest/apptest.py +++ b/pypy/tool/pytest/apptest.py @@ -114,7 +114,8 @@ elif isinstance(value, types.ModuleType): name = value.__name__ defs.append("import %s; self.%s = %s\n" % (name, symbol, name)) - elif isinstance(value, (str, unicode, int, long, float, list, tuple, dict)): + elif isinstance(value, (str, unicode, int, long, float, list, tuple, + dict)) or value is None: defs.append("self.%s = %s\n" % (symbol, py3k_repr(value))) source = py.code.Source(target_)[1:] pyfile = udir.join('src.py') From noreply at buildbot.pypy.org Mon Apr 15 02:51:57 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Mon, 15 Apr 2013 02:51:57 +0200 (CEST) Subject: [pypy-commit] pypy py3k: attempt to normalize the exception before passing it off, print_exception Message-ID: <20130415005157.E360C1C05C8@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63359:392b6ee52f63 Date: 2013-04-14 17:51 -0700 http://bitbucket.org/pypy/pypy/changeset/392b6ee52f63/ Log: attempt to normalize the exception before passing it off, print_exception requires it in py3 diff --git a/pypy/interpreter/error.py b/pypy/interpreter/error.py --- a/pypy/interpreter/error.py +++ b/pypy/interpreter/error.py @@ -287,6 +287,10 @@ # try: if with_traceback: + try: + self.normalize_exception(space) + except OperationError: + pass w_t = self.w_type w_v = self.get_w_value(space) w_tb = space.wrap(self.get_traceback()) From noreply at buildbot.pypy.org Mon Apr 15 09:20:15 2013 From: noreply at buildbot.pypy.org (mattip) Date: Mon, 15 Apr 2013 09:20:15 +0200 (CEST) Subject: [pypy-commit] pypy default: revert bogus skip, fix tests don't skip them Message-ID: <20130415072015.85E491C0292@cobra.cs.uni-duesseldorf.de> Author: mattip Branch: Changeset: r63360:3dec220af6fd Date: 2013-04-15 10:19 +0300 http://bitbucket.org/pypy/pypy/changeset/3dec220af6fd/ Log: revert bogus skip, fix tests don't skip them added print prevents hang on untranslated windows perhaps connected to the order of translating rlib.rposix to a dll and calling start_new_thread diff --git a/pypy/module/__pypy__/test/test_signal.py b/pypy/module/__pypy__/test/test_signal.py --- a/pypy/module/__pypy__/test/test_signal.py +++ b/pypy/module/__pypy__/test/test_signal.py @@ -25,9 +25,6 @@ __pypy__.thread._signals_enter() def test_enable_signals(self): - import sys - if sys.platform.startswith('win'): - skip('signals not operable on windows') import __pypy__, thread, signal, time def subthread(): @@ -50,8 +47,9 @@ try: done = [] interrupted = [] + print 'starting',i thread.start_new_thread(subthread, ()) - for i in range(10): + for j in range(10): if len(done): break print '.' time.sleep(0.1) From noreply at buildbot.pypy.org Mon Apr 15 10:23:38 2013 From: noreply at buildbot.pypy.org (timfel) Date: Mon, 15 Apr 2013 10:23:38 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: BE_CURSOR can take an optional second argument Message-ID: <20130415082338.131C61C0F1A@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: Changeset: r266:15253d8d8891 Date: 2013-04-15 10:13 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/15253d8d8891/ Log: BE_CURSOR can take an optional second argument diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -577,8 +577,14 @@ # in case we return normally, we have to restore the removed w_rcvr return w_rcvr - at expose_primitive(BE_CURSOR, unwrap_spec=[object]) -def func(interp, s_frame, w_rcvr): + at expose_primitive(BE_CURSOR) +def func(interp, s_frame, argcount): + if not (0 <= argcount <= 1): + raise PrimitiveFailedError() + w_rcvr = s_frame.peek(argcount) + if argcount == 1: + # TODO: use mask + w_mask = s_frame.peek(0) # TODO: Use info from cursor object. interp.space.objtable['w_cursor'] = w_rcvr return w_rcvr From noreply at buildbot.pypy.org Mon Apr 15 10:23:36 2013 From: noreply at buildbot.pypy.org (timfel) Date: Mon, 15 Apr 2013 10:23:36 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: Cast SDL pixelbuffer into ULONGP, so we can set words instead of bytes Message-ID: <20130415082336.E0F7D1C05C8@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: Changeset: r265:f24368c0ec5a Date: 2013-04-15 10:12 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/f24368c0ec5a/ Log: Cast SDL pixelbuffer into ULONGP, so we can set words instead of bytes diff --git a/spyvm/display.py b/spyvm/display.py --- a/spyvm/display.py +++ b/spyvm/display.py @@ -61,7 +61,7 @@ assert self.screen def get_pixelbuffer(self): - return self.screen.c_pixels + return rffi.cast(rffi.ULONGP, self.screen.c_pixels) def flip(self): RSDL.Flip(self.screen) diff --git a/spyvm/model.py b/spyvm/model.py --- a/spyvm/model.py +++ b/spyvm/model.py @@ -807,17 +807,15 @@ @jit.unroll_safe def setword(self, n, word): self._real_depth_buffer[n] = word - pos = n * NATIVE_DEPTH * 4 + pos = n * NATIVE_DEPTH mask = r_uint(1) mask <<= 31 for i in xrange(32): bit = mask & word - self.pixelbuffer[pos] = rffi.r_uchar(0xff * (bit == 0)) - self.pixelbuffer[pos + 1] = rffi.r_uchar(0xff * (bit == 0)) - self.pixelbuffer[pos + 2] = rffi.r_uchar(0xff * (bit == 0)) - self.pixelbuffer[pos + 3] = rffi.r_uchar(0xff) + pixel = r_uint((0x00ffffff * (bit == 0)) | r_uint(0xff000000)) + self.pixelbuffer[pos] = pixel mask >>= 1 - pos += 4 + pos += 1 # XXX Shouldn't compiledmethod have class reference for subclassed compiled From noreply at buildbot.pypy.org Mon Apr 15 10:27:28 2013 From: noreply at buildbot.pypy.org (bivab) Date: Mon, 15 Apr 2013 10:27:28 +0200 (CEST) Subject: =?iso-8859-1?q?_=5Bpypy-commit=5D_buildbot_default=3A_add_builde?= =?iso-8859-1?q?rs_and_schedulers_for_an_armv7/hardfloat_buildbot=1B=5B39?= =?iso-8859-1?q?=3B_49=3B_00m=1B=5B39=3B_49=3B_00m=1B=5B39=3B_49=3B_00m?= Message-ID: <20130415082728.4C3511C01FD@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r784:6798ee30698f Date: 2013-04-15 10:26 +0200 http://bitbucket.org/pypy/buildbot/changeset/6798ee30698f/ Log: add builders and schedulers for an armv7/hardfloat buildbot diff --git a/bot2/pypybuildbot/arm_master.py b/bot2/pypybuildbot/arm_master.py --- a/bot2/pypybuildbot/arm_master.py +++ b/bot2/pypybuildbot/arm_master.py @@ -1,4 +1,3 @@ - from buildbot.scheduler import Nightly, Triggerable from pypybuildbot.util import we_are_debugging, load @@ -86,13 +85,16 @@ ) # APPLVLLINUXARM = "pypy-c-app-level-linux-armel" +APPLVLLINUXARMHF_v7 = "pypy-c-app-level-linux-armhf-v7" APPLVLLINUXARMHF_RASPBIAN = "pypy-c-app-level-linux-armhf-raspbian" JITLINUXARM = "pypy-c-jit-linux-armel" +JITLINUXARMHF_v7 = "pypy-c-jit-linux-armhf-v7" JITLINUXARMHF_RASPBIAN = "pypy-c-jit-linux-armhf-raspbian" JITBACKENDONLYLINUXARMEL = "jitbackendonly-own-linux-armel" JITBACKENDONLYLINUXARMHF = "jitbackendonly-own-linux-armhf" +JITBACKENDONLYLINUXARMHF_v7 = "jitbackendonly-own-linux-armhf-v7" # build only BUILDLINUXARM = "build-pypy-c-linux-armel" @@ -109,6 +111,7 @@ BUILDJITLINUXARMHF_RASPBIAN, # on hhu-cross-raspbianhf, uses 1 core JITBACKENDONLYLINUXARMEL, # on hhu-imx.53 JITBACKENDONLYLINUXARMHF, # on hhu-raspberry-pi + JITBACKENDONLYLINUXARMHF_v7, # on cubieboard-bob ], branch=None, hour=0, minute=0), Triggerable("APPLVLLINUXARM_scheduler", [ @@ -119,17 +122,20 @@ JITLINUXARM, # triggered by BUILDJITLINUXARM, on hhu-beagleboard ]), Triggerable("APPLVLLINUXARMHF_RASPBIAN_scheduler", [ - APPLVLLINUXARMHF_RASPBIAN, # triggered by BUILDLINUXARMHF_RASPBIAN, on hhu-raspberry-pi + APPLVLLINUXARMHF_RASPBIAN, # triggered by BUILDLINUXARMHF_RASPBIAN, on hhu-raspberry-pi + APPLVLLINUXARMHF_v7, # triggered by BUILDLINUXARMHF_RASPBIAN, on cubieboard-bob ]), Triggerable("JITLINUXARMHF_RASPBIAN_scheduler", [ - JITLINUXARMHF_RASPBIAN, # triggered by BUILDJITLINUXARMHF_RASPBIAN, on hhu-raspberry-pi + JITLINUXARMHF_RASPBIAN, # triggered by BUILDJITLINUXARMHF_RASPBIAN, on hhu-raspberry-pi + JITBACKENDONLYLINUXARMHF_v7, # triggered by BUILDJITLINUXARMHF_RASPBIAN, on cubieboard-bob ]), ] builders = [ # ARM # armel + ## armv7 {"name": JITBACKENDONLYLINUXARMEL, "slavenames": ['hhu-i.mx53'], "builddir": JITBACKENDONLYLINUXARMEL, @@ -138,6 +144,7 @@ "locks": [ARMBoardLock.access('counting')], }, # armhf + ## armv6 {"name": JITBACKENDONLYLINUXARMHF, "slavenames": ['hhu-raspberry-pi'], "builddir": JITBACKENDONLYLINUXARMHF, @@ -145,7 +152,16 @@ "category": 'linux-armhf', "locks": [ARMBoardLock.access('counting')], }, + ## armv7 + {"name": JITBACKENDONLYLINUXARMHF_v7, + "slavenames": ['cubieboard-bob'], + "builddir": JITBACKENDONLYLINUXARMHF_v7, + "factory": pypyJitBackendOnlyOwnTestFactoryARM, + "category": 'linux-armhf', + "locks": [ARMBoardLock.access('counting')], + }, # app level builders + ## armv7 softfloat {"name": APPLVLLINUXARM, "slavenames": ["hhu-beagleboard"], "builddir": APPLVLLINUXARM, @@ -160,6 +176,7 @@ 'category': 'linux-armel', "locks": [ARMBoardLock.access('counting')], }, + ## armv6 hardfloat {"name": APPLVLLINUXARMHF_RASPBIAN, "slavenames": ["hhu-raspberry-pi"], "builddir": APPLVLLINUXARMHF_RASPBIAN, @@ -174,6 +191,21 @@ 'category': 'linux-armhf', "locks": [ARMBoardLock.access('counting')], }, + ## armv7 hardfloat + {"name": APPLVLLINUXARMHF_v7, + "slavenames": ["cubieboard-bob"], + "builddir": APPLVLLINUXARMHF_v7, + "factory": pypyARMHF_RASPBIAN_TranslatedAppLevelTestFactory, # XXX replace this with a custom build + "category": "linux-armhf", + "locks": [ARMBoardLock.access('counting')], + }, + {"name": JITLINUXARMHF_v7, + "slavenames": ["cubieboard-bob"], + 'builddir': JITLINUXARMHF_v7, + 'factory': pypyARMHF_RASPBIAN_JITTranslatedTestFactory, # XXX replace this with a custom build + 'category': 'linux-armhf', + "locks": [ARMBoardLock.access('counting')], + }, # Translation Builders for ARM {"name": BUILDLINUXARM, "slavenames": ['hhu-cross-armel'], @@ -192,7 +224,7 @@ {"name": BUILDLINUXARMHF_RASPBIAN, "slavenames": ['hhu-cross-raspbianhf'], "builddir": BUILDLINUXARMHF_RASPBIAN, - "factory": pypyCrossTranslationFactoryRaspbianHF , + "factory": pypyCrossTranslationFactoryRaspbianHF, "category": 'linux-armhf', "locks": [ARMCrossLock.access('counting')], }, From noreply at buildbot.pypy.org Mon Apr 15 11:05:54 2013 From: noreply at buildbot.pypy.org (timfel) Date: Mon, 15 Apr 2013 11:05:54 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: fail STRING_REPLACE primitive for out-of-bounds access to pointer Message-ID: <20130415090554.2AE7E1C10AF@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: Changeset: r268:b8b65d5a85bb Date: 2013-04-15 11:05 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/b8b65d5a85bb/ Log: fail STRING_REPLACE primitive for out-of-bounds access to pointer objects, fallback to in-image code diff --git a/spyvm/model.py b/spyvm/model.py --- a/spyvm/model.py +++ b/spyvm/model.py @@ -36,6 +36,11 @@ space, as memory representation varies depending on PyPy translation.""" return 0 + def instsize(self, space): + """Return the size of the object reserved for instance variables. + Only returns something non-zero for W_PointersObjects""" + return 0 + def varsize(self, space): """Return bytesize of variable-sized part. diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -655,8 +655,8 @@ # might be different (e.g. Symbol and ByteString) if w_rcvr.__class__ is not w_replacement.__class__: raise PrimitiveFailedError() - if (w_rcvr.size() <= stop - or w_replacement.size() < repStart + (stop - start)): + if (w_rcvr.size() - w_rcvr.instsize(interp.space) <= stop + or w_replacement.size() - w_replacement.instsize(interp.space) < repStart + (stop - start)): raise PrimitiveFailedError() repOff = repStart - start for i0 in range(start, stop + 1): From noreply at buildbot.pypy.org Mon Apr 15 11:05:53 2013 From: noreply at buildbot.pypy.org (timfel) Date: Mon, 15 Apr 2013 11:05:53 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: fix some SDL event handling Message-ID: <20130415090553.121431C0F1A@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: Changeset: r267:4e9499c16e75 Date: 2013-04-15 10:26 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/4e9499c16e75/ Log: fix some SDL event handling diff --git a/spyvm/display.py b/spyvm/display.py --- a/spyvm/display.py +++ b/spyvm/display.py @@ -6,50 +6,26 @@ from rsdl import RSDL, RSDL_helper -class SDLEventQueue(object): - def __init__(self, default, maxlen=10): - assert default - self.default = default - self.ary = [] - self.maxlen = 10 - - def push(self, event): - if len(self.ary) == self.maxlen: - self.ary.pop(0) - self.ary.append(event) - - def shift(self): - if not self.ary: - self.ary += self.default - return self.ary.pop(0) - - def peek(self): - if self.ary: - return self.ary[0] - else: - return self.default[0] - - def size(self): - if not self.ary: - return len(self.default) - else: - return len(self.ary) +MOUSE_BTN_RIGHT = 1 +MOUSE_BTN_MIDDLE = 2 +MOUSE_BTN_LEFT = 4 +MOD_SHIFT = 8 +MOD_CONTROL = 16 +MOD_ALT = 64 class SDLDisplay(object): _attrs_ = ["screen", "width", "height", "depth", "surface", "has_surface", - "last_mouse_position", "mouse_downs", "mouse_ups", "key_ups", "key_downs"] + "mouse_position", "button", "key"] def __init__(self, title): assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 RSDL.WM_SetCaption(title, "RSqueakVM") RSDL.EnableUNICODE(1) self.has_surface = False - self.last_mouse_position = [0, 0] - self.mouse_downs = SDLEventQueue([0]) - self.mouse_ups = SDLEventQueue([0]) - self.key_ups = SDLEventQueue([0]) - self.key_downs = SDLEventQueue([0]) + self.mouse_position = [0, 0] + self.button = 0 + self.key = 0 def set_video_mode(self, w, h, d): assert w > 0 and h > 0 @@ -77,46 +53,60 @@ if c_type == RSDL.MOUSEBUTTONDOWN or c_type == RSDL.MOUSEBUTTONUP: b = rffi.cast(RSDL.MouseButtonEventPtr, event) btn = rffi.getintfield(b, 'c_button') - if btn == RSDL.BUTTON_LEFT: - btn = 1 + if btn == RSDL.BUTTON_RIGHT: + btn = MOUSE_BTN_RIGHT elif btn == RSDL.BUTTON_MIDDLE: - btn = 2 - elif btn == RSDL.BUTTON_RIGHT: - btn = 4 + btn = MOUSE_BTN_MIDDLE + elif btn == RSDL.BUTTON_LEFT: + btn = MOUSE_BTN_LEFT if c_type == RSDL.MOUSEBUTTONDOWN: - self.mouse_downs.push(btn) + self.button |= btn else: - self.mouse_ups.push(btn) + self.button &= ~btn elif c_type == RSDL.MOUSEMOTION: m = rffi.cast(RSDL.MouseMotionEventPtr, event) x = rffi.getintfield(m, "c_x") y = rffi.getintfield(m, "c_y") - self.last_mouse_position = [x, y] + self.mouse_position = [x, y] elif c_type == RSDL.KEYUP or c_type == RSDL.KEYDOWN: p = rffi.cast(RSDL.KeyboardEventPtr, event) char = rffi.getintfield(p.c_keysym, 'c_unicode') if char != 0: - for c in unicode_encode_utf_8(unichr(char), 1, "ignore"): - if c_type == RSDL.KEYUP: - self.key_ups.push(ord(c)) + chars = unicode_encode_utf_8(unichr(char), 1, "ignore") + if len(chars) == 1: + if c_type == RSDL.KEYDOWN: + self.key = ord(chars[0]) else: - self.key_downs.push(ord(c)) + pass # XXX: Todo? finally: lltype.free(event, flavor='raw') + def get_modifier_mask(self): + RSDL.PumpEvents() + mod = RSDL.GetModState() + modifier = 0 + if mod & RSDL.KMOD_CTRL != 0: + modifier |= MOD_CONTROL + if mod & RSDL.KMOD_SHIFT != 0: + modifier |= MOD_SHIFT + if mod & RSDL.KMOD_ALT != 0: + modifier |= MOD_ALT + return modifier + def mouse_point(self): self.get_next_event() - return self.last_mouse_position + return self.mouse_position def mouse_button(self): self.get_next_event() - return self.mouse_ups.shift() + return self.button | self.get_modifier_mask() def next_keycode(self): - self.get_next_event() - return self.key_downs.shift() + key = self.key + self.key = 0 + return key def peek_keycode(self): self.get_next_event() - return self.key_downs.peek() + return self.key From noreply at buildbot.pypy.org Mon Apr 15 11:21:06 2013 From: noreply at buildbot.pypy.org (timfel) Date: Mon, 15 Apr 2013 11:21:06 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: fixup last commit Message-ID: <20130415092106.DD8031C01FD@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: Changeset: r269:f2a5a4692579 Date: 2013-04-15 11:19 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/f2a5a4692579/ Log: fixup last commit diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -656,7 +656,7 @@ if w_rcvr.__class__ is not w_replacement.__class__: raise PrimitiveFailedError() if (w_rcvr.size() - w_rcvr.instsize(interp.space) <= stop - or w_replacement.size() - w_replacement.instsize(interp.space) < repStart + (stop - start)): + or w_replacement.size() - w_replacement.instsize(interp.space) <= repStart + (stop - start)): raise PrimitiveFailedError() repOff = repStart - start for i0 in range(start, stop + 1): From noreply at buildbot.pypy.org Mon Apr 15 11:21:08 2013 From: noreply at buildbot.pypy.org (timfel) Date: Mon, 15 Apr 2013 11:21:08 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: don't push on semaphore wait Message-ID: <20130415092108.0CC301C01FD@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: Changeset: r270:cdd409f11d15 Date: 2013-04-15 11:19 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/cdd409f11d15/ Log: don't push on semaphore wait diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -1136,7 +1136,7 @@ if not w_rcvr.getclass(interp.space).is_same_object( interp.space.w_Semaphore): raise PrimitiveFailedError() - s_frame.push(w_rcvr) # w_rcvr is the result in the old frame + # s_frame.push(w_rcvr) # w_rcvr is the result in the old frame return wrapper.SemaphoreWrapper(interp.space, w_rcvr).wait(s_frame.w_self()) @expose_primitive(RESUME, unwrap_spec=[object], result_is_new_frame=True) From noreply at buildbot.pypy.org Mon Apr 15 14:23:19 2013 From: noreply at buildbot.pypy.org (arigo) Date: Mon, 15 Apr 2013 14:23:19 +0200 (CEST) Subject: [pypy-commit] pypy.org extradoc: Found the reason. Message-ID: <20130415122319.35DBC1C0292@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: extradoc Changeset: r401:2156c3f89074 Date: 2013-04-15 14:23 +0200 http://bitbucket.org/pypy/pypy.org/changeset/2156c3f89074/ Log: Found the reason. diff --git a/download.html b/download.html --- a/download.html +++ b/download.html @@ -135,7 +135,7 @@

        Building from source

        Warning: the new gcc 4.8 doesn't compile PyPy correctly. -We are investigating.

        +As a workaround, run with CFLAGS=-fno-aggressive-loop-optimizations

        1. Get the source code. The following packages contain the source at the same revision as the above binaries:

          diff --git a/source/download.txt b/source/download.txt --- a/source/download.txt +++ b/source/download.txt @@ -135,7 +135,7 @@ ------------------------------- **Warning:** the new gcc 4.8 doesn't compile PyPy correctly. -We are investigating. +As a workaround, run with ``CFLAGS=-fno-aggressive-loop-optimizations`` 1. Get the source code. The following packages contain the source at the same revision as the above binaries: From noreply at buildbot.pypy.org Mon Apr 15 14:28:34 2013 From: noreply at buildbot.pypy.org (bivab) Date: Mon, 15 Apr 2013 14:28:34 +0200 (CEST) Subject: [pypy-commit] pypy default: this is clearly nonsense, load from the address in reg and not from the number of reg -.- Message-ID: <20130415122834.44A751C05C8@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63361:5cad4f307202 Date: 2013-04-15 14:28 +0200 http://bitbucket.org/pypy/pypy/changeset/5cad4f307202/ Log: this is clearly nonsense, load from the address in reg and not from the number of reg -.- diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -764,13 +764,13 @@ # restore registers self._pop_all_regs_from_jitframe(mc, [], self.cpu.supports_floats) - mc.POP([r.ip.value, r.pc.value]) # return + mc.POP([r.ip.value, r.pc.value]) # return self._frame_realloc_slowpath = mc.materialize(self.cpu.asmmemmgr, []) def _load_shadowstack_top(self, mc, reg, gcrootmap): rst = gcrootmap.get_root_stack_top_addr() mc.gen_load_int(reg.value, rst) - mc.gen_load_int(reg.value, reg.value) + self.load_reg(mc, reg.value, reg.value) return rst def fixup_target_tokens(self, rawstart): From noreply at buildbot.pypy.org Mon Apr 15 14:58:33 2013 From: noreply at buildbot.pypy.org (fijal) Date: Mon, 15 Apr 2013 14:58:33 +0200 (CEST) Subject: [pypy-commit] pypy default: a test and a fix for multiple threads in call_release_gil Message-ID: <20130415125833.546141C05C8@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r63362:a9073815e95a Date: 2013-04-15 14:50 +0200 http://bitbucket.org/pypy/pypy/changeset/a9073815e95a/ Log: a test and a fix for multiple threads in call_release_gil diff --git a/rpython/jit/backend/llsupport/test/test_gc_integration.py b/rpython/jit/backend/llsupport/test/test_gc_integration.py --- a/rpython/jit/backend/llsupport/test/test_gc_integration.py +++ b/rpython/jit/backend/llsupport/test/test_gc_integration.py @@ -671,25 +671,31 @@ # people actually wreck xmm registers cpu = self.cpu l = [] + copied_stack = [None] def before(): + # put nonsense on the top of shadowstack + frame = rffi.cast(JITFRAMEPTR, cpu.gc_ll_descr.gcrootmap.stack[0]) + assert getmap(frame).count('1') == 7 # + copied_stack[0] = cpu.gc_ll_descr.gcrootmap.stack[0] + cpu.gc_ll_descr.gcrootmap.stack[0] = 0 l.append("before") def after(): + cpu.gc_ll_descr.gcrootmap.stack[0] = copied_stack[0] l.append("after") invoke_around_extcall(before, after) def f(frame, x): # all the gc pointers are alive p1 -> p7 (but not p0) - assert getmap(frame).count('1') == 7 # assert x == 1 return 2 - + FUNC = lltype.FuncType([JITFRAMEPTR, lltype.Signed], lltype.Signed) fptr = llhelper(lltype.Ptr(FUNC), f) calldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, - EffectInfo.MOST_GENERAL) + EffectInfo.MOST_GENERAL) loop = self.parse(""" [i0, p1, p2, p3, p4, p5, p6, p7] p0 = force_token() diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -1926,6 +1926,9 @@ self.pending_guard_tokens.append(guard_token) def genop_call(self, op, arglocs, resloc): + return self._genop_call(op, arglocs, resloc) + + def _genop_call(self, op, arglocs, resloc, is_call_release_gil=False): from rpython.jit.backend.llsupport.descr import CallDescr sizeloc = arglocs[0] @@ -1943,11 +1946,14 @@ assert isinstance(descr, CallDescr) stack_max = PASS_ON_MY_FRAME - if self._is_asmgcc() and op.getopnum() == rop.CALL_RELEASE_GIL: - from rpython.memory.gctransform import asmgcroot - stack_max -= asmgcroot.JIT_USE_WORDS - can_collect = 3 # asmgcc only: don't write jf_extra_stack_depth, - # and reload ebp from the css + if is_call_release_gil: + if self._is_asmgcc(): + from rpython.memory.gctransform import asmgcroot + stack_max -= asmgcroot.JIT_USE_WORDS + can_collect = 3 # asmgcc only: don't write jf_extra_stack_depth, + # and reload ebp from the css + else: + can_collect = 0 else: can_collect = 1 @@ -2015,10 +2021,13 @@ # first, close the stack in the sense of the asmgcc GC root tracker gcrootmap = self.cpu.gc_ll_descr.gcrootmap if gcrootmap: + noregs = self.cpu.gc_ll_descr.is_shadow_stack() + gcmap = self._regalloc.get_gcmap([eax], noregs=noregs) + self.push_gcmap(self.mc, gcmap, store=True) self.call_release_gil(gcrootmap, arglocs) # do the call self._store_force_index(guard_op) - self.genop_call(op, arglocs, result_loc) + self._genop_call(op, arglocs, result_loc, is_call_release_gil=True) # then reopen the stack if gcrootmap: self.call_reacquire_gil(gcrootmap, result_loc) From noreply at buildbot.pypy.org Mon Apr 15 14:58:35 2013 From: noreply at buildbot.pypy.org (fijal) Date: Mon, 15 Apr 2013 14:58:35 +0200 (CEST) Subject: [pypy-commit] pypy default: merge Message-ID: <20130415125835.21D2A1C05C8@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r63363:a18f8527134a Date: 2013-04-15 14:58 +0200 http://bitbucket.org/pypy/pypy/changeset/a18f8527134a/ Log: merge diff --git a/lib_pypy/_pypy_interact.py b/lib_pypy/_pypy_interact.py --- a/lib_pypy/_pypy_interact.py +++ b/lib_pypy/_pypy_interact.py @@ -44,7 +44,7 @@ import code if mainmodule is None: import __main__ as mainmodule - console = code.InteractiveConsole(mainmodule.__dict__) + console = code.InteractiveConsole(mainmodule.__dict__, filename='') # some parts of code.py are copied here because it seems to be impossible # to start an interactive console without printing at least one line # of banner diff --git a/lib_pypy/pyrepl/python_reader.py b/lib_pypy/pyrepl/python_reader.py --- a/lib_pypy/pyrepl/python_reader.py +++ b/lib_pypy/pyrepl/python_reader.py @@ -171,11 +171,11 @@ def execute(self, text): try: - # ooh, look at the hack: + # ooh, look at the hack: code = self.compile("# coding:utf8\n"+text.encode('utf-8'), - '', 'single') + '', 'single') except (OverflowError, SyntaxError, ValueError): - self.showsyntaxerror("") + self.showsyntaxerror('') else: self.runcode(code) if sys.stdout and not sys.stdout.closed: diff --git a/lib_pypy/pyrepl/simple_interact.py b/lib_pypy/pyrepl/simple_interact.py --- a/lib_pypy/pyrepl/simple_interact.py +++ b/lib_pypy/pyrepl/simple_interact.py @@ -37,13 +37,13 @@ import code if mainmodule is None: import __main__ as mainmodule - console = code.InteractiveConsole(mainmodule.__dict__) + console = code.InteractiveConsole(mainmodule.__dict__, filename='') def more_lines(unicodetext): # ooh, look at the hack: src = "#coding:utf-8\n"+unicodetext.encode('utf-8') try: - code = console.compile(src, '', 'single') + code = console.compile(src, '', 'single') except (OverflowError, SyntaxError, ValueError): return False else: diff --git a/pypy/module/__pypy__/test/test_signal.py b/pypy/module/__pypy__/test/test_signal.py --- a/pypy/module/__pypy__/test/test_signal.py +++ b/pypy/module/__pypy__/test/test_signal.py @@ -47,8 +47,9 @@ try: done = [] interrupted = [] + print 'starting',i thread.start_new_thread(subthread, ()) - for i in range(10): + for j in range(10): if len(done): break print '.' time.sleep(0.1) diff --git a/pypy/module/micronumpy/interp_dtype.py b/pypy/module/micronumpy/interp_dtype.py --- a/pypy/module/micronumpy/interp_dtype.py +++ b/pypy/module/micronumpy/interp_dtype.py @@ -282,7 +282,10 @@ return dtype if w_dtype is dtype.w_box_type: return dtype - raise OperationError(space.w_TypeError, space.wrap("data type %r not understood" % w_dtype)) + typename = space.type(w_dtype).getname(space) + raise OperationError(space.w_TypeError, space.wrap( + "data type not understood (value of type " + + "%s not expected here)" % typename)) W_Dtype.typedef = TypeDef("dtype", __module__ = "numpypy", diff --git a/pypy/module/micronumpy/test/test_dtypes.py b/pypy/module/micronumpy/test/test_dtypes.py --- a/pypy/module/micronumpy/test/test_dtypes.py +++ b/pypy/module/micronumpy/test/test_dtypes.py @@ -32,7 +32,8 @@ assert dtype(None) is dtype(float) - raises(TypeError, dtype, 1042) + exc = raises(TypeError, dtype, (1, 2)) + assert 'data type not understood' in str(exc.value) raises(KeyError, 'dtype(int)["asdasd"]') def test_dtype_eq(self): diff --git a/pypy/objspace/std/test/test_listobject.py b/pypy/objspace/std/test/test_listobject.py --- a/pypy/objspace/std/test/test_listobject.py +++ b/pypy/objspace/std/test/test_listobject.py @@ -1109,7 +1109,7 @@ self.i = i def __eq__(self, other): if self.i == 9: - del l[i - 1] + del l[self.i - 1] return True else: return False diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -764,13 +764,13 @@ # restore registers self._pop_all_regs_from_jitframe(mc, [], self.cpu.supports_floats) - mc.POP([r.ip.value, r.pc.value]) # return + mc.POP([r.ip.value, r.pc.value]) # return self._frame_realloc_slowpath = mc.materialize(self.cpu.asmmemmgr, []) def _load_shadowstack_top(self, mc, reg, gcrootmap): rst = gcrootmap.get_root_stack_top_addr() mc.gen_load_int(reg.value, rst) - mc.gen_load_int(reg.value, reg.value) + self.load_reg(mc, reg.value, reg.value) return rst def fixup_target_tokens(self, rawstart): diff --git a/rpython/jit/backend/test/runner_test.py b/rpython/jit/backend/test/runner_test.py --- a/rpython/jit/backend/test/runner_test.py +++ b/rpython/jit/backend/test/runner_test.py @@ -2455,12 +2455,12 @@ lltype.free(raw, flavor='raw') def test_call_to_winapi_function(self): - from rpython.rlib.clibffi import _WIN32, FUNCFLAG_STDCALL + from rpython.rlib.clibffi import _WIN32 if not _WIN32: py.test.skip("Windows test only") - from rpython.rlib.libffi import CDLL, types, ArgChain + from rpython.rlib.libffi import WinDLL, types, ArgChain from rpython.rlib.rwin32 import DWORD - libc = CDLL('KERNEL32') + libc = WinDLL('KERNEL32') c_GetCurrentDir = libc.getpointer('GetCurrentDirectoryA', [types.ulong, types.pointer], types.ulong) diff --git a/rpython/jit/codewriter/jtransform.py b/rpython/jit/codewriter/jtransform.py --- a/rpython/jit/codewriter/jtransform.py +++ b/rpython/jit/codewriter/jtransform.py @@ -1753,11 +1753,15 @@ return SpaceOperation('libffi_save_result_%s' % kind, op.args[1:], None) def rewrite_op_jit_force_virtual(self, op): - return self._do_builtin_call(op) + op0 = SpaceOperation('-live-', [], None) + op1 = self._do_builtin_call(op) + if isinstance(op1, list): + return [op0] + op1 + else: + return [op0, op1] def rewrite_op_jit_is_virtual(self, op): - raise Exception, ( - "'vref.virtual' should not be used from jit-visible code") + raise Exception("'vref.virtual' should not be used from jit-visible code") def rewrite_op_jit_force_virtualizable(self, op): # this one is for virtualizables diff --git a/rpython/jit/codewriter/test/test_flatten.py b/rpython/jit/codewriter/test/test_flatten.py --- a/rpython/jit/codewriter/test/test_flatten.py +++ b/rpython/jit/codewriter/test/test_flatten.py @@ -689,6 +689,7 @@ self.encoding_test(f, [], """ new_with_vtable -> %r0 virtual_ref %r0 -> %r1 + -live- residual_call_r_r $<* fn jit_force_virtual>, R[%r1], -> %r2 ref_return %r2 """, transform=True, cc=FakeCallControlWithVRefInfo()) diff --git a/rpython/jit/metainterp/pyjitpl.py b/rpython/jit/metainterp/pyjitpl.py --- a/rpython/jit/metainterp/pyjitpl.py +++ b/rpython/jit/metainterp/pyjitpl.py @@ -1,25 +1,27 @@ -import py, sys +import sys + +import py + +from rpython.jit.codewriter import heaptracker +from rpython.jit.codewriter.effectinfo import EffectInfo +from rpython.jit.codewriter.jitcode import JitCode, SwitchDictDescr +from rpython.jit.metainterp import history, compile, resume, executor +from rpython.jit.metainterp.heapcache import HeapCache +from rpython.jit.metainterp.history import (Const, ConstInt, ConstPtr, + ConstFloat, Box, TargetToken) +from rpython.jit.metainterp.jitexc import JitException, get_llexception +from rpython.jit.metainterp.jitprof import EmptyProfiler +from rpython.jit.metainterp.logger import Logger +from rpython.jit.metainterp.optimizeopt.util import args_dict_box +from rpython.jit.metainterp.resoperation import rop +from rpython.rlib import nonconst, rstack +from rpython.rlib.debug import debug_start, debug_stop, debug_print, make_sure_not_resized +from rpython.rlib.jit import Counters +from rpython.rlib.objectmodel import we_are_translated, specialize +from rpython.rlib.unroll import unrolling_iterable from rpython.rtyper.lltypesystem import lltype, rclass -from rpython.rlib.objectmodel import we_are_translated -from rpython.rlib.unroll import unrolling_iterable -from rpython.rlib.debug import debug_start, debug_stop, debug_print -from rpython.rlib.debug import make_sure_not_resized -from rpython.rlib import nonconst, rstack -from rpython.jit.metainterp import history, compile, resume -from rpython.jit.metainterp.history import Const, ConstInt, ConstPtr, ConstFloat -from rpython.jit.metainterp.history import Box, TargetToken -from rpython.jit.metainterp.resoperation import rop -from rpython.jit.metainterp import executor -from rpython.jit.metainterp.logger import Logger -from rpython.jit.metainterp.jitprof import EmptyProfiler -from rpython.rlib.jit import Counters -from rpython.jit.metainterp.jitexc import JitException, get_llexception -from rpython.jit.metainterp.heapcache import HeapCache -from rpython.rlib.objectmodel import specialize -from rpython.jit.codewriter.jitcode import JitCode, SwitchDictDescr -from rpython.jit.codewriter import heaptracker -from rpython.jit.metainterp.optimizeopt.util import args_dict_box + # ____________________________________________________________ @@ -831,15 +833,17 @@ opimpl_inline_call_irf_f = _opimpl_inline_call3 opimpl_inline_call_irf_v = _opimpl_inline_call3 - @arguments("box", "boxes", "descr") - def _opimpl_residual_call1(self, funcbox, argboxes, calldescr): - return self.do_residual_or_indirect_call(funcbox, argboxes, calldescr) - @arguments("box", "boxes2", "descr") - def _opimpl_residual_call2(self, funcbox, argboxes, calldescr): - return self.do_residual_or_indirect_call(funcbox, argboxes, calldescr) - @arguments("box", "boxes3", "descr") - def _opimpl_residual_call3(self, funcbox, argboxes, calldescr): - return self.do_residual_or_indirect_call(funcbox, argboxes, calldescr) + @arguments("box", "boxes", "descr", "orgpc") + def _opimpl_residual_call1(self, funcbox, argboxes, calldescr, pc): + return self.do_residual_or_indirect_call(funcbox, argboxes, calldescr, pc) + + @arguments("box", "boxes2", "descr", "orgpc") + def _opimpl_residual_call2(self, funcbox, argboxes, calldescr, pc): + return self.do_residual_or_indirect_call(funcbox, argboxes, calldescr, pc) + + @arguments("box", "boxes3", "descr", "orgpc") + def _opimpl_residual_call3(self, funcbox, argboxes, calldescr, pc): + return self.do_residual_or_indirect_call(funcbox, argboxes, calldescr, pc) opimpl_residual_call_r_i = _opimpl_residual_call1 opimpl_residual_call_r_r = _opimpl_residual_call1 @@ -852,8 +856,8 @@ opimpl_residual_call_irf_f = _opimpl_residual_call3 opimpl_residual_call_irf_v = _opimpl_residual_call3 - @arguments("int", "boxes3", "boxes3") - def _opimpl_recursive_call(self, jdindex, greenboxes, redboxes): + @arguments("int", "boxes3", "boxes3", "orgpc") + def _opimpl_recursive_call(self, jdindex, greenboxes, redboxes, pc): targetjitdriver_sd = self.metainterp.staticdata.jitdrivers_sd[jdindex] allboxes = greenboxes + redboxes warmrunnerstate = targetjitdriver_sd.warmstate @@ -868,15 +872,15 @@ # that assembler that we call is still correct self.verify_green_args(targetjitdriver_sd, greenboxes) # - return self.do_recursive_call(targetjitdriver_sd, allboxes, + return self.do_recursive_call(targetjitdriver_sd, allboxes, pc, assembler_call) - def do_recursive_call(self, targetjitdriver_sd, allboxes, + def do_recursive_call(self, targetjitdriver_sd, allboxes, pc, assembler_call=False): portal_code = targetjitdriver_sd.mainjitcode k = targetjitdriver_sd.portal_runner_adr funcbox = ConstInt(heaptracker.adr2int(k)) - return self.do_residual_call(funcbox, allboxes, portal_code.calldescr, + return self.do_residual_call(funcbox, allboxes, portal_code.calldescr, pc, assembler_call=assembler_call, assembler_call_jd=targetjitdriver_sd) @@ -935,7 +939,7 @@ return box # no promotion needed, already a Const else: constbox = box.constbox() - resbox = self.do_residual_call(funcbox, [box, constbox], descr) + resbox = self.do_residual_call(funcbox, [box, constbox], descr, orgpc) promoted_box = resbox.constbox() # This is GUARD_VALUE because GUARD_TRUE assumes the existance # of a label when computing resumepc @@ -1027,7 +1031,7 @@ except ChangeFrame: pass frame = self.metainterp.framestack[-1] - frame.do_recursive_call(jitdriver_sd, greenboxes + redboxes, + frame.do_recursive_call(jitdriver_sd, greenboxes + redboxes, orgpc, assembler_call=True) raise ChangeFrame @@ -1329,7 +1333,7 @@ self.metainterp.assert_no_exception() return resbox - def do_residual_call(self, funcbox, argboxes, descr, + def do_residual_call(self, funcbox, argboxes, descr, pc, assembler_call=False, assembler_call_jd=None): # First build allboxes: it may need some reordering from the @@ -1369,6 +1373,10 @@ effectinfo.check_forces_virtual_or_virtualizable()): # residual calls require attention to keep virtualizables in-sync self.metainterp.clear_exception() + if effectinfo.oopspecindex == EffectInfo.OS_JIT_FORCE_VIRTUAL: + resbox = self._do_jit_force_virtual(allboxes, descr, pc) + if resbox is not None: + return resbox self.metainterp.vable_and_vrefs_before_residual_call() resbox = self.metainterp.execute_and_record_varargs( rop.CALL_MAY_FORCE, allboxes, descr=descr) @@ -1399,7 +1407,27 @@ pure = effectinfo.check_is_elidable() return self.execute_varargs(rop.CALL, allboxes, descr, exc, pure) - def do_residual_or_indirect_call(self, funcbox, argboxes, calldescr): + def _do_jit_force_virtual(self, allboxes, descr, pc): + assert len(allboxes) == 2 + if (self.metainterp.jitdriver_sd.virtualizable_info is None and + self.metainterp.jitdriver_sd.greenfield_info is None): + # can occur in case of multiple JITs + return None + vref_box = allboxes[1] + standard_box = self.metainterp.virtualizable_boxes[-1] + if standard_box is vref_box: + return vref_box + if self.metainterp.heapcache.is_nonstandard_virtualizable(vref_box): + return None + eqbox = self.metainterp.execute_and_record(rop.PTR_EQ, None, vref_box, standard_box) + eqbox = self.implement_guard_value(eqbox, pc) + isstandard = eqbox.getint() + if isstandard: + return standard_box + else: + return None + + def do_residual_or_indirect_call(self, funcbox, argboxes, calldescr, pc): """The 'residual_call' operation is emitted in two cases: when we have to generate a residual CALL operation, but also to handle an indirect_call that may need to be inlined.""" @@ -1411,7 +1439,7 @@ # we should follow calls to this graph return self.metainterp.perform_call(jitcode, argboxes) # but we should not follow calls to that graph - return self.do_residual_call(funcbox, argboxes, calldescr) + return self.do_residual_call(funcbox, argboxes, calldescr, pc) # ____________________________________________________________ diff --git a/rpython/jit/metainterp/test/test_virtualizable.py b/rpython/jit/metainterp/test/test_virtualizable.py --- a/rpython/jit/metainterp/test/test_virtualizable.py +++ b/rpython/jit/metainterp/test/test_virtualizable.py @@ -1,20 +1,22 @@ import py + +from rpython.jit.codewriter import heaptracker +from rpython.jit.codewriter.policy import StopAtXPolicy +from rpython.jit.metainterp.optimizeopt.test.test_util import LLtypeMixin +from rpython.jit.metainterp.test.support import LLJitMixin, OOJitMixin +from rpython.jit.metainterp.warmspot import get_translator +from rpython.rlib.jit import JitDriver, hint, dont_look_inside, promote, virtual_ref +from rpython.rlib.rarithmetic import intmask +from rpython.rtyper.annlowlevel import hlstr from rpython.rtyper.extregistry import ExtRegistryEntry from rpython.rtyper.lltypesystem import lltype, lloperation, rclass, llmemory -from rpython.rtyper.annlowlevel import llhelper -from rpython.rtyper.rclass import IR_IMMUTABLE, IR_IMMUTABLE_ARRAY -from rpython.jit.codewriter.policy import StopAtXPolicy -from rpython.jit.codewriter import heaptracker -from rpython.rlib.jit import JitDriver, hint, dont_look_inside, promote -from rpython.rlib.rarithmetic import intmask -from rpython.jit.metainterp.test.support import LLJitMixin, OOJitMixin -from rpython.rtyper.rclass import FieldListAccessor -from rpython.jit.metainterp.warmspot import get_stats, get_translator -from rpython.jit.metainterp import history -from rpython.jit.metainterp.optimizeopt.test.test_util import LLtypeMixin +from rpython.rtyper.rclass import IR_IMMUTABLE, IR_IMMUTABLE_ARRAY, FieldListAccessor + def promote_virtualizable(*args): pass + + class Entry(ExtRegistryEntry): "Annotation and rtyping of LLOp instances, which are callable." _about_ = promote_virtualizable @@ -46,7 +48,7 @@ ('inst_node', lltype.Ptr(LLtypeMixin.NODE)), hints = {'virtualizable2_accessor': FieldListAccessor()}) XY._hints['virtualizable2_accessor'].initialize( - XY, {'inst_x' : IR_IMMUTABLE, 'inst_node' : IR_IMMUTABLE}) + XY, {'inst_x': IR_IMMUTABLE, 'inst_node': IR_IMMUTABLE}) xy_vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) heaptracker.set_testing_vtable_for_gcstruct(XY, xy_vtable, 'XY') @@ -73,7 +75,7 @@ x = xy.inst_x xy.inst_x = x + 1 n -= 1 - promote_virtualizable(xy, 'inst_x') + promote_virtualizable(xy, 'inst_x') return xy.inst_x res = self.meta_interp(f, [20]) assert res == 30 @@ -97,7 +99,7 @@ x = xy.inst_x xy.inst_x = x + 10 n -= 1 - promote_virtualizable(xy, 'inst_x') + promote_virtualizable(xy, 'inst_x') return xy.inst_x assert f(5) == 185 res = self.meta_interp(f, [5]) @@ -118,10 +120,10 @@ x = xy.inst_x if n <= 10: x += 1000 - promote_virtualizable(xy, 'inst_x') + promote_virtualizable(xy, 'inst_x') xy.inst_x = x + 1 n -= 1 - promote_virtualizable(xy, 'inst_x') + promote_virtualizable(xy, 'inst_x') return xy.inst_x res = self.meta_interp(f, [18]) assert res == 10118 @@ -164,7 +166,7 @@ xy.inst_x = x + 1 m = (m+1) & 3 # the loop gets unrolled 4 times n -= 1 - promote_virtualizable(xy, 'inst_x') + promote_virtualizable(xy, 'inst_x') return xy.inst_x def f(n): res = 0 @@ -194,7 +196,7 @@ promote_virtualizable(xy, 'inst_x') xy.inst_x = value + 100 # virtualized away n -= 1 - promote_virtualizable(xy, 'inst_x') + promote_virtualizable(xy, 'inst_x') return xy.inst_x res = self.meta_interp(f, [20]) assert res == 134 @@ -212,8 +214,8 @@ ('inst_l2', lltype.Ptr(lltype.GcArray(lltype.Signed))), hints = {'virtualizable2_accessor': FieldListAccessor()}) XY2._hints['virtualizable2_accessor'].initialize( - XY2, {'inst_x' : IR_IMMUTABLE, - 'inst_l1' : IR_IMMUTABLE_ARRAY, 'inst_l2' : IR_IMMUTABLE_ARRAY}) + XY2, {'inst_x': IR_IMMUTABLE, + 'inst_l1': IR_IMMUTABLE_ARRAY, 'inst_l2': IR_IMMUTABLE_ARRAY}) xy2_vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) heaptracker.set_testing_vtable_for_gcstruct(XY2, xy2_vtable, 'XY2') @@ -241,11 +243,11 @@ while n > 0: myjitdriver.can_enter_jit(xy2=xy2, n=n) myjitdriver.jit_merge_point(xy2=xy2, n=n) - promote_virtualizable(xy2, 'inst_l1') + promote_virtualizable(xy2, 'inst_l1') promote_virtualizable(xy2, 'inst_l2') xy2.inst_l1[2] += xy2.inst_l2[0] n -= 1 - promote_virtualizable(xy2, 'inst_l1') + promote_virtualizable(xy2, 'inst_l1') return xy2.inst_l1[2] res = self.meta_interp(f, [16]) assert res == 3001 + 16 * 80 @@ -292,7 +294,7 @@ myjitdriver.can_enter_jit(xy2=xy2, n=n) myjitdriver.jit_merge_point(xy2=xy2, n=n) promote_virtualizable(xy2, 'inst_l1') - promote_virtualizable(xy2, 'inst_l2') + promote_virtualizable(xy2, 'inst_l2') xy2.inst_l1[1] += len(xy2.inst_l2) n -= 1 def f(n): @@ -373,7 +375,7 @@ promote_virtualizable(xy2, 'inst_l2') xy2.inst_l2[0] = value + 100 # virtualized away n -= 1 - promote_virtualizable(xy2, 'inst_l2') + promote_virtualizable(xy2, 'inst_l2') return xy2.inst_l2[0] expected = f(20) res = self.meta_interp(f, [20], enable_opts='') @@ -406,8 +408,8 @@ myjitdriver.can_enter_jit(xy2=xy2, n=n) myjitdriver.jit_merge_point(xy2=xy2, n=n) parent = xy2.parent - promote_virtualizable(parent, 'inst_x') - promote_virtualizable(parent, 'inst_l2') + promote_virtualizable(parent, 'inst_x') + promote_virtualizable(parent, 'inst_l2') parent.inst_l2[0] += parent.inst_x n -= 1 def f(n): @@ -432,8 +434,7 @@ # ------------------------------ -class ImplicitVirtualizableTests: - +class ImplicitVirtualizableTests(object): def test_simple_implicit(self): myjitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) @@ -473,9 +474,9 @@ def __init__(self, l, s): self.l = l self.s = s - + def f(n, a): - frame = Frame([a,a+1,a+2,a+3], 0) + frame = Frame([a, a+1, a+2, a+3], 0) x = 0 while n > 0: myjitdriver.can_enter_jit(frame=frame, n=n, x=x) @@ -544,7 +545,7 @@ def f(n): BaseFrame([]) # hack to force 'x' to be in BaseFrame - frame = Frame([1,2,3]) + frame = Frame([1, 2, 3]) z = 0 while n > 0: jitdriver.can_enter_jit(frame=frame, n=n, z=z) @@ -560,9 +561,10 @@ def test_external_read(self): jitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) - + class Frame(object): _virtualizable2_ = ['x', 'y'] + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -592,9 +594,10 @@ def test_external_read_with_exception(self): jitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) - + class Frame(object): _virtualizable2_ = ['x', 'y'] + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -634,6 +637,7 @@ class Frame(object): _virtualizable2_ = ['x', 'y'] + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -663,9 +667,10 @@ def test_external_read_sometimes(self): jitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) - + class Frame(object): _virtualizable2_ = ['x', 'y'] + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -699,11 +704,13 @@ def test_external_read_sometimes_with_virtuals(self): jitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) - + class Frame(object): _virtualizable2_ = ['x', 'y'] + class Y: pass + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -742,11 +749,13 @@ def test_external_read_sometimes_changing_virtuals(self): jitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) - + class Frame(object): _virtualizable2_ = ['x', 'y'] + class Y: pass + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -790,11 +799,13 @@ def test_external_read_sometimes_with_exception(self): jitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) - + class Frame(object): _virtualizable2_ = ['x', 'y'] + class FooBarError(Exception): pass + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -832,9 +843,10 @@ def test_external_read_sometimes_dont_compile_guard(self): jitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) - + class Frame(object): _virtualizable2_ = ['x', 'y'] + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -868,9 +880,10 @@ def test_external_read_sometimes_recursive(self): jitdriver = JitDriver(greens = [], reds = ['rec', 'frame'], virtualizables = ['frame']) - + class Frame(object): _virtualizable2_ = ['x', 'y'] + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -919,9 +932,10 @@ def test_external_write_sometimes(self): jitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) - + class Frame(object): _virtualizable2_ = ['x', 'y'] + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -955,9 +969,10 @@ def test_bridge_forces(self): jitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) - + class Frame(object): _virtualizable2_ = ['x', 'y'] + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -988,6 +1003,7 @@ def test_promote_index_in_virtualizable_list(self): jitdriver = JitDriver(greens = [], reds = ['n', 'frame'], virtualizables = ['frame']) + class Frame(object): _virtualizable2_ = ['stackpos', 'stack[*]'] @@ -1063,8 +1079,8 @@ assert direct_calls(f_graph) == ['__init__', 'force_virtualizable_if_necessary', 'll_portal_runner'] - assert direct_calls(portal_graph)==['force_virtualizable_if_necessary', - 'maybe_enter_jit'] + assert direct_calls(portal_graph) == ['force_virtualizable_if_necessary', + 'maybe_enter_jit'] assert direct_calls(init_graph) == [] def test_virtual_child_frame(self): @@ -1262,7 +1278,7 @@ somewhere_else = SomewhereElse() def jump_back(frame, fail): - myjitdriver.can_enter_jit(frame=frame, fail=fail) + myjitdriver.can_enter_jit(frame=frame, fail=fail) def f(n, fail): frame = Frame(n, 0) @@ -1315,8 +1331,10 @@ f.x -= 1 result += indirection(f) return result + def indirection(arg): return interp(arg) + def run_interp(n): f = hint(Frame(n), access_directly=True) return interp(f) @@ -1325,7 +1343,7 @@ assert res == run_interp(4) def test_guard_failure_in_inlined_function(self): - from rpython.rtyper.annlowlevel import hlstr + class Frame(object): _virtualizable2_ = ['n', 'next'] @@ -1368,11 +1386,12 @@ assert 0 pc += 1 return frame.n + def main(n): frame = Frame(n) return f("c-l", frame) - print main(100) res = self.meta_interp(main, [100], inline=True, enable_opts='') + assert res == main(100) def test_stuff_from_backend_test(self): class Thing(object): @@ -1385,6 +1404,7 @@ driver = JitDriver(greens = ['codeno'], reds = ['i', 'frame'], virtualizables = ['frame'], get_printable_location = lambda codeno: str(codeno)) + class SomewhereElse(object): pass @@ -1422,13 +1442,40 @@ print hex(res) assert res == main(0) + def test_force_virtualref_to_virtualizable(self): + jitdriver = JitDriver( + greens=[], + reds=['i', 'n', 'f', 'f_ref'], + virtualizables=['f'] + ) + + class Frame(object): + _virtualizable2_ = ['x'] + + def main(n): + f = Frame() + f.x = 1 + f_ref = virtual_ref(f) + i = 0 + while i < n: + jitdriver.jit_merge_point(f=f, i=i, f_ref=f_ref, n=n) + i += f_ref().x + return i + + res = self.meta_interp(main, [10]) + assert res == main(10) + self.check_resops({ + "getfield_gc": 1, "int_lt": 2, "ptr_eq": 1, "guard_true": 3, + "int_add": 2, "jump": 1 + }) + class TestOOtype(#ExplicitVirtualizableTests, ImplicitVirtualizableTests, OOJitMixin): pass - + class TestLLtype(ExplicitVirtualizableTests, ImplicitVirtualizableTests, LLJitMixin): From noreply at buildbot.pypy.org Mon Apr 15 15:11:49 2013 From: noreply at buildbot.pypy.org (bivab) Date: Mon, 15 Apr 2013 15:11:49 +0200 (CEST) Subject: [pypy-commit] pypy default: fix, bah Message-ID: <20130415131149.E678B1C01FD@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63364:0ac570dff7e5 Date: 2013-04-15 15:11 +0200 http://bitbucket.org/pypy/pypy/changeset/0ac570dff7e5/ Log: fix, bah diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -770,7 +770,7 @@ def _load_shadowstack_top(self, mc, reg, gcrootmap): rst = gcrootmap.get_root_stack_top_addr() mc.gen_load_int(reg.value, rst) - self.load_reg(mc, reg.value, reg.value) + self.load_reg(mc, reg, reg) return rst def fixup_target_tokens(self, rawstart): From noreply at buildbot.pypy.org Mon Apr 15 15:11:51 2013 From: noreply at buildbot.pypy.org (bivab) Date: Mon, 15 Apr 2013 15:11:51 +0200 (CEST) Subject: [pypy-commit] pypy default: merge heads Message-ID: <20130415131151.466B51C01FD@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63365:c2d0282acb2a Date: 2013-04-15 15:11 +0200 http://bitbucket.org/pypy/pypy/changeset/c2d0282acb2a/ Log: merge heads diff --git a/rpython/jit/backend/llsupport/test/test_gc_integration.py b/rpython/jit/backend/llsupport/test/test_gc_integration.py --- a/rpython/jit/backend/llsupport/test/test_gc_integration.py +++ b/rpython/jit/backend/llsupport/test/test_gc_integration.py @@ -671,25 +671,31 @@ # people actually wreck xmm registers cpu = self.cpu l = [] + copied_stack = [None] def before(): + # put nonsense on the top of shadowstack + frame = rffi.cast(JITFRAMEPTR, cpu.gc_ll_descr.gcrootmap.stack[0]) + assert getmap(frame).count('1') == 7 # + copied_stack[0] = cpu.gc_ll_descr.gcrootmap.stack[0] + cpu.gc_ll_descr.gcrootmap.stack[0] = 0 l.append("before") def after(): + cpu.gc_ll_descr.gcrootmap.stack[0] = copied_stack[0] l.append("after") invoke_around_extcall(before, after) def f(frame, x): # all the gc pointers are alive p1 -> p7 (but not p0) - assert getmap(frame).count('1') == 7 # assert x == 1 return 2 - + FUNC = lltype.FuncType([JITFRAMEPTR, lltype.Signed], lltype.Signed) fptr = llhelper(lltype.Ptr(FUNC), f) calldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, - EffectInfo.MOST_GENERAL) + EffectInfo.MOST_GENERAL) loop = self.parse(""" [i0, p1, p2, p3, p4, p5, p6, p7] p0 = force_token() diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -1926,6 +1926,9 @@ self.pending_guard_tokens.append(guard_token) def genop_call(self, op, arglocs, resloc): + return self._genop_call(op, arglocs, resloc) + + def _genop_call(self, op, arglocs, resloc, is_call_release_gil=False): from rpython.jit.backend.llsupport.descr import CallDescr sizeloc = arglocs[0] @@ -1943,11 +1946,14 @@ assert isinstance(descr, CallDescr) stack_max = PASS_ON_MY_FRAME - if self._is_asmgcc() and op.getopnum() == rop.CALL_RELEASE_GIL: - from rpython.memory.gctransform import asmgcroot - stack_max -= asmgcroot.JIT_USE_WORDS - can_collect = 3 # asmgcc only: don't write jf_extra_stack_depth, - # and reload ebp from the css + if is_call_release_gil: + if self._is_asmgcc(): + from rpython.memory.gctransform import asmgcroot + stack_max -= asmgcroot.JIT_USE_WORDS + can_collect = 3 # asmgcc only: don't write jf_extra_stack_depth, + # and reload ebp from the css + else: + can_collect = 0 else: can_collect = 1 @@ -2015,10 +2021,13 @@ # first, close the stack in the sense of the asmgcc GC root tracker gcrootmap = self.cpu.gc_ll_descr.gcrootmap if gcrootmap: + noregs = self.cpu.gc_ll_descr.is_shadow_stack() + gcmap = self._regalloc.get_gcmap([eax], noregs=noregs) + self.push_gcmap(self.mc, gcmap, store=True) self.call_release_gil(gcrootmap, arglocs) # do the call self._store_force_index(guard_op) - self.genop_call(op, arglocs, result_loc) + self._genop_call(op, arglocs, result_loc, is_call_release_gil=True) # then reopen the stack if gcrootmap: self.call_reacquire_gil(gcrootmap, result_loc) From noreply at buildbot.pypy.org Mon Apr 15 15:13:09 2013 From: noreply at buildbot.pypy.org (timfel) Date: Mon, 15 Apr 2013 15:13:09 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: Apply cursor shape Message-ID: <20130415131309.8931D1C311F@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: Changeset: r271:cb4ecb195c6e Date: 2013-04-15 15:12 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/cb4ecb195c6e/ Log: Apply cursor shape diff --git a/spyvm/display.py b/spyvm/display.py --- a/spyvm/display.py +++ b/spyvm/display.py @@ -22,6 +22,7 @@ assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 RSDL.WM_SetCaption(title, "RSqueakVM") RSDL.EnableUNICODE(1) + SDLCursor.has_display = True self.has_surface = False self.mouse_position = [0, 0] self.button = 0 @@ -79,6 +80,8 @@ self.key = ord(chars[0]) else: pass # XXX: Todo? + elif c_type == RSDL.QUIT: + exit(0) finally: lltype.free(event, flavor='raw') @@ -110,3 +113,46 @@ def peek_keycode(self): self.get_next_event() return self.key + + +class SDLCursorClass(object): + _attrs_ = ["cursor", "has_cursor", "has_display"] + + instance = None + + def __init__(self): + self.has_cursor = False + self.has_display = False + + def set(self, data_words, w, h, x, y, mask_words=None): + if not self.has_display: + return + if self.has_cursor: + RSDL.FreeCursor(self.cursor) + try: + data = self.words_to_bytes(len(data_words) * 4, data_words) + try: + mask = self.words_to_bytes(len(data_words) * 4, mask_words) + self.cursor = RSDL.CreateCursor(data, mask, w, h, x, y) + self.has_cursor = True + RSDL.SetCursor(self.cursor) + finally: + lltype.free(mask, flavor="raw") + finally: + lltype.free(data, flavor="raw") + + def words_to_bytes(self, bytenum, words): + bytes = lltype.malloc(RSDL.Uint8P.TO, bytenum, flavor="raw") + if words: + for pos in range(bytenum / 4): + word = words[pos] + bytes[pos * 4] = rffi.r_uchar((word >> 24) & 0xff) + bytes[pos * 4 + 1] = rffi.r_uchar((word >> 16) & 0xff) + bytes[pos * 4 + 2] = rffi.r_uchar((word >> 8) & 0xff) + bytes[pos * 4 + 3] = rffi.r_uchar(word & 0xff) + else: + for idx in range(bytenum): + bytes[idx] = rffi.r_uchar(0) + return bytes + +SDLCursor = SDLCursorClass() diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -585,7 +585,26 @@ if argcount == 1: # TODO: use mask w_mask = s_frame.peek(0) - # TODO: Use info from cursor object. + if not isinstance(w_mask, model.W_WordsObject): + raise PrimitiveFailedError() + else: + w_mask = None + w_bitmap = w_rcvr.fetch(interp.space, 0) + if not isinstance(w_bitmap, model.W_WordsObject): + raise PrimitiveFailedError() + width = interp.space.unwrap_int(w_rcvr.fetch(interp.space, 1)) + height = interp.space.unwrap_int(w_rcvr.fetch(interp.space, 2)) + depth = interp.space.unwrap_int(w_rcvr.fetch(interp.space, 3)) + hotpt = wrapper.PointWrapper(interp.space, w_rcvr.fetch(interp.space, 4)) + display.SDLCursor.set( + w_bitmap.words, + width, + height, + hotpt.x(), + hotpt.y(), + w_mask.words if w_mask else None + ) + interp.space.objtable['w_cursor'] = w_rcvr return w_rcvr From noreply at buildbot.pypy.org Mon Apr 15 16:09:11 2013 From: noreply at buildbot.pypy.org (bivab) Date: Mon, 15 Apr 2013 16:09:11 +0200 (CEST) Subject: [pypy-commit] pypy default: Port a9073815e95a to ARM Message-ID: <20130415140911.BC7731C0292@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63366:7d1501e50c21 Date: 2013-04-15 16:08 +0200 http://bitbucket.org/pypy/pypy/changeset/7d1501e50c21/ Log: Port a9073815e95a to ARM diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -352,7 +352,8 @@ def _emit_call(self, adr, arglocs, fcond=c.AL, resloc=None, result_info=(-1, -1), - can_collect=1): + can_collect=1, + reload_frame=False): if self.cpu.hf_abi: stack_args, adr = self._setup_call_hf(adr, arglocs, fcond, resloc, result_info) @@ -365,7 +366,6 @@ gcmap = self._regalloc.get_gcmap([r.r0], noregs=noregs) self.push_gcmap(self.mc, gcmap, store=True) #the actual call - #self.mc.BKPT() if adr.is_imm(): self.mc.BL(adr.value) elif adr.is_stack(): @@ -388,6 +388,8 @@ if can_collect: self._reload_frame_if_necessary(self.mc, can_collect=can_collect) self.pop_gcmap(self.mc) + elif reload_frame: + self._reload_frame_if_necessary(self.mc) return fcond def _restore_sp(self, stack_args, fcond): @@ -1266,6 +1268,10 @@ resloc = arglocs[0] if gcrootmap: + noregs = self.cpu.gc_ll_descr.is_shadow_stack() + assert noregs + gcmap = self._regalloc.get_gcmap([r.r0], noregs=noregs) + self.push_gcmap(self.mc, gcmap, store=True) self.call_release_gil(gcrootmap, arglocs, regalloc, fcond) # do the call self._store_force_index(guard_op) @@ -1275,7 +1281,8 @@ signed = descr.is_result_signed() # self._emit_call(adr, callargs, fcond, - resloc, (size, signed)) + resloc, (size, signed), + can_collect=0) # then reopen the stack if gcrootmap: self.call_reacquire_gil(gcrootmap, resloc, regalloc, fcond) @@ -1288,7 +1295,8 @@ # NOTE: We assume that the floating point registers won't be modified. assert gcrootmap.is_shadow_stack with saved_registers(self.mc, regalloc.rm.save_around_call_regs): - self._emit_call(imm(self.releasegil_addr), [], fcond) + self._emit_call(imm(self.releasegil_addr), [], + fcond, can_collect=False) def call_reacquire_gil(self, gcrootmap, save_loc, regalloc, fcond): # save the previous result into the stack temporarily, in case it is in @@ -1305,7 +1313,8 @@ assert gcrootmap.is_shadow_stack # call the reopenstack() function (also reacquiring the GIL) with saved_registers(self.mc, regs_to_save, vfp_regs_to_save): - self._emit_call(imm(self.reacqgil_addr), [], fcond) + self._emit_call(imm(self.reacqgil_addr), [], fcond, + can_collect=False, reload_frame=True) def _store_force_index(self, guard_op): faildescr = guard_op.getdescr() From noreply at buildbot.pypy.org Mon Apr 15 16:14:46 2013 From: noreply at buildbot.pypy.org (arigo) Date: Mon, 15 Apr 2013 16:14:46 +0200 (CEST) Subject: [pypy-commit] pypy default: Add a workaround for GCC 4.8. Message-ID: <20130415141446.1DAE61C311F@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63367:7b4d1048f5c9 Date: 2013-04-15 16:17 +0200 http://bitbucket.org/pypy/pypy/changeset/7b4d1048f5c9/ Log: Add a workaround for GCC 4.8. diff --git a/rpython/translator/c/src/support.h b/rpython/translator/c/src/support.h --- a/rpython/translator/c/src/support.h +++ b/rpython/translator/c/src/support.h @@ -2,6 +2,16 @@ /************************************************************/ /*** C header subsection: support functions ***/ +/* a temporary(?) workaround for GCC 4.8. See: + http://stackoverflow.com/questions/16016627/ +*/ +#ifdef __GNUC__ +# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) +# pragma GCC optimize("no-aggressive-loop-optimizations") +# endif +#endif + + #define RUNNING_ON_LLINTERP 0 #define OP_JIT_RECORD_KNOWN_CLASS(i, c, r) /* nothing */ From noreply at buildbot.pypy.org Mon Apr 15 16:38:35 2013 From: noreply at buildbot.pypy.org (fijal) Date: Mon, 15 Apr 2013 16:38:35 +0200 (CEST) Subject: [pypy-commit] pypy default: pffff Message-ID: <20130415143835.AAEEC1C3128@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r63368:41ffa1b27b0c Date: 2013-04-15 16:37 +0200 http://bitbucket.org/pypy/pypy/changeset/41ffa1b27b0c/ Log: pffff diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -2018,6 +2018,7 @@ def genop_guard_call_release_gil(self, op, guard_op, guard_token, arglocs, result_loc): + self._store_force_index(guard_op) # first, close the stack in the sense of the asmgcc GC root tracker gcrootmap = self.cpu.gc_ll_descr.gcrootmap if gcrootmap: @@ -2026,7 +2027,6 @@ self.push_gcmap(self.mc, gcmap, store=True) self.call_release_gil(gcrootmap, arglocs) # do the call - self._store_force_index(guard_op) self._genop_call(op, arglocs, result_loc, is_call_release_gil=True) # then reopen the stack if gcrootmap: From noreply at buildbot.pypy.org Mon Apr 15 16:38:37 2013 From: noreply at buildbot.pypy.org (fijal) Date: Mon, 15 Apr 2013 16:38:37 +0200 (CEST) Subject: [pypy-commit] pypy default: merge Message-ID: <20130415143837.377911C3128@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r63369:b0630c2d6da5 Date: 2013-04-15 16:38 +0200 http://bitbucket.org/pypy/pypy/changeset/b0630c2d6da5/ Log: merge diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -770,7 +770,7 @@ def _load_shadowstack_top(self, mc, reg, gcrootmap): rst = gcrootmap.get_root_stack_top_addr() mc.gen_load_int(reg.value, rst) - self.load_reg(mc, reg.value, reg.value) + self.load_reg(mc, reg, reg) return rst def fixup_target_tokens(self, rawstart): diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -352,7 +352,8 @@ def _emit_call(self, adr, arglocs, fcond=c.AL, resloc=None, result_info=(-1, -1), - can_collect=1): + can_collect=1, + reload_frame=False): if self.cpu.hf_abi: stack_args, adr = self._setup_call_hf(adr, arglocs, fcond, resloc, result_info) @@ -365,7 +366,6 @@ gcmap = self._regalloc.get_gcmap([r.r0], noregs=noregs) self.push_gcmap(self.mc, gcmap, store=True) #the actual call - #self.mc.BKPT() if adr.is_imm(): self.mc.BL(adr.value) elif adr.is_stack(): @@ -388,6 +388,8 @@ if can_collect: self._reload_frame_if_necessary(self.mc, can_collect=can_collect) self.pop_gcmap(self.mc) + elif reload_frame: + self._reload_frame_if_necessary(self.mc) return fcond def _restore_sp(self, stack_args, fcond): @@ -1266,6 +1268,10 @@ resloc = arglocs[0] if gcrootmap: + noregs = self.cpu.gc_ll_descr.is_shadow_stack() + assert noregs + gcmap = self._regalloc.get_gcmap([r.r0], noregs=noregs) + self.push_gcmap(self.mc, gcmap, store=True) self.call_release_gil(gcrootmap, arglocs, regalloc, fcond) # do the call self._store_force_index(guard_op) @@ -1275,7 +1281,8 @@ signed = descr.is_result_signed() # self._emit_call(adr, callargs, fcond, - resloc, (size, signed)) + resloc, (size, signed), + can_collect=0) # then reopen the stack if gcrootmap: self.call_reacquire_gil(gcrootmap, resloc, regalloc, fcond) @@ -1288,7 +1295,8 @@ # NOTE: We assume that the floating point registers won't be modified. assert gcrootmap.is_shadow_stack with saved_registers(self.mc, regalloc.rm.save_around_call_regs): - self._emit_call(imm(self.releasegil_addr), [], fcond) + self._emit_call(imm(self.releasegil_addr), [], + fcond, can_collect=False) def call_reacquire_gil(self, gcrootmap, save_loc, regalloc, fcond): # save the previous result into the stack temporarily, in case it is in @@ -1305,7 +1313,8 @@ assert gcrootmap.is_shadow_stack # call the reopenstack() function (also reacquiring the GIL) with saved_registers(self.mc, regs_to_save, vfp_regs_to_save): - self._emit_call(imm(self.reacqgil_addr), [], fcond) + self._emit_call(imm(self.reacqgil_addr), [], fcond, + can_collect=False, reload_frame=True) def _store_force_index(self, guard_op): faildescr = guard_op.getdescr() diff --git a/rpython/translator/c/src/support.h b/rpython/translator/c/src/support.h --- a/rpython/translator/c/src/support.h +++ b/rpython/translator/c/src/support.h @@ -2,6 +2,16 @@ /************************************************************/ /*** C header subsection: support functions ***/ +/* a temporary(?) workaround for GCC 4.8. See: + http://stackoverflow.com/questions/16016627/ +*/ +#ifdef __GNUC__ +# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) +# pragma GCC optimize("no-aggressive-loop-optimizations") +# endif +#endif + + #define RUNNING_ON_LLINTERP 0 #define OP_JIT_RECORD_KNOWN_CLASS(i, c, r) /* nothing */ From noreply at buildbot.pypy.org Mon Apr 15 16:58:39 2013 From: noreply at buildbot.pypy.org (fijal) Date: Mon, 15 Apr 2013 16:58:39 +0200 (CEST) Subject: [pypy-commit] pypy default: skip this test on llgraph Message-ID: <20130415145839.DC5A21C313E@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r63370:571e7692fafd Date: 2013-04-15 16:58 +0200 http://bitbucket.org/pypy/pypy/changeset/571e7692fafd/ Log: skip this test on llgraph diff --git a/rpython/jit/backend/test/runner_test.py b/rpython/jit/backend/test/runner_test.py --- a/rpython/jit/backend/test/runner_test.py +++ b/rpython/jit/backend/test/runner_test.py @@ -348,7 +348,7 @@ i0 = BoxInt() class UntouchableFailDescr(AbstractFailDescr): final_descr = True - + def __setattr__(self, name, value): if (name == 'index' or name == '_carry_around_for_tests' or name == '_TYPE' or name == '_cpu'): @@ -2832,6 +2832,11 @@ assert not called def test_assembler_call_propagate_exc(self): + from rpython.jit.backend.llsupport.llmodel import AbstractLLCPU + + if not isinstance(self.cpu, AbstractLLCPU): + py.test.skip("llgraph can't fake exceptions well enough, give up") + excdescr = BasicFailDescr(666) self.cpu.propagate_exception_descr = excdescr self.cpu.setup_once() # xxx redo it, because we added @@ -3420,7 +3425,7 @@ calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, effectinfo) testcases = [(4.0, 2.0), (6.25, 2.5)] for arg, expected in testcases: - res = self.execute_operation(rop.CALL, + res = self.execute_operation(rop.CALL, [funcbox, boxfloat(arg)], 'float', descr=calldescr) assert res.getfloat() == expected @@ -3776,7 +3781,7 @@ # memory assert values[0] == 0 - def test_compile_bridge_while_running(self): + def test_compile_bridge_while_running(self): def func(): bridge = parse(""" [i1, i2, px] @@ -3823,9 +3828,9 @@ func2_ptr = llhelper(FPTR2, func2) calldescr2 = cpu.calldescrof(FUNC2, FUNC2.ARGS, FUNC2.RESULT, EffectInfo.MOST_GENERAL) - + faildescr = BasicFailDescr(0) - + looptoken = JitCellToken() loop = parse(""" [i0, i1, i2] @@ -3841,7 +3846,7 @@ if not isinstance(self.cpu, AbstractLLCPU): py.test.skip("pointless test on non-asm") - + frame = lltype.cast_opaque_ptr(jitframe.JITFRAMEPTR, frame) assert len(frame.jf_frame) == frame.jf_frame_info.jfi_frame_depth ref = self.cpu.get_ref_value(frame, 9) @@ -3903,7 +3908,7 @@ 'calldescr': calldescr, 'faildescr': faildescr, 'finaldescr2': BasicFinalDescr(1)}) - + self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken) frame = self.cpu.execute_token(looptoken, 1, 2, 3) descr = self.cpu.get_latest_descr(frame) From noreply at buildbot.pypy.org Mon Apr 15 17:05:19 2013 From: noreply at buildbot.pypy.org (fijal) Date: Mon, 15 Apr 2013 17:05:19 +0200 (CEST) Subject: [pypy-commit] pypy virtual-raw-mallocs: close about to be merged branch Message-ID: <20130415150519.0847B1C313F@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: virtual-raw-mallocs Changeset: r63371:5f2ebe73cd6b Date: 2013-04-15 17:03 +0200 http://bitbucket.org/pypy/pypy/changeset/5f2ebe73cd6b/ Log: close about to be merged branch From noreply at buildbot.pypy.org Mon Apr 15 17:05:20 2013 From: noreply at buildbot.pypy.org (fijal) Date: Mon, 15 Apr 2013 17:05:20 +0200 (CEST) Subject: [pypy-commit] pypy default: (antocuni) remerge the branch that was likely not at fault Message-ID: <20130415150520.76EAA1C313F@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r63372:ea27bafd1cd3 Date: 2013-04-15 17:04 +0200 http://bitbucket.org/pypy/pypy/changeset/ea27bafd1cd3/ Log: (antocuni) remerge the branch that was likely not at fault diff too long, truncating to 2000 out of 2643 lines diff --git a/pypy/module/_cffi_backend/ccallback.py b/pypy/module/_cffi_backend/ccallback.py --- a/pypy/module/_cffi_backend/ccallback.py +++ b/pypy/module/_cffi_backend/ccallback.py @@ -134,7 +134,7 @@ # W_CTypePrimitiveSigned.convert_from_object() in order # to write a whole 'ffi_arg'. value = misc.as_long(space, w_res) - misc.write_raw_integer_data(ll_res, value, SIZE_OF_FFI_ARG) + misc.write_raw_signed_data(ll_res, value, SIZE_OF_FFI_ARG) return else: # zero extension: fill the '*result' with zeros, and (on big- diff --git a/pypy/module/_cffi_backend/cdataobj.py b/pypy/module/_cffi_backend/cdataobj.py --- a/pypy/module/_cffi_backend/cdataobj.py +++ b/pypy/module/_cffi_backend/cdataobj.py @@ -280,8 +280,13 @@ return self.ctype.iter(self) @specialize.argtype(1) - def write_raw_integer_data(self, source): - misc.write_raw_integer_data(self._cdata, source, self.ctype.size) + def write_raw_signed_data(self, source): + misc.write_raw_signed_data(self._cdata, source, self.ctype.size) + keepalive_until_here(self) + + @specialize.argtype(1) + def write_raw_unsigned_data(self, source): + misc.write_raw_unsigned_data(self._cdata, source, self.ctype.size) keepalive_until_here(self) def write_raw_float_data(self, source): diff --git a/pypy/module/_cffi_backend/ctypeprim.py b/pypy/module/_cffi_backend/ctypeprim.py --- a/pypy/module/_cffi_backend/ctypeprim.py +++ b/pypy/module/_cffi_backend/ctypeprim.py @@ -63,7 +63,7 @@ else: value = self._cast_generic(w_ob) w_cdata = cdataobj.W_CDataMem(space, self.size, self) - w_cdata.write_raw_integer_data(value) + self.write_raw_integer_data(w_cdata, value) return w_cdata def _cast_result(self, intvalue): @@ -94,6 +94,9 @@ from pypy.module._cffi_backend import newtype return newtype.new_primitive_type(self.space, "int") + def write_raw_integer_data(self, w_cdata, value): + w_cdata.write_raw_unsigned_data(value) + class W_CTypePrimitiveChar(W_CTypePrimitiveCharOrUniChar): _attrs_ = [] @@ -185,10 +188,10 @@ if self.size < rffi.sizeof(lltype.Signed): if r_uint(value) - self.vmin > self.vrangemax: self._overflow(w_ob) - misc.write_raw_integer_data(cdata, value, self.size) + misc.write_raw_signed_data(cdata, value, self.size) else: value = misc.as_long_long(self.space, w_ob) - misc.write_raw_integer_data(cdata, value, self.size) + misc.write_raw_signed_data(cdata, value, self.size) def get_vararg_type(self): if self.size < rffi.sizeof(rffi.INT): @@ -196,6 +199,9 @@ return newtype.new_primitive_type(self.space, "int") return self + def write_raw_integer_data(self, w_cdata, value): + w_cdata.write_raw_signed_data(value) + class W_CTypePrimitiveUnsigned(W_CTypePrimitive): _attrs_ = ['value_fits_long', 'value_fits_ulong', 'vrangemax'] @@ -222,10 +228,10 @@ if self.value_fits_long: if value > self.vrangemax: self._overflow(w_ob) - misc.write_raw_integer_data(cdata, value, self.size) + misc.write_raw_unsigned_data(cdata, value, self.size) else: value = misc.as_unsigned_long_long(self.space, w_ob, strict=True) - misc.write_raw_integer_data(cdata, value, self.size) + misc.write_raw_unsigned_data(cdata, value, self.size) def convert_to_object(self, cdata): if self.value_fits_ulong: @@ -244,6 +250,9 @@ return newtype.new_primitive_type(self.space, "int") return self + def write_raw_integer_data(self, w_cdata, value): + w_cdata.write_raw_unsigned_data(value) + class W_CTypePrimitiveBool(W_CTypePrimitiveUnsigned): _attrs_ = [] diff --git a/pypy/module/_cffi_backend/ctypestruct.py b/pypy/module/_cffi_backend/ctypestruct.py --- a/pypy/module/_cffi_backend/ctypestruct.py +++ b/pypy/module/_cffi_backend/ctypestruct.py @@ -242,11 +242,13 @@ # value = misc.as_long_long(space, w_ob) if isinstance(ctype, ctypeprim.W_CTypePrimitiveSigned): + is_signed = True fmin = -(r_longlong(1) << (self.bitsize - 1)) fmax = (r_longlong(1) << (self.bitsize - 1)) - 1 if fmax == 0: fmax = 1 # special case to let "int x:1" receive "1" else: + is_signed = False fmin = r_longlong(0) fmax = r_longlong((r_ulonglong(1) << self.bitsize) - 1) if value < fmin or value > fmax: @@ -258,7 +260,10 @@ rawvalue = r_ulonglong(value) << self.bitshift rawfielddata = misc.read_raw_unsigned_data(cdata, ctype.size) rawfielddata = (rawfielddata & ~rawmask) | (rawvalue & rawmask) - misc.write_raw_integer_data(cdata, rawfielddata, ctype.size) + if is_signed: + misc.write_raw_signed_data(cdata, rawfielddata, ctype.size) + else: + misc.write_raw_unsigned_data(cdata, rawfielddata, ctype.size) W_CField.typedef = TypeDef( diff --git a/pypy/module/_cffi_backend/misc.py b/pypy/module/_cffi_backend/misc.py --- a/pypy/module/_cffi_backend/misc.py +++ b/pypy/module/_cffi_backend/misc.py @@ -9,6 +9,7 @@ from rpython.rtyper.lltypesystem import lltype, llmemory, rffi from rpython.translator.tool.cbuild import ExternalCompilationInfo + # ____________________________________________________________ _prim_signed_types = unrolling_iterable([ @@ -65,19 +66,22 @@ return rffi.cast(rffi.LONGDOUBLEP, target)[0] @specialize.argtype(1) -def write_raw_integer_data(target, source, size): - if is_signed_integer_type(lltype.typeOf(source)): - for TP, TPP in _prim_signed_types: - if size == rffi.sizeof(TP): - rffi.cast(TPP, target)[0] = rffi.cast(TP, source) - return - else: - for TP, TPP in _prim_unsigned_types: - if size == rffi.sizeof(TP): - rffi.cast(TPP, target)[0] = rffi.cast(TP, source) - return +def write_raw_unsigned_data(target, source, size): + for TP, TPP in _prim_unsigned_types: + if size == rffi.sizeof(TP): + rffi.cast(TPP, target)[0] = rffi.cast(TP, source) + return raise NotImplementedError("bad integer size") + at specialize.argtype(1) +def write_raw_signed_data(target, source, size): + for TP, TPP in _prim_signed_types: + if size == rffi.sizeof(TP): + rffi.cast(TPP, target)[0] = rffi.cast(TP, source) + return + raise NotImplementedError("bad integer size") + + def write_raw_float_data(target, source, size): for TP, TPP in _prim_float_types: if size == rffi.sizeof(TP): diff --git a/pypy/module/pypyjit/test_pypy_c/test__ffi.py b/pypy/module/pypyjit/test_pypy_c/test__ffi.py deleted file mode 100644 --- a/pypy/module/pypyjit/test_pypy_c/test__ffi.py +++ /dev/null @@ -1,272 +0,0 @@ -import sys, py -from pypy.module.pypyjit.test_pypy_c.test_00_model import BaseTestPyPyC - -class Test__ffi(BaseTestPyPyC): - - def test__ffi_call(self): - from rpython.rlib.test.test_clibffi import get_libm_name - def main(libm_name): - try: - from _ffi import CDLL, types - except ImportError: - sys.stderr.write('SKIP: cannot import _ffi\n') - return 0 - - libm = CDLL(libm_name) - pow = libm.getfunc('pow', [types.double, types.double], - types.double) - i = 0 - res = 0 - while i < 300: - tmp = pow(2, 3) # ID: fficall - res += tmp - i += 1 - return pow.getaddr(), res - # - libm_name = get_libm_name(sys.platform) - log = self.run(main, [libm_name]) - pow_addr, res = log.result - assert res == 8.0 * 300 - py.test.xfail() # XXX re-optimize _ffi for the JIT? - loop, = log.loops_by_filename(self.filepath) - if 'ConstClass(pow)' in repr(loop): # e.g. OS/X - pow_addr = 'ConstClass(pow)' - assert loop.match_by_id('fficall', """ - guard_not_invalidated(descr=...) - i17 = force_token() - setfield_gc(p0, i17, descr=<.* .*PyFrame.vable_token .*>) - f21 = call_release_gil(%s, 2.000000, 3.000000, descr=) - guard_not_forced(descr=...) - guard_no_exception(descr=...) - """ % pow_addr) - - - def test__ffi_call_frame_does_not_escape(self): - from rpython.rlib.test.test_clibffi import get_libm_name - def main(libm_name): - try: - from _ffi import CDLL, types - except ImportError: - sys.stderr.write('SKIP: cannot import _ffi\n') - return 0 - - libm = CDLL(libm_name) - pow = libm.getfunc('pow', [types.double, types.double], - types.double) - - def mypow(a, b): - return pow(a, b) - - i = 0 - res = 0 - while i < 300: - tmp = mypow(2, 3) - res += tmp - i += 1 - return pow.getaddr(), res - # - libm_name = get_libm_name(sys.platform) - log = self.run(main, [libm_name]) - pow_addr, res = log.result - assert res == 8.0 * 300 - loop, = log.loops_by_filename(self.filepath) - opnames = log.opnames(loop.allops()) - # we only force the virtualref, not its content - assert opnames.count('new_with_vtable') == 1 - - def test__ffi_call_releases_gil(self): - from rpython.rlib.clibffi import get_libc_name - def main(libc_name, n): - import time - import os - from threading import Thread - # - if os.name == 'nt': - from _ffi import WinDLL, types - libc = WinDLL('Kernel32.dll') - sleep = libc.getfunc('Sleep', [types.uint], types.uint) - delays = [0]*n + [1000] - else: - from _ffi import CDLL, types - libc = CDLL(libc_name) - sleep = libc.getfunc('sleep', [types.uint], types.uint) - delays = [0]*n + [1] - # - def loop_of_sleeps(i, delays): - for delay in delays: - sleep(delay) # ID: sleep - # - threads = [Thread(target=loop_of_sleeps, args=[i, delays]) for i in range(5)] - start = time.time() - for i, thread in enumerate(threads): - thread.start() - for thread in threads: - thread.join() - end = time.time() - return end - start - log = self.run(main, [get_libc_name(), 200], threshold=150, - import_site=True) - assert 1 <= log.result <= 1.5 # at most 0.5 seconds of overhead - loops = log.loops_by_id('sleep') - assert len(loops) == 1 # make sure that we actually JITted the loop - - def test_ctypes_call(self): - from rpython.rlib.test.test_clibffi import get_libm_name - def main(libm_name): - import ctypes - libm = ctypes.CDLL(libm_name) - fabs = libm.fabs - fabs.argtypes = [ctypes.c_double] - fabs.restype = ctypes.c_double - x = -4 - i = 0 - while i < 300: - x = fabs(x) - x = x - 100 - i += 1 - return fabs._ptr.getaddr(), x - - libm_name = get_libm_name(sys.platform) - log = self.run(main, [libm_name], import_site=True) - fabs_addr, res = log.result - assert res == -4.0 - loop, = log.loops_by_filename(self.filepath) - ops = loop.allops() - opnames = log.opnames(ops) - assert opnames.count('new_with_vtable') == 1 # only the virtualref - py.test.xfail() # XXX re-optimize _ffi for the JIT? - assert opnames.count('call_release_gil') == 1 - idx = opnames.index('call_release_gil') - call = ops[idx] - assert (call.args[0] == 'ConstClass(fabs)' or # e.g. OS/X - int(call.args[0]) == fabs_addr) - - - def test__ffi_struct(self): - def main(): - from _ffi import _StructDescr, Field, types - fields = [ - Field('x', types.slong), - ] - descr = _StructDescr('foo', fields) - struct = descr.allocate() - i = 0 - while i < 300: - x = struct.getfield('x') # ID: getfield - x = x+1 - struct.setfield('x', x) # ID: setfield - i += 1 - return struct.getfield('x') - # - log = self.run(main, []) - py.test.xfail() # XXX re-optimize _ffi for the JIT? - loop, = log.loops_by_filename(self.filepath) - assert loop.match_by_id('getfield', """ - guard_not_invalidated(descr=...) - i57 = getfield_raw(i46, descr=) - """) - assert loop.match_by_id('setfield', """ - setfield_raw(i44, i57, descr=) - """) - - - def test__cffi_call(self): - from rpython.rlib.test.test_clibffi import get_libm_name - def main(libm_name): - try: - import _cffi_backend - except ImportError: - sys.stderr.write('SKIP: cannot import _cffi_backend\n') - return 0 - - libm = _cffi_backend.load_library(libm_name) - BDouble = _cffi_backend.new_primitive_type("double") - BPow = _cffi_backend.new_function_type([BDouble, BDouble], BDouble) - pow = libm.load_function(BPow, 'pow') - i = 0 - res = 0 - while i < 300: - tmp = pow(2, 3) # ID: cfficall - res += tmp - i += 1 - BLong = _cffi_backend.new_primitive_type("long") - pow_addr = int(_cffi_backend.cast(BLong, pow)) - return pow_addr, res - # - libm_name = get_libm_name(sys.platform) - log = self.run(main, [libm_name]) - pow_addr, res = log.result - assert res == 8.0 * 300 - loop, = log.loops_by_filename(self.filepath) - if 'ConstClass(pow)' in repr(loop): # e.g. OS/X - pow_addr = 'ConstClass(pow)' - assert loop.match_by_id('cfficall', """ - ... - f1 = call_release_gil(..., descr=) - ... - """) - # so far just check that call_release_gil() is produced. - # later, also check that the arguments to call_release_gil() - # are constants, and that the numerous raw_mallocs are removed - - def test_cffi_call_guard_not_forced_fails(self): - # this is the test_pypy_c equivalent of - # rpython/jit/metainterp/test/test_fficall::test_guard_not_forced_fails - # - # it requires cffi to be installed for pypy in order to run - def main(): - import sys - try: - import cffi - except ImportError: - sys.stderr.write('SKIP: cannot import cffi\n') - return 0 - - ffi = cffi.FFI() - - ffi.cdef(""" - typedef void (*functype)(int); - int foo(int n, functype func); - """) - - lib = ffi.verify(""" - #include - typedef void (*functype)(int); - - int foo(int n, functype func) { - if (n >= 2000) { - func(n); - } - return n*2; - } - """) - - @ffi.callback("functype") - def mycallback(n): - if n < 5000: - return - # make sure that guard_not_forced fails - d = {} - f = sys._getframe() - while f: - d.update(f.f_locals) - f = f.f_back - - n = 0 - while n < 10000: - res = lib.foo(n, mycallback) # ID: cfficall - # this is the real point of the test: before the - # refactor-call_release_gil branch, the assert failed when - # res == 5000 - assert res == n*2 - n += 1 - return n - - log = self.run(main, [], import_site=True) - assert log.result == 10000 - loop, = log.loops_by_id('cfficall') - assert loop.match_by_id('cfficall', """ - ... - f1 = call_release_gil(..., descr=) - ... - """) diff --git a/pypy/module/pypyjit/test_pypy_c/test_ffi.py b/pypy/module/pypyjit/test_pypy_c/test_ffi.py new file mode 100644 --- /dev/null +++ b/pypy/module/pypyjit/test_pypy_c/test_ffi.py @@ -0,0 +1,279 @@ +import sys, py +from pypy.module.pypyjit.test_pypy_c.test_00_model import BaseTestPyPyC + +class Test__ffi(BaseTestPyPyC): + + def test__ffi_call(self): + from rpython.rlib.test.test_clibffi import get_libm_name + def main(libm_name): + try: + from _ffi import CDLL, types + except ImportError: + sys.stderr.write('SKIP: cannot import _ffi\n') + return 0 + + libm = CDLL(libm_name) + pow = libm.getfunc('pow', [types.double, types.double], + types.double) + i = 0 + res = 0 + while i < 300: + tmp = pow(2, 3) # ID: fficall + res += tmp + i += 1 + return pow.getaddr(), res + # + libm_name = get_libm_name(sys.platform) + log = self.run(main, [libm_name]) + pow_addr, res = log.result + assert res == 8.0 * 300 + py.test.xfail() # XXX re-optimize _ffi for the JIT? + loop, = log.loops_by_filename(self.filepath) + if 'ConstClass(pow)' in repr(loop): # e.g. OS/X + pow_addr = 'ConstClass(pow)' + assert loop.match_by_id('fficall', """ + guard_not_invalidated(descr=...) + i17 = force_token() + setfield_gc(p0, i17, descr=<.* .*PyFrame.vable_token .*>) + f21 = call_release_gil(%s, 2.000000, 3.000000, descr=) + guard_not_forced(descr=...) + guard_no_exception(descr=...) + """ % pow_addr) + + + def test__ffi_call_frame_does_not_escape(self): + from rpython.rlib.test.test_clibffi import get_libm_name + def main(libm_name): + try: + from _ffi import CDLL, types + except ImportError: + sys.stderr.write('SKIP: cannot import _ffi\n') + return 0 + + libm = CDLL(libm_name) + pow = libm.getfunc('pow', [types.double, types.double], + types.double) + + def mypow(a, b): + return pow(a, b) + + i = 0 + res = 0 + while i < 300: + tmp = mypow(2, 3) + res += tmp + i += 1 + return pow.getaddr(), res + # + libm_name = get_libm_name(sys.platform) + log = self.run(main, [libm_name]) + pow_addr, res = log.result + assert res == 8.0 * 300 + loop, = log.loops_by_filename(self.filepath) + opnames = log.opnames(loop.allops()) + # we only force the virtualref, not its content + assert opnames.count('new_with_vtable') == 1 + + def test__ffi_call_releases_gil(self): + from rpython.rlib.clibffi import get_libc_name + def main(libc_name, n): + import time + import os + from threading import Thread + # + if os.name == 'nt': + from _ffi import WinDLL, types + libc = WinDLL('Kernel32.dll') + sleep = libc.getfunc('Sleep', [types.uint], types.uint) + delays = [0]*n + [1000] + else: + from _ffi import CDLL, types + libc = CDLL(libc_name) + sleep = libc.getfunc('sleep', [types.uint], types.uint) + delays = [0]*n + [1] + # + def loop_of_sleeps(i, delays): + for delay in delays: + sleep(delay) # ID: sleep + # + threads = [Thread(target=loop_of_sleeps, args=[i, delays]) for i in range(5)] + start = time.time() + for i, thread in enumerate(threads): + thread.start() + for thread in threads: + thread.join() + end = time.time() + return end - start + log = self.run(main, [get_libc_name(), 200], threshold=150, + import_site=True) + assert 1 <= log.result <= 1.5 # at most 0.5 seconds of overhead + loops = log.loops_by_id('sleep') + assert len(loops) == 1 # make sure that we actually JITted the loop + + def test_ctypes_call(self): + from rpython.rlib.test.test_clibffi import get_libm_name + def main(libm_name): + import ctypes + libm = ctypes.CDLL(libm_name) + fabs = libm.fabs + fabs.argtypes = [ctypes.c_double] + fabs.restype = ctypes.c_double + x = -4 + i = 0 + while i < 300: + x = fabs(x) + x = x - 100 + i += 1 + return fabs._ptr.getaddr(), x + + libm_name = get_libm_name(sys.platform) + log = self.run(main, [libm_name], import_site=True) + fabs_addr, res = log.result + assert res == -4.0 + loop, = log.loops_by_filename(self.filepath) + ops = loop.allops() + opnames = log.opnames(ops) + assert opnames.count('new_with_vtable') == 1 # only the virtualref + py.test.xfail() # XXX re-optimize _ffi for the JIT? + assert opnames.count('call_release_gil') == 1 + idx = opnames.index('call_release_gil') + call = ops[idx] + assert (call.args[0] == 'ConstClass(fabs)' or # e.g. OS/X + int(call.args[0]) == fabs_addr) + + + def test__ffi_struct(self): + def main(): + from _ffi import _StructDescr, Field, types + fields = [ + Field('x', types.slong), + ] + descr = _StructDescr('foo', fields) + struct = descr.allocate() + i = 0 + while i < 300: + x = struct.getfield('x') # ID: getfield + x = x+1 + struct.setfield('x', x) # ID: setfield + i += 1 + return struct.getfield('x') + # + log = self.run(main, []) + py.test.xfail() # XXX re-optimize _ffi for the JIT? + loop, = log.loops_by_filename(self.filepath) + assert loop.match_by_id('getfield', """ + guard_not_invalidated(descr=...) + i57 = getfield_raw(i46, descr=) + """) + assert loop.match_by_id('setfield', """ + setfield_raw(i44, i57, descr=) + """) + + + def test__cffi_call(self): + from rpython.rlib.test.test_clibffi import get_libm_name + def main(libm_name): + try: + import _cffi_backend + except ImportError: + sys.stderr.write('SKIP: cannot import _cffi_backend\n') + return 0 + + libm = _cffi_backend.load_library(libm_name) + BDouble = _cffi_backend.new_primitive_type("double") + BInt = _cffi_backend.new_primitive_type("int") + BPow = _cffi_backend.new_function_type([BDouble, BInt], BDouble) + ldexp = libm.load_function(BPow, 'ldexp') + i = 0 + res = 0 + while i < 300: + tmp = ldexp(1, 3) # ID: cfficall + res += tmp + i += 1 + BLong = _cffi_backend.new_primitive_type("long") + ldexp_addr = int(_cffi_backend.cast(BLong, ldexp)) + return ldexp_addr, res + # + libm_name = get_libm_name(sys.platform) + log = self.run(main, [libm_name]) + ldexp_addr, res = log.result + assert res == 8.0 * 300 + loop, = log.loops_by_filename(self.filepath) + if 'ConstClass(ldexp)' in repr(loop): # e.g. OS/X + ldexp_addr = 'ConstClass(ldexp)' + assert loop.match_by_id('cfficall', """ + ... + f1 = call_release_gil(..., descr=) + ... + """) + ops = loop.ops_by_id('cfficall') + assert 'raw_malloc' not in str(ops) + assert 'raw_free' not in str(ops) + assert 'getarrayitem_raw' not in log.opnames(ops) + assert 'setarrayitem_raw' not in log.opnames(ops) + # so far just check that call_release_gil() is produced. + # later, also check that the arguments to call_release_gil() + # are constants + # are constants, and that the numerous raw_mallocs are removed + + def test_cffi_call_guard_not_forced_fails(self): + # this is the test_pypy_c equivalent of + # rpython/jit/metainterp/test/test_fficall::test_guard_not_forced_fails + # + # it requires cffi to be installed for pypy in order to run + def main(): + import sys + try: + import cffi + except ImportError: + sys.stderr.write('SKIP: cannot import cffi\n') + return 0 + + ffi = cffi.FFI() + + ffi.cdef(""" + typedef void (*functype)(int); + int foo(int n, functype func); + """) + + lib = ffi.verify(""" + #include + typedef void (*functype)(int); + + int foo(int n, functype func) { + if (n >= 2000) { + func(n); + } + return n*2; + } + """) + + @ffi.callback("functype") + def mycallback(n): + if n < 5000: + return + # make sure that guard_not_forced fails + d = {} + f = sys._getframe() + while f: + d.update(f.f_locals) + f = f.f_back + + n = 0 + while n < 10000: + res = lib.foo(n, mycallback) # ID: cfficall + # this is the real point of the test: before the + # refactor-call_release_gil branch, the assert failed when + # res == 5000 + assert res == n*2 + n += 1 + return n + + log = self.run(main, [], import_site=True) + assert log.result == 10000 + loop, = log.loops_by_id('cfficall') + assert loop.match_by_id('cfficall', """ + ... + f1 = call_release_gil(..., descr=) + ... + """) diff --git a/rpython/jit/backend/llgraph/runner.py b/rpython/jit/backend/llgraph/runner.py --- a/rpython/jit/backend/llgraph/runner.py +++ b/rpython/jit/backend/llgraph/runner.py @@ -484,6 +484,15 @@ else: return self.bh_raw_load_i(struct, offset, descr) + def unpack_arraydescr_size(self, arraydescr): + from rpython.jit.backend.llsupport.symbolic import get_array_token + from rpython.jit.backend.llsupport.descr import get_type_flag, FLAG_SIGNED + assert isinstance(arraydescr, ArrayDescr) + basesize, itemsize, _ = get_array_token(arraydescr.A, False) + flag = get_type_flag(arraydescr.A.OF) + is_signed = (flag == FLAG_SIGNED) + return basesize, itemsize, is_signed + def bh_raw_store_i(self, struct, offset, newvalue, descr): ll_p = rffi.cast(rffi.CCHARP, struct) ll_p = rffi.cast(lltype.Ptr(descr.A), rffi.ptradd(ll_p, offset)) @@ -566,10 +575,14 @@ def bh_read_timestamp(self): return read_timestamp() + def bh_new_raw_buffer(self, size): + return lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') + def store_fail_descr(self, deadframe, descr): pass # I *think* + class LLDeadFrame(object): _TYPE = llmemory.GCREF diff --git a/rpython/jit/backend/llsupport/llmodel.py b/rpython/jit/backend/llsupport/llmodel.py --- a/rpython/jit/backend/llsupport/llmodel.py +++ b/rpython/jit/backend/llsupport/llmodel.py @@ -742,6 +742,9 @@ as_array[self.vtable_offset/WORD] = vtable return res + def bh_new_raw_buffer(self, size): + return lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') + def bh_classof(self, struct): struct = lltype.cast_opaque_ptr(rclass.OBJECTPTR, struct) result_adr = llmemory.cast_ptr_to_adr(struct.typeptr) diff --git a/rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py b/rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py --- a/rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py +++ b/rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py @@ -2,6 +2,7 @@ import weakref from rpython.rlib.jit import JitDriver, dont_look_inside from rpython.jit.backend.llsupport.test.zrpy_gc_test import run, get_entry, compile +from rpython.jit.backend.llsupport.test.ztranslation_test import fix_annotator_for_vrawbuffer class X(object): def __init__(self, x=0): @@ -31,7 +32,8 @@ g._dont_inline_ = True return g -def compile_boehm_test(): +def compile_boehm_test(monkeypatch): + fix_annotator_for_vrawbuffer(monkeypatch) myjitdriver = JitDriver(greens = [], reds = ['n', 'x']) @dont_look_inside def see(lst, n): diff --git a/rpython/jit/backend/llsupport/test/ztranslation_test.py b/rpython/jit/backend/llsupport/test/ztranslation_test.py --- a/rpython/jit/backend/llsupport/test/ztranslation_test.py +++ b/rpython/jit/backend/llsupport/test/ztranslation_test.py @@ -9,10 +9,23 @@ from rpython.jit.codewriter.policy import StopAtXPolicy +def fix_annotator_for_vrawbuffer(monkeypatch): + from rpython.rlib.nonconst import NonConstant + from rpython.jit.metainterp.optimizeopt.virtualize import VRawBufferValue + from rpython.jit.metainterp import warmspot + + def my_hook_for_tests(cpu): + # this is needed so that the annotator can see it + if NonConstant(False): + v = VRawBufferValue(cpu, None, -1, None, None) + monkeypatch.setattr(warmspot, 'hook_for_tests', my_hook_for_tests) + + class TranslationTest(CCompiledMixin): CPUClass = getcpuclass() - def test_stuff_translates(self): + def test_stuff_translates(self, monkeypatch): + fix_annotator_for_vrawbuffer(monkeypatch) # this is a basic test that tries to hit a number of features and their # translation: # - jitting of loops and bridges @@ -89,9 +102,10 @@ class TranslationTestCallAssembler(CCompiledMixin): CPUClass = getcpuclass() - def test_direct_assembler_call_translates(self): + def test_direct_assembler_call_translates(self, monkeypatch): """Test CALL_ASSEMBLER and the recursion limit""" from rpython.rlib.rstackovf import StackOverflow + fix_annotator_for_vrawbuffer(monkeypatch) class Thing(object): def __init__(self, val): @@ -169,7 +183,8 @@ class TranslationTestJITStats(CCompiledMixin): CPUClass = getcpuclass() - def test_jit_get_stats(self): + def test_jit_get_stats(self, monkeypatch): + fix_annotator_for_vrawbuffer(monkeypatch) driver = JitDriver(greens = [], reds = ['i']) def f(): @@ -192,7 +207,8 @@ class TranslationRemoveTypePtrTest(CCompiledMixin): CPUClass = getcpuclass() - def test_external_exception_handling_translates(self): + def test_external_exception_handling_translates(self, monkeypatch): + fix_annotator_for_vrawbuffer(monkeypatch) jitdriver = JitDriver(greens = [], reds = ['n', 'total']) class ImDone(Exception): diff --git a/rpython/jit/backend/model.py b/rpython/jit/backend/model.py --- a/rpython/jit/backend/model.py +++ b/rpython/jit/backend/model.py @@ -194,11 +194,18 @@ def typedescrof(self, TYPE): raise NotImplementedError + def unpack_arraydescr_size(self, arraydescr): + """ + Return basesize, itemsize, is_signed + """ + raise NotImplementedError + @staticmethod def cast_int_to_ptr(x, TYPE): x = llmemory.cast_int_to_adr(x) return llmemory.cast_adr_to_ptr(x, TYPE) + # ---------- the backend-dependent operations ---------- # lltype specific operations @@ -235,6 +242,8 @@ raise NotImplementedError def bh_newunicode(self, length): raise NotImplementedError + def bh_new_raw_buffer(self, size): + raise NotImplementedError def bh_arraylen_gc(self, array, arraydescr): raise NotImplementedError diff --git a/rpython/jit/codewriter/effectinfo.py b/rpython/jit/codewriter/effectinfo.py --- a/rpython/jit/codewriter/effectinfo.py +++ b/rpython/jit/codewriter/effectinfo.py @@ -76,14 +76,14 @@ # OS_MATH_SQRT = 100 # - OS_RAW_MALLOC_VARSIZE = 110 + OS_RAW_MALLOC_VARSIZE_CHAR = 110 OS_RAW_FREE = 111 OS_JIT_FORCE_VIRTUAL = 120 # for debugging: _OS_CANRAISE = set([OS_NONE, OS_STR2UNICODE, OS_LIBFFI_CALL, - OS_RAW_MALLOC_VARSIZE, OS_JIT_FORCE_VIRTUAL]) + OS_RAW_MALLOC_VARSIZE_CHAR, OS_JIT_FORCE_VIRTUAL]) def __new__(cls, readonly_descrs_fields, readonly_descrs_arrays, write_descrs_fields, write_descrs_arrays, diff --git a/rpython/jit/codewriter/jtransform.py b/rpython/jit/codewriter/jtransform.py --- a/rpython/jit/codewriter/jtransform.py +++ b/rpython/jit/codewriter/jtransform.py @@ -539,9 +539,11 @@ name += '_no_track_allocation' op1 = self.prepare_builtin_call(op, name, args, (TYPE,), TYPE) if name == 'raw_malloc_varsize': - return self._handle_oopspec_call(op1, args, - EffectInfo.OS_RAW_MALLOC_VARSIZE, - EffectInfo.EF_CAN_RAISE) + ITEMTYPE = op.args[0].value.OF + if ITEMTYPE == lltype.Char: + return self._handle_oopspec_call(op1, args, + EffectInfo.OS_RAW_MALLOC_VARSIZE_CHAR, + EffectInfo.EF_CAN_RAISE) return self.rewrite_op_direct_call(op1) def rewrite_op_malloc_varsize(self, op): diff --git a/rpython/jit/codewriter/test/test_jtransform.py b/rpython/jit/codewriter/test/test_jtransform.py --- a/rpython/jit/codewriter/test/test_jtransform.py +++ b/rpython/jit/codewriter/test/test_jtransform.py @@ -126,7 +126,7 @@ INT = lltype.Signed UNICHAR = lltype.UniChar FLOAT = lltype.Float - ARRAYPTR = rffi.CArrayPtr(lltype.Signed) + ARRAYPTR = rffi.CArrayPtr(lltype.Char) argtypes = { EI.OS_MATH_SQRT: ([FLOAT], FLOAT), EI.OS_STR2UNICODE:([PSTR], PUNICODE), @@ -143,7 +143,7 @@ EI.OS_UNIEQ_NONNULL_CHAR: ([PUNICODE, UNICHAR], INT), EI.OS_UNIEQ_CHECKNULL_CHAR: ([PUNICODE, UNICHAR], INT), EI.OS_UNIEQ_LENGTHOK: ([PUNICODE, PUNICODE], INT), - EI.OS_RAW_MALLOC_VARSIZE: ([INT], ARRAYPTR), + EI.OS_RAW_MALLOC_VARSIZE_CHAR: ([INT], ARRAYPTR), EI.OS_RAW_FREE: ([ARRAYPTR], lltype.Void), } argtypes = argtypes[oopspecindex] @@ -151,7 +151,7 @@ assert argtypes[1] == op.result.concretetype if oopspecindex == EI.OS_STR2UNICODE: assert extraeffect == EI.EF_ELIDABLE_CAN_RAISE - elif oopspecindex == EI.OS_RAW_MALLOC_VARSIZE: + elif oopspecindex == EI.OS_RAW_MALLOC_VARSIZE_CHAR: assert extraeffect == EI.EF_CAN_RAISE elif oopspecindex == EI.OS_RAW_FREE: assert extraeffect == EI.EF_CANNOT_RAISE @@ -161,7 +161,7 @@ def calldescr_canraise(self, calldescr): EI = effectinfo.EffectInfo - if calldescr == 'calldescr-%d' % EI.OS_RAW_MALLOC_VARSIZE: + if calldescr == 'calldescr-%d' % EI.OS_RAW_MALLOC_VARSIZE_CHAR: return True return False @@ -555,7 +555,7 @@ assert op1.args == [] def test_raw_malloc(): - S = rffi.CArray(lltype.Signed) + S = rffi.CArray(lltype.Char) v1 = varoftype(lltype.Signed) v = varoftype(lltype.Ptr(S)) flags = Constant({'flavor': 'raw'}, lltype.Void) @@ -566,7 +566,7 @@ assert op0.opname == 'residual_call_ir_i' assert op0.args[0].value == 'raw_malloc_varsize' # pseudo-function as a str assert (op0.args[-1] == 'calldescr-%d' % - effectinfo.EffectInfo.OS_RAW_MALLOC_VARSIZE) + effectinfo.EffectInfo.OS_RAW_MALLOC_VARSIZE_CHAR) assert op1.opname == '-live-' assert op1.args == [] @@ -608,7 +608,7 @@ assert op1.args == [] def test_raw_free(): - S = rffi.CArray(lltype.Signed) + S = rffi.CArray(lltype.Char) flags = Constant({'flavor': 'raw', 'track_allocation': True}, lltype.Void) op = SpaceOperation('free', [varoftype(lltype.Ptr(S)), flags], diff --git a/rpython/jit/metainterp/compile.py b/rpython/jit/metainterp/compile.py --- a/rpython/jit/metainterp/compile.py +++ b/rpython/jit/metainterp/compile.py @@ -15,7 +15,7 @@ from rpython.jit.metainterp import history, resume from rpython.jit.metainterp.optimize import InvalidLoop from rpython.jit.metainterp.inliner import Inliner -from rpython.jit.metainterp.resume import NUMBERING, PENDINGFIELDSP +from rpython.jit.metainterp.resume import NUMBERING, PENDINGFIELDSP, ResumeDataDirectReader from rpython.jit.codewriter import heaptracker, longlong def giveup(): @@ -656,9 +656,9 @@ class AllVirtuals: llopaque = True - list = [resume.ResumeDataDirectReader.virtual_default] # annotation hack - def __init__(self, list): - self.list = list + cache = None + def __init__(self, cache): + self.cache = cache def hide(self, cpu): ptr = cpu.ts.cast_instance_to_base_ref(self) return cpu.ts.cast_to_ref(ptr) @@ -682,9 +682,9 @@ from rpython.jit.metainterp.blackhole import resume_in_blackhole hidden_all_virtuals = metainterp_sd.cpu.get_savedata_ref(deadframe) obj = AllVirtuals.show(metainterp_sd.cpu, hidden_all_virtuals) - all_virtuals = obj.list + all_virtuals = obj.cache if all_virtuals is None: - all_virtuals = [] + all_virtuals = ResumeDataDirectReader.VirtualCache([], []) assert jitdriver_sd is self.jitdriver_sd resume_in_blackhole(metainterp_sd, jitdriver_sd, self, deadframe, all_virtuals) diff --git a/rpython/jit/metainterp/history.py b/rpython/jit/metainterp/history.py --- a/rpython/jit/metainterp/history.py +++ b/rpython/jit/metainterp/history.py @@ -191,7 +191,6 @@ def get_jitcode_for_class(self, oocls): return self.jitcodes[oocls] - class Const(AbstractValue): __slots__ = () diff --git a/rpython/jit/metainterp/optimizeopt/earlyforce.py b/rpython/jit/metainterp/optimizeopt/earlyforce.py --- a/rpython/jit/metainterp/optimizeopt/earlyforce.py +++ b/rpython/jit/metainterp/optimizeopt/earlyforce.py @@ -1,15 +1,26 @@ +from rpython.jit.codewriter.effectinfo import EffectInfo from rpython.jit.metainterp.optimizeopt.optimizer import Optimization from rpython.jit.metainterp.optimizeopt.vstring import VAbstractStringValue from rpython.jit.metainterp.resoperation import rop, ResOperation +def is_raw_free(op, opnum): + if opnum != rop.CALL: + return False + einfo = op.getdescr().get_extra_info() + return einfo.oopspecindex == EffectInfo.OS_RAW_FREE + + class OptEarlyForce(Optimization): def propagate_forward(self, op): opnum = op.getopnum() + if (opnum != rop.SETFIELD_GC and opnum != rop.SETARRAYITEM_GC and + opnum != rop.SETARRAYITEM_RAW and opnum != rop.QUASIIMMUT_FIELD and opnum != rop.SAME_AS and - opnum != rop.MARK_OPAQUE_PTR): + opnum != rop.MARK_OPAQUE_PTR and + not is_raw_free(op, opnum)): for arg in op.getarglist(): if arg in self.optimizer.values: diff --git a/rpython/jit/metainterp/optimizeopt/optimizer.py b/rpython/jit/metainterp/optimizeopt/optimizer.py --- a/rpython/jit/metainterp/optimizeopt/optimizer.py +++ b/rpython/jit/metainterp/optimizeopt/optimizer.py @@ -231,6 +231,12 @@ def setitem(self, index, value): raise NotImplementedError + def getitem_raw(self, offset, length, descr): + raise NotImplementedError + + def setitem_raw(self, offset, length, descr, value): + raise NotImplementedError + def getinteriorfield(self, index, ofs, default): raise NotImplementedError diff --git a/rpython/jit/metainterp/optimizeopt/rawbuffer.py b/rpython/jit/metainterp/optimizeopt/rawbuffer.py new file mode 100644 --- /dev/null +++ b/rpython/jit/metainterp/optimizeopt/rawbuffer.py @@ -0,0 +1,134 @@ +from rpython.rlib.debug import debug_start, debug_stop, debug_print +from rpython.rlib.objectmodel import compute_unique_id, we_are_translated + +class InvalidRawOperation(Exception): + pass + +class InvalidRawWrite(InvalidRawOperation): + pass + +class InvalidRawRead(InvalidRawOperation): + pass + +class RawBuffer(object): + def __init__(self, cpu, logops=None): + # the following lists represents the writes in the buffer: values[i] + # is the value of length lengths[i] stored at offset[i]. + # + # the invariant is that they are ordered by offset, and that + # offset[i]+length[i] <= offset[i+1], i.e. that the writes never + # overlaps + self.cpu = cpu + self.logops = logops + self.offsets = [] + self.lengths = [] + self.descrs = [] + self.values = [] + + def _get_memory(self): + """ + NOT_RPYTHON + for testing only + """ + return zip(self.offsets, self.lengths, self.descrs, self.values) + + def _repr_of_descr(self, descr): + if self.logops: + s = self.logops.repr_of_descr(descr) + else: + s = str(descr) + s += " at %d" % compute_unique_id(descr) + return s + + def _repr_of_value(self, value): + if not we_are_translated() and isinstance(value, str): + return value # for tests + if self.logops: + s = self.logops.repr_of_arg(value.box) + else: + s = str(value.box) + s += " at %d" % compute_unique_id(value.box) + return s + + def _dump_to_log(self): + debug_print("RawBuffer state") + debug_print("offset, length, descr, box") + debug_print("(box == None means that the value is still virtual)") + for i in range(len(self.offsets)): + descr = self._repr_of_descr(self.descrs[i]) + box = self._repr_of_value(self.values[i]) + debug_print("%d, %d, %s, %s" % (self.offsets[i], self.lengths[i], descr, box)) + + def _invalid_write(self, message, offset, length, descr, value): + debug_start('jit-log-rawbuffer') + debug_print('Invalid write: %s' % message) + debug_print(" offset: %d" % offset) + debug_print(" length: %d" % length) + debug_print(" descr: %s" % self._repr_of_descr(descr)) + debug_print(" value: %s" % self._repr_of_value(value)) + self._dump_to_log() + debug_stop('jit-log-rawbuffer') + raise InvalidRawWrite + + def _invalid_read(self, message, offset, length, descr): + debug_start('jit-log-rawbuffer') + debug_print('Invalid read: %s' % message) + debug_print(" offset: %d" % offset) + debug_print(" length: %d" % length) + debug_print(" descr: %s" % self._repr_of_descr(descr)) + self._dump_to_log() + debug_stop('jit-log-rawbuffer') + raise InvalidRawRead + + def _descrs_are_compatible(self, d1, d2): + # two arraydescrs are compatible if they have the same basesize, + # itemsize and sign, even if they are not identical + unpack = self.cpu.unpack_arraydescr_size + return unpack(d1) == unpack(d2) + + def write_value(self, offset, length, descr, value): + i = 0 + N = len(self.offsets) + while i < N: + if self.offsets[i] == offset: + if (length != self.lengths[i] or not + self._descrs_are_compatible(descr, self.descrs[i])): + # in theory we could add support for the cases in which + # the length or descr is different, but I don't think we + # need it in practice + self._invalid_write('length or descr not compatible', + offset, length, descr, value) + # update the value at this offset + self.values[i] = value + return + elif self.offsets[i] > offset: + break + i += 1 + # + if i < len(self.offsets) and offset+length > self.offsets[i]: + self._invalid_write("overlap with next bytes", + offset, length, descr, value) + if i > 0 and self.offsets[i-1]+self.lengths[i-1] > offset: + self._invalid_write("overlap with previous bytes", + offset, length, descr, value) + # insert a new value at offset + self.offsets.insert(i, offset) + self.lengths.insert(i, length) + self.descrs.insert(i, descr) + self.values.insert(i, value) + + def read_value(self, offset, length, descr): + i = 0 + N = len(self.offsets) + while i < N: + if self.offsets[i] == offset: + if (length != self.lengths[i] or + not self._descrs_are_compatible(descr, self.descrs[i])): + self._invalid_read('length or descr not compatible', + offset, length, descr) + return self.values[i] + i += 1 + # memory location not found: this means we are reading from + # uninitialized memory, give up the optimization + self._invalid_read('uninitialized memory', + offset, length, descr) diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py --- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py @@ -770,8 +770,6 @@ """ self.optimize_loop(ops, expected) - - def test_p123_simple(self): ops = """ [i1, p2, p3] @@ -1730,6 +1728,175 @@ # We cannot track virtuals that survive for more than two iterations. self.optimize_loop(ops, expected, preamble) + def test_virtual_raw_malloc(self): + ops = """ + [i1] + i2 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) + i3 = getarrayitem_raw(i2, 0, descr=rawarraydescr) + call('free', i2, descr=raw_free_descr) + jump(i3) + """ + expected = """ + [i1] + jump(i1) + """ + self.optimize_loop(ops, expected) + + def test_virtual_raw_malloc_force(self): + ops = """ + [i1] + i2 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i2, 0, i1, descr=rawarraydescr_char) + setarrayitem_raw(i2, 2, 456, descr=rawarraydescr_char) + setarrayitem_raw(i2, 1, 123, descr=rawarraydescr_char) + label('foo') # we expect the buffer to be forced *after* the label + escape(i2) + call('free', i2, descr=raw_free_descr) + jump(i1) + """ + expected = """ + [i1] + label('foo') + i2 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i2, 0, i1, descr=rawarraydescr_char) + i3 = int_add(i2, 1) + setarrayitem_raw(i3, 0, 123, descr=rawarraydescr_char) + i4 = int_add(i2, 2) + setarrayitem_raw(i4, 0, 456, descr=rawarraydescr_char) + escape(i2) + call('free', i2, descr=raw_free_descr) + jump(i1) + """ + self.optimize_loop(ops, expected) + + def test_virtual_raw_malloc_invalid_write_force(self): + ops = """ + [i1] + i2 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) + label('foo') # we expect the buffer to be forced *after* the label + setarrayitem_raw(i2, 2, 456, descr=rawarraydescr_char) # overlap! + call('free', i2, descr=raw_free_descr) + jump(i1) + """ + expected = """ + [i1] + label('foo') + i2 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) + setarrayitem_raw(i2, 2, 456, descr=rawarraydescr_char) + call('free', i2, descr=raw_free_descr) + jump(i1) + """ + self.optimize_loop(ops, expected) + + def test_virtual_raw_malloc_invalid_read_force(self): + ops = """ + [i1] + i2 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) + label('foo') # we expect the buffer to be forced *after* the label + i3 = getarrayitem_raw(i2, 0, descr=rawarraydescr_char) + call('free', i2, descr=raw_free_descr) + jump(i1) + """ + expected = """ + [i1] + label('foo') + i2 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) + i3 = getarrayitem_raw(i2, 0, descr=rawarraydescr_char) + call('free', i2, descr=raw_free_descr) + jump(i1) + """ + self.optimize_loop(ops, expected) + + def test_virtual_raw_slice(self): + ops = """ + [i0, i1] + i2 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i2, 0, 42, descr=rawarraydescr_char) + i3 = int_add(i2, 1) # get a slice of the original buffer + setarrayitem_raw(i3, 0, 4242, descr=rawarraydescr) # write to the slice + i4 = getarrayitem_raw(i2, 0, descr=rawarraydescr_char) + i5 = int_add(i2, 1) + i6 = getarrayitem_raw(i5, 0, descr=rawarraydescr) + call('free', i2, descr=raw_free_descr) + jump(i0, i1) + """ + expected = """ + [i0, i1] + jump(i0, i1) + """ + self.optimize_loop(ops, expected) + + def test_virtual_raw_slice_of_a_raw_slice(self): + ops = """ + [i0, i1] + i2 = call('malloc', 10, descr=raw_malloc_descr) + i3 = int_add(i2, 1) # get a slice of the original buffer + i4 = int_add(i3, 1) # get a slice of a slice + setarrayitem_raw(i4, 0, i1, descr=rawarraydescr_char) # write to the slice + i5 = getarrayitem_raw(i2, 2, descr=rawarraydescr_char) + call('free', i2, descr=raw_free_descr) + jump(i0, i5) + """ + expected = """ + [i0, i1] + jump(i0, i1) + """ + self.optimize_loop(ops, expected) + + def test_virtual_raw_slice_force(self): + ops = """ + [i0, i1] + i2 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i2, 0, 42, descr=rawarraydescr_char) + i3 = int_add(i2, 1) # get a slice of the original buffer + setarrayitem_raw(i3, 4, 4242, descr=rawarraydescr_char) # write to the slice + label('foo') + escape(i3) + jump(i0, i1) + """ + expected = """ + [i0, i1] + label('foo') + # these ops are generated by VirtualRawBufferValue._really_force + i2 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i2, 0, 42, descr=rawarraydescr_char) + i3 = int_add(i2, 5) # 1+4*sizeof(char) + setarrayitem_raw(i3, 0, 4242, descr=rawarraydescr_char) + # this is generated by VirtualRawSliceValue._really_force + i4 = int_add(i2, 1) + escape(i4) + jump(i0, i1) + """ + self.optimize_loop(ops, expected) + + def test_virtual_raw_malloc_virtualstate(self): + ops = """ + [i0] + i1 = getarrayitem_raw(i0, 0, descr=rawarraydescr) + i2 = int_add(i1, 1) + call('free', i0, descr=raw_free_descr) + i3 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i3, 0, i2, descr=rawarraydescr) + label('foo') + jump(i3) + """ + expected = """ + [i0] + i1 = getarrayitem_raw(i0, 0, descr=rawarraydescr) + i2 = int_add(i1, 1) + call('free', i0, descr=raw_free_descr) + label('foo') + i3 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i3, 0, i2, descr=rawarraydescr) + jump(i3) + """ + self.optimize_loop(ops, expected) + def test_duplicate_getfield_1(self): ops = """ [p1, p2] diff --git a/rpython/jit/metainterp/optimizeopt/test/test_rawbuffer.py b/rpython/jit/metainterp/optimizeopt/test/test_rawbuffer.py new file mode 100644 --- /dev/null +++ b/rpython/jit/metainterp/optimizeopt/test/test_rawbuffer.py @@ -0,0 +1,90 @@ +import py +from rpython.jit.metainterp.optimizeopt.rawbuffer import (InvalidRawWrite, + InvalidRawRead, RawBuffer) + +class FakeCPU(object): + def unpack_arraydescr_size(self, descr): + return descr, 'foo', 'bar' + +def test_write_value(): + buf = RawBuffer(FakeCPU()) + buf.write_value(8, 4, 'descr3', 'three') + buf.write_value(0, 4, 'descr1', 'one') + buf.write_value(4, 2, 'descr2', 'two') + buf.write_value(12, 2, 'descr4', 'four') + assert buf._get_memory() == [ + ( 0, 4, 'descr1', 'one'), + ( 4, 2, 'descr2', 'two'), + ( 8, 4, 'descr3', 'three'), + (12, 2, 'descr4', 'four'), + ] + # + +def test_write_value_update(): + buf = RawBuffer(FakeCPU()) + buf.write_value(0, 4, 'descr', 'one') + buf.write_value(4, 2, 'descr', 'two') + buf.write_value(0, 4, 'descr', 'ONE') + assert buf._get_memory() == [ + ( 0, 4, 'descr', 'ONE'), + ( 4, 2, 'descr', 'two'), + ] + +def test_write_value_invalid_length(): + buf = RawBuffer(FakeCPU()) + buf.write_value(0, 4, 'descr1', 'one') + with py.test.raises(InvalidRawWrite): + buf.write_value(0, 5, 'descr1', 'two') + with py.test.raises(InvalidRawWrite): + buf.write_value(0, 4, 'descr2', 'two') + + +def test_write_value_overlapping_next(): + buf = RawBuffer(FakeCPU()) + buf.write_value(0, 4, 'descr', 'one') + buf.write_value(6, 4, 'descr', 'two') + with py.test.raises(InvalidRawWrite): + buf.write_value(4, 4, 'descr', 'three') + +def test_write_value_overlapping_prev(): + buf = RawBuffer(FakeCPU()) + buf.write_value(0, 4, 'descr', 'one') + with py.test.raises(InvalidRawWrite): + buf.write_value(2, 1, 'descr', 'two') + +def test_read_value(): + buf = RawBuffer(FakeCPU()) + buf.write_value(0, 4, 'descr', 'one') + buf.write_value(4, 4, 'descr', 'two') + assert buf.read_value(0, 4, 'descr') == 'one' + assert buf.read_value(4, 4, 'descr') == 'two' + with py.test.raises(InvalidRawRead): + buf.read_value(0, 2, 'descr') + with py.test.raises(InvalidRawRead): + buf.read_value(8, 2, 'descr') + with py.test.raises(InvalidRawRead): + buf.read_value(0, 4, 'another descr') + +def test_unpack_descrs(): + ArrayS_8_1 = object() + ArrayS_8_2 = object() + ArrayU_8 = object() + + class FakeCPU(object): + def unpack_arraydescr_size(self, descr): + if descr in (ArrayS_8_1, ArrayS_8_2): + return 0, 8, True + return 0, 8, False + + buf = RawBuffer(FakeCPU()) + buf.write_value(0, 4, ArrayS_8_1, 'one') + assert buf.read_value(0, 4, ArrayS_8_1) == 'one' + assert buf.read_value(0, 4, ArrayS_8_2) == 'one' # with a non-identical descr + # + buf.write_value(0, 4, ArrayS_8_2, 'two') # with a non-identical descr + assert buf.read_value(0, 4, ArrayS_8_1) == 'two' + # + with py.test.raises(InvalidRawRead): + buf.read_value(0, 4, ArrayU_8) + with py.test.raises(InvalidRawWrite): + buf.write_value(0, 4, ArrayU_8, 'three') diff --git a/rpython/jit/metainterp/optimizeopt/test/test_util.py b/rpython/jit/metainterp/optimizeopt/test/test_util.py --- a/rpython/jit/metainterp/optimizeopt/test/test_util.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_util.py @@ -196,6 +196,15 @@ EffectInfo.EF_CANNOT_RAISE, oopspecindex=EffectInfo.OS_ARRAYCOPY)) + raw_malloc_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, + EffectInfo([], [], [], [], + EffectInfo.EF_CAN_RAISE, + oopspecindex=EffectInfo.OS_RAW_MALLOC_VARSIZE_CHAR)) + raw_free_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, + EffectInfo([], [], [], [], + EffectInfo.EF_CANNOT_RAISE, + oopspecindex=EffectInfo.OS_RAW_FREE)) + # array of structs (complex data) complexarray = lltype.GcArray( @@ -208,6 +217,12 @@ complexrealdescr = cpu.interiorfielddescrof(complexarray, "real") compleximagdescr = cpu.interiorfielddescrof(complexarray, "imag") + rawarraydescr = cpu.arraydescrof(lltype.Array(lltype.Signed, + hints={'nolength': True})) + rawarraydescr_char = cpu.arraydescrof(lltype.Array(lltype.Char, + hints={'nolength': True})) + + for _name, _os in [ ('strconcatdescr', 'OS_STR_CONCAT'), ('strslicedescr', 'OS_STR_SLICE'), diff --git a/rpython/jit/metainterp/optimizeopt/virtualize.py b/rpython/jit/metainterp/optimizeopt/virtualize.py --- a/rpython/jit/metainterp/optimizeopt/virtualize.py +++ b/rpython/jit/metainterp/optimizeopt/virtualize.py @@ -6,7 +6,9 @@ from rpython.jit.metainterp.optimizeopt import optimizer from rpython.jit.metainterp.optimizeopt.optimizer import OptValue, REMOVED from rpython.jit.metainterp.optimizeopt.util import (make_dispatcher_method, - descrlist_dict, sort_descrs) + descrlist_dict, sort_descrs) + +from rpython.jit.metainterp.optimizeopt.rawbuffer import RawBuffer, InvalidRawOperation from rpython.jit.metainterp.resoperation import rop, ResOperation from rpython.rlib.objectmodel import we_are_translated @@ -236,8 +238,36 @@ def _get_descr(self): return self.structdescr +class AbstractVArrayValue(AbstractVirtualValue): + """ + Base class for VArrayValue (for normal GC arrays) and VRawBufferValue (for + malloc()ed memory) + """ -class VArrayValue(AbstractVirtualValue): + def getlength(self): + return len(self._items) + + def get_item_value(self, i): + raise NotImplementedError + + def set_item_value(self, i, newval): + raise NotImplementedError + + def get_args_for_fail(self, modifier): + if self.box is None and not modifier.already_seen_virtual(self.keybox): + # checks for recursion: it is False unless + # we have already seen the very same keybox + itemboxes = [] + for i in range(self.getlength()): + itemvalue = self.get_item_value(i) + itemboxes.append(itemvalue.get_key_box()) + modifier.register_virtual_fields(self.keybox, itemboxes) + for i in range(self.getlength()): + itemvalue = self.get_item_value(i) + itemvalue.get_args_for_fail(modifier) + + +class VArrayValue(AbstractVArrayValue): def __init__(self, arraydescr, constvalue, size, keybox, source_op=None): AbstractVirtualValue.__init__(self, keybox, source_op) @@ -248,6 +278,12 @@ def getlength(self): return len(self._items) + def get_item_value(self, i): + return self._items[i] + + def set_item_value(self, i, newval): + self._items[i] = newval + def getitem(self, index): res = self._items[index] return res @@ -257,11 +293,16 @@ self._items[index] = itemvalue def force_at_end_of_preamble(self, already_forced, optforce): + # note that this method is on VArrayValue instead of + # AbstractVArrayValue because we do not want to support virtualstate + # for rawbuffers for now if self in already_forced: return self already_forced[self] = self - for index in range(len(self._items)): - self._items[index] = self._items[index].force_at_end_of_preamble(already_forced, optforce) + for index in range(self.getlength()): + itemval = self.get_item_value(index) + itemval = itemval.force_at_end_of_preamble(already_forced, optforce) + self.set_item_value(index, itemval) return self def _really_force(self, optforce): @@ -281,29 +322,16 @@ descr=self.arraydescr) optforce.emit_operation(op) - def get_args_for_fail(self, modifier): - if self.box is None and not modifier.already_seen_virtual(self.keybox): - # checks for recursion: it is False unless - # we have already seen the very same keybox - itemboxes = [] - for itemvalue in self._items: - itemboxes.append(itemvalue.get_key_box()) - modifier.register_virtual_fields(self.keybox, itemboxes) - for itemvalue in self._items: - itemvalue.get_args_for_fail(modifier) - def _make_virtual(self, modifier): return modifier.make_varray(self.arraydescr) + class VArrayStructValue(AbstractVirtualValue): def __init__(self, arraydescr, size, keybox, source_op=None): AbstractVirtualValue.__init__(self, keybox, source_op) self.arraydescr = arraydescr self._items = [{} for _ in xrange(size)] - def getlength(self): - return len(self._items) - def getinteriorfield(self, index, ofs, default): return self._items[index].get(ofs, default) @@ -363,6 +391,90 @@ return modifier.make_varraystruct(self.arraydescr, self._get_list_of_descrs()) +class VRawBufferValue(AbstractVArrayValue): + + def __init__(self, cpu, logops, size, keybox, source_op): + AbstractVirtualValue.__init__(self, keybox, source_op) + # note that size is unused, because we assume that the buffer is big + # enough to write/read everything we need. If it's not, it's undefined + # behavior anyway, although in theory we could probably detect such + # cases here + self.size = size + self.buffer = RawBuffer(cpu, logops) + + def getlength(self): + return len(self.buffer.values) + + def get_item_value(self, i): + return self.buffer.values[i] + + def set_item_value(self, i, newval): + self.buffer.values[i] = newval + + def getitem_raw(self, offset, length, descr): + return self.buffer.read_value(offset, length, descr) + + def setitem_raw(self, offset, length, descr, value): + self.buffer.write_value(offset, length, descr, value) + + def _really_force(self, optforce): + op = self.source_op + assert op is not None + if not we_are_translated(): + op.name = 'FORCE ' + self.source_op.name + optforce.emit_operation(self.source_op) + self.box = box = self.source_op.result + for i in range(len(self.buffer.offsets)): + # get a pointer to self.box+offset + offset = self.buffer.offsets[i] + if offset == 0: + arraybox = self.box + else: + arraybox = BoxInt() + op = ResOperation(rop.INT_ADD, + [self.box, ConstInt(offset)], arraybox) + optforce.emit_operation(op) + # + # write the value + descr = self.buffer.descrs[i] + itemvalue = self.buffer.values[i] + itembox = itemvalue.force_box(optforce) + op = ResOperation(rop.SETARRAYITEM_RAW, + [arraybox, ConstInt(0), itembox], None, + descr=descr) + optforce.emit_operation(op) + + def _make_virtual(self, modifier): + # I *think* we need to make a copy of offsets and descrs because we + # want a snapshot of the virtual state right now: if we grow more + # elements later, we don't want them to go in this virtual state + return modifier.make_vrawbuffer(self.size, + self.buffer.offsets[:], + self.buffer.descrs[:]) + + +class VRawSliceValue(AbstractVirtualValue): + + def __init__(self, rawbuffer_value, offset, keybox, source_op): + AbstractVirtualValue.__init__(self, keybox, source_op) + self.rawbuffer_value = rawbuffer_value + self.offset = offset + + def _really_force(self, optforce): + op = self.source_op + assert op is not None + if not we_are_translated(): + op.name = 'FORCE ' + self.source_op.name + self.box = self.source_op.result + self.rawbuffer_value.force_box(optforce) + optforce.emit_operation(op) + + def setitem_raw(self, offset, length, descr, value): + self.rawbuffer_value.setitem_raw(self.offset+offset, length, descr, value) + + def getitem_raw(self, offset, length, descr): + return self.rawbuffer_value.getitem_raw(self.offset+offset, length, descr) + class OptVirtualize(optimizer.Optimization): "Virtualize objects until they escape." @@ -388,6 +500,17 @@ self.make_equal_to(box, vvalue) return vvalue + def make_virtual_raw_memory(self, size, box, source_op): + logops = self.optimizer.loop.logops + vvalue = VRawBufferValue(self.optimizer.cpu, logops, size, box, source_op) + self.make_equal_to(box, vvalue) + return vvalue + + def make_virtual_raw_slice(self, rawbuffer_value, offset, box, source_op): + vvalue = VRawSliceValue(rawbuffer_value, offset, box, source_op) + self.make_equal_to(box, vvalue) + return vvalue + def optimize_GUARD_NO_EXCEPTION(self, op): if self.last_emitted_operation is REMOVED: return @@ -524,6 +647,43 @@ self.getvalue(op.result).ensure_nonnull() self.emit_operation(op) + def optimize_CALL(self, op): + effectinfo = op.getdescr().get_extra_info() + if effectinfo.oopspecindex == EffectInfo.OS_RAW_MALLOC_VARSIZE_CHAR: + self.do_RAW_MALLOC_VARSIZE_CHAR(op) + elif effectinfo.oopspecindex == EffectInfo.OS_RAW_FREE: + self.do_RAW_FREE(op) + else: + self.emit_operation(op) + + def do_RAW_MALLOC_VARSIZE_CHAR(self, op): + sizebox = op.getarg(1) + if not isinstance(sizebox, ConstInt): + self.emit_operation(op) + return + size = sizebox.value + self.make_virtual_raw_memory(size, op.result, op) + + def do_RAW_FREE(self, op): + value = self.getvalue(op.getarg(1)) + if value.is_virtual(): + return + self.emit_operation(op) + + def optimize_INT_ADD(self, op): + value = self.getvalue(op.getarg(0)) + offsetbox = self.get_constant_box(op.getarg(1)) + if value.is_virtual() and offsetbox is not None: + offset = offsetbox.getint() + if isinstance(value, VRawBufferValue): + self.make_virtual_raw_slice(value, offset, op.result, op) + return + elif isinstance(value, VRawSliceValue): + offset = offset + value.offset + self.make_virtual_raw_slice(value.rawbuffer_value, offset, op.result, op) + return + self.emit_operation(op) + def optimize_ARRAYLEN_GC(self, op): value = self.getvalue(op.getarg(0)) if value.is_virtual(): @@ -558,6 +718,48 @@ value.ensure_nonnull() self.emit_operation(op) + def _unpack_arrayitem_raw_op(self, op, indexbox): + index = indexbox.getint() + cpu = self.optimizer.cpu + descr = op.getdescr() + basesize, itemsize, _ = cpu.unpack_arraydescr_size(descr) + offset = basesize + (itemsize*index) + return offset, itemsize, descr + + def optimize_GETARRAYITEM_RAW(self, op): + value = self.getvalue(op.getarg(0)) + if value.is_virtual(): + indexbox = self.get_constant_box(op.getarg(1)) + if indexbox is not None: + offset, itemsize, descr = self._unpack_arrayitem_raw_op(op, indexbox) + try: + itemvalue = value.getitem_raw(offset, itemsize, descr) + self.make_equal_to(op.result, itemvalue) + except InvalidRawOperation: + box = value.force_box(self) + op.setarg(0, box) + self.emit_operation(op) + return + value.ensure_nonnull() + self.emit_operation(op) + + def optimize_SETARRAYITEM_RAW(self, op): + value = self.getvalue(op.getarg(0)) + if value.is_virtual(): + indexbox = self.get_constant_box(op.getarg(1)) + if indexbox is not None: + offset, itemsize, descr = self._unpack_arrayitem_raw_op(op, indexbox) + itemvalue = self.getvalue(op.getarg(2)) + try: + value.setitem_raw(offset, itemsize, descr, itemvalue) + except InvalidRawOperation: + box = value.force_box(self) + op.setarg(0, box) + self.emit_operation(op) + return + value.ensure_nonnull() + self.emit_operation(op) + def optimize_GETINTERIORFIELD_GC(self, op): value = self.getvalue(op.getarg(0)) if value.is_virtual(): diff --git a/rpython/jit/metainterp/optimizeopt/virtualstate.py b/rpython/jit/metainterp/optimizeopt/virtualstate.py --- a/rpython/jit/metainterp/optimizeopt/virtualstate.py +++ b/rpython/jit/metainterp/optimizeopt/virtualstate.py @@ -158,10 +158,16 @@ def debug_header(self, indent): debug_print(indent + 'VStructStateInfo(%d):' % self.position) + class VArrayStateInfo(AbstractVirtualStateInfo): + def __init__(self, arraydescr): self.arraydescr = arraydescr + def _generalization_of(self, other): + return (isinstance(other, VArrayStateInfo) and + self.arraydescr is other.arraydescr) + def generalization_of(self, other, renum, bad): assert self.position != -1 if self.position in renum: @@ -187,10 +193,6 @@ return False return True - def _generalization_of(self, other): - return (isinstance(other, VArrayStateInfo) and - self.arraydescr is other.arraydescr) - def enum_forced_boxes(self, boxes, value, optimizer): if not isinstance(value, virtualize.VArrayValue): raise BadVirtualState @@ -198,7 +200,7 @@ raise BadVirtualState for i in range(len(self.fieldstate)): try: - v = value._items[i] + v = value.get_item_value(i) except IndexError: raise BadVirtualState s = self.fieldstate[i] @@ -212,6 +214,8 @@ def debug_header(self, indent): debug_print(indent + 'VArrayStateInfo(%d):' % self.position) + + class VArrayStructStateInfo(AbstractVirtualStateInfo): def __init__(self, arraydescr, fielddescrs): self.arraydescr = arraydescr @@ -287,6 +291,7 @@ debug_print(indent + 'VArrayStructStateInfo(%d):' % self.position) + class NotVirtualStateInfo(AbstractVirtualStateInfo): def __init__(self, value, is_opaque=False): self.is_opaque = is_opaque @@ -579,6 +584,9 @@ def make_varraystruct(self, arraydescr, fielddescrs): return VArrayStructStateInfo(arraydescr, fielddescrs) + def make_vrawbuffer(self, size, offsets, descrs): + raise NotImplementedError + class BoxNotProducable(Exception): pass diff --git a/rpython/jit/metainterp/pyjitpl.py b/rpython/jit/metainterp/pyjitpl.py --- a/rpython/jit/metainterp/pyjitpl.py +++ b/rpython/jit/metainterp/pyjitpl.py @@ -2623,6 +2623,7 @@ box_exchange_buffer = op.getarg(3) self.history.operations.pop() arg_boxes = [] + for i in range(cif_description.nargs): kind, descr, itemsize = get_arg_descr(self.cpu, cif_description.atypes[i]) diff --git a/rpython/jit/metainterp/resume.py b/rpython/jit/metainterp/resume.py --- a/rpython/jit/metainterp/resume.py +++ b/rpython/jit/metainterp/resume.py @@ -275,6 +275,9 @@ def make_varraystruct(self, arraydescr, fielddescrs): return VArrayStructInfo(arraydescr, fielddescrs) + def make_vrawbuffer(self, size, offsets, descrs): + return VRawBufferStateInfo(size, offsets, descrs) + def make_vstrplain(self, is_unicode=False): if is_unicode: return VUniPlainInfo() @@ -446,8 +449,8 @@ return self.liveboxes_from_env[box] return self.liveboxes[box] - class AbstractVirtualInfo(object): + kind = REF #def allocate(self, decoder, index): # raise NotImplementedError def equals(self, fieldnums): @@ -458,6 +461,7 @@ def debug_prints(self): raise NotImplementedError + class AbstractVirtualStructInfo(AbstractVirtualInfo): def __init__(self, fielddescrs): @@ -486,7 +490,7 @@ @specialize.argtype(1) def allocate(self, decoder, index): struct = decoder.allocate_with_vtable(self.known_class) - decoder.virtuals_cache[index] = struct + decoder.virtuals_cache.set_ptr(index, struct) return self.setfields(decoder, struct) def debug_prints(self): @@ -502,7 +506,7 @@ @specialize.argtype(1) def allocate(self, decoder, index): struct = decoder.allocate_struct(self.typedescr) - decoder.virtuals_cache[index] = struct + decoder.virtuals_cache.set_ptr(index, struct) return self.setfields(decoder, struct) def debug_prints(self): @@ -519,7 +523,7 @@ length = len(self.fieldnums) arraydescr = self.arraydescr array = decoder.allocate_array(length, arraydescr) - decoder.virtuals_cache[index] = array + decoder.virtuals_cache.set_ptr(index, array) # NB. the check for the kind of array elements is moved out of the loop if arraydescr.is_array_of_pointers(): for i in range(length): @@ -541,6 +545,31 @@ From noreply at buildbot.pypy.org Mon Apr 15 17:52:10 2013 From: noreply at buildbot.pypy.org (fijal) Date: Mon, 15 Apr 2013 17:52:10 +0200 (CEST) Subject: [pypy-commit] pypy fast-newarray: merge default Message-ID: <20130415155210.332261C3128@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: fast-newarray Changeset: r63373:5c9cbab255ac Date: 2013-04-15 17:51 +0200 http://bitbucket.org/pypy/pypy/changeset/5c9cbab255ac/ Log: merge default diff too long, truncating to 2000 out of 2634 lines diff --git a/lib_pypy/_pypy_interact.py b/lib_pypy/_pypy_interact.py --- a/lib_pypy/_pypy_interact.py +++ b/lib_pypy/_pypy_interact.py @@ -44,7 +44,7 @@ import code if mainmodule is None: import __main__ as mainmodule - console = code.InteractiveConsole(mainmodule.__dict__) + console = code.InteractiveConsole(mainmodule.__dict__, filename='') # some parts of code.py are copied here because it seems to be impossible # to start an interactive console without printing at least one line # of banner diff --git a/lib_pypy/pyrepl/python_reader.py b/lib_pypy/pyrepl/python_reader.py --- a/lib_pypy/pyrepl/python_reader.py +++ b/lib_pypy/pyrepl/python_reader.py @@ -171,11 +171,11 @@ def execute(self, text): try: - # ooh, look at the hack: + # ooh, look at the hack: code = self.compile("# coding:utf8\n"+text.encode('utf-8'), - '', 'single') + '', 'single') except (OverflowError, SyntaxError, ValueError): - self.showsyntaxerror("") + self.showsyntaxerror('') else: self.runcode(code) if sys.stdout and not sys.stdout.closed: diff --git a/lib_pypy/pyrepl/simple_interact.py b/lib_pypy/pyrepl/simple_interact.py --- a/lib_pypy/pyrepl/simple_interact.py +++ b/lib_pypy/pyrepl/simple_interact.py @@ -37,13 +37,13 @@ import code if mainmodule is None: import __main__ as mainmodule - console = code.InteractiveConsole(mainmodule.__dict__) + console = code.InteractiveConsole(mainmodule.__dict__, filename='') def more_lines(unicodetext): # ooh, look at the hack: src = "#coding:utf-8\n"+unicodetext.encode('utf-8') try: - code = console.compile(src, '', 'single') + code = console.compile(src, '', 'single') except (OverflowError, SyntaxError, ValueError): return False else: diff --git a/pypy/doc/index.rst b/pypy/doc/index.rst --- a/pypy/doc/index.rst +++ b/pypy/doc/index.rst @@ -31,6 +31,7 @@ .. _`Starting with RPython`: getting-started-dev.html .. _`how to contribute`: how-to-contribute.html .. _`PyPy website`: http://pypy.org +.. _`LICENSE`: https://bitbucket.org/pypy/pypy/src/default/LICENSE Index of various topics: ======================== @@ -66,11 +67,9 @@ * `Sandboxing Python code`_ * `Garbage collection environment variables`_ -Status_ of the project. - .. _`Differences between PyPy and CPython`: cpython_differences.html .. _`What PyPy can do for your objects`: objspace-proxies.html -.. _`Continulets and greenlets_`: stackless.html +.. _`Continulets and greenlets`: stackless.html .. _`JIT Generation in PyPy`: jit/index.html .. _`JIT hooks`: jit-hooks.html .. _`Sandboxing Python code`: sandbox.html diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -50,6 +50,9 @@ JIT optimizations which makes cffi calls even faster, by removing the need to allocate a temporary buffer where to store the arguments. +.. branch: improve-docs-2 +Improve documents and straighten out links + .. branches we don't care about .. branch: autoreds .. branch: reflex-support diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py --- a/pypy/interpreter/pyopcode.py +++ b/pypy/interpreter/pyopcode.py @@ -255,19 +255,7 @@ "code=%d, name=%s" % (self.last_instr, opcode, methodname)) - try: - res = meth(oparg, next_instr) - except Exception: - if 0: - import dis, sys - print "*** %s at offset %d (%s)" % (sys.exc_info()[0], - self.last_instr, - methodname) - try: - dis.dis(co_code) - except: - pass - raise + res = meth(oparg, next_instr) if res is not None: next_instr = res diff --git a/pypy/module/__pypy__/test/test_signal.py b/pypy/module/__pypy__/test/test_signal.py --- a/pypy/module/__pypy__/test/test_signal.py +++ b/pypy/module/__pypy__/test/test_signal.py @@ -47,8 +47,9 @@ try: done = [] interrupted = [] + print 'starting',i thread.start_new_thread(subthread, ()) - for i in range(10): + for j in range(10): if len(done): break print '.' time.sleep(0.1) diff --git a/pypy/module/_io/interp_bytesio.py b/pypy/module/_io/interp_bytesio.py --- a/pypy/module/_io/interp_bytesio.py +++ b/pypy/module/_io/interp_bytesio.py @@ -2,37 +2,26 @@ TypeDef, generic_new_descr, GetSetProperty) from pypy.interpreter.gateway import interp2app, unwrap_spec from pypy.interpreter.error import OperationError, operationerrfmt +from rpython.rlib.rStringIO import RStringIO from rpython.rlib.rarithmetic import r_longlong from pypy.module._io.interp_bufferedio import W_BufferedIOBase from pypy.module._io.interp_iobase import convert_size import sys -def buffer2string(buffer, start, end): - from rpython.rlib.rstring import StringBuilder - builder = StringBuilder(end - start) - for i in range(start, end): - builder.append(buffer[i]) - return builder.build() -class W_BytesIO(W_BufferedIOBase): +class W_BytesIO(RStringIO, W_BufferedIOBase): def __init__(self, space): W_BufferedIOBase.__init__(self, space) - self.pos = 0 - self.string_size = 0 - self.buf = None + self.init() def descr_init(self, space, w_initial_bytes=None): - # In case __init__ is called multiple times - self.buf = [] - self.string_size = 0 - self.pos = 0 - + self.init() if not space.is_none(w_initial_bytes): self.write_w(space, w_initial_bytes) - self.pos = 0 + self.seek(0) def _check_closed(self, space, message=None): - if self.buf is None: + if self.is_closed(): if message is None: message = "I/O operation on closed file" raise OperationError(space.w_ValueError, space.wrap(message)) @@ -40,36 +29,12 @@ def read_w(self, space, w_size=None): self._check_closed(space) size = convert_size(space, w_size) - - # adjust invalid sizes - available = self.string_size - self.pos - if not 0 <= size <= available: - size = available - if size < 0: - size = 0 - - output = buffer2string(self.buf, self.pos, self.pos + size) - self.pos += size - return space.wrap(output) + return space.wrap(self.read(size)) def readline_w(self, space, w_limit=None): self._check_closed(space) limit = convert_size(space, w_limit) - - cur_pos = self.pos - if limit < 0: - end_pos = self.string_size - else: - end_pos = min(cur_pos + limit, self.string_size) - while cur_pos != end_pos: - if self.buf[cur_pos] == '\n': - cur_pos += 1 - break - cur_pos += 1 - - output = buffer2string(self.buf, self.pos, cur_pos) - self.pos = cur_pos - return space.wrap(output) + return space.wrap(self.readline(limit)) def read1_w(self, space, w_size): return self.read_w(space, w_size) @@ -79,56 +44,28 @@ rwbuffer = space.rwbuffer_w(w_buffer) size = rwbuffer.getlength() - if self.pos + size > self.string_size: - size = self.string_size - self.pos - - output = buffer2string(self.buf, self.pos, self.pos + size) - length = len(output) + output = self.read(size) rwbuffer.setslice(0, output) - self.pos += length - return space.wrap(length) + return space.wrap(len(output)) def write_w(self, space, w_data): self._check_closed(space) if space.isinstance_w(w_data, space.w_unicode): raise OperationError(space.w_TypeError, space.wrap( "bytes string of buffer expected")) - buf = space.buffer_w(w_data) - length = buf.getlength() + buf = space.bufferstr_w(w_data) + length = len(buf) if length <= 0: - return - - if self.pos + length > len(self.buf): - self.buf.extend(['\0'] * (self.pos + length - len(self.buf))) - - if self.pos > self.string_size: - # In case of overseek, pad with null bytes the buffer region - # between the end of stream and the current position. - # - # 0 lo string_size hi - # | |<---used--->|<----------available----------->| - # | | <--to pad-->|<---to write---> | - # 0 buf position - for i in range(self.string_size, self.pos): - self.buf[i] = '\0' - - # Copy the data to the internal buffer, overwriting some of the - # existing data if self->pos < self->string_size. - for i in range(length): - self.buf[self.pos + i] = buf.getitem(i) - self.pos += length - - # Set the new length of the internal string if it has changed - if self.string_size < self.pos: - self.string_size = self.pos - + return space.wrap(0) + self.write(buf) return space.wrap(length) def truncate_w(self, space, w_size=None): self._check_closed(space) + pos = self.tell() if space.is_none(w_size): - size = self.pos + size = pos else: size = space.r_longlong_w(w_size) @@ -136,19 +73,20 @@ raise OperationError(space.w_ValueError, space.wrap( "negative size value")) - if size < self.string_size: - self.string_size = size - del self.buf[size:] - + self.truncate(size) + if size == pos: + self.seek(0, 2) + else: + self.seek(pos) return space.wrap(size) def getvalue_w(self, space): self._check_closed(space) - return space.wrap(buffer2string(self.buf, 0, self.string_size)) + return space.wrap(self.getvalue()) def tell_w(self, space): self._check_closed(space) - return space.wrap(self.pos) + return space.wrap(self.tell()) @unwrap_spec(pos=r_longlong, whence=int) def seek_w(self, space, pos, whence=0): @@ -159,24 +97,19 @@ raise OperationError(space.w_ValueError, space.wrap( "negative seek value")) elif whence == 1: - if pos > sys.maxint - self.pos: + if pos > sys.maxint - self.tell(): raise OperationError(space.w_OverflowError, space.wrap( "new position too large")) - pos += self.pos elif whence == 2: - if pos > sys.maxint - self.string_size: + if pos > sys.maxint - self.getsize(): raise OperationError(space.w_OverflowError, space.wrap( "new position too large")) - pos += self.string_size else: raise operationerrfmt(space.w_ValueError, "whence must be between 0 and 2, not %d", whence) - if pos >= 0: - self.pos = pos - else: - self.pos = 0 - return space.wrap(self.pos) + self.seek(pos, whence) + return space.wrap(self.tell()) def readable_w(self, space): return space.w_True @@ -188,17 +121,16 @@ return space.w_True def close_w(self, space): - self.buf = None + self.close() def closed_get_w(self, space): - return space.wrap(self.buf is None) + return space.wrap(self.is_closed()) def getstate_w(self, space): self._check_closed(space) - w_content = space.wrap(buffer2string(self.buf, 0, self.string_size)) return space.newtuple([ - w_content, - space.wrap(self.pos), + space.wrap(self.getvalue()), + space.wrap(self.tell()), self.getdict(space)]) def setstate_w(self, space, w_state): @@ -211,13 +143,13 @@ space.type(w_state).getname(space) ) w_content, w_pos, w_dict = space.unpackiterable(w_state, 3) + self.truncate(0) + self.write_w(space, w_content) pos = space.int_w(w_pos) - self.buf = [] - self.write_w(space, w_content) if pos < 0: raise OperationError(space.w_ValueError, space.wrap( "position value cannot be negative")) - self.pos = pos + self.seek(pos) if not space.is_w(w_dict, space.w_None): space.call_method(self.getdict(space), "update", w_dict) diff --git a/pypy/module/_io/interp_stringio.py b/pypy/module/_io/interp_stringio.py --- a/pypy/module/_io/interp_stringio.py +++ b/pypy/module/_io/interp_stringio.py @@ -169,9 +169,9 @@ self.pos = end return space.wrap(u''.join(self.buf[start:end])) - @unwrap_spec(limit=int) - def readline_w(self, space, limit=-1): + def readline_w(self, space, w_limit=None): self._check_closed(space) + limit = convert_size(space, w_limit) if self.pos >= len(self.buf): return space.wrap(u"") diff --git a/pypy/module/_io/test/test_bytesio.py b/pypy/module/_io/test/test_bytesio.py --- a/pypy/module/_io/test/test_bytesio.py +++ b/pypy/module/_io/test/test_bytesio.py @@ -4,6 +4,15 @@ def test_init(self): import _io raises(TypeError, _io.BytesIO, u"12345") + buf = "1234567890" + b = _io.BytesIO(buf) + assert b.getvalue() == buf + b = _io.BytesIO(None) + assert b.getvalue() == "" + b.__init__(buf * 2) + assert b.getvalue() == buf * 2 + b.__init__(buf) + assert b.getvalue() == buf def test_init_kwargs(self): import _io @@ -24,6 +33,7 @@ def test_write(self): import _io f = _io.BytesIO() + assert f.write("") == 0 assert f.write("hello") == 5 import gc; gc.collect() assert f.getvalue() == "hello" @@ -47,10 +57,17 @@ def test_truncate(self): import _io - f = _io.BytesIO("hello") + f = _io.BytesIO() + f.write("hello") + assert f.truncate(0) == 0 + assert f.tell() == 5 + f.seek(0) + f.write("hello") f.seek(3) assert f.truncate() == 3 assert f.getvalue() == "hel" + assert f.truncate(2) == 2 + assert f.tell() == 3 def test_setstate(self): # state is (content, position, __dict__) @@ -73,7 +90,13 @@ import _io b = _io.BytesIO("hello") + a1 = bytearray('t') + a2 = bytearray('testing') + assert b.readinto(a1) == 1 + assert b.readinto(a2) == 4 b.close() + assert a1 == "h" + assert a2 == "elloing" raises(ValueError, b.readinto, bytearray("hello")) def test_readline(self): diff --git a/pypy/module/_io/test/test_stringio.py b/pypy/module/_io/test/test_stringio.py --- a/pypy/module/_io/test/test_stringio.py +++ b/pypy/module/_io/test/test_stringio.py @@ -32,7 +32,7 @@ raises(ValueError, sio.read, 1) raises(ValueError, sio.write, u"text") - def testRead(self): + def test_read(self): import io buf = u"1234567890" sio = io.StringIO(buf) @@ -42,6 +42,13 @@ assert buf[5:] == sio.read(900) assert u"" == sio.read() + def test_readline(self): + import io + sio = io.StringIO(u'123\n456') + assert sio.readline(2) == '12' + assert sio.readline(None) == '3\n' + assert sio.readline() == '456' + def test_seek(self): import io diff --git a/pypy/module/_io/test/test_ztranslation.py b/pypy/module/_io/test/test_ztranslation.py new file mode 100644 --- /dev/null +++ b/pypy/module/_io/test/test_ztranslation.py @@ -0,0 +1,4 @@ +from pypy.objspace.fake.checkmodule import checkmodule + +def test_checkmodule(): + checkmodule('_io') diff --git a/pypy/module/_minimal_curses/__init__.py b/pypy/module/_minimal_curses/__init__.py --- a/pypy/module/_minimal_curses/__init__.py +++ b/pypy/module/_minimal_curses/__init__.py @@ -2,10 +2,12 @@ import _curses except ImportError: try: - import _minimal_curses as _curses # when running on top of pypy-c + # when running on top of pypy before it had _curses, settle for minimal + # we prefer _curses so any constants added make it into _minimal_curses + import _minimal_curses as _curses except ImportError: import py - py.test.skip("no _curses or _minimal_curses module") #no _curses at all + py.test.skip("no _curses or _minimal_curses module") # no _curses at all from pypy.interpreter.mixedmodule import MixedModule from pypy.module._minimal_curses import fficurses # for side effects diff --git a/pypy/module/cStringIO/interp_stringio.py b/pypy/module/cStringIO/interp_stringio.py --- a/pypy/module/cStringIO/interp_stringio.py +++ b/pypy/module/cStringIO/interp_stringio.py @@ -146,7 +146,7 @@ class W_OutputType(RStringIO, W_InputOutputType): def __init__(self, space): - RStringIO.__init__(self) + self.init() self.space = space def descr_truncate(self, w_size=None): @@ -159,6 +159,7 @@ if size < 0: raise OperationError(space.w_IOError, space.wrap("negative size")) self.truncate(size) + self.seek(0, 2) @unwrap_spec(buffer='bufferstr') def descr_write(self, buffer): diff --git a/pypy/module/cStringIO/test/test_interp_stringio.py b/pypy/module/cStringIO/test/test_interp_stringio.py --- a/pypy/module/cStringIO/test/test_interp_stringio.py +++ b/pypy/module/cStringIO/test/test_interp_stringio.py @@ -142,8 +142,11 @@ f.write(' world') f.truncate(30) assert f.getvalue() == '\x00' * 20 + 'hello worl' + assert f.tell() == 30 + f.seek(0) f.truncate(25) assert f.getvalue() == '\x00' * 20 + 'hello' + assert f.tell() == 25 f.write('baz') f.write('egg') f.truncate(3) diff --git a/pypy/module/cpyext/test/test_cpyext.py b/pypy/module/cpyext/test/test_cpyext.py --- a/pypy/module/cpyext/test/test_cpyext.py +++ b/pypy/module/cpyext/test/test_cpyext.py @@ -1,6 +1,6 @@ import sys import weakref -import os.path +import os import py @@ -19,6 +19,21 @@ from rpython.tool.identity_dict import identity_dict from rpython.tool import leakfinder +def setup_module(module): + if os.name == 'nt': + # Do not open dreaded dialog box on segfault + import ctypes + SEM_NOGPFAULTERRORBOX = 0x0002 # From MSDN + old_err_mode = ctypes.windll.kernel32.GetErrorMode() + new_err_mode = old_err_mode | SEM_NOGPFAULTERRORBOX + ctypes.windll.kernel32.SetErrorMode(new_err_mode) + module.old_err_mode = old_err_mode + +def teardown_module(module): + if os.name == 'nt': + import ctypes + ctypes.windll.kernel32.SetErrorMode(module.old_err_mode) + @api.cpython_api([], api.PyObject) def PyPy_Crash1(space): 1/0 diff --git a/pypy/module/micronumpy/interp_dtype.py b/pypy/module/micronumpy/interp_dtype.py --- a/pypy/module/micronumpy/interp_dtype.py +++ b/pypy/module/micronumpy/interp_dtype.py @@ -282,7 +282,10 @@ return dtype if w_dtype is dtype.w_box_type: return dtype - raise OperationError(space.w_TypeError, space.wrap("data type %r not understood" % w_dtype)) + typename = space.type(w_dtype).getname(space) + raise OperationError(space.w_TypeError, space.wrap( + "data type not understood (value of type " + + "%s not expected here)" % typename)) W_Dtype.typedef = TypeDef("dtype", __module__ = "numpypy", diff --git a/pypy/module/micronumpy/test/test_dtypes.py b/pypy/module/micronumpy/test/test_dtypes.py --- a/pypy/module/micronumpy/test/test_dtypes.py +++ b/pypy/module/micronumpy/test/test_dtypes.py @@ -32,7 +32,8 @@ assert dtype(None) is dtype(float) - raises(TypeError, dtype, 1042) + exc = raises(TypeError, dtype, (1, 2)) + assert 'data type not understood' in str(exc.value) raises(KeyError, 'dtype(int)["asdasd"]') def test_dtype_eq(self): diff --git a/pypy/module/thread/os_thread.py b/pypy/module/thread/os_thread.py --- a/pypy/module/thread/os_thread.py +++ b/pypy/module/thread/os_thread.py @@ -132,7 +132,7 @@ if not e.match(space, space.w_SystemExit): ident = rthread.get_ident() where = 'thread %d started by ' % ident - e.write_unraisable(space, where, w_callable) + e.write_unraisable(space, where, w_callable, with_traceback=True) e.clear(space) # clean up space.threadlocals to remove the ExecutionContext # entry corresponding to the current thread diff --git a/pypy/module/thread/test/test_thread.py b/pypy/module/thread/test/test_thread.py --- a/pypy/module/thread/test/test_thread.py +++ b/pypy/module/thread/test/test_thread.py @@ -129,10 +129,10 @@ sys.stderr = StringIO.StringIO() thread.start_new_thread(fn3, ()) self.waitfor(lambda: "ValueError" in sys.stderr.getvalue()) - result = sys.stderr.getvalue() - assert "ValueError" in result - assert "hello world" in result - assert len(result.splitlines()) == 1 + result = sys.stderr.getvalue().splitlines() + #assert result[0].startswith("Unhandled exception in thread ") + assert result[1].startswith("Traceback ") + assert result[-1] == "ValueError: hello world" finally: sys.stderr = prev diff --git a/pypy/objspace/fake/objspace.py b/pypy/objspace/fake/objspace.py --- a/pypy/objspace/fake/objspace.py +++ b/pypy/objspace/fake/objspace.py @@ -58,6 +58,10 @@ class W_MyType(W_MyObject): def __init__(self): self.mro_w = [w_some_obj(), w_some_obj()] + self.dict_w = {'__str__': w_some_obj()} + + def get_module(self): + return w_some_obj() def w_some_obj(): if NonConstant(False): @@ -318,7 +322,7 @@ ObjSpace.ExceptionTable + ['int', 'str', 'float', 'long', 'tuple', 'list', 'dict', 'unicode', 'complex', 'slice', 'bool', - 'basestring', 'object']): + 'basestring', 'object', 'bytearray']): setattr(FakeObjSpace, 'w_' + name, w_some_obj()) FakeObjSpace.w_type = w_some_type() # diff --git a/pypy/objspace/std/test/test_listobject.py b/pypy/objspace/std/test/test_listobject.py --- a/pypy/objspace/std/test/test_listobject.py +++ b/pypy/objspace/std/test/test_listobject.py @@ -1109,7 +1109,7 @@ self.i = i def __eq__(self, other): if self.i == 9: - del l[i - 1] + del l[self.i - 1] return True else: return False diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -74,29 +74,6 @@ def setup_failure_recovery(self): self.failure_recovery_code = [0, 0, 0, 0] - @staticmethod - def _release_gil_shadowstack(): - before = rffi.aroundstate.before - if before: - before() - - @staticmethod - def _reacquire_gil_shadowstack(): - after = rffi.aroundstate.after - if after: - after() - - _NOARG_FUNC = lltype.Ptr(lltype.FuncType([], lltype.Void)) - - def _build_release_gil(self, gcrootmap): - assert gcrootmap.is_shadow_stack - releasegil_func = llhelper(self._NOARG_FUNC, - self._release_gil_shadowstack) - reacqgil_func = llhelper(self._NOARG_FUNC, - self._reacquire_gil_shadowstack) - self.releasegil_addr = rffi.cast(lltype.Signed, releasegil_func) - self.reacqgil_addr = rffi.cast(lltype.Signed, reacqgil_func) - def _build_propagate_exception_path(self): if not self.cpu.propagate_exception_descr: return # not supported (for tests, or non-translated) @@ -537,7 +514,7 @@ clt.allgcrefs = [] clt.frame_info.clear() # for now - if False and log: + if log: operations = self._inject_debugging_code(looptoken, operations, 'e', looptoken.number) @@ -787,13 +764,13 @@ # restore registers self._pop_all_regs_from_jitframe(mc, [], self.cpu.supports_floats) - mc.POP([r.ip.value, r.pc.value]) # return + mc.POP([r.ip.value, r.pc.value]) # return self._frame_realloc_slowpath = mc.materialize(self.cpu.asmmemmgr, []) def _load_shadowstack_top(self, mc, reg, gcrootmap): rst = gcrootmap.get_root_stack_top_addr() mc.gen_load_int(reg.value, rst) - mc.gen_load_int(reg.value, reg.value) + self.load_reg(mc, reg, reg) return rst def fixup_target_tokens(self, rawstart): diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -352,7 +352,8 @@ def _emit_call(self, adr, arglocs, fcond=c.AL, resloc=None, result_info=(-1, -1), - can_collect=1): + can_collect=1, + reload_frame=False): if self.cpu.hf_abi: stack_args, adr = self._setup_call_hf(adr, arglocs, fcond, resloc, result_info) @@ -365,7 +366,6 @@ gcmap = self._regalloc.get_gcmap([r.r0], noregs=noregs) self.push_gcmap(self.mc, gcmap, store=True) #the actual call - #self.mc.BKPT() if adr.is_imm(): self.mc.BL(adr.value) elif adr.is_stack(): @@ -388,6 +388,8 @@ if can_collect: self._reload_frame_if_necessary(self.mc, can_collect=can_collect) self.pop_gcmap(self.mc) + elif reload_frame: + self._reload_frame_if_necessary(self.mc) return fcond def _restore_sp(self, stack_args, fcond): @@ -630,7 +632,9 @@ # argument the address of the structure we are writing into # (the first argument to COND_CALL_GC_WB). helper_num = card_marking - if self._regalloc is not None and self._regalloc.vfprm.reg_bindings: + if is_frame: + helper_num = 4 + elif self._regalloc is not None and self._regalloc.vfprm.reg_bindings: helper_num += 2 if self.wb_slowpath[helper_num] == 0: # tests only assert not we_are_translated() @@ -1264,7 +1268,11 @@ resloc = arglocs[0] if gcrootmap: - self.call_release_gil(gcrootmap, arglocs, fcond) + noregs = self.cpu.gc_ll_descr.is_shadow_stack() + assert noregs + gcmap = self._regalloc.get_gcmap([r.r0], noregs=noregs) + self.push_gcmap(self.mc, gcmap, store=True) + self.call_release_gil(gcrootmap, arglocs, regalloc, fcond) # do the call self._store_force_index(guard_op) # @@ -1273,42 +1281,40 @@ signed = descr.is_result_signed() # self._emit_call(adr, callargs, fcond, - resloc, (size, signed)) + resloc, (size, signed), + can_collect=0) # then reopen the stack if gcrootmap: - self.call_reacquire_gil(gcrootmap, resloc, fcond) + self.call_reacquire_gil(gcrootmap, resloc, regalloc, fcond) self._emit_guard_may_force(guard_op, arglocs[numargs+1:], numargs) return fcond - def call_release_gil(self, gcrootmap, save_registers, fcond): - # First, we need to save away the registers listed in - # 'save_registers' that are not callee-save. + def call_release_gil(self, gcrootmap, save_registers, regalloc, fcond): + # Save caller saved registers and do the call # NOTE: We assume that the floating point registers won't be modified. - regs_to_save = [] - for reg in self._regalloc.rm.save_around_call_regs: - if reg in save_registers: - regs_to_save.append(reg) assert gcrootmap.is_shadow_stack - with saved_registers(self.mc, regs_to_save): - self._emit_call(imm(self.releasegil_addr), [], fcond) + with saved_registers(self.mc, regalloc.rm.save_around_call_regs): + self._emit_call(imm(self.releasegil_addr), [], + fcond, can_collect=False) - def call_reacquire_gil(self, gcrootmap, save_loc, fcond): - # save the previous result into the stack temporarily. + def call_reacquire_gil(self, gcrootmap, save_loc, regalloc, fcond): + # save the previous result into the stack temporarily, in case it is in + # a caller saved register. # NOTE: like with call_release_gil(), we assume that we don't need to # save vfp regs in this case. Besides the result location regs_to_save = [] vfp_regs_to_save = [] - if save_loc.is_reg(): + if save_loc and save_loc in regalloc.rm.save_around_call_regs: regs_to_save.append(save_loc) - if save_loc.is_vfp_reg(): + regs_to_save.append(r.ip) # for alingment + elif save_loc and save_loc in regalloc.vfprm.save_around_call_regs: vfp_regs_to_save.append(save_loc) + assert gcrootmap.is_shadow_stack # call the reopenstack() function (also reacquiring the GIL) - if len(regs_to_save) % 2 != 1: - regs_to_save.append(r.ip) # for alingment - assert gcrootmap.is_shadow_stack with saved_registers(self.mc, regs_to_save, vfp_regs_to_save): - self._emit_call(imm(self.reacqgil_addr), [], fcond) + self._emit_call(imm(self.reacqgil_addr), [], fcond, + can_collect=False, reload_frame=True) def _store_force_index(self, guard_op): faildescr = guard_op.getdescr() diff --git a/rpython/jit/backend/arm/regalloc.py b/rpython/jit/backend/arm/regalloc.py --- a/rpython/jit/backend/arm/regalloc.py +++ b/rpython/jit/backend/arm/regalloc.py @@ -554,10 +554,9 @@ return self._prepare_call(op) def _prepare_call(self, op, force_store=[], save_all_regs=False): - args = [] - args.append(None) + args = [None] * (op.numargs() + 1) for i in range(op.numargs()): - args.append(self.loc(op.getarg(i))) + args[i + 1] = self.loc(op.getarg(i)) # spill variables that need to be saved around calls self.vfprm.before_call(save_all_regs=save_all_regs) if not save_all_regs: diff --git a/rpython/jit/backend/arm/test/test_zrpy_gc.py b/rpython/jit/backend/arm/test/test_zrpy_gc.py --- a/rpython/jit/backend/arm/test/test_zrpy_gc.py +++ b/rpython/jit/backend/arm/test/test_zrpy_gc.py @@ -1,4 +1,8 @@ from rpython.jit.backend.arm.test.support import skip_unless_run_slow_tests skip_unless_run_slow_tests() -from rpython.jit.backend.llsupport.test.zrpy_gc_test import TestShadowStack +from rpython.jit.backend.llsupport.test.zrpy_gc_test import CompileFrameworkTests + + +class TestShadowStack(CompileFrameworkTests): + gcrootfinder = "shadowstack" diff --git a/rpython/jit/backend/arm/test/test_zrpy_gc_boehm.py b/rpython/jit/backend/arm/test/test_zrpy_gc_boehm.py --- a/rpython/jit/backend/arm/test/test_zrpy_gc_boehm.py +++ b/rpython/jit/backend/arm/test/test_zrpy_gc_boehm.py @@ -1,3 +1,3 @@ from rpython.jit.backend.arm.test.support import skip_unless_run_slow_tests skip_unless_run_slow_tests() -from rpython.jit.backend.llsupport.test.zrpy_gc_boehm_test import test_compile_boehm +from rpython.jit.backend.llsupport.test.zrpy_gc_boehm_test import compile_boehm_test as test_compile_boehm diff --git a/rpython/jit/backend/arm/test/test_zrpy_releasegil.py b/rpython/jit/backend/arm/test/test_zrpy_releasegil.py --- a/rpython/jit/backend/arm/test/test_zrpy_releasegil.py +++ b/rpython/jit/backend/arm/test/test_zrpy_releasegil.py @@ -1,4 +1,10 @@ from rpython.jit.backend.arm.test.support import skip_unless_run_slow_tests skip_unless_run_slow_tests() -from rpython.jit.backend.llsupport.test.zrpy_releasegil_test import TestShadowStack +from rpython.jit.backend.llsupport.test.zrpy_releasegil_test import ReleaseGILTests + + +class TestShadowStack(ReleaseGILTests): + gcrootfinder = "shadowstack" + + diff --git a/rpython/jit/backend/llsupport/assembler.py b/rpython/jit/backend/llsupport/assembler.py --- a/rpython/jit/backend/llsupport/assembler.py +++ b/rpython/jit/backend/llsupport/assembler.py @@ -9,7 +9,7 @@ debug_print) from rpython.rlib.rarithmetic import r_uint from rpython.rlib.objectmodel import specialize, compute_unique_id -from rpython.rtyper.annlowlevel import cast_instance_to_gcref +from rpython.rtyper.annlowlevel import cast_instance_to_gcref, llhelper from rpython.rtyper.lltypesystem import rffi, lltype @@ -283,6 +283,69 @@ debug_print(prefix + ':' + str(struct.i)) debug_stop('jit-backend-counts') + @staticmethod + @rgc.no_collect + def _release_gil_asmgcc(css): + # similar to trackgcroot.py:pypy_asm_stackwalk, first part + from rpython.memory.gctransform import asmgcroot + new = rffi.cast(asmgcroot.ASM_FRAMEDATA_HEAD_PTR, css) + next = asmgcroot.gcrootanchor.next + new.next = next + new.prev = asmgcroot.gcrootanchor + asmgcroot.gcrootanchor.next = new + next.prev = new + # and now release the GIL + before = rffi.aroundstate.before + if before: + before() + + @staticmethod + @rgc.no_collect + def _reacquire_gil_asmgcc(css): + # first reacquire the GIL + after = rffi.aroundstate.after + if after: + after() + # similar to trackgcroot.py:pypy_asm_stackwalk, second part + from rpython.memory.gctransform import asmgcroot + old = rffi.cast(asmgcroot.ASM_FRAMEDATA_HEAD_PTR, css) + prev = old.prev + next = old.next + prev.next = next + next.prev = prev + + @staticmethod + @rgc.no_collect + def _release_gil_shadowstack(): + before = rffi.aroundstate.before + if before: + before() + + @staticmethod + @rgc.no_collect + def _reacquire_gil_shadowstack(): + after = rffi.aroundstate.after + if after: + after() + + _NOARG_FUNC = lltype.Ptr(lltype.FuncType([], lltype.Void)) + _CLOSESTACK_FUNC = lltype.Ptr(lltype.FuncType([rffi.LONGP], + lltype.Void)) + + def _build_release_gil(self, gcrootmap): + if gcrootmap.is_shadow_stack: + releasegil_func = llhelper(self._NOARG_FUNC, + self._release_gil_shadowstack) + reacqgil_func = llhelper(self._NOARG_FUNC, + self._reacquire_gil_shadowstack) + else: + releasegil_func = llhelper(self._CLOSESTACK_FUNC, + self._release_gil_asmgcc) + reacqgil_func = llhelper(self._CLOSESTACK_FUNC, + self._reacquire_gil_asmgcc) + self.releasegil_addr = self.cpu.cast_ptr_to_int(releasegil_func) + self.reacqgil_addr = self.cpu.cast_ptr_to_int(reacqgil_func) + def debug_bridge(descr_number, rawstart, codeendpos): diff --git a/rpython/jit/backend/llsupport/test/test_gc_integration.py b/rpython/jit/backend/llsupport/test/test_gc_integration.py --- a/rpython/jit/backend/llsupport/test/test_gc_integration.py +++ b/rpython/jit/backend/llsupport/test/test_gc_integration.py @@ -719,18 +719,24 @@ # people actually wreck xmm registers cpu = self.cpu l = [] + copied_stack = [None] def before(): + # put nonsense on the top of shadowstack + frame = rffi.cast(JITFRAMEPTR, cpu.gc_ll_descr.gcrootmap.stack[0]) + assert getmap(frame).count('1') == 7 # + copied_stack[0] = cpu.gc_ll_descr.gcrootmap.stack[0] + cpu.gc_ll_descr.gcrootmap.stack[0] = 0 l.append("before") def after(): + cpu.gc_ll_descr.gcrootmap.stack[0] = copied_stack[0] l.append("after") invoke_around_extcall(before, after) def f(frame, x): # all the gc pointers are alive p1 -> p7 (but not p0) - assert getmap(frame).count('1') == 7 # assert x == 1 return 2 diff --git a/rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py b/rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py --- a/rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py +++ b/rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py @@ -32,7 +32,7 @@ g._dont_inline_ = True return g -def test_compile_boehm(monkeypatch): +def compile_boehm_test(monkeypatch): fix_annotator_for_vrawbuffer(monkeypatch) myjitdriver = JitDriver(greens = [], reds = ['n', 'x']) @dont_look_inside diff --git a/rpython/jit/backend/llsupport/test/zrpy_gc_test.py b/rpython/jit/backend/llsupport/test/zrpy_gc_test.py --- a/rpython/jit/backend/llsupport/test/zrpy_gc_test.py +++ b/rpython/jit/backend/llsupport/test/zrpy_gc_test.py @@ -770,6 +770,3 @@ def test_compile_framework_call_assembler(self): self.run('compile_framework_call_assembler') - -class TestShadowStack(CompileFrameworkTests): - gcrootfinder = "shadowstack" diff --git a/rpython/jit/backend/llsupport/test/zrpy_releasegil_test.py b/rpython/jit/backend/llsupport/test/zrpy_releasegil_test.py --- a/rpython/jit/backend/llsupport/test/zrpy_releasegil_test.py +++ b/rpython/jit/backend/llsupport/test/zrpy_releasegil_test.py @@ -95,10 +95,3 @@ def test_close_stack(self): self.run('close_stack') assert 'call_release_gil' in udir.join('TestCompileFramework.log').read() - - -class TestShadowStack(ReleaseGILTests): - gcrootfinder = "shadowstack" - -class TestAsmGcc(ReleaseGILTests): - gcrootfinder = "asmgcc" diff --git a/rpython/jit/backend/test/runner_test.py b/rpython/jit/backend/test/runner_test.py --- a/rpython/jit/backend/test/runner_test.py +++ b/rpython/jit/backend/test/runner_test.py @@ -348,7 +348,7 @@ i0 = BoxInt() class UntouchableFailDescr(AbstractFailDescr): final_descr = True - + def __setattr__(self, name, value): if (name == 'index' or name == '_carry_around_for_tests' or name == '_TYPE' or name == '_cpu'): @@ -2455,12 +2455,12 @@ lltype.free(raw, flavor='raw') def test_call_to_winapi_function(self): - from rpython.rlib.clibffi import _WIN32, FUNCFLAG_STDCALL + from rpython.rlib.clibffi import _WIN32 if not _WIN32: py.test.skip("Windows test only") - from rpython.rlib.libffi import CDLL, types, ArgChain + from rpython.rlib.libffi import WinDLL, types, ArgChain from rpython.rlib.rwin32 import DWORD - libc = CDLL('KERNEL32') + libc = WinDLL('KERNEL32') c_GetCurrentDir = libc.getpointer('GetCurrentDirectoryA', [types.ulong, types.pointer], types.ulong) @@ -2831,6 +2831,56 @@ assert self.cpu.get_int_value(deadframe, 0) == 97 assert not called + def test_assembler_call_propagate_exc(self): + from rpython.jit.backend.llsupport.llmodel import AbstractLLCPU + + if not isinstance(self.cpu, AbstractLLCPU): + py.test.skip("llgraph can't fake exceptions well enough, give up") + + excdescr = BasicFailDescr(666) + self.cpu.propagate_exception_descr = excdescr + self.cpu.setup_once() # xxx redo it, because we added + # propagate_exception + + def assembler_helper(deadframe, virtualizable): + assert self.cpu.get_latest_descr(deadframe) is excdescr + # let's assume we handled that + return 3 + + FUNCPTR = lltype.Ptr(lltype.FuncType([llmemory.GCREF, + llmemory.GCREF], + lltype.Signed)) + class FakeJitDriverSD: + index_of_virtualizable = -1 + _assembler_helper_ptr = llhelper(FUNCPTR, assembler_helper) + assembler_helper_adr = llmemory.cast_ptr_to_adr( + _assembler_helper_ptr) + + ops = ''' + [i0] + p0 = newunicode(i0) + finish(p0)''' + loop = parse(ops) + looptoken = JitCellToken() + looptoken.outermost_jitdriver_sd = FakeJitDriverSD() + self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken) + ARGS = [lltype.Signed] * 10 + RES = lltype.Signed + FakeJitDriverSD.portal_calldescr = self.cpu.calldescrof( + lltype.Ptr(lltype.FuncType(ARGS, RES)), ARGS, RES, + EffectInfo.MOST_GENERAL) + ops = ''' + [i0] + i11 = call_assembler(i0, descr=looptoken) + guard_not_forced()[] + finish(i11) + ''' + loop = parse(ops, namespace=locals()) + othertoken = JitCellToken() + self.cpu.compile_loop(loop.inputargs, loop.operations, othertoken) + deadframe = self.cpu.execute_token(othertoken, sys.maxint - 1) + assert self.cpu.get_int_value(deadframe, 0) == 3 + def test_assembler_call_float(self): if not self.cpu.supports_floats: py.test.skip("requires floats") @@ -3341,7 +3391,7 @@ excdescr = BasicFailDescr(666) self.cpu.propagate_exception_descr = excdescr self.cpu.setup_once() # xxx redo it, because we added - # propagate_exception_v + # propagate_exception i0 = BoxInt() p0 = BoxPtr() operations = [ @@ -3375,7 +3425,7 @@ calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, effectinfo) testcases = [(4.0, 2.0), (6.25, 2.5)] for arg, expected in testcases: - res = self.execute_operation(rop.CALL, + res = self.execute_operation(rop.CALL, [funcbox, boxfloat(arg)], 'float', descr=calldescr) assert res.getfloat() == expected @@ -3731,7 +3781,7 @@ # memory assert values[0] == 0 - def test_compile_bridge_while_running(self): + def test_compile_bridge_while_running(self): def func(): bridge = parse(""" [i1, i2, px] @@ -3778,9 +3828,9 @@ func2_ptr = llhelper(FPTR2, func2) calldescr2 = cpu.calldescrof(FUNC2, FUNC2.ARGS, FUNC2.RESULT, EffectInfo.MOST_GENERAL) - + faildescr = BasicFailDescr(0) - + looptoken = JitCellToken() loop = parse(""" [i0, i1, i2] @@ -3796,7 +3846,7 @@ if not isinstance(self.cpu, AbstractLLCPU): py.test.skip("pointless test on non-asm") - + frame = lltype.cast_opaque_ptr(jitframe.JITFRAMEPTR, frame) assert len(frame.jf_frame) == frame.jf_frame_info.jfi_frame_depth ref = self.cpu.get_ref_value(frame, 9) @@ -3858,7 +3908,7 @@ 'calldescr': calldescr, 'faildescr': faildescr, 'finaldescr2': BasicFinalDescr(1)}) - + self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken) frame = self.cpu.execute_token(looptoken, 1, 2, 3) descr = self.cpu.get_latest_descr(frame) diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -371,69 +371,6 @@ else: self.wb_slowpath[withcards + 2 * withfloats] = rawstart - @staticmethod - @rgc.no_collect - def _release_gil_asmgcc(css): - # similar to trackgcroot.py:pypy_asm_stackwalk, first part - from rpython.memory.gctransform import asmgcroot - new = rffi.cast(asmgcroot.ASM_FRAMEDATA_HEAD_PTR, css) - next = asmgcroot.gcrootanchor.next - new.next = next - new.prev = asmgcroot.gcrootanchor - asmgcroot.gcrootanchor.next = new - next.prev = new - # and now release the GIL - before = rffi.aroundstate.before - if before: - before() - - @staticmethod - @rgc.no_collect - def _reacquire_gil_asmgcc(css): - # first reacquire the GIL - after = rffi.aroundstate.after - if after: - after() - # similar to trackgcroot.py:pypy_asm_stackwalk, second part - from rpython.memory.gctransform import asmgcroot - old = rffi.cast(asmgcroot.ASM_FRAMEDATA_HEAD_PTR, css) - prev = old.prev - next = old.next - prev.next = next - next.prev = prev - - @staticmethod - @rgc.no_collect - def _release_gil_shadowstack(): - before = rffi.aroundstate.before - if before: - before() - - @staticmethod - @rgc.no_collect - def _reacquire_gil_shadowstack(): - after = rffi.aroundstate.after - if after: - after() - - _NOARG_FUNC = lltype.Ptr(lltype.FuncType([], lltype.Void)) - _CLOSESTACK_FUNC = lltype.Ptr(lltype.FuncType([rffi.LONGP], - lltype.Void)) - - def _build_release_gil(self, gcrootmap): - if gcrootmap.is_shadow_stack: - releasegil_func = llhelper(self._NOARG_FUNC, - self._release_gil_shadowstack) - reacqgil_func = llhelper(self._NOARG_FUNC, - self._reacquire_gil_shadowstack) - else: - releasegil_func = llhelper(self._CLOSESTACK_FUNC, - self._release_gil_asmgcc) - reacqgil_func = llhelper(self._CLOSESTACK_FUNC, - self._reacquire_gil_asmgcc) - self.releasegil_addr = self.cpu.cast_ptr_to_int(releasegil_func) - self.reacqgil_addr = self.cpu.cast_ptr_to_int(reacqgil_func) - def assemble_loop(self, loopname, inputargs, operations, looptoken, log): '''adds the following attributes to looptoken: _ll_function_addr (address of the generated func, as an int) @@ -1041,12 +978,13 @@ def _emit_call(self, x, arglocs, start=0, tmp=eax, argtypes=None, callconv=FFI_DEFAULT_ABI, can_collect=1, - stack_max=PASS_ON_MY_FRAME): + stack_max=PASS_ON_MY_FRAME, reload_frame=False): if can_collect == 1 and not self._is_asmgcc(): can_collect = 2 # don't bother with jf_extra_stack_depth if IS_X86_64: return self._emit_call_64(x, arglocs, start, argtypes, - can_collect, stack_max) + can_collect, stack_max, + reload_frame=reload_frame) stack_depth = 0 n = len(arglocs) for i in range(start, n): @@ -1096,6 +1034,8 @@ ofs = self.cpu.get_ofs_of_frame_field('jf_extra_stack_depth') self.mc.MOV_bi(ofs, 0) self.pop_gcmap(self.mc) + elif reload_frame: + self._reload_frame_if_necessary(self.mc) # def _fix_stdcall(self, callconv, p): @@ -1106,7 +1046,7 @@ self.mc.SUB_ri(esp.value, p) def _emit_call_64(self, x, arglocs, start, argtypes, - can_collect, stack_max): + can_collect, stack_max, reload_frame=False): src_locs = [] dst_locs = [] xmm_src_locs = [] @@ -1196,6 +1136,8 @@ if align and can_collect == 1: ofs = self.cpu.get_ofs_of_frame_field('jf_extra_stack_depth') self.mc.MOV_bi(ofs, 0) + elif reload_frame: + self._reload_frame_if_necessary(self.mc) if align: self.mc.ADD_ri(esp.value, align * WORD) if can_collect: @@ -1988,6 +1930,9 @@ self.pending_guard_tokens.append(guard_token) def genop_call(self, op, arglocs, resloc): + return self._genop_call(op, arglocs, resloc) + + def _genop_call(self, op, arglocs, resloc, is_call_release_gil=False): from rpython.jit.backend.llsupport.descr import CallDescr sizeloc = arglocs[0] @@ -2005,11 +1950,14 @@ assert isinstance(descr, CallDescr) stack_max = PASS_ON_MY_FRAME - if self._is_asmgcc() and op.getopnum() == rop.CALL_RELEASE_GIL: - from rpython.memory.gctransform import asmgcroot - stack_max -= asmgcroot.JIT_USE_WORDS - can_collect = 3 # asmgcc only: don't write jf_extra_stack_depth, - # and reload ebp from the css + if is_call_release_gil: + if self._is_asmgcc(): + from rpython.memory.gctransform import asmgcroot + stack_max -= asmgcroot.JIT_USE_WORDS + can_collect = 3 # asmgcc only: don't write jf_extra_stack_depth, + # and reload ebp from the css + else: + can_collect = 0 else: can_collect = 1 @@ -2074,13 +2022,16 @@ def genop_guard_call_release_gil(self, op, guard_op, guard_token, arglocs, result_loc): + self._store_force_index(guard_op) # first, close the stack in the sense of the asmgcc GC root tracker gcrootmap = self.cpu.gc_ll_descr.gcrootmap if gcrootmap: + noregs = self.cpu.gc_ll_descr.is_shadow_stack() + gcmap = self._regalloc.get_gcmap([eax], noregs=noregs) + self.push_gcmap(self.mc, gcmap, store=True) self.call_release_gil(gcrootmap, arglocs) # do the call - self._store_force_index(guard_op) - self.genop_call(op, arglocs, result_loc) + self._genop_call(op, arglocs, result_loc, is_call_release_gil=True) # then reopen the stack if gcrootmap: self.call_reacquire_gil(gcrootmap, result_loc) @@ -2139,7 +2090,8 @@ reg = edi self.mc.LEA_rs(reg.value, css) args = [reg] - self._emit_call(imm(self.reacqgil_addr), args, can_collect=False) + self._emit_call(imm(self.reacqgil_addr), args, can_collect=False, + reload_frame=True) # restore the result from the stack if isinstance(save_loc, RegLoc) and not save_loc.is_xmm: self.mc.MOV_rs(save_loc.value, WORD) diff --git a/rpython/jit/backend/x86/test/test_zrpy_gc.py b/rpython/jit/backend/x86/test/test_zrpy_gc.py --- a/rpython/jit/backend/x86/test/test_zrpy_gc.py +++ b/rpython/jit/backend/x86/test/test_zrpy_gc.py @@ -1,1 +1,5 @@ -from rpython.jit.backend.llsupport.test.zrpy_gc_test import TestShadowStack +from rpython.jit.backend.llsupport.test.zrpy_gc_test import CompileFrameworkTests + + +class TestShadowStack(CompileFrameworkTests): + gcrootfinder = "shadowstack" diff --git a/rpython/jit/backend/x86/test/test_zrpy_gc_boehm.py b/rpython/jit/backend/x86/test/test_zrpy_gc_boehm.py --- a/rpython/jit/backend/x86/test/test_zrpy_gc_boehm.py +++ b/rpython/jit/backend/x86/test/test_zrpy_gc_boehm.py @@ -1,1 +1,1 @@ -from rpython.jit.backend.llsupport.test.zrpy_gc_boehm_test import test_compile_boehm +from rpython.jit.backend.llsupport.test.zrpy_gc_boehm_test import compile_boehm_test as test_compile_boehm diff --git a/rpython/jit/backend/x86/test/test_zrpy_releasegil.py b/rpython/jit/backend/x86/test/test_zrpy_releasegil.py --- a/rpython/jit/backend/x86/test/test_zrpy_releasegil.py +++ b/rpython/jit/backend/x86/test/test_zrpy_releasegil.py @@ -1,1 +1,9 @@ -from rpython.jit.backend.llsupport.test.zrpy_releasegil_test import TestShadowStack, TestAsmGcc +from rpython.jit.backend.llsupport.test.zrpy_releasegil_test import ReleaseGILTests + + +class TestShadowStack(ReleaseGILTests): + gcrootfinder = "shadowstack" + + +class TestAsmGcc(ReleaseGILTests): + gcrootfinder = "asmgcc" diff --git a/rpython/jit/codewriter/jtransform.py b/rpython/jit/codewriter/jtransform.py --- a/rpython/jit/codewriter/jtransform.py +++ b/rpython/jit/codewriter/jtransform.py @@ -1755,11 +1755,15 @@ return SpaceOperation('libffi_save_result_%s' % kind, op.args[1:], None) def rewrite_op_jit_force_virtual(self, op): - return self._do_builtin_call(op) + op0 = SpaceOperation('-live-', [], None) + op1 = self._do_builtin_call(op) + if isinstance(op1, list): + return [op0] + op1 + else: + return [op0, op1] def rewrite_op_jit_is_virtual(self, op): - raise Exception, ( - "'vref.virtual' should not be used from jit-visible code") + raise Exception("'vref.virtual' should not be used from jit-visible code") def rewrite_op_jit_force_virtualizable(self, op): # this one is for virtualizables diff --git a/rpython/jit/codewriter/test/test_flatten.py b/rpython/jit/codewriter/test/test_flatten.py --- a/rpython/jit/codewriter/test/test_flatten.py +++ b/rpython/jit/codewriter/test/test_flatten.py @@ -689,6 +689,7 @@ self.encoding_test(f, [], """ new_with_vtable -> %r0 virtual_ref %r0 -> %r1 + -live- residual_call_r_r $<* fn jit_force_virtual>, R[%r1], -> %r2 ref_return %r2 """, transform=True, cc=FakeCallControlWithVRefInfo()) diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py --- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py @@ -1747,9 +1747,9 @@ ops = """ [i1] i2 = call('malloc', 10, descr=raw_malloc_descr) - setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) - setarrayitem_raw(i2, 2, 456, descr=rawarraydescr) - setarrayitem_raw(i2, 1, 123, descr=rawarraydescr) + setarrayitem_raw(i2, 0, i1, descr=rawarraydescr_char) + setarrayitem_raw(i2, 2, 456, descr=rawarraydescr_char) + setarrayitem_raw(i2, 1, 123, descr=rawarraydescr_char) label('foo') # we expect the buffer to be forced *after* the label escape(i2) call('free', i2, descr=raw_free_descr) @@ -1759,11 +1759,11 @@ [i1] label('foo') i2 = call('malloc', 10, descr=raw_malloc_descr) - setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) - i3 = int_add(i2, 8) - setarrayitem_raw(i3, 0, 123, descr=rawarraydescr) - i4 = int_add(i2, 16) - setarrayitem_raw(i4, 0, 456, descr=rawarraydescr) + setarrayitem_raw(i2, 0, i1, descr=rawarraydescr_char) + i3 = int_add(i2, 1) + setarrayitem_raw(i3, 0, 123, descr=rawarraydescr_char) + i4 = int_add(i2, 2) + setarrayitem_raw(i4, 0, 456, descr=rawarraydescr_char) escape(i2) call('free', i2, descr=raw_free_descr) jump(i1) diff --git a/rpython/jit/metainterp/pyjitpl.py b/rpython/jit/metainterp/pyjitpl.py --- a/rpython/jit/metainterp/pyjitpl.py +++ b/rpython/jit/metainterp/pyjitpl.py @@ -1,25 +1,27 @@ -import py, sys +import sys + +import py + +from rpython.jit.codewriter import heaptracker +from rpython.jit.codewriter.effectinfo import EffectInfo +from rpython.jit.codewriter.jitcode import JitCode, SwitchDictDescr +from rpython.jit.metainterp import history, compile, resume, executor +from rpython.jit.metainterp.heapcache import HeapCache +from rpython.jit.metainterp.history import (Const, ConstInt, ConstPtr, + ConstFloat, Box, TargetToken) +from rpython.jit.metainterp.jitexc import JitException, get_llexception +from rpython.jit.metainterp.jitprof import EmptyProfiler +from rpython.jit.metainterp.logger import Logger +from rpython.jit.metainterp.optimizeopt.util import args_dict_box +from rpython.jit.metainterp.resoperation import rop +from rpython.rlib import nonconst, rstack +from rpython.rlib.debug import debug_start, debug_stop, debug_print, make_sure_not_resized +from rpython.rlib.jit import Counters +from rpython.rlib.objectmodel import we_are_translated, specialize +from rpython.rlib.unroll import unrolling_iterable from rpython.rtyper.lltypesystem import lltype, rclass -from rpython.rlib.objectmodel import we_are_translated -from rpython.rlib.unroll import unrolling_iterable -from rpython.rlib.debug import debug_start, debug_stop, debug_print -from rpython.rlib.debug import make_sure_not_resized -from rpython.rlib import nonconst, rstack -from rpython.jit.metainterp import history, compile, resume -from rpython.jit.metainterp.history import Const, ConstInt, ConstPtr, ConstFloat -from rpython.jit.metainterp.history import Box, TargetToken -from rpython.jit.metainterp.resoperation import rop -from rpython.jit.metainterp import executor -from rpython.jit.metainterp.logger import Logger -from rpython.jit.metainterp.jitprof import EmptyProfiler -from rpython.rlib.jit import Counters -from rpython.jit.metainterp.jitexc import JitException, get_llexception -from rpython.jit.metainterp.heapcache import HeapCache -from rpython.rlib.objectmodel import specialize -from rpython.jit.codewriter.jitcode import JitCode, SwitchDictDescr -from rpython.jit.codewriter import heaptracker -from rpython.jit.metainterp.optimizeopt.util import args_dict_box + # ____________________________________________________________ @@ -831,15 +833,17 @@ opimpl_inline_call_irf_f = _opimpl_inline_call3 opimpl_inline_call_irf_v = _opimpl_inline_call3 - @arguments("box", "boxes", "descr") - def _opimpl_residual_call1(self, funcbox, argboxes, calldescr): - return self.do_residual_or_indirect_call(funcbox, argboxes, calldescr) - @arguments("box", "boxes2", "descr") - def _opimpl_residual_call2(self, funcbox, argboxes, calldescr): - return self.do_residual_or_indirect_call(funcbox, argboxes, calldescr) - @arguments("box", "boxes3", "descr") - def _opimpl_residual_call3(self, funcbox, argboxes, calldescr): - return self.do_residual_or_indirect_call(funcbox, argboxes, calldescr) + @arguments("box", "boxes", "descr", "orgpc") + def _opimpl_residual_call1(self, funcbox, argboxes, calldescr, pc): + return self.do_residual_or_indirect_call(funcbox, argboxes, calldescr, pc) + + @arguments("box", "boxes2", "descr", "orgpc") + def _opimpl_residual_call2(self, funcbox, argboxes, calldescr, pc): + return self.do_residual_or_indirect_call(funcbox, argboxes, calldescr, pc) + + @arguments("box", "boxes3", "descr", "orgpc") + def _opimpl_residual_call3(self, funcbox, argboxes, calldescr, pc): + return self.do_residual_or_indirect_call(funcbox, argboxes, calldescr, pc) opimpl_residual_call_r_i = _opimpl_residual_call1 opimpl_residual_call_r_r = _opimpl_residual_call1 @@ -852,8 +856,8 @@ opimpl_residual_call_irf_f = _opimpl_residual_call3 opimpl_residual_call_irf_v = _opimpl_residual_call3 - @arguments("int", "boxes3", "boxes3") - def _opimpl_recursive_call(self, jdindex, greenboxes, redboxes): + @arguments("int", "boxes3", "boxes3", "orgpc") + def _opimpl_recursive_call(self, jdindex, greenboxes, redboxes, pc): targetjitdriver_sd = self.metainterp.staticdata.jitdrivers_sd[jdindex] allboxes = greenboxes + redboxes warmrunnerstate = targetjitdriver_sd.warmstate @@ -868,15 +872,15 @@ # that assembler that we call is still correct self.verify_green_args(targetjitdriver_sd, greenboxes) # - return self.do_recursive_call(targetjitdriver_sd, allboxes, + return self.do_recursive_call(targetjitdriver_sd, allboxes, pc, assembler_call) - def do_recursive_call(self, targetjitdriver_sd, allboxes, + def do_recursive_call(self, targetjitdriver_sd, allboxes, pc, assembler_call=False): portal_code = targetjitdriver_sd.mainjitcode k = targetjitdriver_sd.portal_runner_adr funcbox = ConstInt(heaptracker.adr2int(k)) - return self.do_residual_call(funcbox, allboxes, portal_code.calldescr, + return self.do_residual_call(funcbox, allboxes, portal_code.calldescr, pc, assembler_call=assembler_call, assembler_call_jd=targetjitdriver_sd) @@ -935,7 +939,7 @@ return box # no promotion needed, already a Const else: constbox = box.constbox() - resbox = self.do_residual_call(funcbox, [box, constbox], descr) + resbox = self.do_residual_call(funcbox, [box, constbox], descr, orgpc) promoted_box = resbox.constbox() # This is GUARD_VALUE because GUARD_TRUE assumes the existance # of a label when computing resumepc @@ -1027,7 +1031,7 @@ except ChangeFrame: pass frame = self.metainterp.framestack[-1] - frame.do_recursive_call(jitdriver_sd, greenboxes + redboxes, + frame.do_recursive_call(jitdriver_sd, greenboxes + redboxes, orgpc, assembler_call=True) raise ChangeFrame @@ -1329,7 +1333,7 @@ self.metainterp.assert_no_exception() return resbox - def do_residual_call(self, funcbox, argboxes, descr, + def do_residual_call(self, funcbox, argboxes, descr, pc, assembler_call=False, assembler_call_jd=None): # First build allboxes: it may need some reordering from the @@ -1369,6 +1373,10 @@ effectinfo.check_forces_virtual_or_virtualizable()): # residual calls require attention to keep virtualizables in-sync self.metainterp.clear_exception() + if effectinfo.oopspecindex == EffectInfo.OS_JIT_FORCE_VIRTUAL: + resbox = self._do_jit_force_virtual(allboxes, descr, pc) + if resbox is not None: + return resbox self.metainterp.vable_and_vrefs_before_residual_call() resbox = self.metainterp.execute_and_record_varargs( rop.CALL_MAY_FORCE, allboxes, descr=descr) @@ -1399,7 +1407,27 @@ pure = effectinfo.check_is_elidable() return self.execute_varargs(rop.CALL, allboxes, descr, exc, pure) - def do_residual_or_indirect_call(self, funcbox, argboxes, calldescr): + def _do_jit_force_virtual(self, allboxes, descr, pc): + assert len(allboxes) == 2 + if (self.metainterp.jitdriver_sd.virtualizable_info is None and + self.metainterp.jitdriver_sd.greenfield_info is None): + # can occur in case of multiple JITs + return None + vref_box = allboxes[1] + standard_box = self.metainterp.virtualizable_boxes[-1] + if standard_box is vref_box: + return vref_box + if self.metainterp.heapcache.is_nonstandard_virtualizable(vref_box): + return None + eqbox = self.metainterp.execute_and_record(rop.PTR_EQ, None, vref_box, standard_box) + eqbox = self.implement_guard_value(eqbox, pc) + isstandard = eqbox.getint() + if isstandard: + return standard_box + else: + return None + + def do_residual_or_indirect_call(self, funcbox, argboxes, calldescr, pc): """The 'residual_call' operation is emitted in two cases: when we have to generate a residual CALL operation, but also to handle an indirect_call that may need to be inlined.""" @@ -1411,7 +1439,7 @@ # we should follow calls to this graph return self.metainterp.perform_call(jitcode, argboxes) # but we should not follow calls to that graph - return self.do_residual_call(funcbox, argboxes, calldescr) + return self.do_residual_call(funcbox, argboxes, calldescr, pc) # ____________________________________________________________ diff --git a/rpython/jit/metainterp/test/test_virtualizable.py b/rpython/jit/metainterp/test/test_virtualizable.py --- a/rpython/jit/metainterp/test/test_virtualizable.py +++ b/rpython/jit/metainterp/test/test_virtualizable.py @@ -1,20 +1,22 @@ import py + +from rpython.jit.codewriter import heaptracker +from rpython.jit.codewriter.policy import StopAtXPolicy +from rpython.jit.metainterp.optimizeopt.test.test_util import LLtypeMixin +from rpython.jit.metainterp.test.support import LLJitMixin, OOJitMixin +from rpython.jit.metainterp.warmspot import get_translator +from rpython.rlib.jit import JitDriver, hint, dont_look_inside, promote, virtual_ref +from rpython.rlib.rarithmetic import intmask +from rpython.rtyper.annlowlevel import hlstr from rpython.rtyper.extregistry import ExtRegistryEntry from rpython.rtyper.lltypesystem import lltype, lloperation, rclass, llmemory -from rpython.rtyper.annlowlevel import llhelper -from rpython.rtyper.rclass import IR_IMMUTABLE, IR_IMMUTABLE_ARRAY -from rpython.jit.codewriter.policy import StopAtXPolicy -from rpython.jit.codewriter import heaptracker -from rpython.rlib.jit import JitDriver, hint, dont_look_inside, promote -from rpython.rlib.rarithmetic import intmask -from rpython.jit.metainterp.test.support import LLJitMixin, OOJitMixin -from rpython.rtyper.rclass import FieldListAccessor -from rpython.jit.metainterp.warmspot import get_stats, get_translator -from rpython.jit.metainterp import history -from rpython.jit.metainterp.optimizeopt.test.test_util import LLtypeMixin +from rpython.rtyper.rclass import IR_IMMUTABLE, IR_IMMUTABLE_ARRAY, FieldListAccessor + def promote_virtualizable(*args): pass + + class Entry(ExtRegistryEntry): "Annotation and rtyping of LLOp instances, which are callable." _about_ = promote_virtualizable @@ -46,7 +48,7 @@ ('inst_node', lltype.Ptr(LLtypeMixin.NODE)), hints = {'virtualizable2_accessor': FieldListAccessor()}) XY._hints['virtualizable2_accessor'].initialize( - XY, {'inst_x' : IR_IMMUTABLE, 'inst_node' : IR_IMMUTABLE}) + XY, {'inst_x': IR_IMMUTABLE, 'inst_node': IR_IMMUTABLE}) xy_vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) heaptracker.set_testing_vtable_for_gcstruct(XY, xy_vtable, 'XY') @@ -73,7 +75,7 @@ x = xy.inst_x xy.inst_x = x + 1 n -= 1 - promote_virtualizable(xy, 'inst_x') + promote_virtualizable(xy, 'inst_x') return xy.inst_x res = self.meta_interp(f, [20]) assert res == 30 @@ -97,7 +99,7 @@ x = xy.inst_x xy.inst_x = x + 10 n -= 1 - promote_virtualizable(xy, 'inst_x') + promote_virtualizable(xy, 'inst_x') return xy.inst_x assert f(5) == 185 res = self.meta_interp(f, [5]) @@ -118,10 +120,10 @@ x = xy.inst_x if n <= 10: x += 1000 - promote_virtualizable(xy, 'inst_x') + promote_virtualizable(xy, 'inst_x') xy.inst_x = x + 1 n -= 1 - promote_virtualizable(xy, 'inst_x') + promote_virtualizable(xy, 'inst_x') return xy.inst_x res = self.meta_interp(f, [18]) assert res == 10118 @@ -164,7 +166,7 @@ xy.inst_x = x + 1 m = (m+1) & 3 # the loop gets unrolled 4 times n -= 1 - promote_virtualizable(xy, 'inst_x') + promote_virtualizable(xy, 'inst_x') return xy.inst_x def f(n): res = 0 @@ -194,7 +196,7 @@ promote_virtualizable(xy, 'inst_x') xy.inst_x = value + 100 # virtualized away n -= 1 - promote_virtualizable(xy, 'inst_x') + promote_virtualizable(xy, 'inst_x') return xy.inst_x res = self.meta_interp(f, [20]) assert res == 134 @@ -212,8 +214,8 @@ ('inst_l2', lltype.Ptr(lltype.GcArray(lltype.Signed))), hints = {'virtualizable2_accessor': FieldListAccessor()}) XY2._hints['virtualizable2_accessor'].initialize( - XY2, {'inst_x' : IR_IMMUTABLE, - 'inst_l1' : IR_IMMUTABLE_ARRAY, 'inst_l2' : IR_IMMUTABLE_ARRAY}) + XY2, {'inst_x': IR_IMMUTABLE, + 'inst_l1': IR_IMMUTABLE_ARRAY, 'inst_l2': IR_IMMUTABLE_ARRAY}) xy2_vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) heaptracker.set_testing_vtable_for_gcstruct(XY2, xy2_vtable, 'XY2') @@ -241,11 +243,11 @@ while n > 0: myjitdriver.can_enter_jit(xy2=xy2, n=n) myjitdriver.jit_merge_point(xy2=xy2, n=n) - promote_virtualizable(xy2, 'inst_l1') + promote_virtualizable(xy2, 'inst_l1') promote_virtualizable(xy2, 'inst_l2') xy2.inst_l1[2] += xy2.inst_l2[0] n -= 1 - promote_virtualizable(xy2, 'inst_l1') + promote_virtualizable(xy2, 'inst_l1') return xy2.inst_l1[2] res = self.meta_interp(f, [16]) assert res == 3001 + 16 * 80 @@ -292,7 +294,7 @@ myjitdriver.can_enter_jit(xy2=xy2, n=n) myjitdriver.jit_merge_point(xy2=xy2, n=n) promote_virtualizable(xy2, 'inst_l1') - promote_virtualizable(xy2, 'inst_l2') + promote_virtualizable(xy2, 'inst_l2') xy2.inst_l1[1] += len(xy2.inst_l2) n -= 1 def f(n): @@ -373,7 +375,7 @@ promote_virtualizable(xy2, 'inst_l2') xy2.inst_l2[0] = value + 100 # virtualized away n -= 1 - promote_virtualizable(xy2, 'inst_l2') + promote_virtualizable(xy2, 'inst_l2') return xy2.inst_l2[0] expected = f(20) res = self.meta_interp(f, [20], enable_opts='') @@ -406,8 +408,8 @@ myjitdriver.can_enter_jit(xy2=xy2, n=n) myjitdriver.jit_merge_point(xy2=xy2, n=n) parent = xy2.parent - promote_virtualizable(parent, 'inst_x') - promote_virtualizable(parent, 'inst_l2') + promote_virtualizable(parent, 'inst_x') + promote_virtualizable(parent, 'inst_l2') parent.inst_l2[0] += parent.inst_x n -= 1 def f(n): @@ -432,8 +434,7 @@ # ------------------------------ -class ImplicitVirtualizableTests: - +class ImplicitVirtualizableTests(object): def test_simple_implicit(self): myjitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) @@ -473,9 +474,9 @@ def __init__(self, l, s): self.l = l self.s = s - + def f(n, a): - frame = Frame([a,a+1,a+2,a+3], 0) + frame = Frame([a, a+1, a+2, a+3], 0) x = 0 while n > 0: myjitdriver.can_enter_jit(frame=frame, n=n, x=x) @@ -544,7 +545,7 @@ def f(n): BaseFrame([]) # hack to force 'x' to be in BaseFrame - frame = Frame([1,2,3]) + frame = Frame([1, 2, 3]) z = 0 while n > 0: jitdriver.can_enter_jit(frame=frame, n=n, z=z) @@ -560,9 +561,10 @@ def test_external_read(self): jitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) - + class Frame(object): _virtualizable2_ = ['x', 'y'] + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -592,9 +594,10 @@ def test_external_read_with_exception(self): jitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) - + class Frame(object): _virtualizable2_ = ['x', 'y'] + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -634,6 +637,7 @@ class Frame(object): _virtualizable2_ = ['x', 'y'] + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -663,9 +667,10 @@ def test_external_read_sometimes(self): jitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) - + class Frame(object): _virtualizable2_ = ['x', 'y'] + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -699,11 +704,13 @@ def test_external_read_sometimes_with_virtuals(self): jitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) - + class Frame(object): _virtualizable2_ = ['x', 'y'] + class Y: pass + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -742,11 +749,13 @@ def test_external_read_sometimes_changing_virtuals(self): jitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) - + class Frame(object): _virtualizable2_ = ['x', 'y'] + class Y: pass + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -790,11 +799,13 @@ def test_external_read_sometimes_with_exception(self): jitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) - + class Frame(object): _virtualizable2_ = ['x', 'y'] + class FooBarError(Exception): pass + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -832,9 +843,10 @@ def test_external_read_sometimes_dont_compile_guard(self): jitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) - + class Frame(object): _virtualizable2_ = ['x', 'y'] + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -868,9 +880,10 @@ def test_external_read_sometimes_recursive(self): jitdriver = JitDriver(greens = [], reds = ['rec', 'frame'], virtualizables = ['frame']) - + class Frame(object): _virtualizable2_ = ['x', 'y'] + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -919,9 +932,10 @@ def test_external_write_sometimes(self): jitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) - + class Frame(object): _virtualizable2_ = ['x', 'y'] + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -955,9 +969,10 @@ def test_bridge_forces(self): jitdriver = JitDriver(greens = [], reds = ['frame'], virtualizables = ['frame']) - + class Frame(object): _virtualizable2_ = ['x', 'y'] + class SomewhereElse: pass somewhere_else = SomewhereElse() @@ -988,6 +1003,7 @@ def test_promote_index_in_virtualizable_list(self): jitdriver = JitDriver(greens = [], reds = ['n', 'frame'], virtualizables = ['frame']) + class Frame(object): _virtualizable2_ = ['stackpos', 'stack[*]'] @@ -1063,8 +1079,8 @@ assert direct_calls(f_graph) == ['__init__', 'force_virtualizable_if_necessary', 'll_portal_runner'] - assert direct_calls(portal_graph)==['force_virtualizable_if_necessary', - 'maybe_enter_jit'] + assert direct_calls(portal_graph) == ['force_virtualizable_if_necessary', + 'maybe_enter_jit'] assert direct_calls(init_graph) == [] def test_virtual_child_frame(self): @@ -1262,7 +1278,7 @@ somewhere_else = SomewhereElse() def jump_back(frame, fail): - myjitdriver.can_enter_jit(frame=frame, fail=fail) + myjitdriver.can_enter_jit(frame=frame, fail=fail) def f(n, fail): frame = Frame(n, 0) @@ -1315,8 +1331,10 @@ f.x -= 1 result += indirection(f) return result + def indirection(arg): return interp(arg) + def run_interp(n): f = hint(Frame(n), access_directly=True) return interp(f) @@ -1325,7 +1343,7 @@ assert res == run_interp(4) def test_guard_failure_in_inlined_function(self): - from rpython.rtyper.annlowlevel import hlstr + class Frame(object): _virtualizable2_ = ['n', 'next'] @@ -1368,11 +1386,12 @@ assert 0 pc += 1 return frame.n + def main(n): frame = Frame(n) return f("c-l", frame) From noreply at buildbot.pypy.org Mon Apr 15 18:04:39 2013 From: noreply at buildbot.pypy.org (arigo) Date: Mon, 15 Apr 2013 18:04:39 +0200 (CEST) Subject: [pypy-commit] pypy default: Clean up the number and significance of the various flags "can_collect", Message-ID: <20130415160439.EED811C313D@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63374:154e81a46200 Date: 2013-04-15 17:50 +0200 http://bitbucket.org/pypy/pypy/changeset/154e81a46200/ Log: Clean up the number and significance of the various flags "can_collect", "reload_frame" etc. and hopefully fix asmgcc. diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -112,6 +112,11 @@ self.float_const_neg_addr = float_constants self.float_const_abs_addr = float_constants + 16 + def set_extra_stack_depth(self, mc, value): + if self._is_asmgcc(): + extra_ofs = self.cpu.get_ofs_of_frame_field('jf_extra_stack_depth') + mc.MOV_bi(extra_ofs, value) + def build_frame_realloc_slowpath(self): mc = codebuf.MachineCodeBlockWrapper() self._push_all_regs_to_frame(mc, [], self.cpu.supports_floats) @@ -134,16 +139,14 @@ mc.MOV_sr(0, ebp.value) # align - extra_ofs = self.cpu.get_ofs_of_frame_field('jf_extra_stack_depth') - mc.MOV_bi(extra_ofs, align * WORD) + self.set_extra_stack_depth(mc, align * WORD) self._store_and_reset_exception(mc, None, ebx, ecx) mc.CALL(imm(self.cpu.realloc_frame)) mc.MOV_rr(ebp.value, eax.value) self._restore_exception(mc, None, ebx, ecx) mc.ADD_ri(esp.value, (align - 1) * WORD) - mc.MOV_bi(extra_ofs, 0) - + self.set_extra_stack_depth(mc, 0) gcrootmap = self.cpu.gc_ll_descr.gcrootmap if gcrootmap and gcrootmap.is_shadow_stack: @@ -176,8 +179,7 @@ elif hasattr(self.cpu.gc_ll_descr, 'passes_frame'): # for tests only mc.MOV_rr(esi.value, ebp.value) - extra_ofs = self.cpu.get_ofs_of_frame_field('jf_extra_stack_depth') - mc.MOV_bi(extra_ofs, 16) + self.set_extra_stack_depth(mc, 16) mc.CALL(imm(addr)) mc.ADD_ri(esp.value, 16 - WORD) mc.TEST_rr(eax.value, eax.value) @@ -186,7 +188,7 @@ # nursery_free_adr = self.cpu.gc_ll_descr.get_nursery_free_addr() self._reload_frame_if_necessary(mc, align_stack=True) - mc.MOV_bi(extra_ofs, 0) + self.set_extra_stack_depth(mc, 0) self._pop_all_regs_from_frame(mc, [eax, edi], self.cpu.supports_floats) mc.MOV(edi, heap(nursery_free_adr)) # load this in EDI # clear the gc pattern @@ -973,14 +975,17 @@ return bool(gcrootmap) and not gcrootmap.is_shadow_stack def _emit_call(self, x, arglocs, start=0, tmp=eax, - argtypes=None, callconv=FFI_DEFAULT_ABI, can_collect=1, - stack_max=PASS_ON_MY_FRAME, reload_frame=False): - if can_collect == 1 and not self._is_asmgcc(): - can_collect = 2 # don't bother with jf_extra_stack_depth + argtypes=None, callconv=FFI_DEFAULT_ABI, + # whether to worry about a CALL that can collect; this + # is always true except in call_release_gil + can_collect=True, + # max number of arguments we can pass on esp; if more, + # we need to decrease esp temporarily + stack_max=PASS_ON_MY_FRAME): + # if IS_X86_64: return self._emit_call_64(x, arglocs, start, argtypes, - can_collect, stack_max, - reload_frame=reload_frame) + can_collect, stack_max) stack_depth = 0 n = len(arglocs) for i in range(start, n): @@ -989,9 +994,8 @@ if stack_depth > stack_max: align = align_stack_words(stack_depth - stack_max) self.mc.SUB_ri(esp.value, align * WORD) - if can_collect == 1: - ofs = self.cpu.get_ofs_of_frame_field('jf_extra_stack_depth') - self.mc.MOV_bi(ofs, align * WORD) + if can_collect: + self.set_extra_stack_depth(self.mc, align * WORD) else: align = 0 p = 0 @@ -1016,23 +1020,24 @@ p += loc.get_width() # x is a location if can_collect: + # we push *now* the gcmap, describing the status of GC registers + # after the rearrangements done just above, ignoring the return + # value eax, if necessary noregs = self.cpu.gc_ll_descr.is_shadow_stack() gcmap = self._regalloc.get_gcmap([eax], noregs=noregs) self.push_gcmap(self.mc, gcmap, store=True) + # self.mc.CALL(x) if callconv != FFI_DEFAULT_ABI: self._fix_stdcall(callconv, p - align * WORD) elif align: self.mc.ADD_ri(esp.value, align * WORD) + # if can_collect: - self._reload_frame_if_necessary(self.mc, can_collect=can_collect) - if align and can_collect == 1: - ofs = self.cpu.get_ofs_of_frame_field('jf_extra_stack_depth') - self.mc.MOV_bi(ofs, 0) + self._reload_frame_if_necessary(self.mc) + if align: + self.set_extra_stack_depth(self.mc, 0) self.pop_gcmap(self.mc) - elif reload_frame: - self._reload_frame_if_necessary(self.mc) - # def _fix_stdcall(self, callconv, p): from rpython.rlib.clibffi import FFI_STDCALL @@ -1042,7 +1047,7 @@ self.mc.SUB_ri(esp.value, p) def _emit_call_64(self, x, arglocs, start, argtypes, - can_collect, stack_max, reload_frame=False): + can_collect, stack_max): src_locs = [] dst_locs = [] xmm_src_locs = [] @@ -1066,9 +1071,8 @@ align = 0 if stack_depth > stack_max: align = align_stack_words(stack_depth - stack_max) - if can_collect == 1: - ofs = self.cpu.get_ofs_of_frame_field('jf_extra_stack_depth') - self.mc.MOV_bi(ofs, align * WORD) + if can_collect: + self.set_extra_stack_depth(self.mc, align * WORD) self.mc.SUB_ri(esp.value, align * WORD) for i in range(start, len(arglocs)): loc = arglocs[i] @@ -1123,35 +1127,30 @@ x = r10 remap_frame_layout(self, src_locs, dst_locs, X86_64_SCRATCH_REG) if can_collect: + # we push *now* the gcmap, describing the status of GC registers + # after the rearrangements done just above, ignoring the return + # value eax, if necessary noregs = self.cpu.gc_ll_descr.is_shadow_stack() gcmap = self._regalloc.get_gcmap([eax], noregs=noregs) self.push_gcmap(self.mc, gcmap, store=True) + # self.mc.CALL(x) - if can_collect: - self._reload_frame_if_necessary(self.mc, can_collect=can_collect) - if align and can_collect == 1: - ofs = self.cpu.get_ofs_of_frame_field('jf_extra_stack_depth') - self.mc.MOV_bi(ofs, 0) - elif reload_frame: - self._reload_frame_if_necessary(self.mc) if align: self.mc.ADD_ri(esp.value, align * WORD) + # if can_collect: + self._reload_frame_if_necessary(self.mc) + if align: + self.set_extra_stack_depth(self.mc, 0) self.pop_gcmap(self.mc) - def _reload_frame_if_necessary(self, mc, align_stack=False, can_collect=0): + def _reload_frame_if_necessary(self, mc, align_stack=False): gcrootmap = self.cpu.gc_ll_descr.gcrootmap if gcrootmap: if gcrootmap.is_shadow_stack: rst = gcrootmap.get_root_stack_top_addr() mc.MOV(ecx, heap(rst)) mc.MOV(ebp, mem(ecx, -WORD)) - elif can_collect == 3: - # specially for call_release_gil: must reload ebp from the css - from rpython.memory.gctransform import asmgcroot - css = WORD * (PASS_ON_MY_FRAME - asmgcroot.JIT_USE_WORDS) - index_of_ebp = css + WORD * (2+asmgcroot.INDEX_OF_EBP) - mc.MOV_rs(ebp.value, index_of_ebp) # MOV EBP, [css.ebp] wbdescr = self.cpu.gc_ll_descr.write_barrier_descr if gcrootmap and wbdescr: # frame never uses card marking, so we enforce this is not @@ -1950,12 +1949,9 @@ if self._is_asmgcc(): from rpython.memory.gctransform import asmgcroot stack_max -= asmgcroot.JIT_USE_WORDS - can_collect = 3 # asmgcc only: don't write jf_extra_stack_depth, - # and reload ebp from the css - else: - can_collect = 0 + can_collect = False else: - can_collect = 1 + can_collect = True self._emit_call(x, arglocs, 3, tmp=tmp, argtypes=descr.get_arg_types(), @@ -2022,8 +2018,13 @@ # first, close the stack in the sense of the asmgcc GC root tracker gcrootmap = self.cpu.gc_ll_descr.gcrootmap if gcrootmap: - noregs = self.cpu.gc_ll_descr.is_shadow_stack() - gcmap = self._regalloc.get_gcmap([eax], noregs=noregs) + # we put the gcmap now into the frame before releasing the GIL, + # and pop it below after reacquiring the GIL. The assumption + # is that this gcmap describes correctly the situation at any + # point in-between: all values containing GC pointers should + # be safely saved out of registers by now, and will not be + # manipulated by any of the following CALLs. + gcmap = self._regalloc.get_gcmap(noregs=True) self.push_gcmap(self.mc, gcmap, store=True) self.call_release_gil(gcrootmap, arglocs) # do the call @@ -2031,6 +2032,7 @@ # then reopen the stack if gcrootmap: self.call_reacquire_gil(gcrootmap, result_loc) + self.pop_gcmap(self.mc) # remove the gcmap saved above # finally, the guard_not_forced self._emit_guard_not_forced(guard_token) @@ -2059,8 +2061,7 @@ # Set up jf_extra_stack_depth to pretend that the return address # was at css, and so our stack frame is supposedly shorter by # (css+WORD) bytes - extra_ofs = self.cpu.get_ofs_of_frame_field('jf_extra_stack_depth') - self.mc.MOV_bi(extra_ofs, -css-WORD) + self.set_extra_stack_depth(self.mc, -css-WORD) # Call the closestack() function (also releasing the GIL) args = [reg] # @@ -2075,19 +2076,29 @@ # call the reopenstack() function (also reacquiring the GIL) if gcrootmap.is_shadow_stack: args = [] + css = 0 else: from rpython.memory.gctransform import asmgcroot css = WORD * (PASS_ON_MY_FRAME - asmgcroot.JIT_USE_WORDS) - extra_ofs = self.cpu.get_ofs_of_frame_field('jf_extra_stack_depth') - self.mc.MOV_bi(extra_ofs, 0) if IS_X86_32: reg = eax elif IS_X86_64: reg = edi self.mc.LEA_rs(reg.value, css) args = [reg] - self._emit_call(imm(self.reacqgil_addr), args, can_collect=False, - reload_frame=True) + self._emit_call(imm(self.reacqgil_addr), args, can_collect=False) + # + # Now that we required the GIL, we can reload a possibly modified ebp + if not gcrootmap.is_shadow_stack: + # special-case: reload ebp from the css + from rpython.memory.gctransform import asmgcroot + index_of_ebp = css + WORD * (2+asmgcroot.INDEX_OF_EBP) + mc.MOV_rs(ebp.value, index_of_ebp) # MOV EBP, [css.ebp] + #else: + # for shadowstack, done for us by _reload_frame_if_necessary() + self._reload_frame_if_necessary(self.mc) + self.set_extra_stack_depth(self.mc, 0) + # # restore the result from the stack if isinstance(save_loc, RegLoc) and not save_loc.is_xmm: self.mc.MOV_rs(save_loc.value, WORD) From noreply at buildbot.pypy.org Mon Apr 15 18:04:41 2013 From: noreply at buildbot.pypy.org (arigo) Date: Mon, 15 Apr 2013 18:04:41 +0200 (CEST) Subject: [pypy-commit] pypy default: I argue that "-42" looks more like nonsense than "0". Message-ID: <20130415160441.593DD1C313D@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63375:4283488d0fc2 Date: 2013-04-15 17:53 +0200 http://bitbucket.org/pypy/pypy/changeset/4283488d0fc2/ Log: I argue that "-42" looks more like nonsense than "0". diff --git a/rpython/jit/backend/llsupport/test/test_gc_integration.py b/rpython/jit/backend/llsupport/test/test_gc_integration.py --- a/rpython/jit/backend/llsupport/test/test_gc_integration.py +++ b/rpython/jit/backend/llsupport/test/test_gc_integration.py @@ -678,7 +678,7 @@ frame = rffi.cast(JITFRAMEPTR, cpu.gc_ll_descr.gcrootmap.stack[0]) assert getmap(frame).count('1') == 7 # copied_stack[0] = cpu.gc_ll_descr.gcrootmap.stack[0] - cpu.gc_ll_descr.gcrootmap.stack[0] = 0 + cpu.gc_ll_descr.gcrootmap.stack[0] = -42 l.append("before") def after(): From noreply at buildbot.pypy.org Mon Apr 15 18:04:42 2013 From: noreply at buildbot.pypy.org (arigo) Date: Mon, 15 Apr 2013 18:04:42 +0200 (CEST) Subject: [pypy-commit] pypy default: Translation fix Message-ID: <20130415160442.A9EA81C313D@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63376:278985f308f0 Date: 2013-04-15 17:58 +0200 http://bitbucket.org/pypy/pypy/changeset/278985f308f0/ Log: Translation fix diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -2093,7 +2093,7 @@ # special-case: reload ebp from the css from rpython.memory.gctransform import asmgcroot index_of_ebp = css + WORD * (2+asmgcroot.INDEX_OF_EBP) - mc.MOV_rs(ebp.value, index_of_ebp) # MOV EBP, [css.ebp] + self.mc.MOV_rs(ebp.value, index_of_ebp) # MOV EBP, [css.ebp] #else: # for shadowstack, done for us by _reload_frame_if_necessary() self._reload_frame_if_necessary(self.mc) From noreply at buildbot.pypy.org Mon Apr 15 18:04:44 2013 From: noreply at buildbot.pypy.org (arigo) Date: Mon, 15 Apr 2013 18:04:44 +0200 (CEST) Subject: [pypy-commit] pypy default: merge heads Message-ID: <20130415160444.41F951C313D@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63377:b7202d03d1b3 Date: 2013-04-15 18:07 +0200 http://bitbucket.org/pypy/pypy/changeset/b7202d03d1b3/ Log: merge heads diff too long, truncating to 2000 out of 2715 lines diff --git a/pypy/module/_cffi_backend/ccallback.py b/pypy/module/_cffi_backend/ccallback.py --- a/pypy/module/_cffi_backend/ccallback.py +++ b/pypy/module/_cffi_backend/ccallback.py @@ -134,7 +134,7 @@ # W_CTypePrimitiveSigned.convert_from_object() in order # to write a whole 'ffi_arg'. value = misc.as_long(space, w_res) - misc.write_raw_integer_data(ll_res, value, SIZE_OF_FFI_ARG) + misc.write_raw_signed_data(ll_res, value, SIZE_OF_FFI_ARG) return else: # zero extension: fill the '*result' with zeros, and (on big- diff --git a/pypy/module/_cffi_backend/cdataobj.py b/pypy/module/_cffi_backend/cdataobj.py --- a/pypy/module/_cffi_backend/cdataobj.py +++ b/pypy/module/_cffi_backend/cdataobj.py @@ -280,8 +280,13 @@ return self.ctype.iter(self) @specialize.argtype(1) - def write_raw_integer_data(self, source): - misc.write_raw_integer_data(self._cdata, source, self.ctype.size) + def write_raw_signed_data(self, source): + misc.write_raw_signed_data(self._cdata, source, self.ctype.size) + keepalive_until_here(self) + + @specialize.argtype(1) + def write_raw_unsigned_data(self, source): + misc.write_raw_unsigned_data(self._cdata, source, self.ctype.size) keepalive_until_here(self) def write_raw_float_data(self, source): diff --git a/pypy/module/_cffi_backend/ctypeprim.py b/pypy/module/_cffi_backend/ctypeprim.py --- a/pypy/module/_cffi_backend/ctypeprim.py +++ b/pypy/module/_cffi_backend/ctypeprim.py @@ -63,7 +63,7 @@ else: value = self._cast_generic(w_ob) w_cdata = cdataobj.W_CDataMem(space, self.size, self) - w_cdata.write_raw_integer_data(value) + self.write_raw_integer_data(w_cdata, value) return w_cdata def _cast_result(self, intvalue): @@ -94,6 +94,9 @@ from pypy.module._cffi_backend import newtype return newtype.new_primitive_type(self.space, "int") + def write_raw_integer_data(self, w_cdata, value): + w_cdata.write_raw_unsigned_data(value) + class W_CTypePrimitiveChar(W_CTypePrimitiveCharOrUniChar): _attrs_ = [] @@ -185,10 +188,10 @@ if self.size < rffi.sizeof(lltype.Signed): if r_uint(value) - self.vmin > self.vrangemax: self._overflow(w_ob) - misc.write_raw_integer_data(cdata, value, self.size) + misc.write_raw_signed_data(cdata, value, self.size) else: value = misc.as_long_long(self.space, w_ob) - misc.write_raw_integer_data(cdata, value, self.size) + misc.write_raw_signed_data(cdata, value, self.size) def get_vararg_type(self): if self.size < rffi.sizeof(rffi.INT): @@ -196,6 +199,9 @@ return newtype.new_primitive_type(self.space, "int") return self + def write_raw_integer_data(self, w_cdata, value): + w_cdata.write_raw_signed_data(value) + class W_CTypePrimitiveUnsigned(W_CTypePrimitive): _attrs_ = ['value_fits_long', 'value_fits_ulong', 'vrangemax'] @@ -222,10 +228,10 @@ if self.value_fits_long: if value > self.vrangemax: self._overflow(w_ob) - misc.write_raw_integer_data(cdata, value, self.size) + misc.write_raw_unsigned_data(cdata, value, self.size) else: value = misc.as_unsigned_long_long(self.space, w_ob, strict=True) - misc.write_raw_integer_data(cdata, value, self.size) + misc.write_raw_unsigned_data(cdata, value, self.size) def convert_to_object(self, cdata): if self.value_fits_ulong: @@ -244,6 +250,9 @@ return newtype.new_primitive_type(self.space, "int") return self + def write_raw_integer_data(self, w_cdata, value): + w_cdata.write_raw_unsigned_data(value) + class W_CTypePrimitiveBool(W_CTypePrimitiveUnsigned): _attrs_ = [] diff --git a/pypy/module/_cffi_backend/ctypestruct.py b/pypy/module/_cffi_backend/ctypestruct.py --- a/pypy/module/_cffi_backend/ctypestruct.py +++ b/pypy/module/_cffi_backend/ctypestruct.py @@ -242,11 +242,13 @@ # value = misc.as_long_long(space, w_ob) if isinstance(ctype, ctypeprim.W_CTypePrimitiveSigned): + is_signed = True fmin = -(r_longlong(1) << (self.bitsize - 1)) fmax = (r_longlong(1) << (self.bitsize - 1)) - 1 if fmax == 0: fmax = 1 # special case to let "int x:1" receive "1" else: + is_signed = False fmin = r_longlong(0) fmax = r_longlong((r_ulonglong(1) << self.bitsize) - 1) if value < fmin or value > fmax: @@ -258,7 +260,10 @@ rawvalue = r_ulonglong(value) << self.bitshift rawfielddata = misc.read_raw_unsigned_data(cdata, ctype.size) rawfielddata = (rawfielddata & ~rawmask) | (rawvalue & rawmask) - misc.write_raw_integer_data(cdata, rawfielddata, ctype.size) + if is_signed: + misc.write_raw_signed_data(cdata, rawfielddata, ctype.size) + else: + misc.write_raw_unsigned_data(cdata, rawfielddata, ctype.size) W_CField.typedef = TypeDef( diff --git a/pypy/module/_cffi_backend/misc.py b/pypy/module/_cffi_backend/misc.py --- a/pypy/module/_cffi_backend/misc.py +++ b/pypy/module/_cffi_backend/misc.py @@ -9,6 +9,7 @@ from rpython.rtyper.lltypesystem import lltype, llmemory, rffi from rpython.translator.tool.cbuild import ExternalCompilationInfo + # ____________________________________________________________ _prim_signed_types = unrolling_iterable([ @@ -65,19 +66,22 @@ return rffi.cast(rffi.LONGDOUBLEP, target)[0] @specialize.argtype(1) -def write_raw_integer_data(target, source, size): - if is_signed_integer_type(lltype.typeOf(source)): - for TP, TPP in _prim_signed_types: - if size == rffi.sizeof(TP): - rffi.cast(TPP, target)[0] = rffi.cast(TP, source) - return - else: - for TP, TPP in _prim_unsigned_types: - if size == rffi.sizeof(TP): - rffi.cast(TPP, target)[0] = rffi.cast(TP, source) - return +def write_raw_unsigned_data(target, source, size): + for TP, TPP in _prim_unsigned_types: + if size == rffi.sizeof(TP): + rffi.cast(TPP, target)[0] = rffi.cast(TP, source) + return raise NotImplementedError("bad integer size") + at specialize.argtype(1) +def write_raw_signed_data(target, source, size): + for TP, TPP in _prim_signed_types: + if size == rffi.sizeof(TP): + rffi.cast(TPP, target)[0] = rffi.cast(TP, source) + return + raise NotImplementedError("bad integer size") + + def write_raw_float_data(target, source, size): for TP, TPP in _prim_float_types: if size == rffi.sizeof(TP): diff --git a/pypy/module/pypyjit/test_pypy_c/test__ffi.py b/pypy/module/pypyjit/test_pypy_c/test__ffi.py deleted file mode 100644 --- a/pypy/module/pypyjit/test_pypy_c/test__ffi.py +++ /dev/null @@ -1,272 +0,0 @@ -import sys, py -from pypy.module.pypyjit.test_pypy_c.test_00_model import BaseTestPyPyC - -class Test__ffi(BaseTestPyPyC): - - def test__ffi_call(self): - from rpython.rlib.test.test_clibffi import get_libm_name - def main(libm_name): - try: - from _ffi import CDLL, types - except ImportError: - sys.stderr.write('SKIP: cannot import _ffi\n') - return 0 - - libm = CDLL(libm_name) - pow = libm.getfunc('pow', [types.double, types.double], - types.double) - i = 0 - res = 0 - while i < 300: - tmp = pow(2, 3) # ID: fficall - res += tmp - i += 1 - return pow.getaddr(), res - # - libm_name = get_libm_name(sys.platform) - log = self.run(main, [libm_name]) - pow_addr, res = log.result - assert res == 8.0 * 300 - py.test.xfail() # XXX re-optimize _ffi for the JIT? - loop, = log.loops_by_filename(self.filepath) - if 'ConstClass(pow)' in repr(loop): # e.g. OS/X - pow_addr = 'ConstClass(pow)' - assert loop.match_by_id('fficall', """ - guard_not_invalidated(descr=...) - i17 = force_token() - setfield_gc(p0, i17, descr=<.* .*PyFrame.vable_token .*>) - f21 = call_release_gil(%s, 2.000000, 3.000000, descr=) - guard_not_forced(descr=...) - guard_no_exception(descr=...) - """ % pow_addr) - - - def test__ffi_call_frame_does_not_escape(self): - from rpython.rlib.test.test_clibffi import get_libm_name - def main(libm_name): - try: - from _ffi import CDLL, types - except ImportError: - sys.stderr.write('SKIP: cannot import _ffi\n') - return 0 - - libm = CDLL(libm_name) - pow = libm.getfunc('pow', [types.double, types.double], - types.double) - - def mypow(a, b): - return pow(a, b) - - i = 0 - res = 0 - while i < 300: - tmp = mypow(2, 3) - res += tmp - i += 1 - return pow.getaddr(), res - # - libm_name = get_libm_name(sys.platform) - log = self.run(main, [libm_name]) - pow_addr, res = log.result - assert res == 8.0 * 300 - loop, = log.loops_by_filename(self.filepath) - opnames = log.opnames(loop.allops()) - # we only force the virtualref, not its content - assert opnames.count('new_with_vtable') == 1 - - def test__ffi_call_releases_gil(self): - from rpython.rlib.clibffi import get_libc_name - def main(libc_name, n): - import time - import os - from threading import Thread - # - if os.name == 'nt': - from _ffi import WinDLL, types - libc = WinDLL('Kernel32.dll') - sleep = libc.getfunc('Sleep', [types.uint], types.uint) - delays = [0]*n + [1000] - else: - from _ffi import CDLL, types - libc = CDLL(libc_name) - sleep = libc.getfunc('sleep', [types.uint], types.uint) - delays = [0]*n + [1] - # - def loop_of_sleeps(i, delays): - for delay in delays: - sleep(delay) # ID: sleep - # - threads = [Thread(target=loop_of_sleeps, args=[i, delays]) for i in range(5)] - start = time.time() - for i, thread in enumerate(threads): - thread.start() - for thread in threads: - thread.join() - end = time.time() - return end - start - log = self.run(main, [get_libc_name(), 200], threshold=150, - import_site=True) - assert 1 <= log.result <= 1.5 # at most 0.5 seconds of overhead - loops = log.loops_by_id('sleep') - assert len(loops) == 1 # make sure that we actually JITted the loop - - def test_ctypes_call(self): - from rpython.rlib.test.test_clibffi import get_libm_name - def main(libm_name): - import ctypes - libm = ctypes.CDLL(libm_name) - fabs = libm.fabs - fabs.argtypes = [ctypes.c_double] - fabs.restype = ctypes.c_double - x = -4 - i = 0 - while i < 300: - x = fabs(x) - x = x - 100 - i += 1 - return fabs._ptr.getaddr(), x - - libm_name = get_libm_name(sys.platform) - log = self.run(main, [libm_name], import_site=True) - fabs_addr, res = log.result - assert res == -4.0 - loop, = log.loops_by_filename(self.filepath) - ops = loop.allops() - opnames = log.opnames(ops) - assert opnames.count('new_with_vtable') == 1 # only the virtualref - py.test.xfail() # XXX re-optimize _ffi for the JIT? - assert opnames.count('call_release_gil') == 1 - idx = opnames.index('call_release_gil') - call = ops[idx] - assert (call.args[0] == 'ConstClass(fabs)' or # e.g. OS/X - int(call.args[0]) == fabs_addr) - - - def test__ffi_struct(self): - def main(): - from _ffi import _StructDescr, Field, types - fields = [ - Field('x', types.slong), - ] - descr = _StructDescr('foo', fields) - struct = descr.allocate() - i = 0 - while i < 300: - x = struct.getfield('x') # ID: getfield - x = x+1 - struct.setfield('x', x) # ID: setfield - i += 1 - return struct.getfield('x') - # - log = self.run(main, []) - py.test.xfail() # XXX re-optimize _ffi for the JIT? - loop, = log.loops_by_filename(self.filepath) - assert loop.match_by_id('getfield', """ - guard_not_invalidated(descr=...) - i57 = getfield_raw(i46, descr=) - """) - assert loop.match_by_id('setfield', """ - setfield_raw(i44, i57, descr=) - """) - - - def test__cffi_call(self): - from rpython.rlib.test.test_clibffi import get_libm_name - def main(libm_name): - try: - import _cffi_backend - except ImportError: - sys.stderr.write('SKIP: cannot import _cffi_backend\n') - return 0 - - libm = _cffi_backend.load_library(libm_name) - BDouble = _cffi_backend.new_primitive_type("double") - BPow = _cffi_backend.new_function_type([BDouble, BDouble], BDouble) - pow = libm.load_function(BPow, 'pow') - i = 0 - res = 0 - while i < 300: - tmp = pow(2, 3) # ID: cfficall - res += tmp - i += 1 - BLong = _cffi_backend.new_primitive_type("long") - pow_addr = int(_cffi_backend.cast(BLong, pow)) - return pow_addr, res - # - libm_name = get_libm_name(sys.platform) - log = self.run(main, [libm_name]) - pow_addr, res = log.result - assert res == 8.0 * 300 - loop, = log.loops_by_filename(self.filepath) - if 'ConstClass(pow)' in repr(loop): # e.g. OS/X - pow_addr = 'ConstClass(pow)' - assert loop.match_by_id('cfficall', """ - ... - f1 = call_release_gil(..., descr=) - ... - """) - # so far just check that call_release_gil() is produced. - # later, also check that the arguments to call_release_gil() - # are constants, and that the numerous raw_mallocs are removed - - def test_cffi_call_guard_not_forced_fails(self): - # this is the test_pypy_c equivalent of - # rpython/jit/metainterp/test/test_fficall::test_guard_not_forced_fails - # - # it requires cffi to be installed for pypy in order to run - def main(): - import sys - try: - import cffi - except ImportError: - sys.stderr.write('SKIP: cannot import cffi\n') - return 0 - - ffi = cffi.FFI() - - ffi.cdef(""" - typedef void (*functype)(int); - int foo(int n, functype func); - """) - - lib = ffi.verify(""" - #include - typedef void (*functype)(int); - - int foo(int n, functype func) { - if (n >= 2000) { - func(n); - } - return n*2; - } - """) - - @ffi.callback("functype") - def mycallback(n): - if n < 5000: - return - # make sure that guard_not_forced fails - d = {} - f = sys._getframe() - while f: - d.update(f.f_locals) - f = f.f_back - - n = 0 - while n < 10000: - res = lib.foo(n, mycallback) # ID: cfficall - # this is the real point of the test: before the - # refactor-call_release_gil branch, the assert failed when - # res == 5000 - assert res == n*2 - n += 1 - return n - - log = self.run(main, [], import_site=True) - assert log.result == 10000 - loop, = log.loops_by_id('cfficall') - assert loop.match_by_id('cfficall', """ - ... - f1 = call_release_gil(..., descr=) - ... - """) diff --git a/pypy/module/pypyjit/test_pypy_c/test_ffi.py b/pypy/module/pypyjit/test_pypy_c/test_ffi.py new file mode 100644 --- /dev/null +++ b/pypy/module/pypyjit/test_pypy_c/test_ffi.py @@ -0,0 +1,279 @@ +import sys, py +from pypy.module.pypyjit.test_pypy_c.test_00_model import BaseTestPyPyC + +class Test__ffi(BaseTestPyPyC): + + def test__ffi_call(self): + from rpython.rlib.test.test_clibffi import get_libm_name + def main(libm_name): + try: + from _ffi import CDLL, types + except ImportError: + sys.stderr.write('SKIP: cannot import _ffi\n') + return 0 + + libm = CDLL(libm_name) + pow = libm.getfunc('pow', [types.double, types.double], + types.double) + i = 0 + res = 0 + while i < 300: + tmp = pow(2, 3) # ID: fficall + res += tmp + i += 1 + return pow.getaddr(), res + # + libm_name = get_libm_name(sys.platform) + log = self.run(main, [libm_name]) + pow_addr, res = log.result + assert res == 8.0 * 300 + py.test.xfail() # XXX re-optimize _ffi for the JIT? + loop, = log.loops_by_filename(self.filepath) + if 'ConstClass(pow)' in repr(loop): # e.g. OS/X + pow_addr = 'ConstClass(pow)' + assert loop.match_by_id('fficall', """ + guard_not_invalidated(descr=...) + i17 = force_token() + setfield_gc(p0, i17, descr=<.* .*PyFrame.vable_token .*>) + f21 = call_release_gil(%s, 2.000000, 3.000000, descr=) + guard_not_forced(descr=...) + guard_no_exception(descr=...) + """ % pow_addr) + + + def test__ffi_call_frame_does_not_escape(self): + from rpython.rlib.test.test_clibffi import get_libm_name + def main(libm_name): + try: + from _ffi import CDLL, types + except ImportError: + sys.stderr.write('SKIP: cannot import _ffi\n') + return 0 + + libm = CDLL(libm_name) + pow = libm.getfunc('pow', [types.double, types.double], + types.double) + + def mypow(a, b): + return pow(a, b) + + i = 0 + res = 0 + while i < 300: + tmp = mypow(2, 3) + res += tmp + i += 1 + return pow.getaddr(), res + # + libm_name = get_libm_name(sys.platform) + log = self.run(main, [libm_name]) + pow_addr, res = log.result + assert res == 8.0 * 300 + loop, = log.loops_by_filename(self.filepath) + opnames = log.opnames(loop.allops()) + # we only force the virtualref, not its content + assert opnames.count('new_with_vtable') == 1 + + def test__ffi_call_releases_gil(self): + from rpython.rlib.clibffi import get_libc_name + def main(libc_name, n): + import time + import os + from threading import Thread + # + if os.name == 'nt': + from _ffi import WinDLL, types + libc = WinDLL('Kernel32.dll') + sleep = libc.getfunc('Sleep', [types.uint], types.uint) + delays = [0]*n + [1000] + else: + from _ffi import CDLL, types + libc = CDLL(libc_name) + sleep = libc.getfunc('sleep', [types.uint], types.uint) + delays = [0]*n + [1] + # + def loop_of_sleeps(i, delays): + for delay in delays: + sleep(delay) # ID: sleep + # + threads = [Thread(target=loop_of_sleeps, args=[i, delays]) for i in range(5)] + start = time.time() + for i, thread in enumerate(threads): + thread.start() + for thread in threads: + thread.join() + end = time.time() + return end - start + log = self.run(main, [get_libc_name(), 200], threshold=150, + import_site=True) + assert 1 <= log.result <= 1.5 # at most 0.5 seconds of overhead + loops = log.loops_by_id('sleep') + assert len(loops) == 1 # make sure that we actually JITted the loop + + def test_ctypes_call(self): + from rpython.rlib.test.test_clibffi import get_libm_name + def main(libm_name): + import ctypes + libm = ctypes.CDLL(libm_name) + fabs = libm.fabs + fabs.argtypes = [ctypes.c_double] + fabs.restype = ctypes.c_double + x = -4 + i = 0 + while i < 300: + x = fabs(x) + x = x - 100 + i += 1 + return fabs._ptr.getaddr(), x + + libm_name = get_libm_name(sys.platform) + log = self.run(main, [libm_name], import_site=True) + fabs_addr, res = log.result + assert res == -4.0 + loop, = log.loops_by_filename(self.filepath) + ops = loop.allops() + opnames = log.opnames(ops) + assert opnames.count('new_with_vtable') == 1 # only the virtualref + py.test.xfail() # XXX re-optimize _ffi for the JIT? + assert opnames.count('call_release_gil') == 1 + idx = opnames.index('call_release_gil') + call = ops[idx] + assert (call.args[0] == 'ConstClass(fabs)' or # e.g. OS/X + int(call.args[0]) == fabs_addr) + + + def test__ffi_struct(self): + def main(): + from _ffi import _StructDescr, Field, types + fields = [ + Field('x', types.slong), + ] + descr = _StructDescr('foo', fields) + struct = descr.allocate() + i = 0 + while i < 300: + x = struct.getfield('x') # ID: getfield + x = x+1 + struct.setfield('x', x) # ID: setfield + i += 1 + return struct.getfield('x') + # + log = self.run(main, []) + py.test.xfail() # XXX re-optimize _ffi for the JIT? + loop, = log.loops_by_filename(self.filepath) + assert loop.match_by_id('getfield', """ + guard_not_invalidated(descr=...) + i57 = getfield_raw(i46, descr=) + """) + assert loop.match_by_id('setfield', """ + setfield_raw(i44, i57, descr=) + """) + + + def test__cffi_call(self): + from rpython.rlib.test.test_clibffi import get_libm_name + def main(libm_name): + try: + import _cffi_backend + except ImportError: + sys.stderr.write('SKIP: cannot import _cffi_backend\n') + return 0 + + libm = _cffi_backend.load_library(libm_name) + BDouble = _cffi_backend.new_primitive_type("double") + BInt = _cffi_backend.new_primitive_type("int") + BPow = _cffi_backend.new_function_type([BDouble, BInt], BDouble) + ldexp = libm.load_function(BPow, 'ldexp') + i = 0 + res = 0 + while i < 300: + tmp = ldexp(1, 3) # ID: cfficall + res += tmp + i += 1 + BLong = _cffi_backend.new_primitive_type("long") + ldexp_addr = int(_cffi_backend.cast(BLong, ldexp)) + return ldexp_addr, res + # + libm_name = get_libm_name(sys.platform) + log = self.run(main, [libm_name]) + ldexp_addr, res = log.result + assert res == 8.0 * 300 + loop, = log.loops_by_filename(self.filepath) + if 'ConstClass(ldexp)' in repr(loop): # e.g. OS/X + ldexp_addr = 'ConstClass(ldexp)' + assert loop.match_by_id('cfficall', """ + ... + f1 = call_release_gil(..., descr=) + ... + """) + ops = loop.ops_by_id('cfficall') + assert 'raw_malloc' not in str(ops) + assert 'raw_free' not in str(ops) + assert 'getarrayitem_raw' not in log.opnames(ops) + assert 'setarrayitem_raw' not in log.opnames(ops) + # so far just check that call_release_gil() is produced. + # later, also check that the arguments to call_release_gil() + # are constants + # are constants, and that the numerous raw_mallocs are removed + + def test_cffi_call_guard_not_forced_fails(self): + # this is the test_pypy_c equivalent of + # rpython/jit/metainterp/test/test_fficall::test_guard_not_forced_fails + # + # it requires cffi to be installed for pypy in order to run + def main(): + import sys + try: + import cffi + except ImportError: + sys.stderr.write('SKIP: cannot import cffi\n') + return 0 + + ffi = cffi.FFI() + + ffi.cdef(""" + typedef void (*functype)(int); + int foo(int n, functype func); + """) + + lib = ffi.verify(""" + #include + typedef void (*functype)(int); + + int foo(int n, functype func) { + if (n >= 2000) { + func(n); + } + return n*2; + } + """) + + @ffi.callback("functype") + def mycallback(n): + if n < 5000: + return + # make sure that guard_not_forced fails + d = {} + f = sys._getframe() + while f: + d.update(f.f_locals) + f = f.f_back + + n = 0 + while n < 10000: + res = lib.foo(n, mycallback) # ID: cfficall + # this is the real point of the test: before the + # refactor-call_release_gil branch, the assert failed when + # res == 5000 + assert res == n*2 + n += 1 + return n + + log = self.run(main, [], import_site=True) + assert log.result == 10000 + loop, = log.loops_by_id('cfficall') + assert loop.match_by_id('cfficall', """ + ... + f1 = call_release_gil(..., descr=) + ... + """) diff --git a/rpython/jit/backend/llgraph/runner.py b/rpython/jit/backend/llgraph/runner.py --- a/rpython/jit/backend/llgraph/runner.py +++ b/rpython/jit/backend/llgraph/runner.py @@ -484,6 +484,15 @@ else: return self.bh_raw_load_i(struct, offset, descr) + def unpack_arraydescr_size(self, arraydescr): + from rpython.jit.backend.llsupport.symbolic import get_array_token + from rpython.jit.backend.llsupport.descr import get_type_flag, FLAG_SIGNED + assert isinstance(arraydescr, ArrayDescr) + basesize, itemsize, _ = get_array_token(arraydescr.A, False) + flag = get_type_flag(arraydescr.A.OF) + is_signed = (flag == FLAG_SIGNED) + return basesize, itemsize, is_signed + def bh_raw_store_i(self, struct, offset, newvalue, descr): ll_p = rffi.cast(rffi.CCHARP, struct) ll_p = rffi.cast(lltype.Ptr(descr.A), rffi.ptradd(ll_p, offset)) @@ -566,10 +575,14 @@ def bh_read_timestamp(self): return read_timestamp() + def bh_new_raw_buffer(self, size): + return lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') + def store_fail_descr(self, deadframe, descr): pass # I *think* + class LLDeadFrame(object): _TYPE = llmemory.GCREF diff --git a/rpython/jit/backend/llsupport/llmodel.py b/rpython/jit/backend/llsupport/llmodel.py --- a/rpython/jit/backend/llsupport/llmodel.py +++ b/rpython/jit/backend/llsupport/llmodel.py @@ -742,6 +742,9 @@ as_array[self.vtable_offset/WORD] = vtable return res + def bh_new_raw_buffer(self, size): + return lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') + def bh_classof(self, struct): struct = lltype.cast_opaque_ptr(rclass.OBJECTPTR, struct) result_adr = llmemory.cast_ptr_to_adr(struct.typeptr) diff --git a/rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py b/rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py --- a/rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py +++ b/rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py @@ -2,6 +2,7 @@ import weakref from rpython.rlib.jit import JitDriver, dont_look_inside from rpython.jit.backend.llsupport.test.zrpy_gc_test import run, get_entry, compile +from rpython.jit.backend.llsupport.test.ztranslation_test import fix_annotator_for_vrawbuffer class X(object): def __init__(self, x=0): @@ -31,7 +32,8 @@ g._dont_inline_ = True return g -def compile_boehm_test(): +def compile_boehm_test(monkeypatch): + fix_annotator_for_vrawbuffer(monkeypatch) myjitdriver = JitDriver(greens = [], reds = ['n', 'x']) @dont_look_inside def see(lst, n): diff --git a/rpython/jit/backend/llsupport/test/ztranslation_test.py b/rpython/jit/backend/llsupport/test/ztranslation_test.py --- a/rpython/jit/backend/llsupport/test/ztranslation_test.py +++ b/rpython/jit/backend/llsupport/test/ztranslation_test.py @@ -9,10 +9,23 @@ from rpython.jit.codewriter.policy import StopAtXPolicy +def fix_annotator_for_vrawbuffer(monkeypatch): + from rpython.rlib.nonconst import NonConstant + from rpython.jit.metainterp.optimizeopt.virtualize import VRawBufferValue + from rpython.jit.metainterp import warmspot + + def my_hook_for_tests(cpu): + # this is needed so that the annotator can see it + if NonConstant(False): + v = VRawBufferValue(cpu, None, -1, None, None) + monkeypatch.setattr(warmspot, 'hook_for_tests', my_hook_for_tests) + + class TranslationTest(CCompiledMixin): CPUClass = getcpuclass() - def test_stuff_translates(self): + def test_stuff_translates(self, monkeypatch): + fix_annotator_for_vrawbuffer(monkeypatch) # this is a basic test that tries to hit a number of features and their # translation: # - jitting of loops and bridges @@ -89,9 +102,10 @@ class TranslationTestCallAssembler(CCompiledMixin): CPUClass = getcpuclass() - def test_direct_assembler_call_translates(self): + def test_direct_assembler_call_translates(self, monkeypatch): """Test CALL_ASSEMBLER and the recursion limit""" from rpython.rlib.rstackovf import StackOverflow + fix_annotator_for_vrawbuffer(monkeypatch) class Thing(object): def __init__(self, val): @@ -169,7 +183,8 @@ class TranslationTestJITStats(CCompiledMixin): CPUClass = getcpuclass() - def test_jit_get_stats(self): + def test_jit_get_stats(self, monkeypatch): + fix_annotator_for_vrawbuffer(monkeypatch) driver = JitDriver(greens = [], reds = ['i']) def f(): @@ -192,7 +207,8 @@ class TranslationRemoveTypePtrTest(CCompiledMixin): CPUClass = getcpuclass() - def test_external_exception_handling_translates(self): + def test_external_exception_handling_translates(self, monkeypatch): + fix_annotator_for_vrawbuffer(monkeypatch) jitdriver = JitDriver(greens = [], reds = ['n', 'total']) class ImDone(Exception): diff --git a/rpython/jit/backend/model.py b/rpython/jit/backend/model.py --- a/rpython/jit/backend/model.py +++ b/rpython/jit/backend/model.py @@ -194,11 +194,18 @@ def typedescrof(self, TYPE): raise NotImplementedError + def unpack_arraydescr_size(self, arraydescr): + """ + Return basesize, itemsize, is_signed + """ + raise NotImplementedError + @staticmethod def cast_int_to_ptr(x, TYPE): x = llmemory.cast_int_to_adr(x) return llmemory.cast_adr_to_ptr(x, TYPE) + # ---------- the backend-dependent operations ---------- # lltype specific operations @@ -235,6 +242,8 @@ raise NotImplementedError def bh_newunicode(self, length): raise NotImplementedError + def bh_new_raw_buffer(self, size): + raise NotImplementedError def bh_arraylen_gc(self, array, arraydescr): raise NotImplementedError diff --git a/rpython/jit/backend/test/runner_test.py b/rpython/jit/backend/test/runner_test.py --- a/rpython/jit/backend/test/runner_test.py +++ b/rpython/jit/backend/test/runner_test.py @@ -348,7 +348,7 @@ i0 = BoxInt() class UntouchableFailDescr(AbstractFailDescr): final_descr = True - + def __setattr__(self, name, value): if (name == 'index' or name == '_carry_around_for_tests' or name == '_TYPE' or name == '_cpu'): @@ -2832,6 +2832,11 @@ assert not called def test_assembler_call_propagate_exc(self): + from rpython.jit.backend.llsupport.llmodel import AbstractLLCPU + + if not isinstance(self.cpu, AbstractLLCPU): + py.test.skip("llgraph can't fake exceptions well enough, give up") + excdescr = BasicFailDescr(666) self.cpu.propagate_exception_descr = excdescr self.cpu.setup_once() # xxx redo it, because we added @@ -3420,7 +3425,7 @@ calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, effectinfo) testcases = [(4.0, 2.0), (6.25, 2.5)] for arg, expected in testcases: - res = self.execute_operation(rop.CALL, + res = self.execute_operation(rop.CALL, [funcbox, boxfloat(arg)], 'float', descr=calldescr) assert res.getfloat() == expected @@ -3776,7 +3781,7 @@ # memory assert values[0] == 0 - def test_compile_bridge_while_running(self): + def test_compile_bridge_while_running(self): def func(): bridge = parse(""" [i1, i2, px] @@ -3823,9 +3828,9 @@ func2_ptr = llhelper(FPTR2, func2) calldescr2 = cpu.calldescrof(FUNC2, FUNC2.ARGS, FUNC2.RESULT, EffectInfo.MOST_GENERAL) - + faildescr = BasicFailDescr(0) - + looptoken = JitCellToken() loop = parse(""" [i0, i1, i2] @@ -3841,7 +3846,7 @@ if not isinstance(self.cpu, AbstractLLCPU): py.test.skip("pointless test on non-asm") - + frame = lltype.cast_opaque_ptr(jitframe.JITFRAMEPTR, frame) assert len(frame.jf_frame) == frame.jf_frame_info.jfi_frame_depth ref = self.cpu.get_ref_value(frame, 9) @@ -3903,7 +3908,7 @@ 'calldescr': calldescr, 'faildescr': faildescr, 'finaldescr2': BasicFinalDescr(1)}) - + self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken) frame = self.cpu.execute_token(looptoken, 1, 2, 3) descr = self.cpu.get_latest_descr(frame) diff --git a/rpython/jit/codewriter/effectinfo.py b/rpython/jit/codewriter/effectinfo.py --- a/rpython/jit/codewriter/effectinfo.py +++ b/rpython/jit/codewriter/effectinfo.py @@ -76,14 +76,14 @@ # OS_MATH_SQRT = 100 # - OS_RAW_MALLOC_VARSIZE = 110 + OS_RAW_MALLOC_VARSIZE_CHAR = 110 OS_RAW_FREE = 111 OS_JIT_FORCE_VIRTUAL = 120 # for debugging: _OS_CANRAISE = set([OS_NONE, OS_STR2UNICODE, OS_LIBFFI_CALL, - OS_RAW_MALLOC_VARSIZE, OS_JIT_FORCE_VIRTUAL]) + OS_RAW_MALLOC_VARSIZE_CHAR, OS_JIT_FORCE_VIRTUAL]) def __new__(cls, readonly_descrs_fields, readonly_descrs_arrays, write_descrs_fields, write_descrs_arrays, diff --git a/rpython/jit/codewriter/jtransform.py b/rpython/jit/codewriter/jtransform.py --- a/rpython/jit/codewriter/jtransform.py +++ b/rpython/jit/codewriter/jtransform.py @@ -539,9 +539,11 @@ name += '_no_track_allocation' op1 = self.prepare_builtin_call(op, name, args, (TYPE,), TYPE) if name == 'raw_malloc_varsize': - return self._handle_oopspec_call(op1, args, - EffectInfo.OS_RAW_MALLOC_VARSIZE, - EffectInfo.EF_CAN_RAISE) + ITEMTYPE = op.args[0].value.OF + if ITEMTYPE == lltype.Char: + return self._handle_oopspec_call(op1, args, + EffectInfo.OS_RAW_MALLOC_VARSIZE_CHAR, + EffectInfo.EF_CAN_RAISE) return self.rewrite_op_direct_call(op1) def rewrite_op_malloc_varsize(self, op): diff --git a/rpython/jit/codewriter/test/test_jtransform.py b/rpython/jit/codewriter/test/test_jtransform.py --- a/rpython/jit/codewriter/test/test_jtransform.py +++ b/rpython/jit/codewriter/test/test_jtransform.py @@ -126,7 +126,7 @@ INT = lltype.Signed UNICHAR = lltype.UniChar FLOAT = lltype.Float - ARRAYPTR = rffi.CArrayPtr(lltype.Signed) + ARRAYPTR = rffi.CArrayPtr(lltype.Char) argtypes = { EI.OS_MATH_SQRT: ([FLOAT], FLOAT), EI.OS_STR2UNICODE:([PSTR], PUNICODE), @@ -143,7 +143,7 @@ EI.OS_UNIEQ_NONNULL_CHAR: ([PUNICODE, UNICHAR], INT), EI.OS_UNIEQ_CHECKNULL_CHAR: ([PUNICODE, UNICHAR], INT), EI.OS_UNIEQ_LENGTHOK: ([PUNICODE, PUNICODE], INT), - EI.OS_RAW_MALLOC_VARSIZE: ([INT], ARRAYPTR), + EI.OS_RAW_MALLOC_VARSIZE_CHAR: ([INT], ARRAYPTR), EI.OS_RAW_FREE: ([ARRAYPTR], lltype.Void), } argtypes = argtypes[oopspecindex] @@ -151,7 +151,7 @@ assert argtypes[1] == op.result.concretetype if oopspecindex == EI.OS_STR2UNICODE: assert extraeffect == EI.EF_ELIDABLE_CAN_RAISE - elif oopspecindex == EI.OS_RAW_MALLOC_VARSIZE: + elif oopspecindex == EI.OS_RAW_MALLOC_VARSIZE_CHAR: assert extraeffect == EI.EF_CAN_RAISE elif oopspecindex == EI.OS_RAW_FREE: assert extraeffect == EI.EF_CANNOT_RAISE @@ -161,7 +161,7 @@ def calldescr_canraise(self, calldescr): EI = effectinfo.EffectInfo - if calldescr == 'calldescr-%d' % EI.OS_RAW_MALLOC_VARSIZE: + if calldescr == 'calldescr-%d' % EI.OS_RAW_MALLOC_VARSIZE_CHAR: return True return False @@ -555,7 +555,7 @@ assert op1.args == [] def test_raw_malloc(): - S = rffi.CArray(lltype.Signed) + S = rffi.CArray(lltype.Char) v1 = varoftype(lltype.Signed) v = varoftype(lltype.Ptr(S)) flags = Constant({'flavor': 'raw'}, lltype.Void) @@ -566,7 +566,7 @@ assert op0.opname == 'residual_call_ir_i' assert op0.args[0].value == 'raw_malloc_varsize' # pseudo-function as a str assert (op0.args[-1] == 'calldescr-%d' % - effectinfo.EffectInfo.OS_RAW_MALLOC_VARSIZE) + effectinfo.EffectInfo.OS_RAW_MALLOC_VARSIZE_CHAR) assert op1.opname == '-live-' assert op1.args == [] @@ -608,7 +608,7 @@ assert op1.args == [] def test_raw_free(): - S = rffi.CArray(lltype.Signed) + S = rffi.CArray(lltype.Char) flags = Constant({'flavor': 'raw', 'track_allocation': True}, lltype.Void) op = SpaceOperation('free', [varoftype(lltype.Ptr(S)), flags], diff --git a/rpython/jit/metainterp/compile.py b/rpython/jit/metainterp/compile.py --- a/rpython/jit/metainterp/compile.py +++ b/rpython/jit/metainterp/compile.py @@ -15,7 +15,7 @@ from rpython.jit.metainterp import history, resume from rpython.jit.metainterp.optimize import InvalidLoop from rpython.jit.metainterp.inliner import Inliner -from rpython.jit.metainterp.resume import NUMBERING, PENDINGFIELDSP +from rpython.jit.metainterp.resume import NUMBERING, PENDINGFIELDSP, ResumeDataDirectReader from rpython.jit.codewriter import heaptracker, longlong def giveup(): @@ -656,9 +656,9 @@ class AllVirtuals: llopaque = True - list = [resume.ResumeDataDirectReader.virtual_default] # annotation hack - def __init__(self, list): - self.list = list + cache = None + def __init__(self, cache): + self.cache = cache def hide(self, cpu): ptr = cpu.ts.cast_instance_to_base_ref(self) return cpu.ts.cast_to_ref(ptr) @@ -682,9 +682,9 @@ from rpython.jit.metainterp.blackhole import resume_in_blackhole hidden_all_virtuals = metainterp_sd.cpu.get_savedata_ref(deadframe) obj = AllVirtuals.show(metainterp_sd.cpu, hidden_all_virtuals) - all_virtuals = obj.list + all_virtuals = obj.cache if all_virtuals is None: - all_virtuals = [] + all_virtuals = ResumeDataDirectReader.VirtualCache([], []) assert jitdriver_sd is self.jitdriver_sd resume_in_blackhole(metainterp_sd, jitdriver_sd, self, deadframe, all_virtuals) diff --git a/rpython/jit/metainterp/history.py b/rpython/jit/metainterp/history.py --- a/rpython/jit/metainterp/history.py +++ b/rpython/jit/metainterp/history.py @@ -191,7 +191,6 @@ def get_jitcode_for_class(self, oocls): return self.jitcodes[oocls] - class Const(AbstractValue): __slots__ = () diff --git a/rpython/jit/metainterp/optimizeopt/earlyforce.py b/rpython/jit/metainterp/optimizeopt/earlyforce.py --- a/rpython/jit/metainterp/optimizeopt/earlyforce.py +++ b/rpython/jit/metainterp/optimizeopt/earlyforce.py @@ -1,15 +1,26 @@ +from rpython.jit.codewriter.effectinfo import EffectInfo from rpython.jit.metainterp.optimizeopt.optimizer import Optimization from rpython.jit.metainterp.optimizeopt.vstring import VAbstractStringValue from rpython.jit.metainterp.resoperation import rop, ResOperation +def is_raw_free(op, opnum): + if opnum != rop.CALL: + return False + einfo = op.getdescr().get_extra_info() + return einfo.oopspecindex == EffectInfo.OS_RAW_FREE + + class OptEarlyForce(Optimization): def propagate_forward(self, op): opnum = op.getopnum() + if (opnum != rop.SETFIELD_GC and opnum != rop.SETARRAYITEM_GC and + opnum != rop.SETARRAYITEM_RAW and opnum != rop.QUASIIMMUT_FIELD and opnum != rop.SAME_AS and - opnum != rop.MARK_OPAQUE_PTR): + opnum != rop.MARK_OPAQUE_PTR and + not is_raw_free(op, opnum)): for arg in op.getarglist(): if arg in self.optimizer.values: diff --git a/rpython/jit/metainterp/optimizeopt/optimizer.py b/rpython/jit/metainterp/optimizeopt/optimizer.py --- a/rpython/jit/metainterp/optimizeopt/optimizer.py +++ b/rpython/jit/metainterp/optimizeopt/optimizer.py @@ -231,6 +231,12 @@ def setitem(self, index, value): raise NotImplementedError + def getitem_raw(self, offset, length, descr): + raise NotImplementedError + + def setitem_raw(self, offset, length, descr, value): + raise NotImplementedError + def getinteriorfield(self, index, ofs, default): raise NotImplementedError diff --git a/rpython/jit/metainterp/optimizeopt/rawbuffer.py b/rpython/jit/metainterp/optimizeopt/rawbuffer.py new file mode 100644 --- /dev/null +++ b/rpython/jit/metainterp/optimizeopt/rawbuffer.py @@ -0,0 +1,134 @@ +from rpython.rlib.debug import debug_start, debug_stop, debug_print +from rpython.rlib.objectmodel import compute_unique_id, we_are_translated + +class InvalidRawOperation(Exception): + pass + +class InvalidRawWrite(InvalidRawOperation): + pass + +class InvalidRawRead(InvalidRawOperation): + pass + +class RawBuffer(object): + def __init__(self, cpu, logops=None): + # the following lists represents the writes in the buffer: values[i] + # is the value of length lengths[i] stored at offset[i]. + # + # the invariant is that they are ordered by offset, and that + # offset[i]+length[i] <= offset[i+1], i.e. that the writes never + # overlaps + self.cpu = cpu + self.logops = logops + self.offsets = [] + self.lengths = [] + self.descrs = [] + self.values = [] + + def _get_memory(self): + """ + NOT_RPYTHON + for testing only + """ + return zip(self.offsets, self.lengths, self.descrs, self.values) + + def _repr_of_descr(self, descr): + if self.logops: + s = self.logops.repr_of_descr(descr) + else: + s = str(descr) + s += " at %d" % compute_unique_id(descr) + return s + + def _repr_of_value(self, value): + if not we_are_translated() and isinstance(value, str): + return value # for tests + if self.logops: + s = self.logops.repr_of_arg(value.box) + else: + s = str(value.box) + s += " at %d" % compute_unique_id(value.box) + return s + + def _dump_to_log(self): + debug_print("RawBuffer state") + debug_print("offset, length, descr, box") + debug_print("(box == None means that the value is still virtual)") + for i in range(len(self.offsets)): + descr = self._repr_of_descr(self.descrs[i]) + box = self._repr_of_value(self.values[i]) + debug_print("%d, %d, %s, %s" % (self.offsets[i], self.lengths[i], descr, box)) + + def _invalid_write(self, message, offset, length, descr, value): + debug_start('jit-log-rawbuffer') + debug_print('Invalid write: %s' % message) + debug_print(" offset: %d" % offset) + debug_print(" length: %d" % length) + debug_print(" descr: %s" % self._repr_of_descr(descr)) + debug_print(" value: %s" % self._repr_of_value(value)) + self._dump_to_log() + debug_stop('jit-log-rawbuffer') + raise InvalidRawWrite + + def _invalid_read(self, message, offset, length, descr): + debug_start('jit-log-rawbuffer') + debug_print('Invalid read: %s' % message) + debug_print(" offset: %d" % offset) + debug_print(" length: %d" % length) + debug_print(" descr: %s" % self._repr_of_descr(descr)) + self._dump_to_log() + debug_stop('jit-log-rawbuffer') + raise InvalidRawRead + + def _descrs_are_compatible(self, d1, d2): + # two arraydescrs are compatible if they have the same basesize, + # itemsize and sign, even if they are not identical + unpack = self.cpu.unpack_arraydescr_size + return unpack(d1) == unpack(d2) + + def write_value(self, offset, length, descr, value): + i = 0 + N = len(self.offsets) + while i < N: + if self.offsets[i] == offset: + if (length != self.lengths[i] or not + self._descrs_are_compatible(descr, self.descrs[i])): + # in theory we could add support for the cases in which + # the length or descr is different, but I don't think we + # need it in practice + self._invalid_write('length or descr not compatible', + offset, length, descr, value) + # update the value at this offset + self.values[i] = value + return + elif self.offsets[i] > offset: + break + i += 1 + # + if i < len(self.offsets) and offset+length > self.offsets[i]: + self._invalid_write("overlap with next bytes", + offset, length, descr, value) + if i > 0 and self.offsets[i-1]+self.lengths[i-1] > offset: + self._invalid_write("overlap with previous bytes", + offset, length, descr, value) + # insert a new value at offset + self.offsets.insert(i, offset) + self.lengths.insert(i, length) + self.descrs.insert(i, descr) + self.values.insert(i, value) + + def read_value(self, offset, length, descr): + i = 0 + N = len(self.offsets) + while i < N: + if self.offsets[i] == offset: + if (length != self.lengths[i] or + not self._descrs_are_compatible(descr, self.descrs[i])): + self._invalid_read('length or descr not compatible', + offset, length, descr) + return self.values[i] + i += 1 + # memory location not found: this means we are reading from + # uninitialized memory, give up the optimization + self._invalid_read('uninitialized memory', + offset, length, descr) diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py --- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py @@ -770,8 +770,6 @@ """ self.optimize_loop(ops, expected) - - def test_p123_simple(self): ops = """ [i1, p2, p3] @@ -1730,6 +1728,175 @@ # We cannot track virtuals that survive for more than two iterations. self.optimize_loop(ops, expected, preamble) + def test_virtual_raw_malloc(self): + ops = """ + [i1] + i2 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) + i3 = getarrayitem_raw(i2, 0, descr=rawarraydescr) + call('free', i2, descr=raw_free_descr) + jump(i3) + """ + expected = """ + [i1] + jump(i1) + """ + self.optimize_loop(ops, expected) + + def test_virtual_raw_malloc_force(self): + ops = """ + [i1] + i2 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i2, 0, i1, descr=rawarraydescr_char) + setarrayitem_raw(i2, 2, 456, descr=rawarraydescr_char) + setarrayitem_raw(i2, 1, 123, descr=rawarraydescr_char) + label('foo') # we expect the buffer to be forced *after* the label + escape(i2) + call('free', i2, descr=raw_free_descr) + jump(i1) + """ + expected = """ + [i1] + label('foo') + i2 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i2, 0, i1, descr=rawarraydescr_char) + i3 = int_add(i2, 1) + setarrayitem_raw(i3, 0, 123, descr=rawarraydescr_char) + i4 = int_add(i2, 2) + setarrayitem_raw(i4, 0, 456, descr=rawarraydescr_char) + escape(i2) + call('free', i2, descr=raw_free_descr) + jump(i1) + """ + self.optimize_loop(ops, expected) + + def test_virtual_raw_malloc_invalid_write_force(self): + ops = """ + [i1] + i2 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) + label('foo') # we expect the buffer to be forced *after* the label + setarrayitem_raw(i2, 2, 456, descr=rawarraydescr_char) # overlap! + call('free', i2, descr=raw_free_descr) + jump(i1) + """ + expected = """ + [i1] + label('foo') + i2 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) + setarrayitem_raw(i2, 2, 456, descr=rawarraydescr_char) + call('free', i2, descr=raw_free_descr) + jump(i1) + """ + self.optimize_loop(ops, expected) + + def test_virtual_raw_malloc_invalid_read_force(self): + ops = """ + [i1] + i2 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) + label('foo') # we expect the buffer to be forced *after* the label + i3 = getarrayitem_raw(i2, 0, descr=rawarraydescr_char) + call('free', i2, descr=raw_free_descr) + jump(i1) + """ + expected = """ + [i1] + label('foo') + i2 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) + i3 = getarrayitem_raw(i2, 0, descr=rawarraydescr_char) + call('free', i2, descr=raw_free_descr) + jump(i1) + """ + self.optimize_loop(ops, expected) + + def test_virtual_raw_slice(self): + ops = """ + [i0, i1] + i2 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i2, 0, 42, descr=rawarraydescr_char) + i3 = int_add(i2, 1) # get a slice of the original buffer + setarrayitem_raw(i3, 0, 4242, descr=rawarraydescr) # write to the slice + i4 = getarrayitem_raw(i2, 0, descr=rawarraydescr_char) + i5 = int_add(i2, 1) + i6 = getarrayitem_raw(i5, 0, descr=rawarraydescr) + call('free', i2, descr=raw_free_descr) + jump(i0, i1) + """ + expected = """ + [i0, i1] + jump(i0, i1) + """ + self.optimize_loop(ops, expected) + + def test_virtual_raw_slice_of_a_raw_slice(self): + ops = """ + [i0, i1] + i2 = call('malloc', 10, descr=raw_malloc_descr) + i3 = int_add(i2, 1) # get a slice of the original buffer + i4 = int_add(i3, 1) # get a slice of a slice + setarrayitem_raw(i4, 0, i1, descr=rawarraydescr_char) # write to the slice + i5 = getarrayitem_raw(i2, 2, descr=rawarraydescr_char) + call('free', i2, descr=raw_free_descr) + jump(i0, i5) + """ + expected = """ + [i0, i1] + jump(i0, i1) + """ + self.optimize_loop(ops, expected) + + def test_virtual_raw_slice_force(self): + ops = """ + [i0, i1] + i2 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i2, 0, 42, descr=rawarraydescr_char) + i3 = int_add(i2, 1) # get a slice of the original buffer + setarrayitem_raw(i3, 4, 4242, descr=rawarraydescr_char) # write to the slice + label('foo') + escape(i3) + jump(i0, i1) + """ + expected = """ + [i0, i1] + label('foo') + # these ops are generated by VirtualRawBufferValue._really_force + i2 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i2, 0, 42, descr=rawarraydescr_char) + i3 = int_add(i2, 5) # 1+4*sizeof(char) + setarrayitem_raw(i3, 0, 4242, descr=rawarraydescr_char) + # this is generated by VirtualRawSliceValue._really_force + i4 = int_add(i2, 1) + escape(i4) + jump(i0, i1) + """ + self.optimize_loop(ops, expected) + + def test_virtual_raw_malloc_virtualstate(self): + ops = """ + [i0] + i1 = getarrayitem_raw(i0, 0, descr=rawarraydescr) + i2 = int_add(i1, 1) + call('free', i0, descr=raw_free_descr) + i3 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i3, 0, i2, descr=rawarraydescr) + label('foo') + jump(i3) + """ + expected = """ + [i0] + i1 = getarrayitem_raw(i0, 0, descr=rawarraydescr) + i2 = int_add(i1, 1) + call('free', i0, descr=raw_free_descr) + label('foo') + i3 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i3, 0, i2, descr=rawarraydescr) + jump(i3) + """ + self.optimize_loop(ops, expected) + def test_duplicate_getfield_1(self): ops = """ [p1, p2] diff --git a/rpython/jit/metainterp/optimizeopt/test/test_rawbuffer.py b/rpython/jit/metainterp/optimizeopt/test/test_rawbuffer.py new file mode 100644 --- /dev/null +++ b/rpython/jit/metainterp/optimizeopt/test/test_rawbuffer.py @@ -0,0 +1,90 @@ +import py +from rpython.jit.metainterp.optimizeopt.rawbuffer import (InvalidRawWrite, + InvalidRawRead, RawBuffer) + +class FakeCPU(object): + def unpack_arraydescr_size(self, descr): + return descr, 'foo', 'bar' + +def test_write_value(): + buf = RawBuffer(FakeCPU()) + buf.write_value(8, 4, 'descr3', 'three') + buf.write_value(0, 4, 'descr1', 'one') + buf.write_value(4, 2, 'descr2', 'two') + buf.write_value(12, 2, 'descr4', 'four') + assert buf._get_memory() == [ + ( 0, 4, 'descr1', 'one'), + ( 4, 2, 'descr2', 'two'), + ( 8, 4, 'descr3', 'three'), + (12, 2, 'descr4', 'four'), + ] + # + +def test_write_value_update(): + buf = RawBuffer(FakeCPU()) + buf.write_value(0, 4, 'descr', 'one') + buf.write_value(4, 2, 'descr', 'two') + buf.write_value(0, 4, 'descr', 'ONE') + assert buf._get_memory() == [ + ( 0, 4, 'descr', 'ONE'), + ( 4, 2, 'descr', 'two'), + ] + +def test_write_value_invalid_length(): + buf = RawBuffer(FakeCPU()) + buf.write_value(0, 4, 'descr1', 'one') + with py.test.raises(InvalidRawWrite): + buf.write_value(0, 5, 'descr1', 'two') + with py.test.raises(InvalidRawWrite): + buf.write_value(0, 4, 'descr2', 'two') + + +def test_write_value_overlapping_next(): + buf = RawBuffer(FakeCPU()) + buf.write_value(0, 4, 'descr', 'one') + buf.write_value(6, 4, 'descr', 'two') + with py.test.raises(InvalidRawWrite): + buf.write_value(4, 4, 'descr', 'three') + +def test_write_value_overlapping_prev(): + buf = RawBuffer(FakeCPU()) + buf.write_value(0, 4, 'descr', 'one') + with py.test.raises(InvalidRawWrite): + buf.write_value(2, 1, 'descr', 'two') + +def test_read_value(): + buf = RawBuffer(FakeCPU()) + buf.write_value(0, 4, 'descr', 'one') + buf.write_value(4, 4, 'descr', 'two') + assert buf.read_value(0, 4, 'descr') == 'one' + assert buf.read_value(4, 4, 'descr') == 'two' + with py.test.raises(InvalidRawRead): + buf.read_value(0, 2, 'descr') + with py.test.raises(InvalidRawRead): + buf.read_value(8, 2, 'descr') + with py.test.raises(InvalidRawRead): + buf.read_value(0, 4, 'another descr') + +def test_unpack_descrs(): + ArrayS_8_1 = object() + ArrayS_8_2 = object() + ArrayU_8 = object() + + class FakeCPU(object): + def unpack_arraydescr_size(self, descr): + if descr in (ArrayS_8_1, ArrayS_8_2): + return 0, 8, True + return 0, 8, False + + buf = RawBuffer(FakeCPU()) + buf.write_value(0, 4, ArrayS_8_1, 'one') + assert buf.read_value(0, 4, ArrayS_8_1) == 'one' + assert buf.read_value(0, 4, ArrayS_8_2) == 'one' # with a non-identical descr + # + buf.write_value(0, 4, ArrayS_8_2, 'two') # with a non-identical descr + assert buf.read_value(0, 4, ArrayS_8_1) == 'two' + # + with py.test.raises(InvalidRawRead): + buf.read_value(0, 4, ArrayU_8) + with py.test.raises(InvalidRawWrite): + buf.write_value(0, 4, ArrayU_8, 'three') diff --git a/rpython/jit/metainterp/optimizeopt/test/test_util.py b/rpython/jit/metainterp/optimizeopt/test/test_util.py --- a/rpython/jit/metainterp/optimizeopt/test/test_util.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_util.py @@ -196,6 +196,15 @@ EffectInfo.EF_CANNOT_RAISE, oopspecindex=EffectInfo.OS_ARRAYCOPY)) + raw_malloc_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, + EffectInfo([], [], [], [], + EffectInfo.EF_CAN_RAISE, + oopspecindex=EffectInfo.OS_RAW_MALLOC_VARSIZE_CHAR)) + raw_free_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, + EffectInfo([], [], [], [], + EffectInfo.EF_CANNOT_RAISE, + oopspecindex=EffectInfo.OS_RAW_FREE)) + # array of structs (complex data) complexarray = lltype.GcArray( @@ -208,6 +217,12 @@ complexrealdescr = cpu.interiorfielddescrof(complexarray, "real") compleximagdescr = cpu.interiorfielddescrof(complexarray, "imag") + rawarraydescr = cpu.arraydescrof(lltype.Array(lltype.Signed, + hints={'nolength': True})) + rawarraydescr_char = cpu.arraydescrof(lltype.Array(lltype.Char, + hints={'nolength': True})) + + for _name, _os in [ ('strconcatdescr', 'OS_STR_CONCAT'), ('strslicedescr', 'OS_STR_SLICE'), diff --git a/rpython/jit/metainterp/optimizeopt/virtualize.py b/rpython/jit/metainterp/optimizeopt/virtualize.py --- a/rpython/jit/metainterp/optimizeopt/virtualize.py +++ b/rpython/jit/metainterp/optimizeopt/virtualize.py @@ -6,7 +6,9 @@ from rpython.jit.metainterp.optimizeopt import optimizer from rpython.jit.metainterp.optimizeopt.optimizer import OptValue, REMOVED from rpython.jit.metainterp.optimizeopt.util import (make_dispatcher_method, - descrlist_dict, sort_descrs) + descrlist_dict, sort_descrs) + +from rpython.jit.metainterp.optimizeopt.rawbuffer import RawBuffer, InvalidRawOperation from rpython.jit.metainterp.resoperation import rop, ResOperation from rpython.rlib.objectmodel import we_are_translated @@ -236,8 +238,36 @@ def _get_descr(self): return self.structdescr +class AbstractVArrayValue(AbstractVirtualValue): + """ + Base class for VArrayValue (for normal GC arrays) and VRawBufferValue (for + malloc()ed memory) + """ -class VArrayValue(AbstractVirtualValue): + def getlength(self): + return len(self._items) + + def get_item_value(self, i): + raise NotImplementedError + + def set_item_value(self, i, newval): + raise NotImplementedError + + def get_args_for_fail(self, modifier): + if self.box is None and not modifier.already_seen_virtual(self.keybox): + # checks for recursion: it is False unless + # we have already seen the very same keybox + itemboxes = [] + for i in range(self.getlength()): + itemvalue = self.get_item_value(i) + itemboxes.append(itemvalue.get_key_box()) + modifier.register_virtual_fields(self.keybox, itemboxes) + for i in range(self.getlength()): + itemvalue = self.get_item_value(i) + itemvalue.get_args_for_fail(modifier) + + +class VArrayValue(AbstractVArrayValue): def __init__(self, arraydescr, constvalue, size, keybox, source_op=None): AbstractVirtualValue.__init__(self, keybox, source_op) @@ -248,6 +278,12 @@ def getlength(self): return len(self._items) + def get_item_value(self, i): + return self._items[i] + + def set_item_value(self, i, newval): + self._items[i] = newval + def getitem(self, index): res = self._items[index] return res @@ -257,11 +293,16 @@ self._items[index] = itemvalue def force_at_end_of_preamble(self, already_forced, optforce): + # note that this method is on VArrayValue instead of + # AbstractVArrayValue because we do not want to support virtualstate + # for rawbuffers for now if self in already_forced: return self already_forced[self] = self - for index in range(len(self._items)): - self._items[index] = self._items[index].force_at_end_of_preamble(already_forced, optforce) + for index in range(self.getlength()): + itemval = self.get_item_value(index) + itemval = itemval.force_at_end_of_preamble(already_forced, optforce) + self.set_item_value(index, itemval) return self def _really_force(self, optforce): @@ -281,29 +322,16 @@ descr=self.arraydescr) optforce.emit_operation(op) - def get_args_for_fail(self, modifier): - if self.box is None and not modifier.already_seen_virtual(self.keybox): - # checks for recursion: it is False unless - # we have already seen the very same keybox - itemboxes = [] - for itemvalue in self._items: - itemboxes.append(itemvalue.get_key_box()) - modifier.register_virtual_fields(self.keybox, itemboxes) - for itemvalue in self._items: - itemvalue.get_args_for_fail(modifier) - def _make_virtual(self, modifier): return modifier.make_varray(self.arraydescr) + class VArrayStructValue(AbstractVirtualValue): def __init__(self, arraydescr, size, keybox, source_op=None): AbstractVirtualValue.__init__(self, keybox, source_op) self.arraydescr = arraydescr self._items = [{} for _ in xrange(size)] - def getlength(self): - return len(self._items) - def getinteriorfield(self, index, ofs, default): return self._items[index].get(ofs, default) @@ -363,6 +391,90 @@ return modifier.make_varraystruct(self.arraydescr, self._get_list_of_descrs()) +class VRawBufferValue(AbstractVArrayValue): + + def __init__(self, cpu, logops, size, keybox, source_op): + AbstractVirtualValue.__init__(self, keybox, source_op) + # note that size is unused, because we assume that the buffer is big + # enough to write/read everything we need. If it's not, it's undefined + # behavior anyway, although in theory we could probably detect such + # cases here + self.size = size + self.buffer = RawBuffer(cpu, logops) + + def getlength(self): + return len(self.buffer.values) + + def get_item_value(self, i): + return self.buffer.values[i] + + def set_item_value(self, i, newval): + self.buffer.values[i] = newval + + def getitem_raw(self, offset, length, descr): + return self.buffer.read_value(offset, length, descr) + + def setitem_raw(self, offset, length, descr, value): + self.buffer.write_value(offset, length, descr, value) + + def _really_force(self, optforce): + op = self.source_op + assert op is not None + if not we_are_translated(): + op.name = 'FORCE ' + self.source_op.name + optforce.emit_operation(self.source_op) + self.box = box = self.source_op.result + for i in range(len(self.buffer.offsets)): + # get a pointer to self.box+offset + offset = self.buffer.offsets[i] + if offset == 0: + arraybox = self.box + else: + arraybox = BoxInt() + op = ResOperation(rop.INT_ADD, + [self.box, ConstInt(offset)], arraybox) + optforce.emit_operation(op) + # + # write the value + descr = self.buffer.descrs[i] + itemvalue = self.buffer.values[i] + itembox = itemvalue.force_box(optforce) + op = ResOperation(rop.SETARRAYITEM_RAW, + [arraybox, ConstInt(0), itembox], None, + descr=descr) + optforce.emit_operation(op) + + def _make_virtual(self, modifier): + # I *think* we need to make a copy of offsets and descrs because we + # want a snapshot of the virtual state right now: if we grow more + # elements later, we don't want them to go in this virtual state + return modifier.make_vrawbuffer(self.size, + self.buffer.offsets[:], + self.buffer.descrs[:]) + + +class VRawSliceValue(AbstractVirtualValue): + + def __init__(self, rawbuffer_value, offset, keybox, source_op): + AbstractVirtualValue.__init__(self, keybox, source_op) + self.rawbuffer_value = rawbuffer_value + self.offset = offset + + def _really_force(self, optforce): + op = self.source_op + assert op is not None + if not we_are_translated(): + op.name = 'FORCE ' + self.source_op.name + self.box = self.source_op.result + self.rawbuffer_value.force_box(optforce) + optforce.emit_operation(op) + + def setitem_raw(self, offset, length, descr, value): + self.rawbuffer_value.setitem_raw(self.offset+offset, length, descr, value) + + def getitem_raw(self, offset, length, descr): + return self.rawbuffer_value.getitem_raw(self.offset+offset, length, descr) + class OptVirtualize(optimizer.Optimization): "Virtualize objects until they escape." @@ -388,6 +500,17 @@ self.make_equal_to(box, vvalue) return vvalue + def make_virtual_raw_memory(self, size, box, source_op): + logops = self.optimizer.loop.logops + vvalue = VRawBufferValue(self.optimizer.cpu, logops, size, box, source_op) + self.make_equal_to(box, vvalue) + return vvalue + + def make_virtual_raw_slice(self, rawbuffer_value, offset, box, source_op): + vvalue = VRawSliceValue(rawbuffer_value, offset, box, source_op) + self.make_equal_to(box, vvalue) + return vvalue + def optimize_GUARD_NO_EXCEPTION(self, op): if self.last_emitted_operation is REMOVED: return @@ -524,6 +647,43 @@ self.getvalue(op.result).ensure_nonnull() self.emit_operation(op) + def optimize_CALL(self, op): + effectinfo = op.getdescr().get_extra_info() + if effectinfo.oopspecindex == EffectInfo.OS_RAW_MALLOC_VARSIZE_CHAR: + self.do_RAW_MALLOC_VARSIZE_CHAR(op) + elif effectinfo.oopspecindex == EffectInfo.OS_RAW_FREE: + self.do_RAW_FREE(op) + else: + self.emit_operation(op) + + def do_RAW_MALLOC_VARSIZE_CHAR(self, op): + sizebox = op.getarg(1) + if not isinstance(sizebox, ConstInt): + self.emit_operation(op) + return + size = sizebox.value + self.make_virtual_raw_memory(size, op.result, op) + + def do_RAW_FREE(self, op): + value = self.getvalue(op.getarg(1)) + if value.is_virtual(): + return + self.emit_operation(op) + + def optimize_INT_ADD(self, op): + value = self.getvalue(op.getarg(0)) + offsetbox = self.get_constant_box(op.getarg(1)) + if value.is_virtual() and offsetbox is not None: + offset = offsetbox.getint() + if isinstance(value, VRawBufferValue): + self.make_virtual_raw_slice(value, offset, op.result, op) + return + elif isinstance(value, VRawSliceValue): + offset = offset + value.offset + self.make_virtual_raw_slice(value.rawbuffer_value, offset, op.result, op) + return + self.emit_operation(op) + def optimize_ARRAYLEN_GC(self, op): value = self.getvalue(op.getarg(0)) if value.is_virtual(): @@ -558,6 +718,48 @@ value.ensure_nonnull() self.emit_operation(op) + def _unpack_arrayitem_raw_op(self, op, indexbox): + index = indexbox.getint() + cpu = self.optimizer.cpu + descr = op.getdescr() + basesize, itemsize, _ = cpu.unpack_arraydescr_size(descr) + offset = basesize + (itemsize*index) + return offset, itemsize, descr + + def optimize_GETARRAYITEM_RAW(self, op): + value = self.getvalue(op.getarg(0)) + if value.is_virtual(): + indexbox = self.get_constant_box(op.getarg(1)) + if indexbox is not None: + offset, itemsize, descr = self._unpack_arrayitem_raw_op(op, indexbox) + try: + itemvalue = value.getitem_raw(offset, itemsize, descr) + self.make_equal_to(op.result, itemvalue) + except InvalidRawOperation: + box = value.force_box(self) + op.setarg(0, box) + self.emit_operation(op) + return + value.ensure_nonnull() + self.emit_operation(op) + + def optimize_SETARRAYITEM_RAW(self, op): + value = self.getvalue(op.getarg(0)) + if value.is_virtual(): + indexbox = self.get_constant_box(op.getarg(1)) + if indexbox is not None: + offset, itemsize, descr = self._unpack_arrayitem_raw_op(op, indexbox) + itemvalue = self.getvalue(op.getarg(2)) + try: + value.setitem_raw(offset, itemsize, descr, itemvalue) + except InvalidRawOperation: + box = value.force_box(self) + op.setarg(0, box) + self.emit_operation(op) + return + value.ensure_nonnull() + self.emit_operation(op) + def optimize_GETINTERIORFIELD_GC(self, op): value = self.getvalue(op.getarg(0)) if value.is_virtual(): diff --git a/rpython/jit/metainterp/optimizeopt/virtualstate.py b/rpython/jit/metainterp/optimizeopt/virtualstate.py --- a/rpython/jit/metainterp/optimizeopt/virtualstate.py +++ b/rpython/jit/metainterp/optimizeopt/virtualstate.py @@ -158,10 +158,16 @@ def debug_header(self, indent): debug_print(indent + 'VStructStateInfo(%d):' % self.position) + class VArrayStateInfo(AbstractVirtualStateInfo): + def __init__(self, arraydescr): self.arraydescr = arraydescr + def _generalization_of(self, other): + return (isinstance(other, VArrayStateInfo) and + self.arraydescr is other.arraydescr) + def generalization_of(self, other, renum, bad): assert self.position != -1 if self.position in renum: @@ -187,10 +193,6 @@ return False return True - def _generalization_of(self, other): - return (isinstance(other, VArrayStateInfo) and - self.arraydescr is other.arraydescr) - def enum_forced_boxes(self, boxes, value, optimizer): if not isinstance(value, virtualize.VArrayValue): raise BadVirtualState @@ -198,7 +200,7 @@ raise BadVirtualState for i in range(len(self.fieldstate)): try: - v = value._items[i] + v = value.get_item_value(i) except IndexError: raise BadVirtualState s = self.fieldstate[i] @@ -212,6 +214,8 @@ def debug_header(self, indent): debug_print(indent + 'VArrayStateInfo(%d):' % self.position) + + class VArrayStructStateInfo(AbstractVirtualStateInfo): def __init__(self, arraydescr, fielddescrs): self.arraydescr = arraydescr @@ -287,6 +291,7 @@ debug_print(indent + 'VArrayStructStateInfo(%d):' % self.position) + class NotVirtualStateInfo(AbstractVirtualStateInfo): def __init__(self, value, is_opaque=False): self.is_opaque = is_opaque @@ -579,6 +584,9 @@ def make_varraystruct(self, arraydescr, fielddescrs): return VArrayStructStateInfo(arraydescr, fielddescrs) + def make_vrawbuffer(self, size, offsets, descrs): + raise NotImplementedError + class BoxNotProducable(Exception): From noreply at buildbot.pypy.org Mon Apr 15 18:28:15 2013 From: noreply at buildbot.pypy.org (arigo) Date: Mon, 15 Apr 2013 18:28:15 +0200 (CEST) Subject: [pypy-commit] pypy default: Bah :-/ should we find a more general solution? Message-ID: <20130415162815.8B7931C313C@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63378:62c1ded9724a Date: 2013-04-15 18:27 +0200 http://bitbucket.org/pypy/pypy/changeset/62c1ded9724a/ Log: Bah :-/ should we find a more general solution? diff --git a/rpython/jit/backend/llsupport/test/test_gc_integration.py b/rpython/jit/backend/llsupport/test/test_gc_integration.py --- a/rpython/jit/backend/llsupport/test/test_gc_integration.py +++ b/rpython/jit/backend/llsupport/test/test_gc_integration.py @@ -537,6 +537,9 @@ self.S = S self.cpu = cpu + def teardown_method(self, meth): + rffi.aroundstate._cleanup_() + def test_shadowstack_call(self): cpu = self.cpu cpu.gc_ll_descr.init_nursery(100) From noreply at buildbot.pypy.org Mon Apr 15 19:12:26 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Mon, 15 Apr 2013 19:12:26 +0200 (CEST) Subject: [pypy-commit] pypy default: speed up sqlite3 when cursors aren't fetched to exhaustion Message-ID: <20130415171226.986E61C01FD@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63379:30ad7ec330d1 Date: 2013-04-15 13:11 -0400 http://bitbucket.org/pypy/pypy/changeset/30ad7ec330d1/ Log: speed up sqlite3 when cursors aren't fetched to exhaustion diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -1089,7 +1089,6 @@ try: next_row = self.__next_row except AttributeError: - self.__statement._reset() raise StopIteration del self.__next_row @@ -1097,11 +1096,12 @@ next_row = self.row_factory(self, next_row) ret = _lib.sqlite3_step(self.__statement._statement) - if ret not in (_lib.SQLITE_DONE, _lib.SQLITE_ROW): + if ret == _lib.SQLITE_ROW: + self.__next_row = self.__fetch_one_row() + else: self.__statement._reset() - raise self.__connection._get_exception(ret) - elif ret == _lib.SQLITE_ROW: - self.__next_row = self.__fetch_one_row() + if ret != _lib.SQLITE_DONE: + raise self.__connection._get_exception(ret) return next_row if sys.version_info[0] < 3: From noreply at buildbot.pypy.org Mon Apr 15 19:13:50 2013 From: noreply at buildbot.pypy.org (arigo) Date: Mon, 15 Apr 2013 19:13:50 +0200 (CEST) Subject: [pypy-commit] cffi default: Fix for issue 77: give cdatas __module__, __name__ and __doc__ attributes, Message-ID: <20130415171350.1A8D61C311F@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r1245:184ddf196151 Date: 2013-04-15 19:13 +0200 http://bitbucket.org/cffi/cffi/changeset/184ddf196151/ Log: Fix for issue 77: give cdatas __module__, __name__ and __doc__ attributes, for convenience with functools.wraps(). diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c --- a/c/_cffi_backend.c +++ b/c/_cffi_backend.c @@ -5096,6 +5096,15 @@ if (PyType_Ready(&MiniBuffer_Type) < 0) INITERROR; + v = PyString_FromString("_cffi_backend"); + if (v == NULL || PyDict_SetItemString(CData_Type.tp_dict, + "__module__", v) < 0) + INITERROR; + v = PyString_FromString(""); + if (v == NULL || PyDict_SetItemString(CData_Type.tp_dict, + "__name__", v) < 0) + INITERROR; + v = PyCapsule_New((void *)cffi_exports, "cffi", NULL); if (v == NULL || PyModule_AddObject(m, "_C_API", v) < 0) INITERROR; diff --git a/c/test_c.py b/c/test_c.py --- a/c/test_c.py +++ b/c/test_c.py @@ -2723,6 +2723,13 @@ c[1:3] = d assert list(c) == [0, 40, 50, 30, 0] +def test_cdata_name_module_doc(): + p = new_primitive_type("signed char") + x = cast(p, 17) + assert x.__module__ == '_cffi_backend' + assert x.__name__ == '' + assert hasattr(x, '__doc__') + def test_version(): # this test is here mostly for PyPy assert __version__ == "0.6" diff --git a/cffi/backend_ctypes.py b/cffi/backend_ctypes.py --- a/cffi/backend_ctypes.py +++ b/cffi/backend_ctypes.py @@ -16,6 +16,7 @@ class CTypesData(object): __metaclass__ = CTypesType __slots__ = ['__weakref__'] + __name__ = '' def __init__(self, *args): raise TypeError("cannot instantiate %r" % (self.__class__,)) diff --git a/testing/test_function.py b/testing/test_function.py --- a/testing/test_function.py +++ b/testing/test_function.py @@ -365,3 +365,19 @@ """) m = ffi.dlopen("m") assert not hasattr(m, 'nonexistent') + + def test_wraps_from_stdlib(self): + import functools + ffi = FFI(backend=self.Backend()) + ffi.cdef(""" + double sin(double x); + """) + def my_decorator(f): + @functools.wraps(f) + def wrapper(*args): + return f(*args) + 100 + return wrapper + m = ffi.dlopen("m") + sin100 = my_decorator(m.sin) + x = sin100(1.23) + assert x == math.sin(1.23) + 100 From noreply at buildbot.pypy.org Mon Apr 15 19:16:11 2013 From: noreply at buildbot.pypy.org (arigo) Date: Mon, 15 Apr 2013 19:16:11 +0200 (CEST) Subject: [pypy-commit] pypy default: Update to cffi/184ddf196151 Message-ID: <20130415171611.CCC5D1C311F@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63380:237b4e412bd5 Date: 2013-04-15 19:15 +0200 http://bitbucket.org/pypy/pypy/changeset/237b4e412bd5/ Log: Update to cffi/184ddf196151 diff --git a/pypy/module/_cffi_backend/cdataobj.py b/pypy/module/_cffi_backend/cdataobj.py --- a/pypy/module/_cffi_backend/cdataobj.py +++ b/pypy/module/_cffi_backend/cdataobj.py @@ -394,6 +394,7 @@ W_CData.typedef = TypeDef( 'CData', __module__ = '_cffi_backend', + __name__ = '', __repr__ = interp2app(W_CData.repr), __nonzero__ = interp2app(W_CData.nonzero), __int__ = interp2app(W_CData.int), diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py --- a/pypy/module/_cffi_backend/test/_backend_test_c.py +++ b/pypy/module/_cffi_backend/test/_backend_test_c.py @@ -2712,6 +2712,13 @@ c[1:3] = d assert list(c) == [0, 40, 50, 30, 0] +def test_cdata_name_module_doc(): + p = new_primitive_type("signed char") + x = cast(p, 17) + assert x.__module__ == '_cffi_backend' + assert x.__name__ == '' + assert hasattr(x, '__doc__') + def test_version(): # this test is here mostly for PyPy assert __version__ == "0.6" From noreply at buildbot.pypy.org Mon Apr 15 19:55:25 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Mon, 15 Apr 2013 19:55:25 +0200 (CEST) Subject: [pypy-commit] pypy default: clean up this logic to match __next__ Message-ID: <20130415175525.AA8651C323F@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63381:fea5257cc5ba Date: 2013-04-15 13:54 -0400 http://bitbucket.org/pypy/pypy/changeset/fea5257cc5ba/ Log: clean up this logic to match __next__ diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -998,17 +998,18 @@ # Actually execute the SQL statement ret = _lib.sqlite3_step(self.__statement._statement) - if ret not in (_lib.SQLITE_DONE, _lib.SQLITE_ROW): - self.__statement._reset() - raise self.__connection._get_exception(ret) if ret == _lib.SQLITE_ROW: if multiple: raise ProgrammingError("executemany() can only execute DML statements.") self.__build_row_cast_map() self.__next_row = self.__fetch_one_row() - elif ret == _lib.SQLITE_DONE and not multiple: + elif ret == _lib.SQLITE_DONE: + if not multiple: + self.__statement._reset() + else: self.__statement._reset() + raise self.__connection._get_exception(ret) if self.__statement._type in ("UPDATE", "DELETE", "INSERT", "REPLACE"): if self.__rowcount == -1: From noreply at buildbot.pypy.org Mon Apr 15 20:18:55 2013 From: noreply at buildbot.pypy.org (fijal) Date: Mon, 15 Apr 2013 20:18:55 +0200 (CEST) Subject: [pypy-commit] pypy fast-newarray: make this test pass Message-ID: <20130415181855.7D6051C01FD@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: fast-newarray Changeset: r63382:c28bf44097c6 Date: 2013-04-15 18:13 +0200 http://bitbucket.org/pypy/pypy/changeset/c28bf44097c6/ Log: make this test pass diff --git a/rpython/jit/backend/llsupport/rewrite.py b/rpython/jit/backend/llsupport/rewrite.py --- a/rpython/jit/backend/llsupport/rewrite.py +++ b/rpython/jit/backend/llsupport/rewrite.py @@ -128,6 +128,9 @@ elif (self.gc_ll_descr.can_use_nursery_malloc(1) and self.gen_malloc_nursery_varsize(arraydescr.itemsize, v_length, op.result, arraydescr)): + # note that we cannot initialize tid here, because the array + # might end up being allocated by malloc_external or some + # stuff that initializes GC header fields differently self.gen_initialize_len(op.result, v_length, arraydescr.lendescr) return if (total_size >= 0 and diff --git a/rpython/jit/backend/llsupport/test/test_gc_integration.py b/rpython/jit/backend/llsupport/test/test_gc_integration.py --- a/rpython/jit/backend/llsupport/test/test_gc_integration.py +++ b/rpython/jit/backend/llsupport/test/test_gc_integration.py @@ -265,8 +265,8 @@ assert rffi.cast(lltype.Signed, ref(0)) == nurs_adr + 0 assert rffi.cast(lltype.Signed, ref(1)) == nurs_adr + 2*WORD + 8*1 # check the nursery content and state - assert gc_ll_descr.nursery[0] == 15 - assert gc_ll_descr.nursery[2 + 8 / WORD] == 15 + assert gc_ll_descr.nursery[0] == chr(15) + assert gc_ll_descr.nursery[2 * WORD + 8] == chr(15) assert gc_ll_descr.addrs[0] == nurs_adr + 4 * WORD + 8*1 + 5*2 # slowpath never called assert gc_ll_descr.calls == [] diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -2355,9 +2355,11 @@ self.mc.MOV(eax, edi) self.mc.MOV(edi, lengthloc) self.mc.IMUL(edi, imm(itemsize)) + self.mc.ADD(edi, imm(WORD * 2)) self.mc.ADD(edi, heap(nursery_free_adr)) - self.mc.ADD(edi, imm(WORD * 2)) self.mc.CMP(edi, heap(nursery_top_adr)) + # write down the tid + self.mc.MOV(mem(eax, 0), imm(arraydescr.tid)) self.mc.J_il8(rx86.Conditions['NA'], 0) # patched later jmp_adr1 = self.mc.get_relative_pos() offset = self.mc.get_relative_pos() - jmp_adr0 From noreply at buildbot.pypy.org Mon Apr 15 20:18:56 2013 From: noreply at buildbot.pypy.org (fijal) Date: Mon, 15 Apr 2013 20:18:56 +0200 (CEST) Subject: [pypy-commit] pypy fast-newarray: finish implementing fast path of varsize malloc (not quite done for 32bit Message-ID: <20130415181856.CD97D1C01FD@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: fast-newarray Changeset: r63383:c8b472530e5f Date: 2013-04-15 20:16 +0200 http://bitbucket.org/pypy/pypy/changeset/c8b472530e5f/ Log: finish implementing fast path of varsize malloc (not quite done for 32bit and not quite done for strings) diff --git a/rpython/jit/backend/llsupport/gc.py b/rpython/jit/backend/llsupport/gc.py --- a/rpython/jit/backend/llsupport/gc.py +++ b/rpython/jit/backend/llsupport/gc.py @@ -415,6 +415,7 @@ return llop1.do_malloc_fixedsize_clear(llmemory.GCREF, type_id, size, False, False, False) + self.generate_function('malloc_nursery', malloc_nursery_slowpath, [lltype.Signed]) @@ -567,6 +568,9 @@ def get_malloc_slowpath_addr(self): return self.get_malloc_fn_addr('malloc_nursery') + def get_malloc_slowpath_array_addr(self): + return self.get_malloc_fn_addr('malloc_array') + # ____________________________________________________________ def get_ll_description(gcdescr, translator=None, rtyper=None): diff --git a/rpython/jit/backend/llsupport/test/test_gc_integration.py b/rpython/jit/backend/llsupport/test/test_gc_integration.py --- a/rpython/jit/backend/llsupport/test/test_gc_integration.py +++ b/rpython/jit/backend/llsupport/test/test_gc_integration.py @@ -173,6 +173,14 @@ [lltype.Signed, jitframe.JITFRAMEPTR], lltype.Signed) + def malloc_array(itemsize, tid, num_elem): + self.calls.append((itemsize, tid, num_elem)) + return 13 + + self.malloc_slowpath_array_fnptr = llhelper_args(malloc_array, + [lltype.Signed] * 3, + lltype.Signed) + def get_nursery_free_addr(self): return rffi.cast(lltype.Signed, self.addrs) @@ -182,6 +190,9 @@ def get_malloc_slowpath_addr(self): return self.get_malloc_fn_addr('malloc_nursery') + def get_malloc_slowpath_array_addr(self): + return self.malloc_slowpath_array_fnptr + def check_nothing_in_nursery(self): # CALL_MALLOC_NURSERY should not write anything in the nursery for i in range(64): @@ -254,7 +265,7 @@ [i0, i1, i2] p0 = call_malloc_nursery_varsize(8, i0, descr=arraydescr) p1 = call_malloc_nursery_varsize(5, i1, descr=arraydescr) - guard_true(i0) [p0, p1] + guard_false(i0) [p0, p1] ''' self.interpret(ops, [1, 2, 3], namespace={'arraydescr': arraydescr}) @@ -275,22 +286,22 @@ self.cpu = self.getcpu(None) ops = ''' [i0, i1, i2] - p0 = call_malloc_nursery_varsize(8, i0) - p1 = call_malloc_nursery_varsize(5, i1) - guard_true(i0) [p0, p1] + p0 = call_malloc_nursery_varsize(8, i0, descr=arraydescr) + p1 = call_malloc_nursery_varsize(5, i1, descr=arraydescr) + p3 = call_malloc_nursery_varsize(5, i2, descr=arraydescr) + p4 = call_malloc_nursery_varsize(5, i2, descr=arraydescr) + # overflow + guard_false(i0) [p0, p1, p3, p4] ''' - self.interpret(ops, [10, 2, 3]) + A = lltype.GcArray(lltype.Signed) + arraydescr = self.cpu.arraydescrof(A) + arraydescr.tid = 15 + self.interpret(ops, [10, 3, 3], + namespace={'arraydescr': arraydescr}) # check the returned pointers gc_ll_descr = self.cpu.gc_ll_descr - nurs_adr = rffi.cast(lltype.Signed, gc_ll_descr.nursery) - ref = lambda n: self.cpu.get_ref_value(self.deadframe, n) - assert rffi.cast(lltype.Signed, ref(0)) == nurs_adr + 0 - assert rffi.cast(lltype.Signed, ref(1)) == nurs_adr + 2*WORD + 8*1 - # check the nursery content and state - gc_ll_descr.check_nothing_in_nursery() - assert gc_ll_descr.addrs[0] == nurs_adr + 4 * WORD + 8*1 + 5*2 - # slowpath never called - assert gc_ll_descr.calls == [] + assert gc_ll_descr.calls == [(8, 15, 10), (5, 15, 3)] + # one fit, one was too large, one was not fitting def test_malloc_slowpath(self): def check(frame): @@ -490,6 +501,15 @@ self.malloc_slowpath_fnptr = llhelper_args(malloc_slowpath, [lltype.Signed], lltype.Signed) + + def malloc_array(itemsize, tid, num_elem): + import pdb + pdb.set_trace() + + self.malloc_slowpath_array_fnptr = llhelper_args(malloc_array, + [lltype.Signed] * 3, + lltype.Signed) + self.all_nurseries = [] def init_nursery(self, nursery_size=None): @@ -545,6 +565,9 @@ def get_malloc_slowpath_addr(self): return self.malloc_slowpath_fnptr + def get_malloc_slowpath_array_addr(self): + return self.malloc_slowpath_array_fnptr + def get_nursery_free_addr(self): return self.nursery_addr @@ -805,7 +828,7 @@ cpu.compile_loop(loop.inputargs, loop.operations, token) frame = lltype.cast_opaque_ptr(JITFRAMEPTR, cpu.execute_token(token, 1, a)) - + assert getmap(frame).count('1') == 4 def test_call_gcmap_no_guard(self): diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -166,11 +166,14 @@ # store the gc pattern mc.MOV_rs(ecx.value, WORD) mc.MOV_br(ofs, ecx.value) - addr = self.cpu.gc_ll_descr.get_malloc_slowpath_addr() - mc.SUB_rr(edi.value, eax.value) # compute the size we want - # the arg is already in edi + if varsize: + addr = self.cpu.gc_ll_descr.get_malloc_slowpath_array_addr() + else: + addr = self.cpu.gc_ll_descr.get_malloc_slowpath_addr() mc.SUB_ri(esp.value, 16 - WORD) if not varsize: + mc.SUB_rr(edi.value, eax.value) # compute the size we want + # the arg is already in edi if IS_X86_32: mc.MOV_sr(0, edi.value) if hasattr(self.cpu.gc_ll_descr, 'passes_frame'): @@ -179,7 +182,13 @@ # for tests only mc.MOV_rr(esi.value, ebp.value) else: - return 0 + if IS_X86_32: + xxx + else: + # offset is 1 extra for call + 1 for SUB above + mc.MOV_rs(edi.value, WORD * 3) # itemsize + mc.MOV_rs(esi.value, WORD * 5) + mc.MOV_rs(edx.value, WORD * 4) # lengthloc extra_ofs = self.cpu.get_ofs_of_frame_field('jf_extra_stack_depth') mc.MOV_bi(extra_ofs, 16) mc.CALL(imm(addr)) @@ -2351,8 +2360,7 @@ self.mc.CMP(lengthloc, imm(maxlength)) self.mc.J_il8(rx86.Conditions['G'], 0) # patched later jmp_adr0 = self.mc.get_relative_pos() - self.mc.MOV(edi, heap(nursery_free_adr)) - self.mc.MOV(eax, edi) + self.mc.MOV(eax, heap(nursery_free_adr)) self.mc.MOV(edi, lengthloc) self.mc.IMUL(edi, imm(itemsize)) self.mc.ADD(edi, imm(WORD * 2)) @@ -2365,6 +2373,9 @@ offset = self.mc.get_relative_pos() - jmp_adr0 assert 0 < offset <= 127 self.mc.overwrite(jmp_adr0-1, chr(offset)) + self.mc.MOV_si(WORD, itemsize) + self.mc.MOV(RawEspLoc(WORD * 2, INT), lengthloc) + self.mc.MOV_si(WORD * 3, arraydescr.tid) # save the gcmap self.push_gcmap(self.mc, gcmap, mov=True) self.mc.CALL(imm(self.malloc_slowpath_varsize)) From noreply at buildbot.pypy.org Mon Apr 15 20:53:48 2013 From: noreply at buildbot.pypy.org (fijal) Date: Mon, 15 Apr 2013 20:53:48 +0200 (CEST) Subject: [pypy-commit] pypy fast-newarray: RPythonize Message-ID: <20130415185348.6F9211C313B@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: fast-newarray Changeset: r63384:3e0774fd541c Date: 2013-04-15 20:53 +0200 http://bitbucket.org/pypy/pypy/changeset/3e0774fd541c/ Log: RPythonize diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -2357,6 +2357,9 @@ def malloc_cond_varsize(self, nursery_free_adr, nursery_top_adr, lengthloc, itemsize, maxlength, gcmap, arraydescr): + from rpython.jit.backend.llsupport.descr import ArrayDescr + assert isinstance(arraydescr, ArrayDescr) + self.mc.CMP(lengthloc, imm(maxlength)) self.mc.J_il8(rx86.Conditions['G'], 0) # patched later jmp_adr0 = self.mc.get_relative_pos() From noreply at buildbot.pypy.org Mon Apr 15 21:25:49 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Mon, 15 Apr 2013 21:25:49 +0200 (CEST) Subject: [pypy-commit] pypy default: mark getlogin as not threadsafe Message-ID: <20130415192549.608621C3128@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63385:3cc08cd87e88 Date: 2013-04-15 15:25 -0400 http://bitbucket.org/pypy/pypy/changeset/3cc08cd87e88/ Log: mark getlogin as not threadsafe diff --git a/rpython/rtyper/module/ll_os.py b/rpython/rtyper/module/ll_os.py --- a/rpython/rtyper/module/ll_os.py +++ b/rpython/rtyper/module/ll_os.py @@ -425,7 +425,7 @@ @registering_if(os, "getlogin", condition=not _WIN32) def register_os_getlogin(self): - os_getlogin = self.llexternal('getlogin', [], rffi.CCHARP) + os_getlogin = self.llexternal('getlogin', [], rffi.CCHARP, threadsafe=False) def getlogin_llimpl(): result = os_getlogin() From noreply at buildbot.pypy.org Mon Apr 15 21:31:14 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Mon, 15 Apr 2013 21:31:14 +0200 (CEST) Subject: [pypy-commit] pypy default: (fijal) mark some other os funcs as not threadsafe also Message-ID: <20130415193114.5315A1C313B@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63386:93ae7ecaef3e Date: 2013-04-15 15:30 -0400 http://bitbucket.org/pypy/pypy/changeset/93ae7ecaef3e/ Log: (fijal) mark some other os funcs as not threadsafe also diff --git a/rpython/rtyper/module/ll_os.py b/rpython/rtyper/module/ll_os.py --- a/rpython/rtyper/module/ll_os.py +++ b/rpython/rtyper/module/ll_os.py @@ -1393,7 +1393,7 @@ @registering(os.strerror) def register_os_strerror(self): - os_strerror = self.llexternal('strerror', [rffi.INT], rffi.CCHARP) + os_strerror = self.llexternal('strerror', [rffi.INT], rffi.CCHARP, threadsafe=False) def strerror_llimpl(errnum): res = os_strerror(rffi.cast(rffi.INT, errnum)) @@ -1784,7 +1784,7 @@ @registering_if(os, 'ttyname') def register_os_ttyname(self): - os_ttyname = self.llexternal('ttyname', [lltype.Signed], rffi.CCHARP) + os_ttyname = self.llexternal('ttyname', [lltype.Signed], rffi.CCHARP, threadsafe=False) def ttyname_llimpl(fd): l_name = os_ttyname(fd) From noreply at buildbot.pypy.org Mon Apr 15 21:36:23 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Mon, 15 Apr 2013 21:36:23 +0200 (CEST) Subject: [pypy-commit] pypy default: getenv also Message-ID: <20130415193623.B5B0F1C3128@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63387:8da09b1dbb90 Date: 2013-04-15 15:36 -0400 http://bitbucket.org/pypy/pypy/changeset/8da09b1dbb90/ Log: getenv also diff --git a/rpython/rtyper/module/ll_os_environ.py b/rpython/rtyper/module/ll_os_environ.py --- a/rpython/rtyper/module/ll_os_environ.py +++ b/rpython/rtyper/module/ll_os_environ.py @@ -57,7 +57,7 @@ def r_getenv(name): just_a_placeholder # should return None if name not found -os_getenv = rffi.llexternal('getenv', [rffi.CCHARP], rffi.CCHARP) +os_getenv = rffi.llexternal('getenv', [rffi.CCHARP], rffi.CCHARP, threadsafe=False) def getenv_llimpl(name): l_name = rffi.str2charp(name) From noreply at buildbot.pypy.org Mon Apr 15 21:46:04 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Mon, 15 Apr 2013 21:46:04 +0200 (CEST) Subject: [pypy-commit] pypy py3k: merge default (17df5567c9a0) Message-ID: <20130415194604.3D1161C3128@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63388:24bbff6786de Date: 2013-04-15 12:42 -0700 http://bitbucket.org/pypy/pypy/changeset/24bbff6786de/ Log: merge default (17df5567c9a0) diff too long, truncating to 2000 out of 8611 lines diff --git a/README.rst b/README.rst --- a/README.rst +++ b/README.rst @@ -13,9 +13,9 @@ http://pypy.org/ -The getting-started document will help guide you: +If you want to help developing PyPy, this document might help you: - http://doc.pypy.org/en/latest/getting-started.html + http://doc.pypy.org/ It will also point you to the rest of the documentation which is generated from files in the pypy/doc directory within the source repositories. Enjoy diff --git a/lib_pypy/_functools.py b/lib_pypy/_functools.py --- a/lib_pypy/_functools.py +++ b/lib_pypy/_functools.py @@ -58,3 +58,16 @@ for k, v in self.keywords.items(): tmp.append("{}={!r}".format(k, v)) return "{}({})".format(name, ', '.join(tmp)) + + def __reduce__(self): + d = dict((k, v) for k, v in self.__dict__.iteritems() if k not in + ('func', 'args', 'keywords')) + if len(d) == 0: + d = None + return (type(self), (self.func,), + (self.func, self.args, self.keywords, d)) + + def __setstate__(self, state): + self.func, self.args, self.keywords, d = state + if d is not None: + self.__dict__.update(d) diff --git a/lib_pypy/_pypy_interact.py b/lib_pypy/_pypy_interact.py --- a/lib_pypy/_pypy_interact.py +++ b/lib_pypy/_pypy_interact.py @@ -47,7 +47,7 @@ import code if mainmodule is None: import __main__ as mainmodule - console = code.InteractiveConsole(mainmodule.__dict__) + console = code.InteractiveConsole(mainmodule.__dict__, filename='') # some parts of code.py are copied here because it seems to be impossible # to start an interactive console without printing at least one line # of banner diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -765,9 +765,9 @@ if isinstance(name, unicode): name = name.encode('utf-8') ret = _lib.sqlite3_create_collation(self._db, name, - _lib.SQLITE_UTF8, - _ffi.NULL, - collation_callback) + _lib.SQLITE_UTF8, + _ffi.NULL, + collation_callback) if ret != _lib.SQLITE_OK: raise self._get_exception(ret) @@ -786,9 +786,7 @@ return _lib.SQLITE_DENY self.__func_cache[callback] = authorizer - ret = _lib.sqlite3_set_authorizer(self._db, - authorizer, - _ffi.NULL) + ret = _lib.sqlite3_set_authorizer(self._db, authorizer, _ffi.NULL) if ret != _lib.SQLITE_OK: raise self._get_exception(ret) @@ -804,15 +802,13 @@ @_ffi.callback("int(void*)") def progress_handler(userdata): try: - ret = callable() - return bool(ret) + return bool(callable()) except Exception: # abort query if error occurred return 1 self.__func_cache[callable] = progress_handler - _lib.sqlite3_progress_handler(self._db, nsteps, - progress_handler, - _ffi.NULL) + _lib.sqlite3_progress_handler(self._db, nsteps, progress_handler, + _ffi.NULL) if sys.version_info[0] >= 3: def __get_in_transaction(self): @@ -894,8 +890,8 @@ def __check_reset(self): if self._reset: raise InterfaceError( - "Cursor needed to be reset because of commit/rollback " - "and can no longer be fetched from.") + "Cursor needed to be reset because of commit/rollback " + "and can no longer be fetched from.") def __build_row_cast_map(self): if not self.__connection._detect_types: diff --git a/lib_pypy/pyrepl/python_reader.py b/lib_pypy/pyrepl/python_reader.py --- a/lib_pypy/pyrepl/python_reader.py +++ b/lib_pypy/pyrepl/python_reader.py @@ -186,10 +186,10 @@ def execute(self, text): try: - # ooh, look at the hack: - code = self.compile(text, '', 'single') + # ooh, look at the hack: + code = self.compile(text, '', 'single') except (OverflowError, SyntaxError, ValueError): - self.showsyntaxerror("") + self.showsyntaxerror('') else: self.runcode(code) if sys.stdout and not sys.stdout.closed: diff --git a/lib_pypy/pyrepl/simple_interact.py b/lib_pypy/pyrepl/simple_interact.py --- a/lib_pypy/pyrepl/simple_interact.py +++ b/lib_pypy/pyrepl/simple_interact.py @@ -38,7 +38,7 @@ import code import __main__ mainmodule = mainmodule or __main__ - console = code.InteractiveConsole(mainmodule.__dict__) + console = code.InteractiveConsole(mainmodule.__dict__, filename='') def more_lines(unicodetext): # ooh, look at the hack: @@ -47,7 +47,7 @@ else: src = unicodetext try: - code = console.compile(src, '', 'single') + code = console.compile(src, '', 'single') except (OverflowError, SyntaxError, ValueError): return False else: diff --git a/pypy/doc/dir-reference.rst b/pypy/doc/dir-reference.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/dir-reference.rst @@ -0,0 +1,140 @@ +PyPy directory cross-reference +------------------------------ + +Here is a fully referenced alphabetical two-level deep +directory overview of PyPy: + +================================= ============================================ +Directory explanation/links +================================= ============================================ +`pypy/bin/`_ command-line scripts, mainly + `pypy/bin/pyinteractive.py`_ + +`pypy/config/`_ handles the numerous options for building + and running PyPy + +`pypy/doc/`_ text versions of PyPy developer + documentation + +`pypy/doc/config/`_ documentation for the numerous translation + options + +`pypy/doc/discussion/`_ drafts of ideas and documentation + +``doc/*/`` other specific documentation topics or tools + +`pypy/interpreter/`_ `bytecode interpreter`_ and related objects + (frames, functions, modules,...) + +`pypy/interpreter/pyparser/`_ interpreter-level Python source parser + +`pypy/interpreter/astcompiler/`_ interpreter-level bytecode compiler, + via an AST representation + +`pypy/module/`_ contains `mixed modules`_ + implementing core modules with + both application and interpreter level code. + Not all are finished and working. Use + the ``--withmod-xxx`` + or ``--allworkingmodules`` translation + options. + +`pypy/objspace/`_ `object space`_ implementations + +`pypy/objspace/std/`_ the StdObjSpace_ implementing CPython's + objects and types + +`pypy/tool/`_ various utilities and hacks used + from various places + +`pypy/tool/algo/`_ general-purpose algorithmic and mathematic + tools + +`pypy/tool/pytest/`_ support code for our `testing methods`_ + + +`rpython/annotator/`_ `type inferencing code`_ for + `RPython`_ programs + +`rpython/config/`_ handles the numerous options for RPython + + +`rpython/flowspace/`_ the FlowObjSpace_ implementing + `abstract interpretation`_ + +`rpython/rlib/`_ a `"standard library"`_ for RPython_ + programs + +`rpython/rtyper/`_ the `RPython Typer`_ + +`rpython/rtyper/lltypesystem/`_ the `low-level type system`_ for + C-like backends + +`rpython/rtyper/ootypesystem/`_ the `object-oriented type system`_ + for OO backends + +`rpython/memory/`_ the `garbage collector`_ construction + framework + +`rpython/translator/`_ translation_ backends and support code + +`rpython/translator/backendopt/`_ general optimizations that run before a + backend generates code + +`rpython/translator/c/`_ the `GenC backend`_, producing C code + from an + RPython program (generally via the rtyper_) + +`rpython/translator/cli/`_ the `CLI backend`_ for `.NET`_ + (Microsoft CLR or Mono_) + +`pypy/goal/`_ our `main PyPy-translation scripts`_ + live here + +`rpython/translator/jvm/`_ the Java backend + +`rpython/translator/tool/`_ helper tools for translation + +`dotviewer/`_ `graph viewer`_ + +``*/test/`` many directories have a test subdirectory + containing test + modules (see `Testing in PyPy`_) + +``_cache/`` holds cache files from various purposes +================================= ============================================ + +.. _`bytecode interpreter`: interpreter.html +.. _`Testing in PyPy`: coding-guide.html#testing-in-pypy +.. _`mixed modules`: coding-guide.html#mixed-modules +.. _`modules`: coding-guide.html#modules +.. _`basil`: http://people.cs.uchicago.edu/~jriehl/BasilTalk.pdf +.. _`object space`: objspace.html +.. _FlowObjSpace: objspace.html#the-flow-object-space +.. _`transparent proxies`: objspace-proxies.html#tproxy +.. _`Differences between PyPy and CPython`: cpython_differences.html +.. _`What PyPy can do for your objects`: objspace-proxies.html +.. _`Continulets and greenlets`: stackless.html +.. _StdObjSpace: objspace.html#the-standard-object-space +.. _`abstract interpretation`: http://en.wikipedia.org/wiki/Abstract_interpretation +.. _`rpython`: coding-guide.html#rpython +.. _`type inferencing code`: translation.html#the-annotation-pass +.. _`RPython Typer`: translation.html#rpython-typer +.. _`testing methods`: coding-guide.html#testing-in-pypy +.. _`translation`: translation.html +.. _`GenC backend`: translation.html#genc +.. _`CLI backend`: cli-backend.html +.. _`py.py`: getting-started-python.html#the-py.py-interpreter +.. _`translatorshell.py`: getting-started-dev.html#try-out-the-translator +.. _JIT: jit/index.html +.. _`JIT Generation in PyPy`: jit/index.html +.. _`just-in-time compiler generator`: jit/index.html +.. _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 +.. _`main PyPy-translation scripts`: getting-started-python.html#translating-the-pypy-python-interpreter +.. _`.NET`: http://www.microsoft.com/net/ +.. _Mono: http://www.mono-project.com/ +.. _`"standard library"`: rlib.html +.. _`graph viewer`: getting-started-dev.html#try-out-the-translator diff --git a/pypy/doc/getting-started-dev.rst b/pypy/doc/getting-started-dev.rst --- a/pypy/doc/getting-started-dev.rst +++ b/pypy/doc/getting-started-dev.rst @@ -1,13 +1,58 @@ -=============================================================================== -Getting Started with the Translation Toolchain and Development Process -=============================================================================== +============================ +Getting Started with RPython +============================ .. contents:: +RPython is a subset of Python that can be statically compiled. The PyPy +interpreter is written mostly in RPython (with pieces in Python), while +the RPython compiler is written in Python. The hard to understand part +is that Python is a meta-programming language for RPython, that is, +RPython is considered from live objects **after** the imports are done. +This might require more explanation. You start writing RPython from +``entry_point``, a good starting point is +``rpython/translator/goal/targetnopstandalone.py``. This does not do all that +much, but is a start. Now if code analyzed (in this case ``entry_point``) +calls some functions, those calls will be followed. Those followed calls +have to be RPython themselves (and everything they call etc.), however not +entire module files. To show how you can use metaprogramming, we can do +a silly example (note that closures are not RPython):: + + def generator(operation): + if operation == 'add': + def f(a, b): + return a + b + else: + def f(a, b): + return a - b + return f + + add = generator('add') + sub = generator('sub') + + def entry_point(argv): + print add(sub(int(argv[1]), 3) 4) + return 0 + +In this example ``entry_point`` is RPython, ``add`` and ``sub`` are RPython, +however, ``generator`` is not. + +A good introductory level articles are available: + +* Laurence Tratt -- `Fast Enough VMs in Fast Enough Time`_. + +* `How to write interpreters in RPython`_ and `part 2`_ by Andrew Brown. + +.. _`Fast Enough VMs in Fast Enough Time`: http://tratt.net/laurie/tech_articles/articles/fast_enough_vms_in_fast_enough_time + +.. _`How to write interpreters in RPython`: http://morepypy.blogspot.com/2011/04/tutorial-writing-interpreter-with-pypy.html + +.. _`part 2`: http://morepypy.blogspot.com/2011/04/tutorial-part-2-adding-jit.html + .. _`try out the translator`: Trying out the translator -------------------------- +------------------------- The translator is a tool based on the PyPy interpreter which can translate sufficiently static RPython programs into low-level code (in particular it can @@ -28,7 +73,7 @@ >>> t = Translation(snippet.is_perfect_number, [int]) >>> t.view() - + After that, the graph viewer pops up, that lets you interactively inspect the flow graph. To move around, click on something that you want to inspect. To get help about how to use it, press 'H'. To close it again, press 'Q'. @@ -83,10 +128,10 @@ The object returned by ``compile_cli`` or ``compile_jvm`` is a wrapper around the real executable: the parameters are passed as command line arguments, and -the returned value is read from the standard output. +the returned value is read from the standard output. Once you have compiled the snippet, you can also try to launch the -executable directly from the shell. You will find the +executable directly from the shell. You will find the executable in one of the ``/tmp/usession-*`` directories:: # For CLI: diff --git a/pypy/doc/getting-started-python.rst b/pypy/doc/getting-started-python.rst --- a/pypy/doc/getting-started-python.rst +++ b/pypy/doc/getting-started-python.rst @@ -6,7 +6,7 @@ PyPy's Python interpreter is a very compliant Python -interpreter implemented in Python. When translated to C, it passes most of +interpreter implemented in RPython. When compiled, it passes most of `CPythons core language regression tests`_ and comes with many of the extension modules included in the standard library including ``ctypes``. It can run large libraries such as Django_ and Twisted_. There are some small behavioral @@ -147,6 +147,8 @@ Translating using the CLI backend +++++++++++++++++++++++++++++++++ +**Note: the CLI backend is no longer maintained** + To create a standalone .NET executable using the `CLI backend`_:: ./translate.py --backend=cli targetpypystandalone.py diff --git a/pypy/doc/how-to-contribute.rst b/pypy/doc/how-to-contribute.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/how-to-contribute.rst @@ -0,0 +1,78 @@ +How to contribute to PyPy +------------------------- + +This page describes how to contribute to the PyPy project. The first thing +to remember is that PyPy project is very different than most projects out there. +It's also different from a classic compiler project, so academic courses +about compilers often don't apply or lead in the wrong direction. + +Don't just hack +--------------- + +The first and most important rule how not to contribute to PyPy is +"just hacking". This won't work. There are two major reasons why not +-- build times are large and PyPy has very thick layer separation which +make it harder to "just hack a feature". + +Test driven development +----------------------- + +Instead, we practice a lot of test driven development. This is partly because +of very high quality requirements for compilers and partly because there is +simply no other way to get around such complex project, that will keep you sane. +There are probably people out there who are smart enough not to need it, we're +not one of those. You may consider familiarizing yourself with `pytest`_, +since this is a tool we use for tests. +This leads to the next issue: + +Layers +------ + +PyPy has layers. Those layers help us keep the respective parts separated enough +to be worked on independently and make the complexity manageable. This is, +again, just a sanity requirement for such a complex project. For example writing +a new optimization for the JIT usually does **not** involve touching a Python +interpreter at all or the JIT assembler backend or the garbage collector. +Instead it requires writing small tests in +``rpython/jit/metainterp/optimizeopt/test/test_*`` and fixing files there. +After that, you can just compile PyPy and things should just work. + +The short list of layers for further reading. For each of those layers, a good +entry point is a test subdirectory in respective directories. It usually +describes (better or worse) the interfaces between the submodules. For the +``pypy`` subdirectory, most tests are small snippets of python programs that +check for correctness (calls ``AppTestXxx``) that will call the appropriate +part of the interpreter. For the ``rpython`` directory, most tests are small +RPython interpreters that perform certain tasks. To see how they translate +to low-level graphs, run them with ``--view``. To see small interpreters +with a JIT compiler, use ``--viewloops`` option. + +* **python interpreter** - it's the part implemented in the ``pypy/`` directory. + It's implemented in RPython, which is a high level static language with + classes, garbage collection, just-in-time compiler generation and the ability + to call C. A cool part about it is that it can be run untranslated, so all + the tests are runnable without translating PyPy. + + **interpreter** contains the interpreter core + + **objspace** contains implementations of various objects exported to + the Python layer + + **module** directory contains extension modules written in RPython + +* **rpython compiler** that resides in ``rpython/annotator`` and + ``rpython/rtyper`` directories. Consult `introduction to RPython`_ for + further reading + +* **JIT generator** lives in ``rpython/jit`` directory. optimizations live + in ``rpython/jit/metainterp/optimizeopt``, the main JIT in + ``rpython/jit/metainterp`` (runtime part) and + ``rpython/jit/codewriter`` (translation-time part). Backends live in + ``rpython/jit/backend``. + +* **garbage collection** lives in ``rpython/memory`` + +The rest of directories serve specific niche goal and are unlikely a good +entry point. + +.. _`introduction to RPython`: getting-started-dev.rst diff --git a/pypy/doc/index.rst b/pypy/doc/index.rst --- a/pypy/doc/index.rst +++ b/pypy/doc/index.rst @@ -1,15 +1,40 @@ -Welcome to PyPy Development -============================================= +Welcome to PyPy +=============== -The PyPy project aims at producing a flexible and fast Python_ -implementation. The guiding idea is to translate a Python-level -description of the Python language itself to lower level languages. -Rumors have it that the secret goal is being faster-than-C which is -nonsense, isn't it? `more...`_ +The PyPy project aims to produce a flexible and fast Python_ +implementation. This page documents the development of the PyPy +project itself. If you don't know what PyPy is, consult the `PyPy +website`_. If you just want to use PyPy, consult the `download`_ page +and the `getting started with pypy`_ documents. If you want to help +develop PyPy -- keep reading! -Getting into PyPy ... -============================================= +PyPy is written in a language called `RPython`_, which is suitable for +writing dynamic language interpreters (and not much else). RPython is +a subset of Python and is itself written in Python. If you'd like to +learn more about RPython, `Starting with RPython`_ should provide a +reasonable overview. + +**If you would like to contribute to PyPy**, please read `how to +contribute`_ first. PyPy's development style is somewhat different to +that of many other software projects and it often surprises +newcomers. What is **not** necessary is an academic background from +university in writing compilers -- much of it does not apply to PyPy +any way. + +All of the documentation and source code is available under the MIT license, +unless otherwise specified. Consult `LICENSE`_ + +.. _`download`: http://pypy.org/download.html +.. _`getting started with pypy`: getting-started-python.html +.. _`RPython`: coding-guide.html#RPython +.. _`Starting with RPython`: getting-started-dev.html +.. _`how to contribute`: how-to-contribute.html +.. _`PyPy website`: http://pypy.org +.. _`LICENSE`: https://bitbucket.org/pypy/pypy/src/default/LICENSE + +Index of various topics: +======================== * `Getting started`_: how to install and run the PyPy Python interpreter @@ -25,20 +50,30 @@ * `potential project ideas`_: In case you want to get your feet wet... +* `more stuff`_: this is a collection of documentation that's there, but not + particularly organized + Documentation for the PyPy Python Interpreter -=============================================== +============================================= New features of PyPy's Python Interpreter and Translation Framework: * `Differences between PyPy and CPython`_ - * `What PyPy can do for your objects`_ - * `Continulets and greenlets`_ + * `What PyPy can do for your objects`_ - transparent proxy documentation + * `Continulets and greenlets`_ - documentation about stackless features * `JIT Generation in PyPy`_ + * `JIT hooks`_ * `Sandboxing Python code`_ + * `Garbage collection environment variables`_ -Status_ of the project. - +.. _`Differences between PyPy and CPython`: cpython_differences.html +.. _`What PyPy can do for your objects`: objspace-proxies.html +.. _`Continulets and greenlets`: stackless.html +.. _`JIT Generation in PyPy`: jit/index.html +.. _`JIT hooks`: jit-hooks.html +.. _`Sandboxing Python code`: sandbox.html +.. _`Garbage collection environment variables`: gc_info.html Mailing lists, bug tracker, IRC channel ============================================= @@ -79,354 +114,6 @@ .. _`speed.pypy.org`: http://speed.pypy.org .. _`RPython toolchain`: translation.html .. _`potential project ideas`: project-ideas.html - -Project Documentation -===================================== - -PyPy was funded by the EU for several years. See the `web site of the EU -project`_ for more details. - -.. _`web site of the EU project`: http://pypy.org - -architecture_ gives a complete view of PyPy's basic design. - -`coding guide`_ helps you to write code for PyPy (especially also describes -coding in RPython a bit). - -`sprint reports`_ lists reports written at most of our sprints, from -2003 to the present. - -`papers, talks and related projects`_ lists presentations -and related projects as well as our published papers. - -`PyPy video documentation`_ is a page linking to the videos (e.g. of talks and -introductions) that are available. - -`Technical reports`_ is a page that contains links to the -reports that we submitted to the European Union. - -`development methodology`_ describes our sprint-driven approach. - -`LICENSE`_ contains licensing details (basically a straight MIT-license). - -`Glossary`_ of PyPy words to help you align your inner self with -the PyPy universe. - - -Status -=================================== - -PyPy can be used to run Python programs on Linux, OS/X, -Windows, on top of .NET, and on top of Java. -To dig into PyPy it is recommended to try out the current -Mercurial default branch, which is always working or mostly working, -instead of the latest release, which is `2.0 beta1`__. - -.. __: release-2.0.0-beta1.html - -PyPy is mainly developed on Linux and Mac OS X. Windows is supported, -but platform-specific bugs tend to take longer before we notice and fix -them. Linux 64-bit machines are supported (though it may also take some -time before we notice and fix bugs). - -PyPy's own tests `summary`_, daily updated, run through BuildBot infrastructure. -You can also find CPython's compliance tests run with compiled ``pypy-c`` -executables there. - - -Source Code Documentation -=============================================== - -`object spaces`_ discusses the object space interface -and several implementations. - -`bytecode interpreter`_ explains the basic mechanisms -of the bytecode interpreter and virtual machine. - -`interpreter optimizations`_ describes our various strategies for -improving the performance of our interpreter, including alternative -object implementations (for strings, dictionaries and lists) in the -standard object space. - -`translation`_ is a detailed overview of our translation process. The -rtyper_ is the largest component of our translation process. - -`dynamic-language translation`_ is a paper that describes -the translation process, especially the flow object space -and the annotator in detail. (This document is one -of the `EU reports`_.) - -`low-level encapsulation`_ describes how our approach hides -away a lot of low level details. This document is also part -of the `EU reports`_. - -`translation aspects`_ describes how we weave different -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. - -`rlib`_ describes some modules that can be used when implementing programs in -RPython. - -`configuration documentation`_ describes the various configuration options that -allow you to customize PyPy. - -`CLI backend`_ describes the details of the .NET backend. - -`JIT Generation in PyPy`_ describes how we produce the Python Just-in-time Compiler -from our Python interpreter. - - - -.. _`FAQ`: faq.html -.. _Glossary: glossary.html -.. _`PyPy video documentation`: video-index.html -.. _parser: parser.html -.. _`development methodology`: dev_method.html -.. _`sprint reports`: sprint-reports.html -.. _`papers, talks and related projects`: extradoc.html -.. _`object spaces`: objspace.html -.. _`interpreter optimizations`: interpreter-optimizations.html -.. _`translation`: translation.html -.. _`dynamic-language translation`: https://bitbucket.org/pypy/extradoc/raw/tip/eu-report/D05.1_Publish_on_translating_a_very-high-level_description.pdf -.. _`low-level encapsulation`: low-level-encapsulation.html -.. _`translation aspects`: translation-aspects.html -.. _`configuration documentation`: config/ -.. _`coding guide`: coding-guide.html -.. _`architecture`: architecture.html -.. _`getting started`: getting-started.html -.. _`bytecode interpreter`: interpreter.html -.. _`EU reports`: index-report.html -.. _`Technical reports`: index-report.html -.. _`summary`: http://buildbot.pypy.org/summary -.. _`ideas for PyPy related projects`: project-ideas.html -.. _`Nightly builds and benchmarks`: http://tuatara.cs.uni-duesseldorf.de/benchmark.html -.. _`directory reference`: -.. _`rlib`: rlib.html -.. _`Sandboxing Python code`: sandbox.html -.. _`LICENSE`: https://bitbucket.org/pypy/pypy/src/default/LICENSE - -PyPy directory cross-reference ------------------------------- - -Here is a fully referenced alphabetical two-level deep -directory overview of PyPy: - -================================= ============================================ -Directory explanation/links -================================= ============================================ -`pypy/bin/`_ command-line scripts, mainly - `pypy/bin/pyinteractive.py`_ - -`pypy/config/`_ handles the numerous options for building - and running PyPy - -`pypy/doc/`_ text versions of PyPy developer - documentation - -`pypy/doc/config/`_ documentation for the numerous translation - options - -`pypy/doc/discussion/`_ drafts of ideas and documentation - -``doc/*/`` other specific documentation topics or tools - -`pypy/interpreter/`_ `bytecode interpreter`_ and related objects - (frames, functions, modules,...) - -`pypy/interpreter/pyparser/`_ interpreter-level Python source parser - -`pypy/interpreter/astcompiler/`_ interpreter-level bytecode compiler, - via an AST representation - -`pypy/module/`_ contains `mixed modules`_ - implementing core modules with - both application and interpreter level code. - Not all are finished and working. Use - the ``--withmod-xxx`` - or ``--allworkingmodules`` translation - options. - -`pypy/objspace/`_ `object space`_ implementations - -`pypy/objspace/std/`_ the StdObjSpace_ implementing CPython's - objects and types - -`pypy/tool/`_ various utilities and hacks used - from various places - -`pypy/tool/algo/`_ general-purpose algorithmic and mathematic - tools - -`pypy/tool/pytest/`_ support code for our `testing methods`_ - - -`rpython/annotator/`_ `type inferencing code`_ for - `RPython`_ programs - -`rpython/config/`_ handles the numerous options for RPython - - -`rpython/flowspace/`_ the FlowObjSpace_ implementing - `abstract interpretation`_ - -`rpython/rlib/`_ a `"standard library"`_ for RPython_ - programs - -`rpython/rtyper/`_ the `RPython Typer`_ - -`rpython/rtyper/lltypesystem/`_ the `low-level type system`_ for - C-like backends - -`rpython/rtyper/ootypesystem/`_ the `object-oriented type system`_ - for OO backends - -`rpython/memory/`_ the `garbage collector`_ construction - framework - -`rpython/translator/`_ translation_ backends and support code - -`rpython/translator/backendopt/`_ general optimizations that run before a - backend generates code - -`rpython/translator/c/`_ the `GenC backend`_, producing C code - from an - RPython program (generally via the rtyper_) - -`rpython/translator/cli/`_ the `CLI backend`_ for `.NET`_ - (Microsoft CLR or Mono_) - -`pypy/goal/`_ our `main PyPy-translation scripts`_ - live here - -`rpython/translator/jvm/`_ the Java backend - -`rpython/translator/tool/`_ helper tools for translation - -`dotviewer/`_ `graph viewer`_ - -``*/test/`` many directories have a test subdirectory - containing test - modules (see `Testing in PyPy`_) - -``_cache/`` holds cache files from various purposes -================================= ============================================ - -.. _`bytecode interpreter`: interpreter.html -.. _`Testing in PyPy`: coding-guide.html#testing-in-pypy -.. _`mixed modules`: coding-guide.html#mixed-modules -.. _`modules`: coding-guide.html#modules -.. _`basil`: http://people.cs.uchicago.edu/~jriehl/BasilTalk.pdf -.. _`object space`: objspace.html -.. _FlowObjSpace: objspace.html#the-flow-object-space -.. _`transparent proxies`: objspace-proxies.html#tproxy -.. _`Differences between PyPy and CPython`: cpython_differences.html -.. _`What PyPy can do for your objects`: objspace-proxies.html -.. _`Continulets and greenlets`: stackless.html -.. _StdObjSpace: objspace.html#the-standard-object-space -.. _`abstract interpretation`: http://en.wikipedia.org/wiki/Abstract_interpretation -.. _`rpython`: coding-guide.html#rpython -.. _`type inferencing code`: translation.html#the-annotation-pass -.. _`RPython Typer`: translation.html#rpython-typer -.. _`testing methods`: coding-guide.html#testing-in-pypy -.. _`translation`: translation.html -.. _`GenC backend`: translation.html#genc -.. _`CLI backend`: cli-backend.html -.. _`py.py`: getting-started-python.html#the-py.py-interpreter -.. _`translatorshell.py`: getting-started-dev.html#try-out-the-translator -.. _JIT: jit/index.html -.. _`JIT Generation in PyPy`: jit/index.html -.. _`just-in-time compiler generator`: jit/index.html -.. _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 -.. _`main PyPy-translation scripts`: getting-started-python.html#translating-the-pypy-python-interpreter -.. _`.NET`: http://www.microsoft.com/net/ -.. _Mono: http://www.mono-project.com/ -.. _`"standard library"`: rlib.html -.. _`graph viewer`: getting-started-dev.html#try-out-the-translator - - -.. The following documentation is important and reasonably up-to-date: - -.. extradoc: should this be integrated one level up: dcolish? - - -.. toctree:: - :maxdepth: 1 - :hidden: - - getting-started.rst - getting-started-python.rst - getting-started-dev.rst - windows.rst - faq.rst - commandline_ref.rst - architecture.rst - coding-guide.rst - cpython_differences.rst - garbage_collection.rst - gc_info.rst - interpreter.rst - objspace.rst - __pypy__-module.rst - objspace-proxies.rst - config/index.rst - - dev_method.rst - extending.rst - - extradoc.rst - video-index.rst - - glossary.rst - - contributor.rst - - interpreter-optimizations.rst - configuration.rst - parser.rst - rlib.rst - rtyper.rst - rffi.rst - - translation.rst - jit/index.rst - jit/overview.rst - jit/pyjitpl5.rst - - index-of-release-notes.rst - - ctypes-implementation.rst - - how-to-release.rst - - index-report.rst - - stackless.rst - sandbox.rst - - discussions.rst - - cleanup.rst - - sprint-reports.rst - - eventhistory.rst - statistic/index.rst - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`search` -* :ref:`glossary` - +.. _`more stuff`: project-documentation.html .. include:: _ref.txt diff --git a/pypy/doc/needswork.txt b/pypy/doc/needswork.txt deleted file mode 100644 --- a/pypy/doc/needswork.txt +++ /dev/null @@ -1,3 +0,0 @@ -.. warning:: - - This documentation needs work (as discussed during the Gothenburg sprint in 2011) diff --git a/pypy/doc/objspace-proxies.rst b/pypy/doc/objspace-proxies.rst --- a/pypy/doc/objspace-proxies.rst +++ b/pypy/doc/objspace-proxies.rst @@ -5,7 +5,6 @@ .. contents:: - Thanks to the `Object Space`_ architecture, any feature that is based on proxying, extending, changing or otherwise controlling the behavior of all objects in a running program is easy to implement on diff --git a/pypy/doc/project-documentation.rst b/pypy/doc/project-documentation.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/project-documentation.rst @@ -0,0 +1,177 @@ + +Project Documentation +===================================== + +`architecture`_ gives a complete view of PyPy's basic design. + +`coding guide`_ helps you to write code for PyPy (especially also describes +coding in RPython a bit). + +`sprint reports`_ lists reports written at most of our sprints, from +2003 to the present. + +`papers, talks and related projects`_ lists presentations +and related projects as well as our published papers. + +`PyPy video documentation`_ is a page linking to the videos (e.g. of talks and +introductions) that are available. + +`Technical reports`_ is a page that contains links to the +reports that we submitted to the European Union. + +`development methodology`_ describes our sprint-driven approach. + +`LICENSE`_ contains licensing details (basically a straight MIT-license). + +`Glossary`_ of PyPy words to help you align your inner self with +the PyPy universe. + +Source Code Documentation +=============================================== + +`object spaces`_ discusses the object space interface +and several implementations. + +`bytecode interpreter`_ explains the basic mechanisms +of the bytecode interpreter and virtual machine. + +`interpreter optimizations`_ describes our various strategies for +improving the performance of our interpreter, including alternative +object implementations (for strings, dictionaries and lists) in the +standard object space. + +`translation`_ is a detailed overview of our translation process. The +rtyper_ is the largest component of our translation process. + +`dynamic-language translation`_ is a paper that describes +the translation process, especially the flow object space +and the annotator in detail. (This document is one +of the `EU reports`_.) + +`low-level encapsulation`_ describes how our approach hides +away a lot of low level details. This document is also part +of the `EU reports`_. + +`translation aspects`_ describes how we weave different +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. + +`rlib`_ describes some modules that can be used when implementing programs in +RPython. + +`configuration documentation`_ describes the various configuration options that +allow you to customize PyPy. + +`pypy on windows`_ + +`command line reference`_ + +`CLI backend`_ describes the details of the .NET backend. + +`JIT Generation in PyPy`_ describes how we produce the Python Just-in-time Compiler +from our Python interpreter. + +`directory cross-reference`_ + +.. _`garbage collector`: garbage_collection.html +.. _`directory cross-reference`: dir-reference.html +.. _`pypy on windows`: windows.html +.. _`command line reference`: commandline_ref.html +.. _`FAQ`: faq.html +.. _Glossary: glossary.html +.. _`PyPy video documentation`: video-index.html +.. _parser: parser.html +.. _`development methodology`: dev_method.html +.. _`sprint reports`: sprint-reports.html +.. _`papers, talks and related projects`: extradoc.html +.. _`object spaces`: objspace.html +.. _`interpreter optimizations`: interpreter-optimizations.html +.. _`translation`: translation.html +.. _`dynamic-language translation`: https://bitbucket.org/pypy/extradoc/raw/tip/eu-report/D05.1_Publish_on_translating_a_very-high-level_description.pdf +.. _`low-level encapsulation`: low-level-encapsulation.html +.. _`translation aspects`: translation-aspects.html +.. _`configuration documentation`: config/ +.. _`coding guide`: coding-guide.html +.. _`Architecture`: architecture.html +.. _`getting started`: getting-started.html +.. _`bytecode interpreter`: interpreter.html +.. _`EU reports`: index-report.html +.. _`Technical reports`: index-report.html +.. _`summary`: http://buildbot.pypy.org/summary +.. _`ideas for PyPy related projects`: project-ideas.html +.. _`Nightly builds and benchmarks`: http://tuatara.cs.uni-duesseldorf.de/benchmark.html +.. _`directory reference`: +.. _`rlib`: rlib.html +.. _`Sandboxing Python code`: sandbox.html +.. _`LICENSE`: https://bitbucket.org/pypy/pypy/src/default/LICENSE + +.. The following documentation is important and reasonably up-to-date: + +.. extradoc: should this be integrated one level up: dcolish? + +.. toctree:: + :maxdepth: 1 + :hidden: + + interpreter.rst + objspace.rst + __pypy__-module.rst + objspace-proxies.rst + config/index.rst + + dev_method.rst + extending.rst + + extradoc.rst + video-index.rst + + glossary.rst + + contributor.rst + + interpreter-optimizations.rst + configuration.rst + parser.rst + rlib.rst + rtyper.rst + rffi.rst + + translation.rst + jit/index.rst + jit/overview.rst + jit/pyjitpl5.rst + + index-of-release-notes.rst + + ctypes-implementation.rst + + how-to-release.rst + + index-report.rst + + stackless.rst + sandbox.rst + + discussions.rst + + cleanup.rst + + sprint-reports.rst + + eventhistory.rst + statistic/index.rst + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`search` +* :ref:`glossary` + +.. include:: _ref.txt diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -46,6 +46,13 @@ Fix a bug which casused cffi to return the wrong result when calling a C function which calls a Python callback which forces the frames +.. branch: virtual-raw-mallocs +JIT optimizations which makes cffi calls even faster, by removing the need to +allocate a temporary buffer where to store the arguments. + +.. branch: improve-docs-2 +Improve documents and straighten out links + .. branches we don't care about .. branch: autoreds .. branch: reflex-support @@ -121,3 +128,4 @@ cffi implementation of sqlite3 .. branch: release-2.0-beta2 +.. branch: unbreak-freebsd diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py --- a/pypy/interpreter/pyopcode.py +++ b/pypy/interpreter/pyopcode.py @@ -259,19 +259,7 @@ "code=%d, name=%s" % (self.last_instr, opcode, methodname)) - try: - res = meth(oparg, next_instr) - except Exception: - if 0: - import dis, sys - print "*** %s at offset %d (%s)" % (sys.exc_info()[0], - self.last_instr, - methodname) - try: - dis.dis(co_code) - except: - pass - raise + res = meth(oparg, next_instr) if res is not None: next_instr = res diff --git a/pypy/module/__pypy__/test/test_signal.py b/pypy/module/__pypy__/test/test_signal.py --- a/pypy/module/__pypy__/test/test_signal.py +++ b/pypy/module/__pypy__/test/test_signal.py @@ -25,6 +25,9 @@ __pypy__.thread._signals_enter() def test_enable_signals(self): + import sys + if sys.platform.startswith('win'): + skip('signals not operable on windows') import __pypy__, _thread, signal, time def subthread(): diff --git a/pypy/module/_codecs/interp_codecs.py b/pypy/module/_codecs/interp_codecs.py --- a/pypy/module/_codecs/interp_codecs.py +++ b/pypy/module/_codecs/interp_codecs.py @@ -1,10 +1,18 @@ +from rpython.rlib import jit +from rpython.rlib.objectmodel import we_are_translated +from rpython.rlib.rstring import UnicodeBuilder + from pypy.interpreter.error import OperationError, operationerrfmt from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault -from rpython.rlib.rstring import UnicodeBuilder -from rpython.rlib.objectmodel import we_are_translated + + +class VersionTag(object): + pass class CodecState(object): + _immutable_fields_ = ["version?"] + def __init__(self, space): self.codec_search_path = [] self.codec_search_cache = {} @@ -14,6 +22,7 @@ self.encode_error_handler = self.make_encode_errorhandler(space) self.unicodedata_handler = None + self.modified() def _make_errorhandler(self, space, decode): def call_errorhandler(errors, encoding, reason, input, startpos, @@ -103,9 +112,20 @@ self.unicodedata_handler = UnicodeData_Handler(space, w_getcode) return self.unicodedata_handler + def modified(self): + self.version = VersionTag() + + def get_codec_from_cache(self, key): + return self._get_codec_with_version(key, self.version) + + @jit.elidable + def _get_codec_with_version(self, key, version): + return self.codec_search_cache.get(key, None) + def _cleanup_(self): assert not self.codec_search_path + def register_codec(space, w_search_function): """register(search_function) @@ -132,11 +152,12 @@ "lookup_codec() should not be called during translation" state = space.fromcache(CodecState) normalized_encoding = encoding.replace(" ", "-").lower() - w_result = state.codec_search_cache.get(normalized_encoding, None) + w_result = state.get_codec_from_cache(normalized_encoding) if w_result is not None: return w_result return _lookup_codec_loop(space, encoding, normalized_encoding) + def _lookup_codec_loop(space, encoding, normalized_encoding): state = space.fromcache(CodecState) if state.codec_need_encodings: @@ -160,6 +181,7 @@ space.wrap("codec search functions must return 4-tuples")) else: state.codec_search_cache[normalized_encoding] = w_result + state.modified() return w_result raise operationerrfmt( space.w_LookupError, diff --git a/pypy/module/_codecs/test/test_codecs.py b/pypy/module/_codecs/test/test_codecs.py --- a/pypy/module/_codecs/test/test_codecs.py +++ b/pypy/module/_codecs/test/test_codecs.py @@ -53,26 +53,25 @@ def test_unicodedecodeerror(self): assert str(UnicodeDecodeError( "ascii", b"g\xfcrk", 1, 2, "ouch")) == "'ascii' codec can't decode byte 0xfc in position 1: ouch" - + assert str(UnicodeDecodeError( "ascii", b"g\xfcrk", 1, 3, "ouch")) == "'ascii' codec can't decode bytes in position 1-2: ouch" - def test_unicodetranslateerror(self): import sys assert str(UnicodeTranslateError( "g\xfcrk", 1, 2, "ouch"))== "can't translate character '\\xfc' in position 1: ouch" - + assert str(UnicodeTranslateError( "g\u0100rk", 1, 2, "ouch"))== "can't translate character '\\u0100' in position 1: ouch" - + assert str(UnicodeTranslateError( "g\uffffrk", 1, 2, "ouch"))== "can't translate character '\\uffff' in position 1: ouch" - + if sys.maxunicode > 0xffff and len(chr(0x10000)) == 1: assert str(UnicodeTranslateError( "g\U00010000rk", 1, 2, "ouch"))== "can't translate character '\\U00010000' in position 1: ouch" - + assert str(UnicodeTranslateError( "g\xfcrk", 1, 3, "ouch"))=="can't translate characters in position 1-2: ouch" @@ -80,22 +79,22 @@ import sys assert str(UnicodeEncodeError( "ascii", "g\xfcrk", 1, 2, "ouch"))=="'ascii' codec can't encode character '\\xfc' in position 1: ouch" - + assert str(UnicodeEncodeError( "ascii", "g\xfcrk", 1, 4, "ouch"))== "'ascii' codec can't encode characters in position 1-3: ouch" - + assert str(UnicodeEncodeError( "ascii", "\xfcx", 0, 1, "ouch"))=="'ascii' codec can't encode character '\\xfc' in position 0: ouch" assert str(UnicodeEncodeError( "ascii", "\u0100x", 0, 1, "ouch"))=="'ascii' codec can't encode character '\\u0100' in position 0: ouch" - + assert str(UnicodeEncodeError( "ascii", "\uffffx", 0, 1, "ouch"))=="'ascii' codec can't encode character '\\uffff' in position 0: ouch" if sys.maxunicode > 0xffff and len(chr(0x10000)) == 1: assert str(UnicodeEncodeError( "ascii", "\U00010000x", 0, 1, "ouch")) =="'ascii' codec can't encode character '\\U00010000' in position 0: ouch" - + def test_indexerror(self): import _codecs test = b"\\" # trailing backslash @@ -137,7 +136,7 @@ "\x00\xff\u07ff\u0800", "\x00\xff\u07ff\u0800\uffff", ] - + buffer = b'' result = "" for (c, partialresult) in zip("\x00\xff\u07ff\u0800\uffff".encode(encoding), check_partial): @@ -174,13 +173,12 @@ assert result == partialresult def test_bug1098990_a(self): - import codecs, io self.encoding = 'utf-8' s1 = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy\r\n" s2 = "offending line: ladfj askldfj klasdj fskla dfzaskdj fasklfj laskd fjasklfzzzzaa%whereisthis!!!\r\n" s3 = "next line.\r\n" - + s = (s1+s2+s3).encode(self.encoding) stream = io.BytesIO(s) reader = codecs.getreader(self.encoding)(stream) @@ -206,8 +204,8 @@ assert reader.readline() == s3 assert reader.readline() == s4 assert reader.readline() == s5 - assert reader.readline() == "" - + assert reader.readline() == "" + def test_seek_utf16le(self): # all codecs should be able to encode these import codecs, io @@ -220,7 +218,6 @@ line = reader.readline() assert s[:len(line)] == line - def test_unicode_internal_encode(self): import sys class U(str): @@ -290,6 +287,12 @@ assert _codecs.escape_decode(b'\\0f')[0] == b'\0' + b'f' assert _codecs.escape_decode(b'\\08')[0] == b'\0' + b'8' + def test_escape_decode_errors(self): + raises(ValueError, br"\x".decode, 'string_escape') + raises(ValueError, br"[\x]".decode, 'string_escape') + raises(ValueError, br"\x0".decode, 'string_escape') + raises(ValueError, br"[\x0]".decode, 'string_escape') + def test_escape_encode(self): import _codecs assert _codecs.escape_encode(b'"')[0] == b'"' diff --git a/pypy/module/_io/interp_bytesio.py b/pypy/module/_io/interp_bytesio.py --- a/pypy/module/_io/interp_bytesio.py +++ b/pypy/module/_io/interp_bytesio.py @@ -3,38 +3,51 @@ from pypy.interpreter.gateway import interp2app, unwrap_spec from pypy.interpreter.error import OperationError, operationerrfmt from pypy.interpreter.buffer import RWBuffer +from rpython.rlib.rStringIO import RStringIO from rpython.rlib.rarithmetic import r_longlong from pypy.module._io.interp_bufferedio import W_BufferedIOBase from pypy.module._io.interp_iobase import convert_size import sys -def buffer2string(buffer, start, end): - from rpython.rlib.rstring import StringBuilder - builder = StringBuilder(end - start) - for i in range(start, end): - builder.append(buffer[i]) - return builder.build() class BytesIOBuffer(RWBuffer): def __init__(self, w_bytesio): self.w_bytesio = w_bytesio def getlength(self): - return int(self.w_bytesio.string_size) + return int(self.w_bytesio.getsize()) + + def as_str(self): + return self.w_bytesio.getvalue() def getitem(self, index): - return self.w_bytesio.buf[index] + # XXX: move this & setitem into rStringIO or some kind of + # rStringIOBufferView + w_bytesio = self.w_bytesio + tell = w_bytesio.tell() + try: + w_bytesio.seek(index) + item = w_bytesio.read(1) + # cast to char + assert len(item) == 1 + return item[0] + finally: + w_bytesio.seek(tell) def setitem(self, index, char): - self.w_bytesio.buf[index] = char + w_bytesio = self.w_bytesio + tell = w_bytesio.tell() + try: + w_bytesio.seek(index) + w_bytesio.write(char) + finally: + w_bytesio.seek(tell) -class W_BytesIO(W_BufferedIOBase): +class W_BytesIO(RStringIO, W_BufferedIOBase): def __init__(self, space): W_BufferedIOBase.__init__(self, space) - self.buf = [] - self.pos = 0 - self.string_size = 0 + self.init() def descr_new(space, w_subtype, __args__): self = space.allocate_instance(W_BytesIO, w_subtype) @@ -42,18 +55,13 @@ return space.wrap(self) def descr_init(self, space, w_initial_bytes=None): - # In case __init__ is called multiple times - if self.buf: - self.buf = [] - self.string_size = 0 - self.pos = 0 - + self.init() if not space.is_none(w_initial_bytes): self.write_w(space, w_initial_bytes) - self.pos = 0 + self.seek(0) def _check_closed(self, space, message=None): - if self.buf is None: + if self.is_closed(): if message is None: message = "I/O operation on closed file" raise OperationError(space.w_ValueError, space.wrap(message)) @@ -61,36 +69,12 @@ def read_w(self, space, w_size=None): self._check_closed(space) size = convert_size(space, w_size) - - # adjust invalid sizes - available = self.string_size - self.pos - if not 0 <= size <= available: - size = available - if size < 0: - size = 0 - - output = buffer2string(self.buf, self.pos, self.pos + size) - self.pos += size - return space.wrapbytes(output) + return space.wrapbytes(self.read(size)) def readline_w(self, space, w_limit=None): self._check_closed(space) limit = convert_size(space, w_limit) - - cur_pos = self.pos - if limit < 0: - end_pos = self.string_size - else: - end_pos = min(cur_pos + limit, self.string_size) - while cur_pos != end_pos: - if self.buf[cur_pos] == '\n': - cur_pos += 1 - break - cur_pos += 1 - - output = buffer2string(self.buf, self.pos, cur_pos) - self.pos = cur_pos - return space.wrapbytes(output) + return space.wrapbytes(self.readline(limit)) def read1_w(self, space, w_size): return self.read_w(space, w_size) @@ -100,56 +84,28 @@ rwbuffer = space.rwbuffer_w(w_buffer) size = rwbuffer.getlength() - if self.pos + size > self.string_size: - size = self.string_size - self.pos - - output = buffer2string(self.buf, self.pos, self.pos + size) - length = len(output) + output = self.read(size) rwbuffer.setslice(0, output) - self.pos += length - return space.wrap(length) + return space.wrap(len(output)) def write_w(self, space, w_data): self._check_closed(space) if space.isinstance_w(w_data, space.w_unicode): raise OperationError(space.w_TypeError, space.wrap( "bytes string of buffer expected")) - buf = space.buffer_w(w_data) - length = buf.getlength() + buf = space.bufferstr_w(w_data) + length = len(buf) if length <= 0: - return - - if self.pos + length > len(self.buf): - self.buf.extend(['\0'] * (self.pos + length - len(self.buf))) - - if self.pos > self.string_size: - # In case of overseek, pad with null bytes the buffer region - # between the end of stream and the current position. - # - # 0 lo string_size hi - # | |<---used--->|<----------available----------->| - # | | <--to pad-->|<---to write---> | - # 0 buf position - for i in range(self.string_size, self.pos): - self.buf[i] = '\0' - - # Copy the data to the internal buffer, overwriting some of the - # existing data if self->pos < self->string_size. - for i in range(length): - self.buf[self.pos + i] = buf.getitem(i) - self.pos += length - - # Set the new length of the internal string if it has changed - if self.string_size < self.pos: - self.string_size = self.pos - + return space.wrap(0) + self.write(buf) return space.wrap(length) def truncate_w(self, space, w_size=None): self._check_closed(space) + pos = self.tell() if space.is_none(w_size): - size = self.pos + size = pos else: size = space.r_longlong_w(w_size) @@ -157,10 +113,11 @@ raise OperationError(space.w_ValueError, space.wrap( "negative size value")) - if size < self.string_size: - self.string_size = size - del self.buf[size:] - + self.truncate(size) + if size == pos: + self.seek(0, 2) + else: + self.seek(pos) return space.wrap(size) def getbuffer_w(self, space): @@ -168,11 +125,11 @@ def getvalue_w(self, space): self._check_closed(space) - return space.wrapbytes(buffer2string(self.buf, 0, self.string_size)) + return space.wrapbytes(self.getvalue()) def tell_w(self, space): self._check_closed(space) - return space.wrap(self.pos) + return space.wrap(self.tell()) @unwrap_spec(pos=r_longlong, whence=int) def seek_w(self, space, pos, whence=0): @@ -183,24 +140,19 @@ raise OperationError(space.w_ValueError, space.wrap( "negative seek value")) elif whence == 1: - if pos > sys.maxint - self.pos: + if pos > sys.maxint - self.tell(): raise OperationError(space.w_OverflowError, space.wrap( "new position too large")) - pos += self.pos elif whence == 2: - if pos > sys.maxint - self.string_size: + if pos > sys.maxint - self.getsize(): raise OperationError(space.w_OverflowError, space.wrap( "new position too large")) - pos += self.string_size else: raise operationerrfmt(space.w_ValueError, "whence must be between 0 and 2, not %d", whence) - if pos >= 0: - self.pos = pos - else: - self.pos = 0 - return space.wrap(self.pos) + self.seek(pos, whence) + return space.wrap(self.tell()) def readable_w(self, space): return space.w_True @@ -212,17 +164,16 @@ return space.w_True def close_w(self, space): - self.buf = None + self.close() def closed_get_w(self, space): - return space.wrap(self.buf is None) + return space.wrap(self.is_closed()) def getstate_w(self, space): self._check_closed(space) - w_content = space.wrapbytes(buffer2string(self.buf, 0, self.string_size)) return space.newtuple([ - w_content, - space.wrap(self.pos), + space.wrapbytes(self.getvalue()), + space.wrap(self.tell()), self.getdict(space)]) def setstate_w(self, space, w_state): @@ -235,13 +186,13 @@ space.type(w_state).getname(space) ) w_content, w_pos, w_dict = space.unpackiterable(w_state, 3) + self.truncate(0) + self.write_w(space, w_content) pos = space.int_w(w_pos) - self.buf = [] - self.write_w(space, w_content) if pos < 0: raise OperationError(space.w_ValueError, space.wrap( "position value cannot be negative")) - self.pos = pos + self.seek(pos) if not space.is_w(w_dict, space.w_None): space.call_method(self.getdict(space), "update", w_dict) diff --git a/pypy/module/_io/interp_stringio.py b/pypy/module/_io/interp_stringio.py --- a/pypy/module/_io/interp_stringio.py +++ b/pypy/module/_io/interp_stringio.py @@ -169,9 +169,9 @@ self.pos = end return space.wrap(u''.join(self.buf[start:end])) - @unwrap_spec(limit=int) - def readline_w(self, space, limit=-1): + def readline_w(self, space, w_limit=None): self._check_closed(space) + limit = convert_size(space, w_limit) if self.pos >= len(self.buf): return space.wrap(u"") diff --git a/pypy/module/_io/test/test_bytesio.py b/pypy/module/_io/test/test_bytesio.py --- a/pypy/module/_io/test/test_bytesio.py +++ b/pypy/module/_io/test/test_bytesio.py @@ -4,6 +4,15 @@ def test_init(self): import _io raises(TypeError, _io.BytesIO, "12345") + buf = b"1234567890" + b = _io.BytesIO(buf) + assert b.getvalue() == buf + b = _io.BytesIO(None) + assert b.getvalue() == b"" + b.__init__(buf * 2) + assert b.getvalue() == buf * 2 + b.__init__(buf) + assert b.getvalue() == buf def test_init_kwargs(self): import _io @@ -29,6 +38,7 @@ def test_write(self): import _io f = _io.BytesIO() + assert f.write(b"") == 0 assert f.write(b"hello") == 5 import gc; gc.collect() assert f.getvalue() == b"hello" @@ -52,10 +62,17 @@ def test_truncate(self): import _io - f = _io.BytesIO(b"hello") + f = _io.BytesIO() + f.write(b"hello") + assert f.truncate(0) == 0 + assert f.tell() == 5 + f.seek(0) + f.write(b"hello") f.seek(3) assert f.truncate() == 3 assert f.getvalue() == b"hel" + assert f.truncate(2) == 2 + assert f.tell() == 3 def test_setstate(self): # state is (content, position, __dict__) @@ -78,7 +95,13 @@ import _io b = _io.BytesIO(b"hello") + a1 = bytearray(b't') + a2 = bytearray(b'testing') + assert b.readinto(a1) == 1 + assert b.readinto(a2) == 4 b.close() + assert a1 == b"h" + assert a2 == b"elloing" raises(ValueError, b.readinto, bytearray(b"hello")) def test_getbuffer(self): diff --git a/pypy/module/_io/test/test_stringio.py b/pypy/module/_io/test/test_stringio.py --- a/pypy/module/_io/test/test_stringio.py +++ b/pypy/module/_io/test/test_stringio.py @@ -32,7 +32,7 @@ raises(ValueError, sio.read, 1) raises(ValueError, sio.write, "text") - def testRead(self): + def test_read(self): import io buf = "1234567890" sio = io.StringIO(buf) @@ -42,6 +42,13 @@ assert buf[5:] == sio.read(900) assert "" == sio.read() + def test_readline(self): + import io + sio = io.StringIO('123\n456') + assert sio.readline(2) == '12' + assert sio.readline(None) == '3\n' + assert sio.readline() == '456' + def test_seek(self): import io diff --git a/pypy/module/_io/test/test_ztranslation.py b/pypy/module/_io/test/test_ztranslation.py new file mode 100644 --- /dev/null +++ b/pypy/module/_io/test/test_ztranslation.py @@ -0,0 +1,4 @@ +from pypy.objspace.fake.checkmodule import checkmodule + +def test_checkmodule(): + checkmodule('_io') diff --git a/pypy/module/_minimal_curses/__init__.py b/pypy/module/_minimal_curses/__init__.py --- a/pypy/module/_minimal_curses/__init__.py +++ b/pypy/module/_minimal_curses/__init__.py @@ -2,10 +2,12 @@ import _curses except ImportError: try: - import _minimal_curses as _curses # when running on top of pypy-c + # when running on top of pypy before it had _curses, settle for minimal + # we prefer _curses so any constants added make it into _minimal_curses + import _minimal_curses as _curses except ImportError: import py - py.test.skip("no _curses or _minimal_curses module") #no _curses at all + py.test.skip("no _curses or _minimal_curses module") # no _curses at all from pypy.interpreter.mixedmodule import MixedModule from pypy.module._minimal_curses import fficurses # for side effects diff --git a/pypy/module/cpyext/test/test_cpyext.py b/pypy/module/cpyext/test/test_cpyext.py --- a/pypy/module/cpyext/test/test_cpyext.py +++ b/pypy/module/cpyext/test/test_cpyext.py @@ -1,6 +1,6 @@ import sys import weakref -import os.path +import os import py @@ -19,6 +19,21 @@ from rpython.tool.identity_dict import identity_dict from rpython.tool import leakfinder +def setup_module(module): + if os.name == 'nt': + # Do not open dreaded dialog box on segfault + import ctypes + SEM_NOGPFAULTERRORBOX = 0x0002 # From MSDN + old_err_mode = ctypes.windll.kernel32.GetErrorMode() + new_err_mode = old_err_mode | SEM_NOGPFAULTERRORBOX + ctypes.windll.kernel32.SetErrorMode(new_err_mode) + module.old_err_mode = old_err_mode + +def teardown_module(module): + if os.name == 'nt': + import ctypes + ctypes.windll.kernel32.SetErrorMode(module.old_err_mode) + @api.cpython_api([], api.PyObject) def PyPy_Crash1(space): 1/0 diff --git a/pypy/module/micronumpy/interp_dtype.py b/pypy/module/micronumpy/interp_dtype.py --- a/pypy/module/micronumpy/interp_dtype.py +++ b/pypy/module/micronumpy/interp_dtype.py @@ -282,7 +282,10 @@ return dtype if w_dtype is dtype.w_box_type: return dtype - raise OperationError(space.w_TypeError, space.wrap("data type %r not understood" % w_dtype)) + typename = space.type(w_dtype).getname(space) + raise OperationError(space.w_TypeError, space.wrap( + "data type not understood (value of type " + + "%s not expected here)" % typename)) W_Dtype.typedef = TypeDef("dtype", __module__ = "numpypy", diff --git a/pypy/module/micronumpy/test/test_dtypes.py b/pypy/module/micronumpy/test/test_dtypes.py --- a/pypy/module/micronumpy/test/test_dtypes.py +++ b/pypy/module/micronumpy/test/test_dtypes.py @@ -32,7 +32,8 @@ assert dtype(None) is dtype(float) - raises(TypeError, dtype, 1042) + exc = raises(TypeError, dtype, (1, 2)) + assert 'data type not understood' in str(exc.value) raises(KeyError, 'dtype(int)["asdasd"]') def test_dtype_eq(self): diff --git a/pypy/module/pypyjit/test_pypy_c/test__ffi.py b/pypy/module/pypyjit/test_pypy_c/test__ffi.py --- a/pypy/module/pypyjit/test_pypy_c/test__ffi.py +++ b/pypy/module/pypyjit/test_pypy_c/test__ffi.py @@ -110,7 +110,6 @@ loops = log.loops_by_id('sleep') assert len(loops) == 1 # make sure that we actually JITted the loop - def test_ctypes_call(self): from rpython.rlib.test.test_clibffi import get_libm_name def main(libm_name): @@ -209,3 +208,65 @@ # so far just check that call_release_gil() is produced. # later, also check that the arguments to call_release_gil() # are constants, and that the numerous raw_mallocs are removed + + def test_cffi_call_guard_not_forced_fails(self): + # this is the test_pypy_c equivalent of + # rpython/jit/metainterp/test/test_fficall::test_guard_not_forced_fails + # + # it requires cffi to be installed for pypy in order to run + def main(): + import sys + try: + import cffi + except ImportError: + sys.stderr.write('SKIP: cannot import cffi\n') + return 0 + + ffi = cffi.FFI() + + ffi.cdef(""" + typedef void (*functype)(int); + int foo(int n, functype func); + """) + + lib = ffi.verify(""" + #include + typedef void (*functype)(int); + + int foo(int n, functype func) { + if (n >= 2000) { + func(n); + } + return n*2; + } + """) + + @ffi.callback("functype") + def mycallback(n): + if n < 5000: + return + # make sure that guard_not_forced fails + d = {} + f = sys._getframe() + while f: + d.update(f.f_locals) + f = f.f_back + + n = 0 + while n < 10000: + res = lib.foo(n, mycallback) # ID: cfficall + # this is the real point of the test: before the + # refactor-call_release_gil branch, the assert failed when + # res == 5000 + assert res == n*2 + n += 1 + return n + + log = self.run(main, [], import_site=True) + assert log.result == 10000 + loop, = log.loops_by_id('cfficall') + assert loop.match_by_id('cfficall', """ + ... + f1 = call_release_gil(..., descr=) + ... + """) diff --git a/pypy/module/pypyjit/test_pypy_c/test_string.py b/pypy/module/pypyjit/test_pypy_c/test_string.py --- a/pypy/module/pypyjit/test_pypy_c/test_string.py +++ b/pypy/module/pypyjit/test_pypy_c/test_string.py @@ -237,3 +237,23 @@ loops = log.loops_by_filename(self.filepath) loop, = loops loop.match_by_id('callone', '') # nothing + + def test_lookup_codec(self): + log = self.run(""" + import codecs + + def main(n): + for i in xrange(n): + codecs.lookup('utf8') + return i + """, [1000]) + loop, = log.loops_by_filename(self.filepath) + loop.match(""" + i45 = int_lt(i43, i26) + guard_true(i45, descr=...) + i46 = int_add(i43, 1) + setfield_gc(p15, i46, descr=) + guard_not_invalidated(descr=...) + --TICK-- + jump(..., descr=...) + """) diff --git a/pypy/module/test_lib_pypy/test_functools.py b/pypy/module/test_lib_pypy/test_functools.py new file mode 100644 --- /dev/null +++ b/pypy/module/test_lib_pypy/test_functools.py @@ -0,0 +1,19 @@ +from lib_pypy import _functools + +def test_partial_reduce(): + partial = _functools.partial(test_partial_reduce) + state = partial.__reduce__() + assert state == (type(partial), (test_partial_reduce,), + (test_partial_reduce, (), None, None)) + +def test_partial_setstate(): + partial = _functools.partial(object) + partial.__setstate__([test_partial_setstate, (), None, None]) + assert partial.func == test_partial_setstate + +def test_partial_pickle(): + import pickle + partial1 = _functools.partial(test_partial_pickle) + string = pickle.dumps(partial1) + partial2 = pickle.loads(string) + assert partial1.func == partial2.func diff --git a/pypy/module/thread/os_thread.py b/pypy/module/thread/os_thread.py --- a/pypy/module/thread/os_thread.py +++ b/pypy/module/thread/os_thread.py @@ -132,7 +132,7 @@ if not e.match(space, space.w_SystemExit): ident = rthread.get_ident() where = 'thread %d started by ' % ident - e.write_unraisable(space, where, w_callable) + e.write_unraisable(space, where, w_callable, with_traceback=True) e.clear(space) # clean up space.threadlocals to remove the ExecutionContext # entry corresponding to the current thread diff --git a/pypy/module/thread/test/test_thread.py b/pypy/module/thread/test/test_thread.py --- a/pypy/module/thread/test/test_thread.py From noreply at buildbot.pypy.org Mon Apr 15 21:46:05 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Mon, 15 Apr 2013 21:46:05 +0200 (CEST) Subject: [pypy-commit] pypy py3k: test plain setitem too Message-ID: <20130415194605.859C91C3128@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63389:92424746587a Date: 2013-04-15 12:43 -0700 http://bitbucket.org/pypy/pypy/changeset/92424746587a/ Log: test plain setitem too diff --git a/pypy/module/_io/test/test_bytesio.py b/pypy/module/_io/test/test_bytesio.py --- a/pypy/module/_io/test/test_bytesio.py +++ b/pypy/module/_io/test/test_bytesio.py @@ -112,6 +112,7 @@ memio.seek(5) buf = memio.getbuffer() assert bytes(buf) == b"1234567890" + assert buf[5] == b"6" # Mutating the buffer updates the BytesIO buf[3:6] = b"abc" assert bytes(buf) == b"123abc7890" From noreply at buildbot.pypy.org Mon Apr 15 21:46:07 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Mon, 15 Apr 2013 21:46:07 +0200 (CEST) Subject: [pypy-commit] pypy py3k: merge default Message-ID: <20130415194607.38C871C3128@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63390:177afb89c10f Date: 2013-04-15 12:45 -0700 http://bitbucket.org/pypy/pypy/changeset/177afb89c10f/ Log: merge default diff too long, truncating to 2000 out of 2797 lines diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -998,17 +998,18 @@ # Actually execute the SQL statement ret = _lib.sqlite3_step(self.__statement._statement) - if ret not in (_lib.SQLITE_DONE, _lib.SQLITE_ROW): - self.__statement._reset() - raise self.__connection._get_exception(ret) if ret == _lib.SQLITE_ROW: if multiple: raise ProgrammingError("executemany() can only execute DML statements.") self.__build_row_cast_map() self.__next_row = self.__fetch_one_row() - elif ret == _lib.SQLITE_DONE and not multiple: + elif ret == _lib.SQLITE_DONE: + if not multiple: + self.__statement._reset() + else: self.__statement._reset() + raise self.__connection._get_exception(ret) if self.__statement._type in ("UPDATE", "DELETE", "INSERT", "REPLACE"): if self.__rowcount == -1: @@ -1089,7 +1090,6 @@ try: next_row = self.__next_row except AttributeError: - self.__statement._reset() raise StopIteration del self.__next_row @@ -1097,11 +1097,12 @@ next_row = self.row_factory(self, next_row) ret = _lib.sqlite3_step(self.__statement._statement) - if ret not in (_lib.SQLITE_DONE, _lib.SQLITE_ROW): + if ret == _lib.SQLITE_ROW: + self.__next_row = self.__fetch_one_row() + else: self.__statement._reset() - raise self.__connection._get_exception(ret) - elif ret == _lib.SQLITE_ROW: - self.__next_row = self.__fetch_one_row() + if ret != _lib.SQLITE_DONE: + raise self.__connection._get_exception(ret) return next_row if sys.version_info[0] < 3: diff --git a/pypy/module/__pypy__/test/test_signal.py b/pypy/module/__pypy__/test/test_signal.py --- a/pypy/module/__pypy__/test/test_signal.py +++ b/pypy/module/__pypy__/test/test_signal.py @@ -25,9 +25,6 @@ __pypy__.thread._signals_enter() def test_enable_signals(self): - import sys - if sys.platform.startswith('win'): - skip('signals not operable on windows') import __pypy__, _thread, signal, time def subthread(): @@ -50,8 +47,9 @@ try: done = [] interrupted = [] + print('starting',i) _thread.start_new_thread(subthread, ()) - for i in range(10): + for j in range(10): if len(done): break print('.') time.sleep(0.1) diff --git a/pypy/module/_cffi_backend/ccallback.py b/pypy/module/_cffi_backend/ccallback.py --- a/pypy/module/_cffi_backend/ccallback.py +++ b/pypy/module/_cffi_backend/ccallback.py @@ -134,7 +134,7 @@ # W_CTypePrimitiveSigned.convert_from_object() in order # to write a whole 'ffi_arg'. value = misc.as_long(space, w_res) - misc.write_raw_integer_data(ll_res, value, SIZE_OF_FFI_ARG) + misc.write_raw_signed_data(ll_res, value, SIZE_OF_FFI_ARG) return else: # zero extension: fill the '*result' with zeros, and (on big- diff --git a/pypy/module/_cffi_backend/cdataobj.py b/pypy/module/_cffi_backend/cdataobj.py --- a/pypy/module/_cffi_backend/cdataobj.py +++ b/pypy/module/_cffi_backend/cdataobj.py @@ -280,8 +280,13 @@ return self.ctype.iter(self) @specialize.argtype(1) - def write_raw_integer_data(self, source): - misc.write_raw_integer_data(self._cdata, source, self.ctype.size) + def write_raw_signed_data(self, source): + misc.write_raw_signed_data(self._cdata, source, self.ctype.size) + keepalive_until_here(self) + + @specialize.argtype(1) + def write_raw_unsigned_data(self, source): + misc.write_raw_unsigned_data(self._cdata, source, self.ctype.size) keepalive_until_here(self) def write_raw_float_data(self, source): @@ -389,6 +394,7 @@ W_CData.typedef = TypeDef( 'CData', __module__ = '_cffi_backend', + __name__ = '', __repr__ = interp2app(W_CData.repr), __bool__ = interp2app(W_CData.bool), __int__ = interp2app(W_CData.int), diff --git a/pypy/module/_cffi_backend/ctypeprim.py b/pypy/module/_cffi_backend/ctypeprim.py --- a/pypy/module/_cffi_backend/ctypeprim.py +++ b/pypy/module/_cffi_backend/ctypeprim.py @@ -63,7 +63,7 @@ else: value = self._cast_generic(w_ob) w_cdata = cdataobj.W_CDataMem(space, self.size, self) - w_cdata.write_raw_integer_data(value) + self.write_raw_integer_data(w_cdata, value) return w_cdata def _cast_result(self, intvalue): @@ -94,6 +94,9 @@ from pypy.module._cffi_backend import newtype return newtype.new_primitive_type(self.space, "int") + def write_raw_integer_data(self, w_cdata, value): + w_cdata.write_raw_unsigned_data(value) + class W_CTypePrimitiveChar(W_CTypePrimitiveCharOrUniChar): _attrs_ = [] @@ -185,10 +188,10 @@ if self.size < rffi.sizeof(lltype.Signed): if r_uint(value) - self.vmin > self.vrangemax: self._overflow(w_ob) - misc.write_raw_integer_data(cdata, value, self.size) + misc.write_raw_signed_data(cdata, value, self.size) else: value = misc.as_long_long(self.space, w_ob) - misc.write_raw_integer_data(cdata, value, self.size) + misc.write_raw_signed_data(cdata, value, self.size) def get_vararg_type(self): if self.size < rffi.sizeof(rffi.INT): @@ -196,6 +199,9 @@ return newtype.new_primitive_type(self.space, "int") return self + def write_raw_integer_data(self, w_cdata, value): + w_cdata.write_raw_signed_data(value) + class W_CTypePrimitiveUnsigned(W_CTypePrimitive): _attrs_ = ['value_fits_long', 'value_fits_ulong', 'vrangemax'] @@ -222,10 +228,10 @@ if self.value_fits_long: if value > self.vrangemax: self._overflow(w_ob) - misc.write_raw_integer_data(cdata, value, self.size) + misc.write_raw_unsigned_data(cdata, value, self.size) else: value = misc.as_unsigned_long_long(self.space, w_ob, strict=True) - misc.write_raw_integer_data(cdata, value, self.size) + misc.write_raw_unsigned_data(cdata, value, self.size) def convert_to_object(self, cdata): if self.value_fits_ulong: @@ -244,6 +250,9 @@ return newtype.new_primitive_type(self.space, "int") return self + def write_raw_integer_data(self, w_cdata, value): + w_cdata.write_raw_unsigned_data(value) + class W_CTypePrimitiveBool(W_CTypePrimitiveUnsigned): _attrs_ = [] diff --git a/pypy/module/_cffi_backend/ctypestruct.py b/pypy/module/_cffi_backend/ctypestruct.py --- a/pypy/module/_cffi_backend/ctypestruct.py +++ b/pypy/module/_cffi_backend/ctypestruct.py @@ -242,11 +242,13 @@ # value = misc.as_long_long(space, w_ob) if isinstance(ctype, ctypeprim.W_CTypePrimitiveSigned): + is_signed = True fmin = -(r_longlong(1) << (self.bitsize - 1)) fmax = (r_longlong(1) << (self.bitsize - 1)) - 1 if fmax == 0: fmax = 1 # special case to let "int x:1" receive "1" else: + is_signed = False fmin = r_longlong(0) fmax = r_longlong((r_ulonglong(1) << self.bitsize) - 1) if value < fmin or value > fmax: @@ -258,7 +260,10 @@ rawvalue = r_ulonglong(value) << self.bitshift rawfielddata = misc.read_raw_unsigned_data(cdata, ctype.size) rawfielddata = (rawfielddata & ~rawmask) | (rawvalue & rawmask) - misc.write_raw_integer_data(cdata, rawfielddata, ctype.size) + if is_signed: + misc.write_raw_signed_data(cdata, rawfielddata, ctype.size) + else: + misc.write_raw_unsigned_data(cdata, rawfielddata, ctype.size) W_CField.typedef = TypeDef( diff --git a/pypy/module/_cffi_backend/misc.py b/pypy/module/_cffi_backend/misc.py --- a/pypy/module/_cffi_backend/misc.py +++ b/pypy/module/_cffi_backend/misc.py @@ -9,6 +9,7 @@ from rpython.rtyper.lltypesystem import lltype, llmemory, rffi from rpython.translator.tool.cbuild import ExternalCompilationInfo + # ____________________________________________________________ _prim_signed_types = unrolling_iterable([ @@ -65,19 +66,22 @@ return rffi.cast(rffi.LONGDOUBLEP, target)[0] @specialize.argtype(1) -def write_raw_integer_data(target, source, size): - if is_signed_integer_type(lltype.typeOf(source)): - for TP, TPP in _prim_signed_types: - if size == rffi.sizeof(TP): - rffi.cast(TPP, target)[0] = rffi.cast(TP, source) - return - else: - for TP, TPP in _prim_unsigned_types: - if size == rffi.sizeof(TP): - rffi.cast(TPP, target)[0] = rffi.cast(TP, source) - return +def write_raw_unsigned_data(target, source, size): + for TP, TPP in _prim_unsigned_types: + if size == rffi.sizeof(TP): + rffi.cast(TPP, target)[0] = rffi.cast(TP, source) + return raise NotImplementedError("bad integer size") + at specialize.argtype(1) +def write_raw_signed_data(target, source, size): + for TP, TPP in _prim_signed_types: + if size == rffi.sizeof(TP): + rffi.cast(TPP, target)[0] = rffi.cast(TP, source) + return + raise NotImplementedError("bad integer size") + + def write_raw_float_data(target, source, size): for TP, TPP in _prim_float_types: if size == rffi.sizeof(TP): diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py --- a/pypy/module/_cffi_backend/test/_backend_test_c.py +++ b/pypy/module/_cffi_backend/test/_backend_test_c.py @@ -2712,6 +2712,13 @@ c[1:3] = d assert list(c) == [0, 40, 50, 30, 0] +def test_cdata_name_module_doc(): + p = new_primitive_type("signed char") + x = cast(p, 17) + assert x.__module__ == '_cffi_backend' + assert x.__name__ == '' + assert hasattr(x, '__doc__') + def test_version(): # this test is here mostly for PyPy assert __version__ == "0.6" diff --git a/pypy/module/pypyjit/test_pypy_c/test__ffi.py b/pypy/module/pypyjit/test_pypy_c/test_ffi.py rename from pypy/module/pypyjit/test_pypy_c/test__ffi.py rename to pypy/module/pypyjit/test_pypy_c/test_ffi.py --- a/pypy/module/pypyjit/test_pypy_c/test__ffi.py +++ b/pypy/module/pypyjit/test_pypy_c/test_ffi.py @@ -181,32 +181,39 @@ libm = _cffi_backend.load_library(libm_name) BDouble = _cffi_backend.new_primitive_type("double") - BPow = _cffi_backend.new_function_type([BDouble, BDouble], BDouble) - pow = libm.load_function(BPow, 'pow') + BInt = _cffi_backend.new_primitive_type("int") + BPow = _cffi_backend.new_function_type([BDouble, BInt], BDouble) + ldexp = libm.load_function(BPow, 'ldexp') i = 0 res = 0 while i < 300: - tmp = pow(2, 3) # ID: cfficall + tmp = ldexp(1, 3) # ID: cfficall res += tmp i += 1 BLong = _cffi_backend.new_primitive_type("long") - pow_addr = int(_cffi_backend.cast(BLong, pow)) - return pow_addr, res + ldexp_addr = int(_cffi_backend.cast(BLong, ldexp)) + return ldexp_addr, res # libm_name = get_libm_name(sys.platform) log = self.run(main, [libm_name]) - pow_addr, res = log.result + ldexp_addr, res = log.result assert res == 8.0 * 300 loop, = log.loops_by_filename(self.filepath) - if 'ConstClass(pow)' in repr(loop): # e.g. OS/X - pow_addr = 'ConstClass(pow)' + if 'ConstClass(ldexp)' in repr(loop): # e.g. OS/X + ldexp_addr = 'ConstClass(ldexp)' assert loop.match_by_id('cfficall', """ ... - f1 = call_release_gil(..., descr=) + f1 = call_release_gil(..., descr=) ... """) + ops = loop.ops_by_id('cfficall') + assert 'raw_malloc' not in str(ops) + assert 'raw_free' not in str(ops) + assert 'getarrayitem_raw' not in log.opnames(ops) + assert 'setarrayitem_raw' not in log.opnames(ops) # so far just check that call_release_gil() is produced. # later, also check that the arguments to call_release_gil() + # are constants # are constants, and that the numerous raw_mallocs are removed def test_cffi_call_guard_not_forced_fails(self): diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -764,13 +764,13 @@ # restore registers self._pop_all_regs_from_jitframe(mc, [], self.cpu.supports_floats) - mc.POP([r.ip.value, r.pc.value]) # return + mc.POP([r.ip.value, r.pc.value]) # return self._frame_realloc_slowpath = mc.materialize(self.cpu.asmmemmgr, []) def _load_shadowstack_top(self, mc, reg, gcrootmap): rst = gcrootmap.get_root_stack_top_addr() mc.gen_load_int(reg.value, rst) - mc.gen_load_int(reg.value, reg.value) + self.load_reg(mc, reg, reg) return rst def fixup_target_tokens(self, rawstart): diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -352,7 +352,8 @@ def _emit_call(self, adr, arglocs, fcond=c.AL, resloc=None, result_info=(-1, -1), - can_collect=1): + can_collect=1, + reload_frame=False): if self.cpu.hf_abi: stack_args, adr = self._setup_call_hf(adr, arglocs, fcond, resloc, result_info) @@ -365,7 +366,6 @@ gcmap = self._regalloc.get_gcmap([r.r0], noregs=noregs) self.push_gcmap(self.mc, gcmap, store=True) #the actual call - #self.mc.BKPT() if adr.is_imm(): self.mc.BL(adr.value) elif adr.is_stack(): @@ -388,6 +388,8 @@ if can_collect: self._reload_frame_if_necessary(self.mc, can_collect=can_collect) self.pop_gcmap(self.mc) + elif reload_frame: + self._reload_frame_if_necessary(self.mc) return fcond def _restore_sp(self, stack_args, fcond): @@ -1266,6 +1268,10 @@ resloc = arglocs[0] if gcrootmap: + noregs = self.cpu.gc_ll_descr.is_shadow_stack() + assert noregs + gcmap = self._regalloc.get_gcmap([r.r0], noregs=noregs) + self.push_gcmap(self.mc, gcmap, store=True) self.call_release_gil(gcrootmap, arglocs, regalloc, fcond) # do the call self._store_force_index(guard_op) @@ -1275,7 +1281,8 @@ signed = descr.is_result_signed() # self._emit_call(adr, callargs, fcond, - resloc, (size, signed)) + resloc, (size, signed), + can_collect=0) # then reopen the stack if gcrootmap: self.call_reacquire_gil(gcrootmap, resloc, regalloc, fcond) @@ -1288,7 +1295,8 @@ # NOTE: We assume that the floating point registers won't be modified. assert gcrootmap.is_shadow_stack with saved_registers(self.mc, regalloc.rm.save_around_call_regs): - self._emit_call(imm(self.releasegil_addr), [], fcond) + self._emit_call(imm(self.releasegil_addr), [], + fcond, can_collect=False) def call_reacquire_gil(self, gcrootmap, save_loc, regalloc, fcond): # save the previous result into the stack temporarily, in case it is in @@ -1305,7 +1313,8 @@ assert gcrootmap.is_shadow_stack # call the reopenstack() function (also reacquiring the GIL) with saved_registers(self.mc, regs_to_save, vfp_regs_to_save): - self._emit_call(imm(self.reacqgil_addr), [], fcond) + self._emit_call(imm(self.reacqgil_addr), [], fcond, + can_collect=False, reload_frame=True) def _store_force_index(self, guard_op): faildescr = guard_op.getdescr() diff --git a/rpython/jit/backend/llgraph/runner.py b/rpython/jit/backend/llgraph/runner.py --- a/rpython/jit/backend/llgraph/runner.py +++ b/rpython/jit/backend/llgraph/runner.py @@ -484,6 +484,15 @@ else: return self.bh_raw_load_i(struct, offset, descr) + def unpack_arraydescr_size(self, arraydescr): + from rpython.jit.backend.llsupport.symbolic import get_array_token + from rpython.jit.backend.llsupport.descr import get_type_flag, FLAG_SIGNED + assert isinstance(arraydescr, ArrayDescr) + basesize, itemsize, _ = get_array_token(arraydescr.A, False) + flag = get_type_flag(arraydescr.A.OF) + is_signed = (flag == FLAG_SIGNED) + return basesize, itemsize, is_signed + def bh_raw_store_i(self, struct, offset, newvalue, descr): ll_p = rffi.cast(rffi.CCHARP, struct) ll_p = rffi.cast(lltype.Ptr(descr.A), rffi.ptradd(ll_p, offset)) @@ -566,10 +575,14 @@ def bh_read_timestamp(self): return read_timestamp() + def bh_new_raw_buffer(self, size): + return lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') + def store_fail_descr(self, deadframe, descr): pass # I *think* + class LLDeadFrame(object): _TYPE = llmemory.GCREF diff --git a/rpython/jit/backend/llsupport/llmodel.py b/rpython/jit/backend/llsupport/llmodel.py --- a/rpython/jit/backend/llsupport/llmodel.py +++ b/rpython/jit/backend/llsupport/llmodel.py @@ -742,6 +742,9 @@ as_array[self.vtable_offset/WORD] = vtable return res + def bh_new_raw_buffer(self, size): + return lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') + def bh_classof(self, struct): struct = lltype.cast_opaque_ptr(rclass.OBJECTPTR, struct) result_adr = llmemory.cast_ptr_to_adr(struct.typeptr) diff --git a/rpython/jit/backend/llsupport/test/test_gc_integration.py b/rpython/jit/backend/llsupport/test/test_gc_integration.py --- a/rpython/jit/backend/llsupport/test/test_gc_integration.py +++ b/rpython/jit/backend/llsupport/test/test_gc_integration.py @@ -537,6 +537,9 @@ self.S = S self.cpu = cpu + def teardown_method(self, meth): + rffi.aroundstate._cleanup_() + def test_shadowstack_call(self): cpu = self.cpu cpu.gc_ll_descr.init_nursery(100) @@ -671,25 +674,31 @@ # people actually wreck xmm registers cpu = self.cpu l = [] + copied_stack = [None] def before(): + # put nonsense on the top of shadowstack + frame = rffi.cast(JITFRAMEPTR, cpu.gc_ll_descr.gcrootmap.stack[0]) + assert getmap(frame).count('1') == 7 # + copied_stack[0] = cpu.gc_ll_descr.gcrootmap.stack[0] + cpu.gc_ll_descr.gcrootmap.stack[0] = -42 l.append("before") def after(): + cpu.gc_ll_descr.gcrootmap.stack[0] = copied_stack[0] l.append("after") invoke_around_extcall(before, after) def f(frame, x): # all the gc pointers are alive p1 -> p7 (but not p0) - assert getmap(frame).count('1') == 7 # assert x == 1 return 2 - + FUNC = lltype.FuncType([JITFRAMEPTR, lltype.Signed], lltype.Signed) fptr = llhelper(lltype.Ptr(FUNC), f) calldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, - EffectInfo.MOST_GENERAL) + EffectInfo.MOST_GENERAL) loop = self.parse(""" [i0, p1, p2, p3, p4, p5, p6, p7] p0 = force_token() diff --git a/rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py b/rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py --- a/rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py +++ b/rpython/jit/backend/llsupport/test/zrpy_gc_boehm_test.py @@ -2,6 +2,7 @@ import weakref from rpython.rlib.jit import JitDriver, dont_look_inside from rpython.jit.backend.llsupport.test.zrpy_gc_test import run, get_entry, compile +from rpython.jit.backend.llsupport.test.ztranslation_test import fix_annotator_for_vrawbuffer class X(object): def __init__(self, x=0): @@ -31,7 +32,8 @@ g._dont_inline_ = True return g -def compile_boehm_test(): +def compile_boehm_test(monkeypatch): + fix_annotator_for_vrawbuffer(monkeypatch) myjitdriver = JitDriver(greens = [], reds = ['n', 'x']) @dont_look_inside def see(lst, n): diff --git a/rpython/jit/backend/llsupport/test/ztranslation_test.py b/rpython/jit/backend/llsupport/test/ztranslation_test.py --- a/rpython/jit/backend/llsupport/test/ztranslation_test.py +++ b/rpython/jit/backend/llsupport/test/ztranslation_test.py @@ -9,10 +9,23 @@ from rpython.jit.codewriter.policy import StopAtXPolicy +def fix_annotator_for_vrawbuffer(monkeypatch): + from rpython.rlib.nonconst import NonConstant + from rpython.jit.metainterp.optimizeopt.virtualize import VRawBufferValue + from rpython.jit.metainterp import warmspot + + def my_hook_for_tests(cpu): + # this is needed so that the annotator can see it + if NonConstant(False): + v = VRawBufferValue(cpu, None, -1, None, None) + monkeypatch.setattr(warmspot, 'hook_for_tests', my_hook_for_tests) + + class TranslationTest(CCompiledMixin): CPUClass = getcpuclass() - def test_stuff_translates(self): + def test_stuff_translates(self, monkeypatch): + fix_annotator_for_vrawbuffer(monkeypatch) # this is a basic test that tries to hit a number of features and their # translation: # - jitting of loops and bridges @@ -89,9 +102,10 @@ class TranslationTestCallAssembler(CCompiledMixin): CPUClass = getcpuclass() - def test_direct_assembler_call_translates(self): + def test_direct_assembler_call_translates(self, monkeypatch): """Test CALL_ASSEMBLER and the recursion limit""" from rpython.rlib.rstackovf import StackOverflow + fix_annotator_for_vrawbuffer(monkeypatch) class Thing(object): def __init__(self, val): @@ -169,7 +183,8 @@ class TranslationTestJITStats(CCompiledMixin): CPUClass = getcpuclass() - def test_jit_get_stats(self): + def test_jit_get_stats(self, monkeypatch): + fix_annotator_for_vrawbuffer(monkeypatch) driver = JitDriver(greens = [], reds = ['i']) def f(): @@ -192,7 +207,8 @@ class TranslationRemoveTypePtrTest(CCompiledMixin): CPUClass = getcpuclass() - def test_external_exception_handling_translates(self): + def test_external_exception_handling_translates(self, monkeypatch): + fix_annotator_for_vrawbuffer(monkeypatch) jitdriver = JitDriver(greens = [], reds = ['n', 'total']) class ImDone(Exception): diff --git a/rpython/jit/backend/model.py b/rpython/jit/backend/model.py --- a/rpython/jit/backend/model.py +++ b/rpython/jit/backend/model.py @@ -194,11 +194,18 @@ def typedescrof(self, TYPE): raise NotImplementedError + def unpack_arraydescr_size(self, arraydescr): + """ + Return basesize, itemsize, is_signed + """ + raise NotImplementedError + @staticmethod def cast_int_to_ptr(x, TYPE): x = llmemory.cast_int_to_adr(x) return llmemory.cast_adr_to_ptr(x, TYPE) + # ---------- the backend-dependent operations ---------- # lltype specific operations @@ -235,6 +242,8 @@ raise NotImplementedError def bh_newunicode(self, length): raise NotImplementedError + def bh_new_raw_buffer(self, size): + raise NotImplementedError def bh_arraylen_gc(self, array, arraydescr): raise NotImplementedError diff --git a/rpython/jit/backend/test/runner_test.py b/rpython/jit/backend/test/runner_test.py --- a/rpython/jit/backend/test/runner_test.py +++ b/rpython/jit/backend/test/runner_test.py @@ -348,7 +348,7 @@ i0 = BoxInt() class UntouchableFailDescr(AbstractFailDescr): final_descr = True - + def __setattr__(self, name, value): if (name == 'index' or name == '_carry_around_for_tests' or name == '_TYPE' or name == '_cpu'): @@ -2832,6 +2832,11 @@ assert not called def test_assembler_call_propagate_exc(self): + from rpython.jit.backend.llsupport.llmodel import AbstractLLCPU + + if not isinstance(self.cpu, AbstractLLCPU): + py.test.skip("llgraph can't fake exceptions well enough, give up") + excdescr = BasicFailDescr(666) self.cpu.propagate_exception_descr = excdescr self.cpu.setup_once() # xxx redo it, because we added @@ -3420,7 +3425,7 @@ calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, effectinfo) testcases = [(4.0, 2.0), (6.25, 2.5)] for arg, expected in testcases: - res = self.execute_operation(rop.CALL, + res = self.execute_operation(rop.CALL, [funcbox, boxfloat(arg)], 'float', descr=calldescr) assert res.getfloat() == expected @@ -3776,7 +3781,7 @@ # memory assert values[0] == 0 - def test_compile_bridge_while_running(self): + def test_compile_bridge_while_running(self): def func(): bridge = parse(""" [i1, i2, px] @@ -3823,9 +3828,9 @@ func2_ptr = llhelper(FPTR2, func2) calldescr2 = cpu.calldescrof(FUNC2, FUNC2.ARGS, FUNC2.RESULT, EffectInfo.MOST_GENERAL) - + faildescr = BasicFailDescr(0) - + looptoken = JitCellToken() loop = parse(""" [i0, i1, i2] @@ -3841,7 +3846,7 @@ if not isinstance(self.cpu, AbstractLLCPU): py.test.skip("pointless test on non-asm") - + frame = lltype.cast_opaque_ptr(jitframe.JITFRAMEPTR, frame) assert len(frame.jf_frame) == frame.jf_frame_info.jfi_frame_depth ref = self.cpu.get_ref_value(frame, 9) @@ -3903,7 +3908,7 @@ 'calldescr': calldescr, 'faildescr': faildescr, 'finaldescr2': BasicFinalDescr(1)}) - + self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken) frame = self.cpu.execute_token(looptoken, 1, 2, 3) descr = self.cpu.get_latest_descr(frame) diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -112,6 +112,11 @@ self.float_const_neg_addr = float_constants self.float_const_abs_addr = float_constants + 16 + def set_extra_stack_depth(self, mc, value): + if self._is_asmgcc(): + extra_ofs = self.cpu.get_ofs_of_frame_field('jf_extra_stack_depth') + mc.MOV_bi(extra_ofs, value) + def build_frame_realloc_slowpath(self): mc = codebuf.MachineCodeBlockWrapper() self._push_all_regs_to_frame(mc, [], self.cpu.supports_floats) @@ -134,16 +139,14 @@ mc.MOV_sr(0, ebp.value) # align - extra_ofs = self.cpu.get_ofs_of_frame_field('jf_extra_stack_depth') - mc.MOV_bi(extra_ofs, align * WORD) + self.set_extra_stack_depth(mc, align * WORD) self._store_and_reset_exception(mc, None, ebx, ecx) mc.CALL(imm(self.cpu.realloc_frame)) mc.MOV_rr(ebp.value, eax.value) self._restore_exception(mc, None, ebx, ecx) mc.ADD_ri(esp.value, (align - 1) * WORD) - mc.MOV_bi(extra_ofs, 0) - + self.set_extra_stack_depth(mc, 0) gcrootmap = self.cpu.gc_ll_descr.gcrootmap if gcrootmap and gcrootmap.is_shadow_stack: @@ -176,8 +179,7 @@ elif hasattr(self.cpu.gc_ll_descr, 'passes_frame'): # for tests only mc.MOV_rr(esi.value, ebp.value) - extra_ofs = self.cpu.get_ofs_of_frame_field('jf_extra_stack_depth') - mc.MOV_bi(extra_ofs, 16) + self.set_extra_stack_depth(mc, 16) mc.CALL(imm(addr)) mc.ADD_ri(esp.value, 16 - WORD) mc.TEST_rr(eax.value, eax.value) @@ -186,7 +188,7 @@ # nursery_free_adr = self.cpu.gc_ll_descr.get_nursery_free_addr() self._reload_frame_if_necessary(mc, align_stack=True) - mc.MOV_bi(extra_ofs, 0) + self.set_extra_stack_depth(mc, 0) self._pop_all_regs_from_frame(mc, [eax, edi], self.cpu.supports_floats) mc.MOV(edi, heap(nursery_free_adr)) # load this in EDI # clear the gc pattern @@ -973,14 +975,17 @@ return bool(gcrootmap) and not gcrootmap.is_shadow_stack def _emit_call(self, x, arglocs, start=0, tmp=eax, - argtypes=None, callconv=FFI_DEFAULT_ABI, can_collect=1, - stack_max=PASS_ON_MY_FRAME, reload_frame=False): - if can_collect == 1 and not self._is_asmgcc(): - can_collect = 2 # don't bother with jf_extra_stack_depth + argtypes=None, callconv=FFI_DEFAULT_ABI, + # whether to worry about a CALL that can collect; this + # is always true except in call_release_gil + can_collect=True, + # max number of arguments we can pass on esp; if more, + # we need to decrease esp temporarily + stack_max=PASS_ON_MY_FRAME): + # if IS_X86_64: return self._emit_call_64(x, arglocs, start, argtypes, - can_collect, stack_max, - reload_frame=reload_frame) + can_collect, stack_max) stack_depth = 0 n = len(arglocs) for i in range(start, n): @@ -989,9 +994,8 @@ if stack_depth > stack_max: align = align_stack_words(stack_depth - stack_max) self.mc.SUB_ri(esp.value, align * WORD) - if can_collect == 1: - ofs = self.cpu.get_ofs_of_frame_field('jf_extra_stack_depth') - self.mc.MOV_bi(ofs, align * WORD) + if can_collect: + self.set_extra_stack_depth(self.mc, align * WORD) else: align = 0 p = 0 @@ -1016,23 +1020,24 @@ p += loc.get_width() # x is a location if can_collect: + # we push *now* the gcmap, describing the status of GC registers + # after the rearrangements done just above, ignoring the return + # value eax, if necessary noregs = self.cpu.gc_ll_descr.is_shadow_stack() gcmap = self._regalloc.get_gcmap([eax], noregs=noregs) self.push_gcmap(self.mc, gcmap, store=True) + # self.mc.CALL(x) if callconv != FFI_DEFAULT_ABI: self._fix_stdcall(callconv, p - align * WORD) elif align: self.mc.ADD_ri(esp.value, align * WORD) + # if can_collect: - self._reload_frame_if_necessary(self.mc, can_collect=can_collect) - if align and can_collect == 1: - ofs = self.cpu.get_ofs_of_frame_field('jf_extra_stack_depth') - self.mc.MOV_bi(ofs, 0) + self._reload_frame_if_necessary(self.mc) + if align: + self.set_extra_stack_depth(self.mc, 0) self.pop_gcmap(self.mc) - elif reload_frame: - self._reload_frame_if_necessary(self.mc) - # def _fix_stdcall(self, callconv, p): from rpython.rlib.clibffi import FFI_STDCALL @@ -1042,7 +1047,7 @@ self.mc.SUB_ri(esp.value, p) def _emit_call_64(self, x, arglocs, start, argtypes, - can_collect, stack_max, reload_frame=False): + can_collect, stack_max): src_locs = [] dst_locs = [] xmm_src_locs = [] @@ -1066,9 +1071,8 @@ align = 0 if stack_depth > stack_max: align = align_stack_words(stack_depth - stack_max) - if can_collect == 1: - ofs = self.cpu.get_ofs_of_frame_field('jf_extra_stack_depth') - self.mc.MOV_bi(ofs, align * WORD) + if can_collect: + self.set_extra_stack_depth(self.mc, align * WORD) self.mc.SUB_ri(esp.value, align * WORD) for i in range(start, len(arglocs)): loc = arglocs[i] @@ -1123,35 +1127,30 @@ x = r10 remap_frame_layout(self, src_locs, dst_locs, X86_64_SCRATCH_REG) if can_collect: + # we push *now* the gcmap, describing the status of GC registers + # after the rearrangements done just above, ignoring the return + # value eax, if necessary noregs = self.cpu.gc_ll_descr.is_shadow_stack() gcmap = self._regalloc.get_gcmap([eax], noregs=noregs) self.push_gcmap(self.mc, gcmap, store=True) + # self.mc.CALL(x) - if can_collect: - self._reload_frame_if_necessary(self.mc, can_collect=can_collect) - if align and can_collect == 1: - ofs = self.cpu.get_ofs_of_frame_field('jf_extra_stack_depth') - self.mc.MOV_bi(ofs, 0) - elif reload_frame: - self._reload_frame_if_necessary(self.mc) if align: self.mc.ADD_ri(esp.value, align * WORD) + # if can_collect: + self._reload_frame_if_necessary(self.mc) + if align: + self.set_extra_stack_depth(self.mc, 0) self.pop_gcmap(self.mc) - def _reload_frame_if_necessary(self, mc, align_stack=False, can_collect=0): + def _reload_frame_if_necessary(self, mc, align_stack=False): gcrootmap = self.cpu.gc_ll_descr.gcrootmap if gcrootmap: if gcrootmap.is_shadow_stack: rst = gcrootmap.get_root_stack_top_addr() mc.MOV(ecx, heap(rst)) mc.MOV(ebp, mem(ecx, -WORD)) - elif can_collect == 3: - # specially for call_release_gil: must reload ebp from the css - from rpython.memory.gctransform import asmgcroot - css = WORD * (PASS_ON_MY_FRAME - asmgcroot.JIT_USE_WORDS) - index_of_ebp = css + WORD * (2+asmgcroot.INDEX_OF_EBP) - mc.MOV_rs(ebp.value, index_of_ebp) # MOV EBP, [css.ebp] wbdescr = self.cpu.gc_ll_descr.write_barrier_descr if gcrootmap and wbdescr: # frame never uses card marking, so we enforce this is not @@ -1926,6 +1925,9 @@ self.pending_guard_tokens.append(guard_token) def genop_call(self, op, arglocs, resloc): + return self._genop_call(op, arglocs, resloc) + + def _genop_call(self, op, arglocs, resloc, is_call_release_gil=False): from rpython.jit.backend.llsupport.descr import CallDescr sizeloc = arglocs[0] @@ -1943,13 +1945,13 @@ assert isinstance(descr, CallDescr) stack_max = PASS_ON_MY_FRAME - if self._is_asmgcc() and op.getopnum() == rop.CALL_RELEASE_GIL: - from rpython.memory.gctransform import asmgcroot - stack_max -= asmgcroot.JIT_USE_WORDS - can_collect = 3 # asmgcc only: don't write jf_extra_stack_depth, - # and reload ebp from the css + if is_call_release_gil: + if self._is_asmgcc(): + from rpython.memory.gctransform import asmgcroot + stack_max -= asmgcroot.JIT_USE_WORDS + can_collect = False else: - can_collect = 1 + can_collect = True self._emit_call(x, arglocs, 3, tmp=tmp, argtypes=descr.get_arg_types(), @@ -2012,16 +2014,25 @@ def genop_guard_call_release_gil(self, op, guard_op, guard_token, arglocs, result_loc): + self._store_force_index(guard_op) # first, close the stack in the sense of the asmgcc GC root tracker gcrootmap = self.cpu.gc_ll_descr.gcrootmap if gcrootmap: + # we put the gcmap now into the frame before releasing the GIL, + # and pop it below after reacquiring the GIL. The assumption + # is that this gcmap describes correctly the situation at any + # point in-between: all values containing GC pointers should + # be safely saved out of registers by now, and will not be + # manipulated by any of the following CALLs. + gcmap = self._regalloc.get_gcmap(noregs=True) + self.push_gcmap(self.mc, gcmap, store=True) self.call_release_gil(gcrootmap, arglocs) # do the call - self._store_force_index(guard_op) - self.genop_call(op, arglocs, result_loc) + self._genop_call(op, arglocs, result_loc, is_call_release_gil=True) # then reopen the stack if gcrootmap: self.call_reacquire_gil(gcrootmap, result_loc) + self.pop_gcmap(self.mc) # remove the gcmap saved above # finally, the guard_not_forced self._emit_guard_not_forced(guard_token) @@ -2050,8 +2061,7 @@ # Set up jf_extra_stack_depth to pretend that the return address # was at css, and so our stack frame is supposedly shorter by # (css+WORD) bytes - extra_ofs = self.cpu.get_ofs_of_frame_field('jf_extra_stack_depth') - self.mc.MOV_bi(extra_ofs, -css-WORD) + self.set_extra_stack_depth(self.mc, -css-WORD) # Call the closestack() function (also releasing the GIL) args = [reg] # @@ -2066,19 +2076,29 @@ # call the reopenstack() function (also reacquiring the GIL) if gcrootmap.is_shadow_stack: args = [] + css = 0 else: from rpython.memory.gctransform import asmgcroot css = WORD * (PASS_ON_MY_FRAME - asmgcroot.JIT_USE_WORDS) - extra_ofs = self.cpu.get_ofs_of_frame_field('jf_extra_stack_depth') - self.mc.MOV_bi(extra_ofs, 0) if IS_X86_32: reg = eax elif IS_X86_64: reg = edi self.mc.LEA_rs(reg.value, css) args = [reg] - self._emit_call(imm(self.reacqgil_addr), args, can_collect=False, - reload_frame=True) + self._emit_call(imm(self.reacqgil_addr), args, can_collect=False) + # + # Now that we required the GIL, we can reload a possibly modified ebp + if not gcrootmap.is_shadow_stack: + # special-case: reload ebp from the css + from rpython.memory.gctransform import asmgcroot + index_of_ebp = css + WORD * (2+asmgcroot.INDEX_OF_EBP) + self.mc.MOV_rs(ebp.value, index_of_ebp) # MOV EBP, [css.ebp] + #else: + # for shadowstack, done for us by _reload_frame_if_necessary() + self._reload_frame_if_necessary(self.mc) + self.set_extra_stack_depth(self.mc, 0) + # # restore the result from the stack if isinstance(save_loc, RegLoc) and not save_loc.is_xmm: self.mc.MOV_rs(save_loc.value, WORD) diff --git a/rpython/jit/codewriter/effectinfo.py b/rpython/jit/codewriter/effectinfo.py --- a/rpython/jit/codewriter/effectinfo.py +++ b/rpython/jit/codewriter/effectinfo.py @@ -76,14 +76,14 @@ # OS_MATH_SQRT = 100 # - OS_RAW_MALLOC_VARSIZE = 110 + OS_RAW_MALLOC_VARSIZE_CHAR = 110 OS_RAW_FREE = 111 OS_JIT_FORCE_VIRTUAL = 120 # for debugging: _OS_CANRAISE = set([OS_NONE, OS_STR2UNICODE, OS_LIBFFI_CALL, - OS_RAW_MALLOC_VARSIZE, OS_JIT_FORCE_VIRTUAL]) + OS_RAW_MALLOC_VARSIZE_CHAR, OS_JIT_FORCE_VIRTUAL]) def __new__(cls, readonly_descrs_fields, readonly_descrs_arrays, write_descrs_fields, write_descrs_arrays, diff --git a/rpython/jit/codewriter/jtransform.py b/rpython/jit/codewriter/jtransform.py --- a/rpython/jit/codewriter/jtransform.py +++ b/rpython/jit/codewriter/jtransform.py @@ -539,9 +539,11 @@ name += '_no_track_allocation' op1 = self.prepare_builtin_call(op, name, args, (TYPE,), TYPE) if name == 'raw_malloc_varsize': - return self._handle_oopspec_call(op1, args, - EffectInfo.OS_RAW_MALLOC_VARSIZE, - EffectInfo.EF_CAN_RAISE) + ITEMTYPE = op.args[0].value.OF + if ITEMTYPE == lltype.Char: + return self._handle_oopspec_call(op1, args, + EffectInfo.OS_RAW_MALLOC_VARSIZE_CHAR, + EffectInfo.EF_CAN_RAISE) return self.rewrite_op_direct_call(op1) def rewrite_op_malloc_varsize(self, op): diff --git a/rpython/jit/codewriter/test/test_jtransform.py b/rpython/jit/codewriter/test/test_jtransform.py --- a/rpython/jit/codewriter/test/test_jtransform.py +++ b/rpython/jit/codewriter/test/test_jtransform.py @@ -126,7 +126,7 @@ INT = lltype.Signed UNICHAR = lltype.UniChar FLOAT = lltype.Float - ARRAYPTR = rffi.CArrayPtr(lltype.Signed) + ARRAYPTR = rffi.CArrayPtr(lltype.Char) argtypes = { EI.OS_MATH_SQRT: ([FLOAT], FLOAT), EI.OS_STR2UNICODE:([PSTR], PUNICODE), @@ -143,7 +143,7 @@ EI.OS_UNIEQ_NONNULL_CHAR: ([PUNICODE, UNICHAR], INT), EI.OS_UNIEQ_CHECKNULL_CHAR: ([PUNICODE, UNICHAR], INT), EI.OS_UNIEQ_LENGTHOK: ([PUNICODE, PUNICODE], INT), - EI.OS_RAW_MALLOC_VARSIZE: ([INT], ARRAYPTR), + EI.OS_RAW_MALLOC_VARSIZE_CHAR: ([INT], ARRAYPTR), EI.OS_RAW_FREE: ([ARRAYPTR], lltype.Void), } argtypes = argtypes[oopspecindex] @@ -151,7 +151,7 @@ assert argtypes[1] == op.result.concretetype if oopspecindex == EI.OS_STR2UNICODE: assert extraeffect == EI.EF_ELIDABLE_CAN_RAISE - elif oopspecindex == EI.OS_RAW_MALLOC_VARSIZE: + elif oopspecindex == EI.OS_RAW_MALLOC_VARSIZE_CHAR: assert extraeffect == EI.EF_CAN_RAISE elif oopspecindex == EI.OS_RAW_FREE: assert extraeffect == EI.EF_CANNOT_RAISE @@ -161,7 +161,7 @@ def calldescr_canraise(self, calldescr): EI = effectinfo.EffectInfo - if calldescr == 'calldescr-%d' % EI.OS_RAW_MALLOC_VARSIZE: + if calldescr == 'calldescr-%d' % EI.OS_RAW_MALLOC_VARSIZE_CHAR: return True return False @@ -555,7 +555,7 @@ assert op1.args == [] def test_raw_malloc(): - S = rffi.CArray(lltype.Signed) + S = rffi.CArray(lltype.Char) v1 = varoftype(lltype.Signed) v = varoftype(lltype.Ptr(S)) flags = Constant({'flavor': 'raw'}, lltype.Void) @@ -566,7 +566,7 @@ assert op0.opname == 'residual_call_ir_i' assert op0.args[0].value == 'raw_malloc_varsize' # pseudo-function as a str assert (op0.args[-1] == 'calldescr-%d' % - effectinfo.EffectInfo.OS_RAW_MALLOC_VARSIZE) + effectinfo.EffectInfo.OS_RAW_MALLOC_VARSIZE_CHAR) assert op1.opname == '-live-' assert op1.args == [] @@ -608,7 +608,7 @@ assert op1.args == [] def test_raw_free(): - S = rffi.CArray(lltype.Signed) + S = rffi.CArray(lltype.Char) flags = Constant({'flavor': 'raw', 'track_allocation': True}, lltype.Void) op = SpaceOperation('free', [varoftype(lltype.Ptr(S)), flags], diff --git a/rpython/jit/metainterp/compile.py b/rpython/jit/metainterp/compile.py --- a/rpython/jit/metainterp/compile.py +++ b/rpython/jit/metainterp/compile.py @@ -15,7 +15,7 @@ from rpython.jit.metainterp import history, resume from rpython.jit.metainterp.optimize import InvalidLoop from rpython.jit.metainterp.inliner import Inliner -from rpython.jit.metainterp.resume import NUMBERING, PENDINGFIELDSP +from rpython.jit.metainterp.resume import NUMBERING, PENDINGFIELDSP, ResumeDataDirectReader from rpython.jit.codewriter import heaptracker, longlong def giveup(): @@ -656,9 +656,9 @@ class AllVirtuals: llopaque = True - list = [resume.ResumeDataDirectReader.virtual_default] # annotation hack - def __init__(self, list): - self.list = list + cache = None + def __init__(self, cache): + self.cache = cache def hide(self, cpu): ptr = cpu.ts.cast_instance_to_base_ref(self) return cpu.ts.cast_to_ref(ptr) @@ -682,9 +682,9 @@ from rpython.jit.metainterp.blackhole import resume_in_blackhole hidden_all_virtuals = metainterp_sd.cpu.get_savedata_ref(deadframe) obj = AllVirtuals.show(metainterp_sd.cpu, hidden_all_virtuals) - all_virtuals = obj.list + all_virtuals = obj.cache if all_virtuals is None: - all_virtuals = [] + all_virtuals = ResumeDataDirectReader.VirtualCache([], []) assert jitdriver_sd is self.jitdriver_sd resume_in_blackhole(metainterp_sd, jitdriver_sd, self, deadframe, all_virtuals) diff --git a/rpython/jit/metainterp/history.py b/rpython/jit/metainterp/history.py --- a/rpython/jit/metainterp/history.py +++ b/rpython/jit/metainterp/history.py @@ -191,7 +191,6 @@ def get_jitcode_for_class(self, oocls): return self.jitcodes[oocls] - class Const(AbstractValue): __slots__ = () diff --git a/rpython/jit/metainterp/optimizeopt/earlyforce.py b/rpython/jit/metainterp/optimizeopt/earlyforce.py --- a/rpython/jit/metainterp/optimizeopt/earlyforce.py +++ b/rpython/jit/metainterp/optimizeopt/earlyforce.py @@ -1,15 +1,26 @@ +from rpython.jit.codewriter.effectinfo import EffectInfo from rpython.jit.metainterp.optimizeopt.optimizer import Optimization from rpython.jit.metainterp.optimizeopt.vstring import VAbstractStringValue from rpython.jit.metainterp.resoperation import rop, ResOperation +def is_raw_free(op, opnum): + if opnum != rop.CALL: + return False + einfo = op.getdescr().get_extra_info() + return einfo.oopspecindex == EffectInfo.OS_RAW_FREE + + class OptEarlyForce(Optimization): def propagate_forward(self, op): opnum = op.getopnum() + if (opnum != rop.SETFIELD_GC and opnum != rop.SETARRAYITEM_GC and + opnum != rop.SETARRAYITEM_RAW and opnum != rop.QUASIIMMUT_FIELD and opnum != rop.SAME_AS and - opnum != rop.MARK_OPAQUE_PTR): + opnum != rop.MARK_OPAQUE_PTR and + not is_raw_free(op, opnum)): for arg in op.getarglist(): if arg in self.optimizer.values: diff --git a/rpython/jit/metainterp/optimizeopt/optimizer.py b/rpython/jit/metainterp/optimizeopt/optimizer.py --- a/rpython/jit/metainterp/optimizeopt/optimizer.py +++ b/rpython/jit/metainterp/optimizeopt/optimizer.py @@ -231,6 +231,12 @@ def setitem(self, index, value): raise NotImplementedError + def getitem_raw(self, offset, length, descr): + raise NotImplementedError + + def setitem_raw(self, offset, length, descr, value): + raise NotImplementedError + def getinteriorfield(self, index, ofs, default): raise NotImplementedError diff --git a/rpython/jit/metainterp/optimizeopt/rawbuffer.py b/rpython/jit/metainterp/optimizeopt/rawbuffer.py new file mode 100644 --- /dev/null +++ b/rpython/jit/metainterp/optimizeopt/rawbuffer.py @@ -0,0 +1,134 @@ +from rpython.rlib.debug import debug_start, debug_stop, debug_print +from rpython.rlib.objectmodel import compute_unique_id, we_are_translated + +class InvalidRawOperation(Exception): + pass + +class InvalidRawWrite(InvalidRawOperation): + pass + +class InvalidRawRead(InvalidRawOperation): + pass + +class RawBuffer(object): + def __init__(self, cpu, logops=None): + # the following lists represents the writes in the buffer: values[i] + # is the value of length lengths[i] stored at offset[i]. + # + # the invariant is that they are ordered by offset, and that + # offset[i]+length[i] <= offset[i+1], i.e. that the writes never + # overlaps + self.cpu = cpu + self.logops = logops + self.offsets = [] + self.lengths = [] + self.descrs = [] + self.values = [] + + def _get_memory(self): + """ + NOT_RPYTHON + for testing only + """ + return zip(self.offsets, self.lengths, self.descrs, self.values) + + def _repr_of_descr(self, descr): + if self.logops: + s = self.logops.repr_of_descr(descr) + else: + s = str(descr) + s += " at %d" % compute_unique_id(descr) + return s + + def _repr_of_value(self, value): + if not we_are_translated() and isinstance(value, str): + return value # for tests + if self.logops: + s = self.logops.repr_of_arg(value.box) + else: + s = str(value.box) + s += " at %d" % compute_unique_id(value.box) + return s + + def _dump_to_log(self): + debug_print("RawBuffer state") + debug_print("offset, length, descr, box") + debug_print("(box == None means that the value is still virtual)") + for i in range(len(self.offsets)): + descr = self._repr_of_descr(self.descrs[i]) + box = self._repr_of_value(self.values[i]) + debug_print("%d, %d, %s, %s" % (self.offsets[i], self.lengths[i], descr, box)) + + def _invalid_write(self, message, offset, length, descr, value): + debug_start('jit-log-rawbuffer') + debug_print('Invalid write: %s' % message) + debug_print(" offset: %d" % offset) + debug_print(" length: %d" % length) + debug_print(" descr: %s" % self._repr_of_descr(descr)) + debug_print(" value: %s" % self._repr_of_value(value)) + self._dump_to_log() + debug_stop('jit-log-rawbuffer') + raise InvalidRawWrite + + def _invalid_read(self, message, offset, length, descr): + debug_start('jit-log-rawbuffer') + debug_print('Invalid read: %s' % message) + debug_print(" offset: %d" % offset) + debug_print(" length: %d" % length) + debug_print(" descr: %s" % self._repr_of_descr(descr)) + self._dump_to_log() + debug_stop('jit-log-rawbuffer') + raise InvalidRawRead + + def _descrs_are_compatible(self, d1, d2): + # two arraydescrs are compatible if they have the same basesize, + # itemsize and sign, even if they are not identical + unpack = self.cpu.unpack_arraydescr_size + return unpack(d1) == unpack(d2) + + def write_value(self, offset, length, descr, value): + i = 0 + N = len(self.offsets) + while i < N: + if self.offsets[i] == offset: + if (length != self.lengths[i] or not + self._descrs_are_compatible(descr, self.descrs[i])): + # in theory we could add support for the cases in which + # the length or descr is different, but I don't think we + # need it in practice + self._invalid_write('length or descr not compatible', + offset, length, descr, value) + # update the value at this offset + self.values[i] = value + return + elif self.offsets[i] > offset: + break + i += 1 + # + if i < len(self.offsets) and offset+length > self.offsets[i]: + self._invalid_write("overlap with next bytes", + offset, length, descr, value) + if i > 0 and self.offsets[i-1]+self.lengths[i-1] > offset: + self._invalid_write("overlap with previous bytes", + offset, length, descr, value) + # insert a new value at offset + self.offsets.insert(i, offset) + self.lengths.insert(i, length) + self.descrs.insert(i, descr) + self.values.insert(i, value) + + def read_value(self, offset, length, descr): + i = 0 + N = len(self.offsets) + while i < N: + if self.offsets[i] == offset: + if (length != self.lengths[i] or + not self._descrs_are_compatible(descr, self.descrs[i])): + self._invalid_read('length or descr not compatible', + offset, length, descr) + return self.values[i] + i += 1 + # memory location not found: this means we are reading from + # uninitialized memory, give up the optimization + self._invalid_read('uninitialized memory', + offset, length, descr) diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py --- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py @@ -770,8 +770,6 @@ """ self.optimize_loop(ops, expected) - - def test_p123_simple(self): ops = """ [i1, p2, p3] @@ -1730,6 +1728,175 @@ # We cannot track virtuals that survive for more than two iterations. self.optimize_loop(ops, expected, preamble) + def test_virtual_raw_malloc(self): + ops = """ + [i1] + i2 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) + i3 = getarrayitem_raw(i2, 0, descr=rawarraydescr) + call('free', i2, descr=raw_free_descr) + jump(i3) + """ + expected = """ + [i1] + jump(i1) + """ + self.optimize_loop(ops, expected) + + def test_virtual_raw_malloc_force(self): + ops = """ + [i1] + i2 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i2, 0, i1, descr=rawarraydescr_char) + setarrayitem_raw(i2, 2, 456, descr=rawarraydescr_char) + setarrayitem_raw(i2, 1, 123, descr=rawarraydescr_char) + label('foo') # we expect the buffer to be forced *after* the label + escape(i2) + call('free', i2, descr=raw_free_descr) + jump(i1) + """ + expected = """ + [i1] + label('foo') + i2 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i2, 0, i1, descr=rawarraydescr_char) + i3 = int_add(i2, 1) + setarrayitem_raw(i3, 0, 123, descr=rawarraydescr_char) + i4 = int_add(i2, 2) + setarrayitem_raw(i4, 0, 456, descr=rawarraydescr_char) + escape(i2) + call('free', i2, descr=raw_free_descr) + jump(i1) + """ + self.optimize_loop(ops, expected) + + def test_virtual_raw_malloc_invalid_write_force(self): + ops = """ + [i1] + i2 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) + label('foo') # we expect the buffer to be forced *after* the label + setarrayitem_raw(i2, 2, 456, descr=rawarraydescr_char) # overlap! + call('free', i2, descr=raw_free_descr) + jump(i1) + """ + expected = """ + [i1] + label('foo') + i2 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) + setarrayitem_raw(i2, 2, 456, descr=rawarraydescr_char) + call('free', i2, descr=raw_free_descr) + jump(i1) + """ + self.optimize_loop(ops, expected) + + def test_virtual_raw_malloc_invalid_read_force(self): + ops = """ + [i1] + i2 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) + label('foo') # we expect the buffer to be forced *after* the label + i3 = getarrayitem_raw(i2, 0, descr=rawarraydescr_char) + call('free', i2, descr=raw_free_descr) + jump(i1) + """ + expected = """ + [i1] + label('foo') + i2 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) + i3 = getarrayitem_raw(i2, 0, descr=rawarraydescr_char) + call('free', i2, descr=raw_free_descr) + jump(i1) + """ + self.optimize_loop(ops, expected) + + def test_virtual_raw_slice(self): + ops = """ + [i0, i1] + i2 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i2, 0, 42, descr=rawarraydescr_char) + i3 = int_add(i2, 1) # get a slice of the original buffer + setarrayitem_raw(i3, 0, 4242, descr=rawarraydescr) # write to the slice + i4 = getarrayitem_raw(i2, 0, descr=rawarraydescr_char) + i5 = int_add(i2, 1) + i6 = getarrayitem_raw(i5, 0, descr=rawarraydescr) + call('free', i2, descr=raw_free_descr) + jump(i0, i1) + """ + expected = """ + [i0, i1] + jump(i0, i1) + """ + self.optimize_loop(ops, expected) + + def test_virtual_raw_slice_of_a_raw_slice(self): + ops = """ + [i0, i1] + i2 = call('malloc', 10, descr=raw_malloc_descr) + i3 = int_add(i2, 1) # get a slice of the original buffer + i4 = int_add(i3, 1) # get a slice of a slice + setarrayitem_raw(i4, 0, i1, descr=rawarraydescr_char) # write to the slice + i5 = getarrayitem_raw(i2, 2, descr=rawarraydescr_char) + call('free', i2, descr=raw_free_descr) + jump(i0, i5) + """ + expected = """ + [i0, i1] + jump(i0, i1) + """ + self.optimize_loop(ops, expected) + + def test_virtual_raw_slice_force(self): + ops = """ + [i0, i1] + i2 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i2, 0, 42, descr=rawarraydescr_char) + i3 = int_add(i2, 1) # get a slice of the original buffer + setarrayitem_raw(i3, 4, 4242, descr=rawarraydescr_char) # write to the slice + label('foo') + escape(i3) + jump(i0, i1) + """ + expected = """ + [i0, i1] + label('foo') + # these ops are generated by VirtualRawBufferValue._really_force + i2 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i2, 0, 42, descr=rawarraydescr_char) + i3 = int_add(i2, 5) # 1+4*sizeof(char) + setarrayitem_raw(i3, 0, 4242, descr=rawarraydescr_char) + # this is generated by VirtualRawSliceValue._really_force + i4 = int_add(i2, 1) + escape(i4) + jump(i0, i1) + """ + self.optimize_loop(ops, expected) + + def test_virtual_raw_malloc_virtualstate(self): + ops = """ + [i0] + i1 = getarrayitem_raw(i0, 0, descr=rawarraydescr) + i2 = int_add(i1, 1) + call('free', i0, descr=raw_free_descr) + i3 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i3, 0, i2, descr=rawarraydescr) + label('foo') + jump(i3) + """ + expected = """ + [i0] + i1 = getarrayitem_raw(i0, 0, descr=rawarraydescr) + i2 = int_add(i1, 1) + call('free', i0, descr=raw_free_descr) + label('foo') + i3 = call('malloc', 10, descr=raw_malloc_descr) + setarrayitem_raw(i3, 0, i2, descr=rawarraydescr) + jump(i3) + """ + self.optimize_loop(ops, expected) + def test_duplicate_getfield_1(self): ops = """ [p1, p2] diff --git a/rpython/jit/metainterp/optimizeopt/test/test_rawbuffer.py b/rpython/jit/metainterp/optimizeopt/test/test_rawbuffer.py new file mode 100644 --- /dev/null +++ b/rpython/jit/metainterp/optimizeopt/test/test_rawbuffer.py @@ -0,0 +1,90 @@ +import py +from rpython.jit.metainterp.optimizeopt.rawbuffer import (InvalidRawWrite, + InvalidRawRead, RawBuffer) + +class FakeCPU(object): + def unpack_arraydescr_size(self, descr): + return descr, 'foo', 'bar' + +def test_write_value(): + buf = RawBuffer(FakeCPU()) + buf.write_value(8, 4, 'descr3', 'three') + buf.write_value(0, 4, 'descr1', 'one') + buf.write_value(4, 2, 'descr2', 'two') + buf.write_value(12, 2, 'descr4', 'four') + assert buf._get_memory() == [ + ( 0, 4, 'descr1', 'one'), + ( 4, 2, 'descr2', 'two'), + ( 8, 4, 'descr3', 'three'), + (12, 2, 'descr4', 'four'), + ] + # + +def test_write_value_update(): + buf = RawBuffer(FakeCPU()) + buf.write_value(0, 4, 'descr', 'one') + buf.write_value(4, 2, 'descr', 'two') + buf.write_value(0, 4, 'descr', 'ONE') + assert buf._get_memory() == [ + ( 0, 4, 'descr', 'ONE'), + ( 4, 2, 'descr', 'two'), + ] + +def test_write_value_invalid_length(): + buf = RawBuffer(FakeCPU()) + buf.write_value(0, 4, 'descr1', 'one') + with py.test.raises(InvalidRawWrite): + buf.write_value(0, 5, 'descr1', 'two') + with py.test.raises(InvalidRawWrite): + buf.write_value(0, 4, 'descr2', 'two') + + +def test_write_value_overlapping_next(): + buf = RawBuffer(FakeCPU()) + buf.write_value(0, 4, 'descr', 'one') + buf.write_value(6, 4, 'descr', 'two') + with py.test.raises(InvalidRawWrite): + buf.write_value(4, 4, 'descr', 'three') + +def test_write_value_overlapping_prev(): + buf = RawBuffer(FakeCPU()) + buf.write_value(0, 4, 'descr', 'one') + with py.test.raises(InvalidRawWrite): + buf.write_value(2, 1, 'descr', 'two') + +def test_read_value(): + buf = RawBuffer(FakeCPU()) + buf.write_value(0, 4, 'descr', 'one') + buf.write_value(4, 4, 'descr', 'two') + assert buf.read_value(0, 4, 'descr') == 'one' + assert buf.read_value(4, 4, 'descr') == 'two' + with py.test.raises(InvalidRawRead): + buf.read_value(0, 2, 'descr') + with py.test.raises(InvalidRawRead): + buf.read_value(8, 2, 'descr') + with py.test.raises(InvalidRawRead): + buf.read_value(0, 4, 'another descr') + +def test_unpack_descrs(): + ArrayS_8_1 = object() + ArrayS_8_2 = object() + ArrayU_8 = object() + + class FakeCPU(object): + def unpack_arraydescr_size(self, descr): + if descr in (ArrayS_8_1, ArrayS_8_2): + return 0, 8, True + return 0, 8, False + + buf = RawBuffer(FakeCPU()) + buf.write_value(0, 4, ArrayS_8_1, 'one') + assert buf.read_value(0, 4, ArrayS_8_1) == 'one' + assert buf.read_value(0, 4, ArrayS_8_2) == 'one' # with a non-identical descr + # + buf.write_value(0, 4, ArrayS_8_2, 'two') # with a non-identical descr + assert buf.read_value(0, 4, ArrayS_8_1) == 'two' + # + with py.test.raises(InvalidRawRead): + buf.read_value(0, 4, ArrayU_8) + with py.test.raises(InvalidRawWrite): + buf.write_value(0, 4, ArrayU_8, 'three') diff --git a/rpython/jit/metainterp/optimizeopt/test/test_util.py b/rpython/jit/metainterp/optimizeopt/test/test_util.py --- a/rpython/jit/metainterp/optimizeopt/test/test_util.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_util.py @@ -196,6 +196,15 @@ EffectInfo.EF_CANNOT_RAISE, oopspecindex=EffectInfo.OS_ARRAYCOPY)) + raw_malloc_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, + EffectInfo([], [], [], [], + EffectInfo.EF_CAN_RAISE, + oopspecindex=EffectInfo.OS_RAW_MALLOC_VARSIZE_CHAR)) + raw_free_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, + EffectInfo([], [], [], [], + EffectInfo.EF_CANNOT_RAISE, + oopspecindex=EffectInfo.OS_RAW_FREE)) + # array of structs (complex data) complexarray = lltype.GcArray( @@ -208,6 +217,12 @@ complexrealdescr = cpu.interiorfielddescrof(complexarray, "real") compleximagdescr = cpu.interiorfielddescrof(complexarray, "imag") + rawarraydescr = cpu.arraydescrof(lltype.Array(lltype.Signed, + hints={'nolength': True})) + rawarraydescr_char = cpu.arraydescrof(lltype.Array(lltype.Char, + hints={'nolength': True})) + + for _name, _os in [ ('strconcatdescr', 'OS_STR_CONCAT'), ('strslicedescr', 'OS_STR_SLICE'), diff --git a/rpython/jit/metainterp/optimizeopt/virtualize.py b/rpython/jit/metainterp/optimizeopt/virtualize.py --- a/rpython/jit/metainterp/optimizeopt/virtualize.py +++ b/rpython/jit/metainterp/optimizeopt/virtualize.py @@ -6,7 +6,9 @@ from rpython.jit.metainterp.optimizeopt import optimizer from rpython.jit.metainterp.optimizeopt.optimizer import OptValue, REMOVED from rpython.jit.metainterp.optimizeopt.util import (make_dispatcher_method, - descrlist_dict, sort_descrs) + descrlist_dict, sort_descrs) + +from rpython.jit.metainterp.optimizeopt.rawbuffer import RawBuffer, InvalidRawOperation from rpython.jit.metainterp.resoperation import rop, ResOperation from rpython.rlib.objectmodel import we_are_translated @@ -236,8 +238,36 @@ def _get_descr(self): return self.structdescr +class AbstractVArrayValue(AbstractVirtualValue): + """ + Base class for VArrayValue (for normal GC arrays) and VRawBufferValue (for + malloc()ed memory) + """ -class VArrayValue(AbstractVirtualValue): + def getlength(self): + return len(self._items) + + def get_item_value(self, i): + raise NotImplementedError + + def set_item_value(self, i, newval): + raise NotImplementedError + + def get_args_for_fail(self, modifier): + if self.box is None and not modifier.already_seen_virtual(self.keybox): + # checks for recursion: it is False unless + # we have already seen the very same keybox + itemboxes = [] + for i in range(self.getlength()): + itemvalue = self.get_item_value(i) + itemboxes.append(itemvalue.get_key_box()) + modifier.register_virtual_fields(self.keybox, itemboxes) + for i in range(self.getlength()): + itemvalue = self.get_item_value(i) + itemvalue.get_args_for_fail(modifier) + + +class VArrayValue(AbstractVArrayValue): def __init__(self, arraydescr, constvalue, size, keybox, source_op=None): AbstractVirtualValue.__init__(self, keybox, source_op) @@ -248,6 +278,12 @@ def getlength(self): return len(self._items) + def get_item_value(self, i): + return self._items[i] + + def set_item_value(self, i, newval): + self._items[i] = newval + def getitem(self, index): res = self._items[index] return res @@ -257,11 +293,16 @@ self._items[index] = itemvalue def force_at_end_of_preamble(self, already_forced, optforce): + # note that this method is on VArrayValue instead of + # AbstractVArrayValue because we do not want to support virtualstate + # for rawbuffers for now if self in already_forced: return self already_forced[self] = self - for index in range(len(self._items)): - self._items[index] = self._items[index].force_at_end_of_preamble(already_forced, optforce) + for index in range(self.getlength()): + itemval = self.get_item_value(index) + itemval = itemval.force_at_end_of_preamble(already_forced, optforce) + self.set_item_value(index, itemval) return self def _really_force(self, optforce): @@ -281,29 +322,16 @@ descr=self.arraydescr) optforce.emit_operation(op) - def get_args_for_fail(self, modifier): - if self.box is None and not modifier.already_seen_virtual(self.keybox): - # checks for recursion: it is False unless - # we have already seen the very same keybox - itemboxes = [] - for itemvalue in self._items: - itemboxes.append(itemvalue.get_key_box()) - modifier.register_virtual_fields(self.keybox, itemboxes) - for itemvalue in self._items: - itemvalue.get_args_for_fail(modifier) - def _make_virtual(self, modifier): return modifier.make_varray(self.arraydescr) + class VArrayStructValue(AbstractVirtualValue): def __init__(self, arraydescr, size, keybox, source_op=None): AbstractVirtualValue.__init__(self, keybox, source_op) self.arraydescr = arraydescr self._items = [{} for _ in xrange(size)] - def getlength(self): - return len(self._items) - def getinteriorfield(self, index, ofs, default): return self._items[index].get(ofs, default) @@ -363,6 +391,90 @@ return modifier.make_varraystruct(self.arraydescr, self._get_list_of_descrs()) +class VRawBufferValue(AbstractVArrayValue): + + def __init__(self, cpu, logops, size, keybox, source_op): + AbstractVirtualValue.__init__(self, keybox, source_op) + # note that size is unused, because we assume that the buffer is big + # enough to write/read everything we need. If it's not, it's undefined + # behavior anyway, although in theory we could probably detect such + # cases here + self.size = size + self.buffer = RawBuffer(cpu, logops) + + def getlength(self): + return len(self.buffer.values) + + def get_item_value(self, i): + return self.buffer.values[i] + + def set_item_value(self, i, newval): + self.buffer.values[i] = newval + + def getitem_raw(self, offset, length, descr): + return self.buffer.read_value(offset, length, descr) + + def setitem_raw(self, offset, length, descr, value): + self.buffer.write_value(offset, length, descr, value) + + def _really_force(self, optforce): + op = self.source_op + assert op is not None + if not we_are_translated(): + op.name = 'FORCE ' + self.source_op.name + optforce.emit_operation(self.source_op) + self.box = box = self.source_op.result + for i in range(len(self.buffer.offsets)): + # get a pointer to self.box+offset + offset = self.buffer.offsets[i] + if offset == 0: + arraybox = self.box + else: + arraybox = BoxInt() + op = ResOperation(rop.INT_ADD, + [self.box, ConstInt(offset)], arraybox) + optforce.emit_operation(op) + # + # write the value + descr = self.buffer.descrs[i] + itemvalue = self.buffer.values[i] + itembox = itemvalue.force_box(optforce) + op = ResOperation(rop.SETARRAYITEM_RAW, + [arraybox, ConstInt(0), itembox], None, + descr=descr) + optforce.emit_operation(op) + + def _make_virtual(self, modifier): + # I *think* we need to make a copy of offsets and descrs because we + # want a snapshot of the virtual state right now: if we grow more + # elements later, we don't want them to go in this virtual state + return modifier.make_vrawbuffer(self.size, + self.buffer.offsets[:], + self.buffer.descrs[:]) + + +class VRawSliceValue(AbstractVirtualValue): + + def __init__(self, rawbuffer_value, offset, keybox, source_op): + AbstractVirtualValue.__init__(self, keybox, source_op) + self.rawbuffer_value = rawbuffer_value + self.offset = offset + + def _really_force(self, optforce): + op = self.source_op + assert op is not None + if not we_are_translated(): + op.name = 'FORCE ' + self.source_op.name + self.box = self.source_op.result + self.rawbuffer_value.force_box(optforce) + optforce.emit_operation(op) + + def setitem_raw(self, offset, length, descr, value): + self.rawbuffer_value.setitem_raw(self.offset+offset, length, descr, value) + + def getitem_raw(self, offset, length, descr): + return self.rawbuffer_value.getitem_raw(self.offset+offset, length, descr) + class OptVirtualize(optimizer.Optimization): "Virtualize objects until they escape." @@ -388,6 +500,17 @@ self.make_equal_to(box, vvalue) return vvalue + def make_virtual_raw_memory(self, size, box, source_op): + logops = self.optimizer.loop.logops + vvalue = VRawBufferValue(self.optimizer.cpu, logops, size, box, source_op) + self.make_equal_to(box, vvalue) + return vvalue + + def make_virtual_raw_slice(self, rawbuffer_value, offset, box, source_op): + vvalue = VRawSliceValue(rawbuffer_value, offset, box, source_op) + self.make_equal_to(box, vvalue) + return vvalue + def optimize_GUARD_NO_EXCEPTION(self, op): if self.last_emitted_operation is REMOVED: return @@ -524,6 +647,43 @@ self.getvalue(op.result).ensure_nonnull() self.emit_operation(op) + def optimize_CALL(self, op): + effectinfo = op.getdescr().get_extra_info() + if effectinfo.oopspecindex == EffectInfo.OS_RAW_MALLOC_VARSIZE_CHAR: + self.do_RAW_MALLOC_VARSIZE_CHAR(op) + elif effectinfo.oopspecindex == EffectInfo.OS_RAW_FREE: + self.do_RAW_FREE(op) + else: + self.emit_operation(op) + + def do_RAW_MALLOC_VARSIZE_CHAR(self, op): + sizebox = op.getarg(1) + if not isinstance(sizebox, ConstInt): + self.emit_operation(op) + return + size = sizebox.value + self.make_virtual_raw_memory(size, op.result, op) + + def do_RAW_FREE(self, op): + value = self.getvalue(op.getarg(1)) + if value.is_virtual(): + return + self.emit_operation(op) + + def optimize_INT_ADD(self, op): + value = self.getvalue(op.getarg(0)) + offsetbox = self.get_constant_box(op.getarg(1)) + if value.is_virtual() and offsetbox is not None: + offset = offsetbox.getint() + if isinstance(value, VRawBufferValue): + self.make_virtual_raw_slice(value, offset, op.result, op) + return + elif isinstance(value, VRawSliceValue): + offset = offset + value.offset + self.make_virtual_raw_slice(value.rawbuffer_value, offset, op.result, op) + return + self.emit_operation(op) + def optimize_ARRAYLEN_GC(self, op): value = self.getvalue(op.getarg(0)) if value.is_virtual(): @@ -558,6 +718,48 @@ value.ensure_nonnull() self.emit_operation(op) + def _unpack_arrayitem_raw_op(self, op, indexbox): + index = indexbox.getint() + cpu = self.optimizer.cpu + descr = op.getdescr() + basesize, itemsize, _ = cpu.unpack_arraydescr_size(descr) + offset = basesize + (itemsize*index) + return offset, itemsize, descr + + def optimize_GETARRAYITEM_RAW(self, op): + value = self.getvalue(op.getarg(0)) + if value.is_virtual(): + indexbox = self.get_constant_box(op.getarg(1)) + if indexbox is not None: + offset, itemsize, descr = self._unpack_arrayitem_raw_op(op, indexbox) + try: + itemvalue = value.getitem_raw(offset, itemsize, descr) + self.make_equal_to(op.result, itemvalue) + except InvalidRawOperation: + box = value.force_box(self) + op.setarg(0, box) + self.emit_operation(op) + return + value.ensure_nonnull() + self.emit_operation(op) + + def optimize_SETARRAYITEM_RAW(self, op): + value = self.getvalue(op.getarg(0)) + if value.is_virtual(): + indexbox = self.get_constant_box(op.getarg(1)) + if indexbox is not None: + offset, itemsize, descr = self._unpack_arrayitem_raw_op(op, indexbox) + itemvalue = self.getvalue(op.getarg(2)) + try: + value.setitem_raw(offset, itemsize, descr, itemvalue) + except InvalidRawOperation: + box = value.force_box(self) + op.setarg(0, box) + self.emit_operation(op) + return + value.ensure_nonnull() + self.emit_operation(op) + def optimize_GETINTERIORFIELD_GC(self, op): value = self.getvalue(op.getarg(0)) if value.is_virtual(): diff --git a/rpython/jit/metainterp/optimizeopt/virtualstate.py b/rpython/jit/metainterp/optimizeopt/virtualstate.py --- a/rpython/jit/metainterp/optimizeopt/virtualstate.py +++ b/rpython/jit/metainterp/optimizeopt/virtualstate.py @@ -158,10 +158,16 @@ def debug_header(self, indent): debug_print(indent + 'VStructStateInfo(%d):' % self.position) + class VArrayStateInfo(AbstractVirtualStateInfo): + def __init__(self, arraydescr): self.arraydescr = arraydescr + def _generalization_of(self, other): + return (isinstance(other, VArrayStateInfo) and + self.arraydescr is other.arraydescr) + def generalization_of(self, other, renum, bad): assert self.position != -1 if self.position in renum: @@ -187,10 +193,6 @@ return False return True - def _generalization_of(self, other): - return (isinstance(other, VArrayStateInfo) and - self.arraydescr is other.arraydescr) - def enum_forced_boxes(self, boxes, value, optimizer): if not isinstance(value, virtualize.VArrayValue): raise BadVirtualState @@ -198,7 +200,7 @@ raise BadVirtualState for i in range(len(self.fieldstate)): try: - v = value._items[i] + v = value.get_item_value(i) except IndexError: raise BadVirtualState s = self.fieldstate[i] @@ -212,6 +214,8 @@ def debug_header(self, indent): debug_print(indent + 'VArrayStateInfo(%d):' % self.position) + From noreply at buildbot.pypy.org Mon Apr 15 22:32:26 2013 From: noreply at buildbot.pypy.org (arigo) Date: Mon, 15 Apr 2013 22:32:26 +0200 (CEST) Subject: [pypy-commit] pypy.org extradoc: Update the status of gcc 4.8. Message-ID: <20130415203226.3DC3E1C01FD@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: extradoc Changeset: r402:216f0090f704 Date: 2013-04-15 22:32 +0200 http://bitbucket.org/pypy/pypy.org/changeset/216f0090f704/ Log: Update the status of gcc 4.8. diff --git a/download.html b/download.html --- a/download.html +++ b/download.html @@ -134,7 +134,7 @@

        Building from source

        -

        Warning: the new gcc 4.8 doesn't compile PyPy correctly. +

        Warning: the new gcc 4.8 doesn't compile the release branch of PyPy correctly. As a workaround, run with CFLAGS=-fno-aggressive-loop-optimizations

        1. Get the source code. The following packages contain the source at diff --git a/source/download.txt b/source/download.txt --- a/source/download.txt +++ b/source/download.txt @@ -134,7 +134,7 @@ Building from source ------------------------------- -**Warning:** the new gcc 4.8 doesn't compile PyPy correctly. +**Warning:** the new gcc 4.8 doesn't compile the release branch of PyPy correctly. As a workaround, run with ``CFLAGS=-fno-aggressive-loop-optimizations`` 1. Get the source code. The following packages contain the source at From noreply at buildbot.pypy.org Mon Apr 15 23:04:17 2013 From: noreply at buildbot.pypy.org (fijal) Date: Mon, 15 Apr 2013 23:04:17 +0200 (CEST) Subject: [pypy-commit] pypy fast-newarray: rewrite for str and unicode Message-ID: <20130415210417.D1C5F1C311F@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: fast-newarray Changeset: r63391:c89be8d76c1e Date: 2013-04-15 22:40 +0200 http://bitbucket.org/pypy/pypy/changeset/c89be8d76c1e/ Log: rewrite for str and unicode diff --git a/rpython/jit/backend/llsupport/rewrite.py b/rpython/jit/backend/llsupport/rewrite.py --- a/rpython/jit/backend/llsupport/rewrite.py +++ b/rpython/jit/backend/llsupport/rewrite.py @@ -8,6 +8,10 @@ from rpython.jit.backend.llsupport.descr import SizeDescr, ArrayDescr from rpython.jit.metainterp.history import JitCellToken +FLAG_ARRAY = 0 +FLAG_STR = 1 +FLAG_UNICODE = 2 + class GcRewriterAssembler(object): """ This class performs the following rewrites on the list of operations: @@ -299,15 +303,28 @@ arraydescr): """ itemsize is an int, v_length and v_result are boxes """ - if (arraydescr.basesize != self.gc_ll_descr.standard_array_basesize - or arraydescr.lendescr.offset != - self.gc_ll_descr.standard_array_length_ofs): + gc_descr = self.gc_ll_descr + str_descr = gc_descr.str_descr + unicode_descr = gc_descr.unicode_descr + if (arraydescr.basesize == gc_descr.standard_array_basesize and + arraydescr.lendescr.offset == gc_descr.standard_array_length_ofs): + flag = FLAG_ARRAY # standard array + elif (arraydescr.basesize == str_descr.basesize and + arraydescr.lendescr.offset == str_descr.lendescr.offset): + flag = FLAG_STR + elif (arraydescr.basesize == unicode_descr.basesize and + arraydescr.lendescr.offset == unicode_descr.lendescr.offset): + # note that this might never be reached if we have the same + # offsets, that does not quite matter though + flag = FLAG_UNICODE + else: return False self.emitting_an_operation_that_can_collect() op = ResOperation(rop.CALL_MALLOC_NURSERY_VARSIZE, - [ConstInt(itemsize), v_length], + [ConstInt(flag), ConstInt(itemsize), v_length], v_result, descr=arraydescr) self.newops.append(op) + self.recent_mallocs[v_result] = None return True def gen_malloc_nursery_varsize_small(self, sizebox, v_result): diff --git a/rpython/jit/backend/llsupport/test/test_rewrite.py b/rpython/jit/backend/llsupport/test/test_rewrite.py --- a/rpython/jit/backend/llsupport/test/test_rewrite.py +++ b/rpython/jit/backend/llsupport/test/test_rewrite.py @@ -408,11 +408,23 @@ jump(i0) """, """ [i0] - p0 = call_malloc_nursery_varsize(1, i0, descr=bdescr) + p0 = call_malloc_nursery_varsize(0, 1, i0, descr=bdescr) setfield_gc(p0, i0, descr=blendescr) jump(i0) """) + def test_rewrite_new_string(self): + self.check_rewrite(""" + [i0] + p0 = newstr(i0) + jump(i0) + """, """ + [i0] + p0 = call_malloc_nursery_varsize(1, 1, i0, descr=strdescr) + setfield_gc(p0, i0, descr=strlendescr) + jump(i0) + """) + def test_rewrite_assembler_nonstandard_array(self): # a non-standard array is a bit hard to get; e.g. GcArray(Float) # is like that on Win32, but not on Linux. Build one manually... @@ -533,10 +545,12 @@ p1 = int_add(p0, %(strdescr.basesize + 16 * strdescr.itemsize)d) setfield_gc(p1, %(unicodedescr.tid)d, descr=tiddescr) setfield_gc(p1, 10, descr=unicodelendescr) - p2 = call_malloc_gc(ConstClass(malloc_unicode), i2, \ - descr=malloc_unicode_descr) - p3 = call_malloc_gc(ConstClass(malloc_str), i2, \ - descr=malloc_str_descr) + p2 = call_malloc_nursery_varsize(1, 4, i2, \ + descr=unicodedescr) + setfield_gc(p2, i2, descr=unicodelendescr) + p3 = call_malloc_nursery_varsize(1, 1, i2, \ + descr=strdescr) + setfield_gc(p3, i2, descr=strlendescr) jump() """) @@ -716,8 +730,9 @@ [i0] p0 = call_malloc_nursery(%(tdescr.size)d) setfield_gc(p0, 5678, descr=tiddescr) - p1 = call_malloc_gc(ConstClass(malloc_str), i0, \ - descr=malloc_str_descr) + p1 = call_malloc_nursery_varsize(1, 1, i0, \ + descr=strdescr) + setfield_gc(p1, i0, descr=strlendescr) cond_call_gc_wb(p0, p1, descr=wbdescr) setfield_raw(p0, p1, descr=tzdescr) jump() diff --git a/rpython/jit/metainterp/resoperation.py b/rpython/jit/metainterp/resoperation.py --- a/rpython/jit/metainterp/resoperation.py +++ b/rpython/jit/metainterp/resoperation.py @@ -525,7 +525,7 @@ 'CALL_PURE/*d', # removed before it's passed to the backend 'CALL_MALLOC_GC/*d', # like CALL, but NULL => propagate MemoryError 'CALL_MALLOC_NURSERY/1', # nursery malloc, const number of bytes, zeroed - 'CALL_MALLOC_NURSERY_VARSIZE/2d', + 'CALL_MALLOC_NURSERY_VARSIZE/3d', 'CALL_MALLOC_NURSERY_VARSIZE_SMALL/1', # nursery malloc, non-const number of bytes, zeroed # note that the number of bytes must be well known to be small enough From noreply at buildbot.pypy.org Mon Apr 15 23:04:20 2013 From: noreply at buildbot.pypy.org (fijal) Date: Mon, 15 Apr 2013 23:04:20 +0200 (CEST) Subject: [pypy-commit] pypy fast-newarray: implement the case for string and unicode too Message-ID: <20130415210420.63B701C311F@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: fast-newarray Changeset: r63392:fed361ad6aaa Date: 2013-04-15 23:03 +0200 http://bitbucket.org/pypy/pypy/changeset/fed361ad6aaa/ Log: implement the case for string and unicode too diff --git a/rpython/jit/backend/llsupport/assembler.py b/rpython/jit/backend/llsupport/assembler.py --- a/rpython/jit/backend/llsupport/assembler.py +++ b/rpython/jit/backend/llsupport/assembler.py @@ -85,8 +85,20 @@ self._build_wb_slowpath(True, withfloats=True) self._build_propagate_exception_path() if gc_ll_descr.get_malloc_slowpath_addr is not None: - self.malloc_slowpath = self._build_malloc_slowpath(varsize=False) - self.malloc_slowpath_varsize = self._build_malloc_slowpath(varsize=True) + # generate few slowpaths for various cases + self.malloc_slowpath = self._build_malloc_slowpath(kind='fixed') + self.malloc_slowpath_varsize = self._build_malloc_slowpath( + kind='var') + if hasattr(gc_ll_descr, 'malloc_str'): + self.malloc_slowpath_str = self._build_malloc_slowpath(kind='str') + else: + self.malloc_slowpath_str = None + if hasattr(gc_ll_descr, 'malloc_unicode'): + self.malloc_slowpath_unicode = self._build_malloc_slowpath( + kind='unicode') + else: + self.malloc_slowpath_unicode = None + self._build_stack_check_slowpath() if gc_ll_descr.gcrootmap: self._build_release_gil(gc_ll_descr.gcrootmap) diff --git a/rpython/jit/backend/llsupport/rewrite.py b/rpython/jit/backend/llsupport/rewrite.py --- a/rpython/jit/backend/llsupport/rewrite.py +++ b/rpython/jit/backend/llsupport/rewrite.py @@ -102,9 +102,11 @@ assert isinstance(descr, ArrayDescr) self.handle_new_array(descr, op) elif opnum == rop.NEWSTR: - self.handle_new_array(self.gc_ll_descr.str_descr, op) + self.handle_new_array(self.gc_ll_descr.str_descr, op, + kind=FLAG_STR) elif opnum == rop.NEWUNICODE: - self.handle_new_array(self.gc_ll_descr.unicode_descr, op) + self.handle_new_array(self.gc_ll_descr.unicode_descr, op, + kind=FLAG_UNICODE) else: raise NotImplementedError(op.getopname()) @@ -116,7 +118,7 @@ else: self.gen_malloc_fixedsize(size, descr.tid, op.result) - def handle_new_array(self, arraydescr, op): + def handle_new_array(self, arraydescr, op, kind=FLAG_ARRAY): v_length = op.getarg(0) total_size = -1 if isinstance(v_length, ConstInt): @@ -131,7 +133,7 @@ total_size = arraydescr.basesize elif (self.gc_ll_descr.can_use_nursery_malloc(1) and self.gen_malloc_nursery_varsize(arraydescr.itemsize, - v_length, op.result, arraydescr)): + v_length, op.result, arraydescr, kind=kind)): # note that we cannot initialize tid here, because the array # might end up being allocated by malloc_external or some # stuff that initializes GC header fields differently @@ -300,28 +302,17 @@ self.gc_ll_descr.malloc_unicode_descr) def gen_malloc_nursery_varsize(self, itemsize, v_length, v_result, - arraydescr): + arraydescr, kind=FLAG_ARRAY): """ itemsize is an int, v_length and v_result are boxes """ gc_descr = self.gc_ll_descr - str_descr = gc_descr.str_descr - unicode_descr = gc_descr.unicode_descr - if (arraydescr.basesize == gc_descr.standard_array_basesize and - arraydescr.lendescr.offset == gc_descr.standard_array_length_ofs): - flag = FLAG_ARRAY # standard array - elif (arraydescr.basesize == str_descr.basesize and - arraydescr.lendescr.offset == str_descr.lendescr.offset): - flag = FLAG_STR - elif (arraydescr.basesize == unicode_descr.basesize and - arraydescr.lendescr.offset == unicode_descr.lendescr.offset): - # note that this might never be reached if we have the same - # offsets, that does not quite matter though - flag = FLAG_UNICODE - else: + if (kind == FLAG_ARRAY and + (arraydescr.basesize != gc_descr.standard_array_basesize or + arraydescr.lendescr.offset != gc_descr.standard_array_length_ofs)): return False self.emitting_an_operation_that_can_collect() op = ResOperation(rop.CALL_MALLOC_NURSERY_VARSIZE, - [ConstInt(flag), ConstInt(itemsize), v_length], + [ConstInt(kind), ConstInt(itemsize), v_length], v_result, descr=arraydescr) self.newops.append(op) self.recent_mallocs[v_result] = None diff --git a/rpython/jit/backend/llsupport/test/test_gc_integration.py b/rpython/jit/backend/llsupport/test/test_gc_integration.py --- a/rpython/jit/backend/llsupport/test/test_gc_integration.py +++ b/rpython/jit/backend/llsupport/test/test_gc_integration.py @@ -263,8 +263,8 @@ arraydescr.tid = 15 ops = ''' [i0, i1, i2] - p0 = call_malloc_nursery_varsize(8, i0, descr=arraydescr) - p1 = call_malloc_nursery_varsize(5, i1, descr=arraydescr) + p0 = call_malloc_nursery_varsize(0, 8, i0, descr=arraydescr) + p1 = call_malloc_nursery_varsize(0, 5, i1, descr=arraydescr) guard_false(i0) [p0, p1] ''' self.interpret(ops, [1, 2, 3], @@ -286,10 +286,10 @@ self.cpu = self.getcpu(None) ops = ''' [i0, i1, i2] - p0 = call_malloc_nursery_varsize(8, i0, descr=arraydescr) - p1 = call_malloc_nursery_varsize(5, i1, descr=arraydescr) - p3 = call_malloc_nursery_varsize(5, i2, descr=arraydescr) - p4 = call_malloc_nursery_varsize(5, i2, descr=arraydescr) + p0 = call_malloc_nursery_varsize(0, 8, i0, descr=arraydescr) + p1 = call_malloc_nursery_varsize(0, 5, i1, descr=arraydescr) + p3 = call_malloc_nursery_varsize(0, 5, i2, descr=arraydescr) + p4 = call_malloc_nursery_varsize(0, 5, i2, descr=arraydescr) # overflow guard_false(i0) [p0, p1, p3, p4] ''' @@ -816,7 +816,7 @@ pdying = getarrayitem_gc(p0, 0, descr=arraydescr) px = call_may_force(ConstClass(fptr), pf, pdying, i0, descr=calldescr) guard_not_forced(descr=faildescr) [p1, p2, p3, px] - finish(px, descr=finishdescr) + finish(px, descr=finaldescr) """, namespace={'fptr': fptr, 'calldescr': calldescr, 'arraydescr': cpu.arraydescrof(A), 'faildescr': BasicFailDescr(1), @@ -860,7 +860,7 @@ pdying = getarrayitem_gc(p0, 0, descr=arraydescr) px = call(ConstClass(fptr), pf, pdying, i0, descr=calldescr) guard_false(i0, descr=faildescr) [p1, p2, p3, px] - finish(px, descr=finishdescr) + finish(px, descr=finaldescr) """, namespace={'fptr': fptr, 'calldescr': calldescr, 'arraydescr': cpu.arraydescrof(A), 'faildescr': BasicFailDescr(1), diff --git a/rpython/jit/backend/llsupport/test/test_rewrite.py b/rpython/jit/backend/llsupport/test/test_rewrite.py --- a/rpython/jit/backend/llsupport/test/test_rewrite.py +++ b/rpython/jit/backend/llsupport/test/test_rewrite.py @@ -545,7 +545,7 @@ p1 = int_add(p0, %(strdescr.basesize + 16 * strdescr.itemsize)d) setfield_gc(p1, %(unicodedescr.tid)d, descr=tiddescr) setfield_gc(p1, 10, descr=unicodelendescr) - p2 = call_malloc_nursery_varsize(1, 4, i2, \ + p2 = call_malloc_nursery_varsize(2, 4, i2, \ descr=unicodedescr) setfield_gc(p2, i2, descr=unicodelendescr) p3 = call_malloc_nursery_varsize(1, 1, i2, \ diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -1,7 +1,7 @@ import sys import os -from rpython.jit.backend.llsupport import symbolic, jitframe +from rpython.jit.backend.llsupport import symbolic, jitframe, gc from rpython.jit.backend.llsupport.assembler import (GuardToken, BaseAssembler, DEBUG_COUNTER, debug_bridge) from rpython.jit.backend.llsupport.asmmemmgr import MachineDataBlockWrapper @@ -156,22 +156,27 @@ mc.RET() self._frame_realloc_slowpath = mc.materialize(self.cpu.asmmemmgr, []) - def _build_malloc_slowpath(self, varsize): + def _build_malloc_slowpath(self, kind): """ While arriving on slowpath, we have a gcpattern on stack, nursery_head in eax and the size in edi - eax """ + assert kind in ['fixed', 'str', 'unicode', 'var'] mc = codebuf.MachineCodeBlockWrapper() self._push_all_regs_to_frame(mc, [eax, edi], self.cpu.supports_floats) ofs = self.cpu.get_ofs_of_frame_field('jf_gcmap') # store the gc pattern mc.MOV_rs(ecx.value, WORD) mc.MOV_br(ofs, ecx.value) - if varsize: + if kind == 'fixed': + addr = self.cpu.gc_ll_descr.get_malloc_slowpath_addr() + elif kind == 'str': + addr = self.cpu.gc_ll_descr.get_malloc_fn_addr('malloc_str') + elif kind == 'unicode': + addr = self.cpu.gc_ll_descr.get_malloc_fn_addr('malloc_unicode') + else: addr = self.cpu.gc_ll_descr.get_malloc_slowpath_array_addr() - else: - addr = self.cpu.gc_ll_descr.get_malloc_slowpath_addr() mc.SUB_ri(esp.value, 16 - WORD) - if not varsize: + if kind == 'fixed': mc.SUB_rr(edi.value, eax.value) # compute the size we want # the arg is already in edi if IS_X86_32: @@ -181,6 +186,11 @@ elif hasattr(self.cpu.gc_ll_descr, 'passes_frame'): # for tests only mc.MOV_rr(esi.value, ebp.value) + elif kind == 'str' or kind == 'unicode': + if IS_X86_32: + xxx + else: + mc.MOV_rs(edi.value, WORD * 3) else: if IS_X86_32: xxx @@ -2354,7 +2364,7 @@ self.mc.overwrite(jmp_adr-1, chr(offset)) self.mc.MOV(heap(nursery_free_adr), edi) - def malloc_cond_varsize(self, nursery_free_adr, nursery_top_adr, + def malloc_cond_varsize(self, kind, nursery_free_adr, nursery_top_adr, lengthloc, itemsize, maxlength, gcmap, arraydescr): from rpython.jit.backend.llsupport.descr import ArrayDescr @@ -2376,9 +2386,12 @@ offset = self.mc.get_relative_pos() - jmp_adr0 assert 0 < offset <= 127 self.mc.overwrite(jmp_adr0-1, chr(offset)) - self.mc.MOV_si(WORD, itemsize) - self.mc.MOV(RawEspLoc(WORD * 2, INT), lengthloc) - self.mc.MOV_si(WORD * 3, arraydescr.tid) + if kind == 0: + self.mc.MOV_si(WORD, itemsize) + self.mc.MOV(RawEspLoc(WORD * 2, INT), lengthloc) + self.mc.MOV_si(WORD * 3, arraydescr.tid) + else: + self.mc.MOV(RawEspLoc(WORD, INT), lengthloc) # save the gcmap self.push_gcmap(self.mc, gcmap, mov=True) self.mc.CALL(imm(self.malloc_slowpath_varsize)) diff --git a/rpython/jit/backend/x86/regalloc.py b/rpython/jit/backend/x86/regalloc.py --- a/rpython/jit/backend/x86/regalloc.py +++ b/rpython/jit/backend/x86/regalloc.py @@ -871,7 +871,7 @@ sizeloc, gcmap) def consider_call_malloc_nursery_varsize(self, op): - length_box = op.getarg(1) + length_box = op.getarg(2) arraydescr = op.getdescr() assert isinstance(length_box, BoxInt) # we cannot have a const here! # looking at the result @@ -886,9 +886,10 @@ self.rm.possibly_free_var(tmp_box) # gc_ll_descr = self.assembler.cpu.gc_ll_descr - itemsize = op.getarg(0).getint() + itemsize = op.getarg(1).getint() maxlength = (gc_ll_descr.max_size_of_young_obj - WORD * 2) / itemsize self.assembler.malloc_cond_varsize( + op.getarg(0).getint(), gc_ll_descr.get_nursery_free_addr(), gc_ll_descr.get_nursery_top_addr(), lengthloc, itemsize, maxlength, gcmap, arraydescr) From noreply at buildbot.pypy.org Mon Apr 15 23:09:46 2013 From: noreply at buildbot.pypy.org (fijal) Date: Mon, 15 Apr 2013 23:09:46 +0200 (CEST) Subject: [pypy-commit] pypy fast-newarray: write a test and fix it Message-ID: <20130415210946.C34F61C01FD@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: fast-newarray Changeset: r63393:4c0c30b1f265 Date: 2013-04-15 23:09 +0200 http://bitbucket.org/pypy/pypy/changeset/4c0c30b1f265/ Log: write a test and fix it diff --git a/rpython/jit/backend/llsupport/test/test_gc_integration.py b/rpython/jit/backend/llsupport/test/test_gc_integration.py --- a/rpython/jit/backend/llsupport/test/test_gc_integration.py +++ b/rpython/jit/backend/llsupport/test/test_gc_integration.py @@ -181,6 +181,12 @@ [lltype.Signed] * 3, lltype.Signed) + def malloc_str(size): + self.calls.append(('str', size)) + return 13 + self.generate_function('malloc_str', malloc_str, [lltype.Signed], + lltype.Signed) + def get_nursery_free_addr(self): return rffi.cast(lltype.Signed, self.addrs) @@ -284,23 +290,26 @@ def test_malloc_nursery_varsize_slowpath(self): self.cpu = self.getcpu(None) - ops = ''' + ops = """ [i0, i1, i2] p0 = call_malloc_nursery_varsize(0, 8, i0, descr=arraydescr) p1 = call_malloc_nursery_varsize(0, 5, i1, descr=arraydescr) p3 = call_malloc_nursery_varsize(0, 5, i2, descr=arraydescr) + # overflow p4 = call_malloc_nursery_varsize(0, 5, i2, descr=arraydescr) - # overflow + # we didn't collect, so still overflow + p5 = call_malloc_nursery_varsize(1, 5, i2, descr=strdescr) guard_false(i0) [p0, p1, p3, p4] - ''' + """ A = lltype.GcArray(lltype.Signed) arraydescr = self.cpu.arraydescrof(A) arraydescr.tid = 15 self.interpret(ops, [10, 3, 3], - namespace={'arraydescr': arraydescr}) + namespace={'arraydescr': arraydescr, + 'strdescr': arraydescr}) # check the returned pointers gc_ll_descr = self.cpu.gc_ll_descr - assert gc_ll_descr.calls == [(8, 15, 10), (5, 15, 3)] + assert gc_ll_descr.calls == [(8, 15, 10), (5, 15, 3), ('str', 3)] # one fit, one was too large, one was not fitting def test_malloc_slowpath(self): diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -2390,11 +2390,17 @@ self.mc.MOV_si(WORD, itemsize) self.mc.MOV(RawEspLoc(WORD * 2, INT), lengthloc) self.mc.MOV_si(WORD * 3, arraydescr.tid) + addr = self.malloc_slowpath_varsize else: + if kind == 1: + addr = self.malloc_slowpath_str + else: + assert kind == 2 + addr = self.malloc_slowpath_unicode self.mc.MOV(RawEspLoc(WORD, INT), lengthloc) # save the gcmap self.push_gcmap(self.mc, gcmap, mov=True) - self.mc.CALL(imm(self.malloc_slowpath_varsize)) + self.mc.CALL(imm(addr)) offset = self.mc.get_relative_pos() - jmp_adr1 assert 0 < offset <= 127 self.mc.overwrite(jmp_adr1-1, chr(offset)) From noreply at buildbot.pypy.org Tue Apr 16 00:20:03 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Tue, 16 Apr 2013 00:20:03 +0200 (CEST) Subject: [pypy-commit] pypy py3k: string-escape no longer a formal codec in py3 Message-ID: <20130415222003.5F93D1C311F@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63394:01af16cf5675 Date: 2013-04-15 15:19 -0700 http://bitbucket.org/pypy/pypy/changeset/01af16cf5675/ Log: string-escape no longer a formal codec in py3 diff --git a/pypy/module/_codecs/test/test_codecs.py b/pypy/module/_codecs/test/test_codecs.py --- a/pypy/module/_codecs/test/test_codecs.py +++ b/pypy/module/_codecs/test/test_codecs.py @@ -288,10 +288,11 @@ assert _codecs.escape_decode(b'\\08')[0] == b'\0' + b'8' def test_escape_decode_errors(self): - raises(ValueError, br"\x".decode, 'string_escape') - raises(ValueError, br"[\x]".decode, 'string_escape') - raises(ValueError, br"\x0".decode, 'string_escape') - raises(ValueError, br"[\x0]".decode, 'string_escape') + import _codecs + raises(ValueError, _codecs.escape_decode, br"\x") + raises(ValueError, _codecs.escape_decode, br"[\x]") + raises(ValueError, _codecs.escape_decode, br"\x0") + raises(ValueError, _codecs.escape_decode, br"[\x0]") def test_escape_encode(self): import _codecs From noreply at buildbot.pypy.org Tue Apr 16 00:40:12 2013 From: noreply at buildbot.pypy.org (fijal) Date: Tue, 16 Apr 2013 00:40:12 +0200 (CEST) Subject: [pypy-commit] pypy fast-newarray: make sure our stuff is correctly aligned Message-ID: <20130415224012.2D6D61C311F@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: fast-newarray Changeset: r63395:68fbb849da58 Date: 2013-04-16 00:39 +0200 http://bitbucket.org/pypy/pypy/changeset/68fbb849da58/ Log: make sure our stuff is correctly aligned diff --git a/rpython/jit/backend/llsupport/test/test_gc_integration.py b/rpython/jit/backend/llsupport/test/test_gc_integration.py --- a/rpython/jit/backend/llsupport/test/test_gc_integration.py +++ b/rpython/jit/backend/llsupport/test/test_gc_integration.py @@ -284,7 +284,7 @@ # check the nursery content and state assert gc_ll_descr.nursery[0] == chr(15) assert gc_ll_descr.nursery[2 * WORD + 8] == chr(15) - assert gc_ll_descr.addrs[0] == nurs_adr + 4 * WORD + 8*1 + 5*2 + assert gc_ll_descr.addrs[0] == nurs_adr + (((4 * WORD + 8*1 + 5*2) + (WORD - 1)) & ~(WORD - 1)) # slowpath never called assert gc_ll_descr.calls == [] diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -2375,8 +2375,12 @@ jmp_adr0 = self.mc.get_relative_pos() self.mc.MOV(eax, heap(nursery_free_adr)) self.mc.MOV(edi, lengthloc) - self.mc.IMUL(edi, imm(itemsize)) - self.mc.ADD(edi, imm(WORD * 2)) + if itemsize == 0: + self.mc.ADD_ri(edi.value, 2 * WORD) + else: + self.mc.IMUL_ri(edi.value, itemsize) + self.mc.ADD_ri(edi.value, WORD * 2 + WORD - 1) + self.mc.AND_ri(edi.value, ~(WORD - 1)) self.mc.ADD(edi, heap(nursery_free_adr)) self.mc.CMP(edi, heap(nursery_top_adr)) # write down the tid From noreply at buildbot.pypy.org Tue Apr 16 00:47:22 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Tue, 16 Apr 2013 00:47:22 +0200 (CEST) Subject: [pypy-commit] pypy default: document this test's workaround better based on mattip's analysis Message-ID: <20130415224722.67ACE1C01FD@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63396:200fdf59cb0d Date: 2013-04-15 18:46 -0400 http://bitbucket.org/pypy/pypy/changeset/200fdf59cb0d/ Log: document this test's workaround better based on mattip's analysis diff --git a/pypy/module/__pypy__/test/test_signal.py b/pypy/module/__pypy__/test/test_signal.py --- a/pypy/module/__pypy__/test/test_signal.py +++ b/pypy/module/__pypy__/test/test_signal.py @@ -25,7 +25,7 @@ __pypy__.thread._signals_enter() def test_enable_signals(self): - import __pypy__, thread, signal, time + import __pypy__, thread, signal, time, sys def subthread(): try: @@ -42,12 +42,16 @@ # This is normally called by app_main.py signal.signal(signal.SIGINT, signal.default_int_handler) + if sys.platform.startswith('win'): + # Windows seems to hang on _setmode when the first print comes from + # a thread, so make sure we've initialized io + sys.stdout + for i in range(10): __pypy__.thread._signals_exit() try: done = [] interrupted = [] - print 'starting',i thread.start_new_thread(subthread, ()) for j in range(10): if len(done): break @@ -101,7 +105,7 @@ py.test.skip("this is only a test for -A runs on top of pypy") def test_enable_signals(self): - import __pypy__, thread, signal, time + import __pypy__, thread, time interrupted = [] lock = thread.allocate_lock() diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py --- a/rpython/rlib/rposix.py +++ b/rpython/rlib/rposix.py @@ -266,4 +266,3 @@ os_kill = rwin32.os_kill else: os_kill = os.kill - diff --git a/rpython/rlib/streamio.py b/rpython/rlib/streamio.py --- a/rpython/rlib/streamio.py +++ b/rpython/rlib/streamio.py @@ -89,7 +89,7 @@ def _setfd_binary(fd): pass - + def fdopen_as_stream(fd, mode, buffering=-1): # XXX XXX XXX you want do check whether the modes are compatible # otherwise you get funny results From noreply at buildbot.pypy.org Tue Apr 16 01:07:11 2013 From: noreply at buildbot.pypy.org (fijal) Date: Tue, 16 Apr 2013 01:07:11 +0200 (CEST) Subject: [pypy-commit] pypy fast-newarray: get correct values instead of hardcoding them Message-ID: <20130415230711.914E11C313B@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: fast-newarray Changeset: r63397:58720f75e1c0 Date: 2013-04-16 01:06 +0200 http://bitbucket.org/pypy/pypy/changeset/58720f75e1c0/ Log: get correct values instead of hardcoding them diff --git a/rpython/jit/backend/llsupport/assembler.py b/rpython/jit/backend/llsupport/assembler.py --- a/rpython/jit/backend/llsupport/assembler.py +++ b/rpython/jit/backend/llsupport/assembler.py @@ -70,6 +70,12 @@ # the address of the function called by 'new' gc_ll_descr = self.cpu.gc_ll_descr gc_ll_descr.initialize() + self.gc_minimal_size_in_nursery = getattr(gc_ll_descr, + 'minimal_size_in_nursery', 0) + if hasattr(gc_ll_descr, 'gcheaderbuilder'): + self.gc_size_of_header = gc_ll_descr.gcheaderbuilder.size_gc_header + else: + self.gc_size_of_header = WORD # for tests self.memcpy_addr = self.cpu.cast_ptr_to_int(memcpy_fn) self._build_failure_recovery(False, withfloats=False) self._build_failure_recovery(True, withfloats=False) diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -2375,12 +2375,11 @@ jmp_adr0 = self.mc.get_relative_pos() self.mc.MOV(eax, heap(nursery_free_adr)) self.mc.MOV(edi, lengthloc) - if itemsize == 0: - self.mc.ADD_ri(edi.value, 2 * WORD) - else: - self.mc.IMUL_ri(edi.value, itemsize) - self.mc.ADD_ri(edi.value, WORD * 2 + WORD - 1) - self.mc.AND_ri(edi.value, ~(WORD - 1)) + assert arraydescr.basesize >= self.gc_minimal_size_in_nursery + self.mc.IMUL_ri(edi.value, itemsize) + header_size = self.gc_size_of_header + self.mc.ADD_ri(edi.value, arraydescr.basesize + header_size + WORD - 1) + self.mc.AND_ri(edi.value, ~(WORD - 1)) self.mc.ADD(edi, heap(nursery_free_adr)) self.mc.CMP(edi, heap(nursery_top_adr)) # write down the tid From noreply at buildbot.pypy.org Tue Apr 16 01:09:53 2013 From: noreply at buildbot.pypy.org (fijal) Date: Tue, 16 Apr 2013 01:09:53 +0200 (CEST) Subject: [pypy-commit] pypy fast-newarray: rpythonize? Message-ID: <20130415230953.CF4751C3128@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: fast-newarray Changeset: r63398:38e5d4280eb8 Date: 2013-04-16 01:09 +0200 http://bitbucket.org/pypy/pypy/changeset/38e5d4280eb8/ Log: rpythonize? diff --git a/rpython/jit/backend/llsupport/assembler.py b/rpython/jit/backend/llsupport/assembler.py --- a/rpython/jit/backend/llsupport/assembler.py +++ b/rpython/jit/backend/llsupport/assembler.py @@ -70,8 +70,10 @@ # the address of the function called by 'new' gc_ll_descr = self.cpu.gc_ll_descr gc_ll_descr.initialize() - self.gc_minimal_size_in_nursery = getattr(gc_ll_descr, - 'minimal_size_in_nursery', 0) + if hasattr(gc_ll_descr, 'minimal_size_in_nursery'): + self.gc_minimal_size_in_nursery = gc_ll_descr.minimal_size_in_nursery + else: + self.gc_minimal_size_in_nursery = 0 if hasattr(gc_ll_descr, 'gcheaderbuilder'): self.gc_size_of_header = gc_ll_descr.gcheaderbuilder.size_gc_header else: From noreply at buildbot.pypy.org Tue Apr 16 02:53:08 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Tue, 16 Apr 2013 02:53:08 +0200 (CEST) Subject: [pypy-commit] pypy default: sometimes sqlite has four verison numbers Message-ID: <20130416005308.C3D471C3128@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r63399:bee55f6d720e Date: 2013-04-15 20:52 -0400 http://bitbucket.org/pypy/pypy/changeset/bee55f6d720e/ Log: sometimes sqlite has four verison numbers diff --git a/pypy/module/test_lib_pypy/test_sqlite3.py b/pypy/module/test_lib_pypy/test_sqlite3.py --- a/pypy/module/test_lib_pypy/test_sqlite3.py +++ b/pypy/module/test_lib_pypy/test_sqlite3.py @@ -136,7 +136,7 @@ resource.setrlimit(resource.RLIMIT_NOFILE, limit) def test_on_conflict_rollback_executemany(con): - major, minor, micro = _sqlite3.sqlite_version.split('.') + major, minor, micro = _sqlite3.sqlite_version.split('.')[:3] if (int(major), int(minor), int(micro)) < (3, 2, 2): pytest.skip("requires sqlite3 version >= 3.2.2") con.execute("create table foo(x, unique(x) on conflict rollback)") From noreply at buildbot.pypy.org Tue Apr 16 10:08:44 2013 From: noreply at buildbot.pypy.org (timfel) Date: Tue, 16 Apr 2013 10:08:44 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: fix cursor width Message-ID: <20130416080844.B19351C016E@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: Changeset: r272:5a6e9e1ccea6 Date: 2013-04-16 10:07 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/5a6e9e1ccea6/ Log: fix cursor width diff --git a/spyvm/display.py b/spyvm/display.py --- a/spyvm/display.py +++ b/spyvm/display.py @@ -133,7 +133,7 @@ data = self.words_to_bytes(len(data_words) * 4, data_words) try: mask = self.words_to_bytes(len(data_words) * 4, mask_words) - self.cursor = RSDL.CreateCursor(data, mask, w, h, x, y) + self.cursor = RSDL.CreateCursor(data, mask, w * 2, h, x, y) self.has_cursor = True RSDL.SetCursor(self.cursor) finally: From noreply at buildbot.pypy.org Tue Apr 16 11:05:29 2013 From: noreply at buildbot.pypy.org (timfel) Date: Tue, 16 Apr 2013 11:05:29 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: add travis config Message-ID: <20130416090529.D5C561C02BE@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: Changeset: r273:ffb67c65b697 Date: 2013-04-16 11:04 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/ffb67c65b697/ Log: add travis config diff --git a/.travis.yml b/.travis.yml new file mode 100644 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,22 @@ +language: python +python: + - 2.7 +env: + matrix: + - TEST_TYPE=own + - TEST_TYPE=translate +install: + - pip install rsdl --use-mirrors + - wget https://bitbucket.org/pypy/pypy/get/default.tar.bz2 -O `pwd`/../pypy.tar.bz2 || wget https://bitbucket.org/pypy/pypy/get/default.tar.bz2 -O `pwd`/../pypy.tar.bz2 + - tar -xf `pwd`/../pypy.tar.bz2 -C `pwd`/../ + - mv ../pypy-pypy* ../pypy-pypy +script: + - export PYTHONPATH=$PYTHONPATH:../pypy-pypy/:. + - "case \"$TEST_TYPE\" in + own) + py.test + ;; + translate) + python ../pypy-pypy/rpython/bin/rpython --batch targetimageloadingsmalltalk.py + ;; + esac" From noreply at buildbot.pypy.org Tue Apr 16 11:25:00 2013 From: noreply at buildbot.pypy.org (fijal) Date: Tue, 16 Apr 2013 11:25:00 +0200 (CEST) Subject: [pypy-commit] pypy default: fix whatsnew Message-ID: <20130416092500.901841C31C2@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r63400:54d761c69466 Date: 2013-04-16 11:24 +0200 http://bitbucket.org/pypy/pypy/changeset/54d761c69466/ Log: fix whatsnew diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -129,3 +129,5 @@ .. branch: release-2.0-beta2 .. branch: unbreak-freebsd + +.. branch: virtualref-virtualizable From noreply at buildbot.pypy.org Tue Apr 16 12:08:09 2013 From: noreply at buildbot.pypy.org (fijal) Date: Tue, 16 Apr 2013 12:08:09 +0200 (CEST) Subject: [pypy-commit] pypy fast-newarray: 32bit fixes Message-ID: <20130416100809.8B2AB1C01A7@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: fast-newarray Changeset: r63401:d15a04ac4d48 Date: 2013-04-16 12:07 +0200 http://bitbucket.org/pypy/pypy/changeset/d15a04ac4d48/ Log: 32bit fixes diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -188,17 +188,24 @@ mc.MOV_rr(esi.value, ebp.value) elif kind == 'str' or kind == 'unicode': if IS_X86_32: - xxx + # 1 for return value, 3 for alignment + mc.MOV_rs(edi.value, WORD * (3 + 1 + 1)) + mc.MOV_sr(0, edi.value) else: mc.MOV_rs(edi.value, WORD * 3) else: if IS_X86_32: - xxx + mc.MOV_rs(edi.value, WORD * (3 + 1 + 1)) # itemsize + mc.MOV_sr(0, edi.value) + mc.MOV_rs(edi.value, WORD * (3 + 3 + 1)) + mc.MOV_sr(WORD, edi.value) # tid + mc.MOV_rs(edi.value, WORD * (3 + 2 + 1)) + mc.MOV_sr(2 * WORD, edi.value) # length else: # offset is 1 extra for call + 1 for SUB above mc.MOV_rs(edi.value, WORD * 3) # itemsize - mc.MOV_rs(esi.value, WORD * 5) - mc.MOV_rs(edx.value, WORD * 4) # lengthloc + mc.MOV_rs(esi.value, WORD * 5) # tid + mc.MOV_rs(edx.value, WORD * 4) # length extra_ofs = self.cpu.get_ofs_of_frame_field('jf_extra_stack_depth') mc.MOV_bi(extra_ofs, 16) mc.CALL(imm(addr)) From noreply at buildbot.pypy.org Tue Apr 16 12:12:41 2013 From: noreply at buildbot.pypy.org (fijal) Date: Tue, 16 Apr 2013 12:12:41 +0200 (CEST) Subject: [pypy-commit] pypy fast-newarray: use flags and disable those on ARM Message-ID: <20130416101241.092751C01FD@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: fast-newarray Changeset: r63402:ca1767184735 Date: 2013-04-16 12:12 +0200 http://bitbucket.org/pypy/pypy/changeset/ca1767184735/ Log: use flags and disable those on ARM diff --git a/rpython/jit/backend/llsupport/llmodel.py b/rpython/jit/backend/llsupport/llmodel.py --- a/rpython/jit/backend/llsupport/llmodel.py +++ b/rpython/jit/backend/llsupport/llmodel.py @@ -21,6 +21,8 @@ class AbstractLLCPU(AbstractCPU): from rpython.jit.metainterp.typesystem import llhelper as ts + can_inline_varsize_malloc = False + def __init__(self, rtyper, stats, opts, translate_support_code=False, gcdescr=None): assert type(opts) is not bool @@ -171,9 +173,9 @@ def pos_exc_value(): addr = llop.get_exc_value_addr(llmemory.Address) return heaptracker.adr2int(addr) - + from rpython.rlib import rstack - + STACK_CHECK_SLOWPATH = lltype.Ptr(lltype.FuncType([lltype.Signed], lltype.Void)) def insert_stack_check(): diff --git a/rpython/jit/backend/llsupport/rewrite.py b/rpython/jit/backend/llsupport/rewrite.py --- a/rpython/jit/backend/llsupport/rewrite.py +++ b/rpython/jit/backend/llsupport/rewrite.py @@ -305,6 +305,8 @@ arraydescr, kind=FLAG_ARRAY): """ itemsize is an int, v_length and v_result are boxes """ + if not self.cpu.can_inline_varsize_malloc: + return False # temporary, kill when ARM supports it gc_descr = self.gc_ll_descr if (kind == FLAG_ARRAY and (arraydescr.basesize != gc_descr.standard_array_basesize or diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -1,7 +1,7 @@ import sys import os -from rpython.jit.backend.llsupport import symbolic, jitframe, gc +from rpython.jit.backend.llsupport import symbolic, jitframe, rewrite from rpython.jit.backend.llsupport.assembler import (GuardToken, BaseAssembler, DEBUG_COUNTER, debug_bridge) from rpython.jit.backend.llsupport.asmmemmgr import MachineDataBlockWrapper @@ -2396,16 +2396,16 @@ offset = self.mc.get_relative_pos() - jmp_adr0 assert 0 < offset <= 127 self.mc.overwrite(jmp_adr0-1, chr(offset)) - if kind == 0: + if kind == rewrite.FLAG_ARRAY: self.mc.MOV_si(WORD, itemsize) self.mc.MOV(RawEspLoc(WORD * 2, INT), lengthloc) self.mc.MOV_si(WORD * 3, arraydescr.tid) addr = self.malloc_slowpath_varsize else: - if kind == 1: + if kind == rewrite.FLAG_STR: addr = self.malloc_slowpath_str else: - assert kind == 2 + assert kind == rewrite.FLAG_UNICODE addr = self.malloc_slowpath_unicode self.mc.MOV(RawEspLoc(WORD, INT), lengthloc) # save the gcmap diff --git a/rpython/jit/backend/x86/runner.py b/rpython/jit/backend/x86/runner.py --- a/rpython/jit/backend/x86/runner.py +++ b/rpython/jit/backend/x86/runner.py @@ -23,6 +23,8 @@ with_threads = False frame_reg = regloc.ebp + can_inline_varsize_malloc = True + from rpython.jit.backend.x86.arch import JITFRAME_FIXED_SIZE all_reg_indexes = gpr_reg_mgr_cls.all_reg_indexes gen_regs = gpr_reg_mgr_cls.all_regs From noreply at buildbot.pypy.org Tue Apr 16 12:19:15 2013 From: noreply at buildbot.pypy.org (fijal) Date: Tue, 16 Apr 2013 12:19:15 +0200 (CEST) Subject: [pypy-commit] pypy default: print line for errors Message-ID: <20130416101915.088DD1C01FD@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r63403:7723f9d7e5a9 Date: 2013-04-16 12:21 +0200 http://bitbucket.org/pypy/pypy/changeset/7723f9d7e5a9/ Log: print line for errors diff --git a/rpython/tool/logparser.py b/rpython/tool/logparser.py --- a/rpython/tool/logparser.py +++ b/rpython/tool/logparser.py @@ -70,7 +70,11 @@ time = int(int(match.group(1), 16)) time_decrase = time_decrase or time < lasttime lasttime = time - record(match.group(2), time=int(match.group(1), 16)) + try: + record(match.group(2), time=int(match.group(1), 16)) + except: + print "Line", i + raise if verbose: sys.stderr.write('loaded\n') if performance_log and time_decrase: From noreply at buildbot.pypy.org Tue Apr 16 12:30:10 2013 From: noreply at buildbot.pypy.org (fijal) Date: Tue, 16 Apr 2013 12:30:10 +0200 (CEST) Subject: [pypy-commit] pypy fast-newarray: fix boehm translation Message-ID: <20130416103010.107161C02BE@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: fast-newarray Changeset: r63404:4d2b35e80583 Date: 2013-04-16 12:29 +0200 http://bitbucket.org/pypy/pypy/changeset/4d2b35e80583/ Log: fix boehm translation diff --git a/rpython/jit/backend/x86/regalloc.py b/rpython/jit/backend/x86/regalloc.py --- a/rpython/jit/backend/x86/regalloc.py +++ b/rpython/jit/backend/x86/regalloc.py @@ -871,6 +871,10 @@ sizeloc, gcmap) def consider_call_malloc_nursery_varsize(self, op): + gc_ll_descr = self.assembler.cpu.gc_ll_descr + if not hasattr(gc_ll_descr, 'max_size_of_young_obj'): + raise Exception("unreachable code") + # for boehm, this function should never be called length_box = op.getarg(2) arraydescr = op.getdescr() assert isinstance(length_box, BoxInt) # we cannot have a const here! @@ -885,7 +889,6 @@ gcmap = self.get_gcmap([eax, edi]) # allocate the gcmap *before* self.rm.possibly_free_var(tmp_box) # - gc_ll_descr = self.assembler.cpu.gc_ll_descr itemsize = op.getarg(1).getint() maxlength = (gc_ll_descr.max_size_of_young_obj - WORD * 2) / itemsize self.assembler.malloc_cond_varsize( From noreply at buildbot.pypy.org Tue Apr 16 13:04:07 2013 From: noreply at buildbot.pypy.org (timfel) Date: Tue, 16 Apr 2013 13:04:07 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: Adjust interrupt check constant, so we don't do it too often and slow Message-ID: <20130416110407.BE1061C01A7@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: Changeset: r274:269e560adae6 Date: 2013-04-16 13:02 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/269e560adae6/ Log: Adjust interrupt check constant, so we don't do it too often and slow down the JIT diff --git a/spyvm/constants.py b/spyvm/constants.py --- a/spyvm/constants.py +++ b/spyvm/constants.py @@ -183,4 +183,4 @@ # MAX_LOOP_DEPTH = 100 -INTERRUPT_COUNTER_SIZE = 1000 \ No newline at end of file +INTERRUPT_COUNTER_SIZE = 10000 From noreply at buildbot.pypy.org Tue Apr 16 13:12:46 2013 From: noreply at buildbot.pypy.org (timfel) Date: Tue, 16 Apr 2013 13:12:46 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: revert ovfcheck on LPI left shift Message-ID: <20130416111246.36CA71C01FD@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: Changeset: r275:69e7111b08cb Date: 2013-04-16 13:11 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/69e7111b08cb/ Log: revert ovfcheck on LPI left shift diff --git a/spyvm/model.py b/spyvm/model.py --- a/spyvm/model.py +++ b/spyvm/model.py @@ -267,15 +267,12 @@ return "W_LargePositiveInteger1Word(%d)" % r_uint(self.value) def lshift(self, space, shift): - from rpython.rlib.rarithmetic import ovfcheck, intmask, r_uint + from rpython.rlib.rarithmetic import intmask, r_uint # shift > 0, therefore the highest bit of upperbound is not set, # i.e. upperbound is positive upperbound = intmask(r_uint(-1) >> shift) if 0 <= self.value <= upperbound: - try: - shifted = intmask(ovfcheck(self.value << shift)) - except OverflowError: - raise error.PrimitiveFailedError() + shifted = intmask(self.value << shift) return space.wrap_positive_32bit_int(shifted) else: raise error.PrimitiveFailedError() From noreply at buildbot.pypy.org Tue Apr 16 13:34:55 2013 From: noreply at buildbot.pypy.org (fijal) Date: Tue, 16 Apr 2013 13:34:55 +0200 (CEST) Subject: [pypy-commit] pypy parallel-c-compilation: A first crude version of invoking multiple versions of a C compiler while Message-ID: <20130416113455.496F31C1522@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: parallel-c-compilation Changeset: r63405:2ac43e16ecda Date: 2013-04-16 13:33 +0200 http://bitbucket.org/pypy/pypy/changeset/2ac43e16ecda/ Log: A first crude version of invoking multiple versions of a C compiler while writing down source files diff --git a/rpython/tool/runsubprocess2.py b/rpython/tool/runsubprocess2.py new file mode 100644 --- /dev/null +++ b/rpython/tool/runsubprocess2.py @@ -0,0 +1,36 @@ + +import os, sys, time, select +from subprocess import Popen, PIPE +import twisted + +_child = None +_source = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +_source = os.path.join(os.path.join(_source, 'translator'), 'invoker.py') + +def spawn_subprocess(): + global _child + _child = Popen([sys.executable, '-u', _source], bufsize=0, + stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True) +spawn_subprocess() + +def cleanup_subprocess(): + global _child + _child = None +import atexit; atexit.register(cleanup_subprocess) + +def run(exe, *args): + _child.stdin.write(repr((exe,) + args) + "\n") + +class SubprocessExploded(Exception): + pass + +def results(): + results = [] + while True: + rl, _, _ = select.select([_child.stdout, _child.stderr], [], [], 0) + if _child.stderr in rl: + raise SubprocessExploded(_child.stderr) + elif _child.stdout in rl: + results.append(eval(_child.stdout.readline())) + else: + return results diff --git a/rpython/translator/c/genc.py b/rpython/translator/c/genc.py --- a/rpython/translator/c/genc.py +++ b/rpython/translator/c/genc.py @@ -1,6 +1,7 @@ import contextlib +from rpython.tool import runsubprocess2 import py -import sys, os +import sys, os, time from rpython.rlib import exports from rpython.rtyper.typesystem import getfunctionptr from rpython.tool import runsubprocess @@ -112,7 +113,7 @@ str(exename), args)) profdrv.probe(exename, args) return profdrv.after() - + class CBuilder(object): c_source_filename = None _compiled = False @@ -129,6 +130,7 @@ self.gcpolicy = gcpolicy # for tests only, e.g. rpython/memory/ self.eci = self.get_eci() self.secondary_entrypoints = secondary_entrypoints + self._files_sent = 0 def get_eci(self): pypy_include_dir = py.path.local(__file__).join('..') @@ -149,7 +151,7 @@ thread_enabled=self.config.translation.thread, sandbox=self.config.translation.sandbox) self.db = db - + # give the gc a chance to register interest in the start-up functions it # need (we call this for its side-effects of db.get()) list(db.gcpolicy.gc_startup_code()) @@ -260,12 +262,40 @@ export_symbols=["pypy_main_startup"])) self.eci, cfile, extra = gen_source(db, modulename, targetdir, self.eci, defines=defines, - split=self.split) + split=self.split, + invoke_c_callback=self._invoke_c_compiler) self.c_source_filename = py.path.local(cfile) self.extrafiles = self.eventually_copy(extra) self.gen_makefile(targetdir, exe_name=exe_name) return cfile + def _invoke_c_compiler(self, name, eci, directory): + if name is None or name.endswith('.h'): + return + shared = self.config.translation.shared + command = self.translator.platform.gen_cc_command(name, directory, eci, + shared=shared) + for name, rescode, out, err in runsubprocess2.results(): + self._files_sent -= 1 + if rescode == 0: + print "Compiled", name + else: + raise Exception("CC failed with", err) + self._files_sent += 1 + runsubprocess2.run(name, *command) + + def _wait_for_c_compiler(self): + while True: + for name, rescode, out, err in runsubprocess2.results(): + if rescode == 0: + print "Compiled", name + else: + raise Exception("CC failed with", err) + self._files_sent -= 1 + if self._files_sent == 0: + return + time.sleep(.1) + def eventually_copy(self, cfiles): extrafiles = [] for fn in cfiles: @@ -352,6 +382,7 @@ outputfilename=exe_name) def compile(self, exe_name=None): + self._wait_for_c_compiler() assert self.c_source_filename assert not self._compiled @@ -499,11 +530,14 @@ class SourceGenerator: one_source_file = True - def __init__(self, database): + def __init__(self, database, eci, invoke_c_callback=None): self.database = database + self.eci = eci self.extrafiles = [] self.path = None self.namespace = NameManager() + self._last_file_name = None + self.invoke_c_callback = invoke_c_callback def set_strategy(self, path, split=True): all_nodes = list(self.database.globalcontainers()) @@ -526,6 +560,10 @@ return self.namespace.uniquename(name[:-2]) + '.c' def makefile(self, name): + if self.invoke_c_callback is not None: + self.invoke_c_callback(self._last_file_name, self.path, + self.eci) + self._last_file_name = name log.writing(name) filepath = self.path.join(name) if name.endswith('.c'): @@ -621,7 +659,7 @@ if self.database.gcpolicy.need_no_typeptr(): pass # XXX gcc uses toooooons of memory??? else: - split_criteria_big = SPLIT_CRITERIA * 4 + split_criteria_big = SPLIT_CRITERIA * 4 # # All declarations @@ -776,7 +814,7 @@ def gen_source(database, modulename, targetdir, - eci, defines={}, split=False): + eci, defines={}, split=False, invoke_c_callback=False): if isinstance(targetdir, str): targetdir = py.path.local(targetdir) @@ -803,7 +841,7 @@ # 1) All declarations # 2) Implementation of functions and global structures and arrays # - sg = SourceGenerator(database) + sg = SourceGenerator(database, eci, invoke_c_callback) sg.set_strategy(targetdir, split) database.prepare_inline_helpers() sg.gen_readable_parts_of_source(f) diff --git a/rpython/translator/invoker.py b/rpython/translator/invoker.py new file mode 100644 --- /dev/null +++ b/rpython/translator/invoker.py @@ -0,0 +1,65 @@ + +import os +from twisted.internet import reactor +from twisted.protocols import basic +from twisted.internet import protocol, stdio +from twisted.internet.error import ProcessDone + +class SubProcessProtocol(protocol.ProcessProtocol): + def __init__(self, commander, name): + self._commander = commander + self._output = [] + self._name = name + self._error = [] + + def outReceived(self, out): + self._output.append(out) + + def errReceived(self, err): + self._error.append(err) + + def processExited(self, status): + self._commander.process_exited() + if status.value == ProcessDone: + print repr((self._name, 0, "".join(self._output), + "".join(self._error))) + else: + print repr((self._name, status.value.exitCode, + "".join(self._output), "".join(self._error))) + +MAX = 8 + +class Commander(basic.LineReceiver): + delimiter = '\n' + + def __init__(self, max=MAX): + self._counter = 0 + self._max = max + self._queue = [] + + def connectionMade(self): + pass + + def process_exited(self): + self._counter -= 1 + if self._queue: + self._run(self._queue.pop()) + + def _run(self, line): + args = eval(line) + reactor.spawnProcess(SubProcessProtocol(self, args[0]), args[1], + args[1:], env=os.environ.copy()) + self._counter += 1 + + def lineReceived(self, line): + if not line: + reactor.stop() + return + assert line.startswith('(') + if self._counter < self._max: + self._run(line) + else: + self._queue.append(line) + +stdio.StandardIO(Commander()) +reactor.run() diff --git a/rpython/translator/platform/__init__.py b/rpython/translator/platform/__init__.py --- a/rpython/translator/platform/__init__.py +++ b/rpython/translator/platform/__init__.py @@ -246,6 +246,9 @@ def _library_dirs_for_libffi(self): raise NotImplementedError("Needs to be overwritten") + def gen_cc_command(self, fname, eci, shared=False): + raise NotImplementedError("abstract base class") + def check___thread(self): return True diff --git a/rpython/translator/platform/posix.py b/rpython/translator/platform/posix.py --- a/rpython/translator/platform/posix.py +++ b/rpython/translator/platform/posix.py @@ -85,6 +85,12 @@ # strip compiler flags return [entry[2:] for entry in out.split()] + def gen_cc_command(self, fname, eci, path, shared=False): + fullname = str(path.join(fname)) + objfullname = fullname[:-2] + '.o' + return ([self.cc] + self._compile_args_from_eci(eci, not shared) + + ['-c', '-o', objfullname, fullname]) + def gen_makefile(self, cfiles, eci, exe_name=None, path=None, shared=False): cfiles = self._all_cfiles(cfiles, eci) @@ -250,7 +256,7 @@ self.defs = {} self.lines = [] self.makefile_dir = py.path.local(path) - + def pathrel(self, fpath): if fpath.dirpath() == self.makefile_dir: return fpath.basename From noreply at buildbot.pypy.org Tue Apr 16 14:01:22 2013 From: noreply at buildbot.pypy.org (timfel) Date: Tue, 16 Apr 2013 14:01:22 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: fix translation Message-ID: <20130416120122.35BE11C313B@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: Changeset: r276:7d2893d503e6 Date: 2013-04-16 14:00 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/7d2893d503e6/ Log: fix translation diff --git a/spyvm/display.py b/spyvm/display.py --- a/spyvm/display.py +++ b/spyvm/display.py @@ -81,7 +81,9 @@ else: pass # XXX: Todo? elif c_type == RSDL.QUIT: - exit(0) + from spyvm.interpreter import ReturnFromTopLevel + print "Window closed.." + raise SystemExit() finally: lltype.free(event, flavor='raw') @@ -121,6 +123,7 @@ instance = None def __init__(self): + self.cursor = lltype.nullptr(RSDL.CursorPtr.TO) self.has_cursor = False self.has_display = False @@ -129,10 +132,10 @@ return if self.has_cursor: RSDL.FreeCursor(self.cursor) + data = self.words_to_bytes(len(data_words) * 4, data_words) try: - data = self.words_to_bytes(len(data_words) * 4, data_words) + mask = self.words_to_bytes(len(data_words) * 4, mask_words) try: - mask = self.words_to_bytes(len(data_words) * 4, mask_words) self.cursor = RSDL.CreateCursor(data, mask, w * 2, h, x, y) self.has_cursor = True RSDL.SetCursor(self.cursor) diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -582,13 +582,13 @@ if not (0 <= argcount <= 1): raise PrimitiveFailedError() w_rcvr = s_frame.peek(argcount) + mask_words = None if argcount == 1: # TODO: use mask w_mask = s_frame.peek(0) if not isinstance(w_mask, model.W_WordsObject): raise PrimitiveFailedError() - else: - w_mask = None + mask_words = w_mask.words w_bitmap = w_rcvr.fetch(interp.space, 0) if not isinstance(w_bitmap, model.W_WordsObject): raise PrimitiveFailedError() @@ -602,7 +602,7 @@ height, hotpt.x(), hotpt.y(), - w_mask.words if w_mask else None + mask_words=mask_words ) interp.space.objtable['w_cursor'] = w_rcvr From noreply at buildbot.pypy.org Tue Apr 16 14:10:34 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Tue, 16 Apr 2013 14:10:34 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: moved the tracing printing code to have also the information of argcount, Message-ID: <20130416121034.CDA6F1C1522@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r277:fe9a3d548b2c Date: 2013-04-12 17:33 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/fe9a3d548b2c/ Log: moved the tracing printing code to have also the information of argcount, printing arguments now diff --git a/spyvm/interpreter.py b/spyvm/interpreter.py --- a/spyvm/interpreter.py +++ b/spyvm/interpreter.py @@ -79,10 +79,6 @@ s_new_context = p.s_new_context def c_loop(self, s_context): - # ###################################################################### - if self.trace: - padding = ' ' * (self.max_stack_depth - self.remaining_stack_depth) - print padding + s_context.short_str() old_pc = 0 if not jit.we_are_jitted(): self.quick_check_for_interrupt(s_context) @@ -112,9 +108,9 @@ def _get_adapted_tick_counter(self): # Normally, the tick counter is decremented by 1 for every message send. # Since we don't know how many messages are called during this trace, we - # just decrement by 10th of the trace length (num of bytecodes). + # just decrement by 100th of the trace length (num of bytecodes). trace_length = jit.current_trace_length() - decr_by = int(trace_length // 10) + decr_by = int(trace_length // 100) return max(decr_by, 1) def stack_frame(self, s_new_frame): @@ -325,6 +321,7 @@ def _sendSelector(self, w_selector, argcount, interp, receiver, receiverclassshadow): + assert isinstance(w_selector, model.W_BytesObject) if interp.should_trace(): print "%sSending selector %r to %r with: %r" % ( interp._last_indent, w_selector.as_string(), receiver, @@ -344,9 +341,9 @@ func = primitives.prim_holder.prim_table[code] # ################################################################## if interp.trace: - print "%s calling primitive %d \t(in #%s)" % ( + print "%s calling primitive %d \t(in #%s, named #%s)" % ( ' ' * (interp.max_stack_depth - interp.remaining_stack_depth), - code, self.w_method()._likely_methodname) + code, self.w_method()._likely_methodname, w_selector.as_string()) try: # note: argcount does not include rcvr return func(interp, self, argcount) @@ -368,6 +365,12 @@ arguments = self.pop_and_return_n(argcount) s_frame = s_method.create_frame(self.space, receiver, arguments, self) self.pop() # receiver + + # ###################################################################### + if interp.trace: + padding = ' ' * (interp.max_stack_depth - interp.remaining_stack_depth) + print padding + s_frame.short_str(argcount) + return interp.stack_frame(s_frame) def _doesNotUnderstand(self, w_selector, argcount, interp, receiver): diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -28,7 +28,6 @@ # completes, and returns a result, or throws a PrimitiveFailedError. def make_failing(code): def raise_failing_default(interp, s_frame, argument_count): -# print "Primitive failed", code raise PrimitiveFailedError return raise_failing_default @@ -527,7 +526,7 @@ INPUT_SEMAPHORE = 93 GET_NEXT_EVENT = 94 INPUT_WORD = 95 -BITBLT_COPY_BITS = 96 # OBSOLETE_INDEXED = 96 +BITBLT_COPY_BITS = 96 SNAPSHOT = 97 STORE_IMAGE_SEGMENT = 98 LOAD_IMAGE_SEGMENT = 99 @@ -542,7 +541,6 @@ KBD_NEXT = 108 KBD_PEEK = 109 - @expose_primitive(MOUSE_POINT, unwrap_spec=[object]) def func(interp, s_frame, w_rcvr): x, y = interp.space.get_display().mouse_point() diff --git a/spyvm/shadow.py b/spyvm/shadow.py --- a/spyvm/shadow.py +++ b/spyvm/shadow.py @@ -798,7 +798,7 @@ # A blockcontext doesn't have any temps return 0 - def short_str(self): + def short_str(self, argcount): return 'BlockContext of %s (%s) [%d]' % ( self.w_method().get_identifier_string(), self.w_receiver().as_repr_string(), @@ -947,13 +947,17 @@ retval += "\nStack : " + str(self.stack()) return retval - def short_str(self): + def short_str(self, argcount): block = '[] of ' if self.is_closure_context() else '' - return '%s%s (rcvr: %s) [pc: %d]' % ( + args = '%d' % argcount + for i in range(argcount - 1, -1, -1): + args += ': %s' % self.peek(i).as_repr_string() + return '%s%s (rcvr: %s) [pc: %d] (%s)' % ( block, self.w_method().get_identifier_string(), self.w_receiver().as_repr_string(), - self.pc() + 1 + self.pc() + 1, + args ) class CompiledMethodShadow(object): diff --git a/spyvm/test/test_primitives.py b/spyvm/test/test_primitives.py --- a/spyvm/test/test_primitives.py +++ b/spyvm/test/test_primitives.py @@ -637,6 +637,7 @@ assert w_1 is not w_2 def test_primitive_be_display(): + py.test.fail("This test leads to a Segfault.") assert space.objtable["w_display"] is None mock_display = model.W_PointersObject(space, space.w_Point, 4) w_wordbmp = model.W_WordsObject(space, space.w_Array, 100) @@ -670,6 +671,7 @@ assert mock_display.fetch(space, 0) is w_bitmap def test_primitive_force_display_update(monkeypatch): + py.test.fail("This test leads to a Segfault.") mock_display = model.W_PointersObject(space, space.w_Point, 4) w_wordbmp = model.W_WordsObject(space, space.w_Array, 100) mock_display.store(space, 0, w_wordbmp) # bitmap From noreply at buildbot.pypy.org Tue Apr 16 14:10:36 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Tue, 16 Apr 2013 14:10:36 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: renamed instance variable ary to contents Message-ID: <20130416121036.5FCA81C1522@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r278:d9517a43bf5e Date: 2013-04-12 17:34 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/d9517a43bf5e/ Log: renamed instance variable ary to contents changed mouse pointer tracking to comply with specifications switched bits of left and right mouse button diff --git a/spyvm/display.py b/spyvm/display.py --- a/spyvm/display.py +++ b/spyvm/display.py @@ -10,35 +10,41 @@ def __init__(self, default, maxlen=10): assert default self.default = default - self.ary = [] + self.contents = [] self.maxlen = 10 def push(self, event): - if len(self.ary) == self.maxlen: - self.ary.pop(0) - self.ary.append(event) + contents = self.contents + assert len(contents) <= self.maxlen + if len(contents) == self.maxlen: + contents.pop(0) + contents.append(event) def shift(self): - if not self.ary: - self.ary += self.default - return self.ary.pop(0) + contents = self.contents + assert len(contents) <= self.maxlen + if contents == []: + contents = list(self.default) + return contents.pop(0) def peek(self): - if self.ary: - return self.ary[0] + contents = self.contents + assert len(contents) <= self.maxlen + if contents: + return contents[0] else: return self.default[0] def size(self): - if not self.ary: + if not self.contents: return len(self.default) else: - return len(self.ary) + return len(self.contents) class SDLDisplay(object): _attrs_ = ["screen", "width", "height", "depth", "surface", "has_surface", - "last_mouse_position", "mouse_downs", "mouse_ups", "key_ups", "key_downs"] + "last_mouse_position", "last_mouse_buttons", "mouse_downs", "mouse_ups", "key_ups", "key_downs"] def __init__(self, title): assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 @@ -46,6 +52,7 @@ RSDL.EnableUNICODE(1) self.has_surface = False self.last_mouse_position = [0, 0] + self.last_mouse_buttons = 0 self.mouse_downs = SDLEventQueue([0]) self.mouse_ups = SDLEventQueue([0]) self.key_ups = SDLEventQueue([0]) @@ -74,25 +81,31 @@ ok = rffi.cast(lltype.Signed, RSDL.PollEvent(event)) if ok == 1: c_type = rffi.getintfield(event, 'c_type') + print ' %d' % c_type, if c_type == RSDL.MOUSEBUTTONDOWN or c_type == RSDL.MOUSEBUTTONUP: b = rffi.cast(RSDL.MouseButtonEventPtr, event) btn = rffi.getintfield(b, 'c_button') if btn == RSDL.BUTTON_LEFT: - btn = 1 + button = 4 elif btn == RSDL.BUTTON_MIDDLE: - btn = 2 + button = 2 elif btn == RSDL.BUTTON_RIGHT: - btn = 4 - + button = 1 + else: + assert 0 + button = 0 + if c_type == RSDL.MOUSEBUTTONDOWN: - self.mouse_downs.push(btn) + self.mouse_downs.push(button) + self.last_mouse_buttons |= button else: - self.mouse_ups.push(btn) + self.mouse_ups.push(button) + self.last_mouse_buttons &= ~button elif c_type == RSDL.MOUSEMOTION: m = rffi.cast(RSDL.MouseMotionEventPtr, event) x = rffi.getintfield(m, "c_x") y = rffi.getintfield(m, "c_y") - self.last_mouse_position = [x, y] + self.last_mouse_position = list([x, y]) elif c_type == RSDL.KEYUP or c_type == RSDL.KEYDOWN: p = rffi.cast(RSDL.KeyboardEventPtr, event) char = rffi.getintfield(p.c_keysym, 'c_unicode') @@ -111,7 +124,7 @@ def mouse_button(self): self.get_next_event() - return self.mouse_ups.shift() + return self.last_mouse_buttons def next_keycode(self): self.get_next_event() From noreply at buildbot.pypy.org Tue Apr 16 14:10:37 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Tue, 16 Apr 2013 14:10:37 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: (cfbolz): added the correct hints to the preliminary type-hinting Message-ID: <20130416121037.D61721C1522@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r279:6b77a8d99cdd Date: 2013-04-12 19:03 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/6b77a8d99cdd/ Log: (cfbolz): added the correct hints to the preliminary type-hinting diff --git a/spyvm/fieldtypes.py b/spyvm/fieldtypes.py --- a/spyvm/fieldtypes.py +++ b/spyvm/fieldtypes.py @@ -31,7 +31,7 @@ w_obj._vars[n0] = w_val class FieldTypes(VarSizedFieldTypes): - _immutable_fields_ = ['types'] + _immutable_fields_ = ['types[*]'] _attrs_ = ['types', 'parent', 'siblings', 'diff'] _settled_ = True @@ -63,7 +63,7 @@ w_object.fieldtypes = self.sibling(n0, changed_type) w_object._vars[n0] = w_value - + @jit.elidable def sibling(self, n0, changed_type): assert self.types[n0] is not changed_type change = (n0, changed_type) @@ -108,6 +108,7 @@ @staticmethod + @jit.elidable def of_length(n): if n not in maps: maps[n] = FieldTypes([obj] * n) From noreply at buildbot.pypy.org Tue Apr 16 14:10:39 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Tue, 16 Apr 2013 14:10:39 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: merge with bit_shift fix Message-ID: <20130416121039.435E01C1522@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r280:ee9841408ae5 Date: 2013-04-12 19:16 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/ee9841408ae5/ Log: merge with bit_shift fix diff --git a/spyvm/model.py b/spyvm/model.py --- a/spyvm/model.py +++ b/spyvm/model.py @@ -262,12 +262,15 @@ return "W_LargePositiveInteger1Word(%d)" % r_uint(self.value) def lshift(self, space, shift): - from rpython.rlib.rarithmetic import intmask, r_uint + from rpython.rlib.rarithmetic import ovfcheck, intmask, r_uint # shift > 0, therefore the highest bit of upperbound is not set, # i.e. upperbound is positive upperbound = intmask(r_uint(-1) >> shift) if 0 <= self.value <= upperbound: - shifted = intmask(self.value << shift) + try: + shifted = intmask(ovfcheck(self.value << shift)) + except OverflowError: + raise error.PrimitiveFailedError() return space.wrap_positive_32bit_int(shifted) else: raise error.PrimitiveFailedError() diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -45,7 +45,7 @@ prim_table_implemented_only = [] # indicates that what is pushed is an index1, but it is unwrapped and -# converted to an index0 +# converted to an index0 index1_0 = object() char = object() pos_32bit_int = object() @@ -207,23 +207,26 @@ if argument == 0: raise PrimitiveFailedError() return interp.space.wrap_int(receiver // argument) - + # #// -- return the result of a division, rounded towards negative infinite @expose_primitive(QUO, unwrap_spec=[int, int]) def func(interp, s_frame, receiver, argument): if argument == 0: raise PrimitiveFailedError() return interp.space.wrap_int(receiver // argument) - + # #bitShift: -- return the shifted value @expose_primitive(BIT_SHIFT, unwrap_spec=[object, int]) def func(interp, s_frame, receiver, argument): - # Failing! Use ovfcheck_lfshift - # (http://codespeak.net/pypy/dist/pypy/doc/coding-guide.html#integer-types) - if argument > 0: - return receiver.lshift(interp.space, argument) + from rpython.rlib.rarithmetic import LONG_BIT + if -LONG_BIT < argument < LONG_BIT: + # overflow-checking done in lshift implementations + if argument > 0: + return receiver.lshift(interp.space, argument) + else: + return receiver.rshift(interp.space, -argument) else: - return receiver.rshift(interp.space, -argument) + raise PrimitiveFailedError() # ___________________________________________________________________________ # Float Primitives @@ -390,7 +393,7 @@ ARRAY_BECOME_ONE_WAY = 72 # Blue Book: primitiveBecome INST_VAR_AT = 73 INST_VAR_AT_PUT = 74 -AS_OOP = 75 +AS_OOP = 75 STORE_STACKP = 76 # Blue Book: primitiveAsObject SOME_INSTANCE = 77 NEXT_INSTANCE = 78 @@ -477,7 +480,7 @@ if not rgc.get_gcflag_extra(gcref): rgc.toggle_gcflag_extra(gcref) w_obj = rgc.try_cast_gcref_to_instance(model.W_Object, gcref) - if (w_obj is not None and w_obj.has_class() + if (w_obj is not None and w_obj.has_class() and w_obj.getclass(interp.space) is w_class): match_w.append(w_obj) pending.extend(rgc.get_rpy_referents(gcref)) @@ -521,7 +524,7 @@ # I/O Primitives MOUSE_POINT = 90 -TEST_DISPLAY_DEPTH = 91 +TEST_DISPLAY_DEPTH = 91 SET_DISPLAY_MODE = 92 INPUT_SEMAPHORE = 93 GET_NEXT_EVENT = 94 @@ -628,10 +631,10 @@ @expose_primitive(STRING_REPLACE, unwrap_spec=[object, index1_0, index1_0, object, index1_0]) def func(interp, s_frame, w_rcvr, start, stop, w_replacement, repStart): - """replaceFrom: start to: stop with: replacement startingAt: repStart - Primitive. This destructively replaces elements from start to stop in the - receiver starting at index, repStart, in the collection, replacement. Answer - the receiver. Range checks are performed in the primitive only. Essential + """replaceFrom: start to: stop with: replacement startingAt: repStart + Primitive. This destructively replaces elements from start to stop in the + receiver starting at index, repStart, in the collection, replacement. Answer + the receiver. Range checks are performed in the primitive only. Essential for Pharo Candle Symbols. | index repOff | repOff := repStart - start. @@ -640,7 +643,7 @@ whileTrue: [self at: index put: (replacement at: repOff + index)]""" if (start < 0 or start - 1 > stop or repStart < 0): raise PrimitiveFailedError() - # This test deliberately test for equal W_Object class. The Smalltalk classes + # This test deliberately test for equal W_Object class. The Smalltalk classes # might be different (e.g. Symbol and ByteString) if w_rcvr.__class__ is not w_replacement.__class__: raise PrimitiveFailedError() @@ -756,7 +759,7 @@ def func(interp, s_frame, argument_count): if argument_count == 0: s_frame.pop() - return interp.space.wrap_string(interp.image_name) + return interp.space.wrap_string(interp.image_name) elif argument_count == 1: pass # XXX raise PrimitiveFailedError @@ -942,7 +945,7 @@ FLOAT_GREATEROREQUAL = 46 FLOAT_EQUAL = 47 FLOAT_NOTEQUAL = 48 - + bool_ops = { LESSTHAN: operator.lt, GREATERTHAN: operator.gt, @@ -968,7 +971,7 @@ w_res = interp.space.wrap_bool(res) return w_res make_func(op) - + # ___________________________________________________________________________ # Quick Push Const Primitives @@ -1002,7 +1005,7 @@ (PUSH_TWO, "w_two"), ]: make_push_const_func(code, name) - + # ___________________________________________________________________________ # Control Primitives @@ -1056,7 +1059,7 @@ 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(interp.space) @@ -1086,7 +1089,7 @@ if len(args_w) != exp_arg_cnt: raise PrimitiveFailedError() - + # Push all the items from the array for i in range(exp_arg_cnt): s_block_ctx.push(args_w[i]) @@ -1189,7 +1192,7 @@ if not (outer_ctxt_class is space.w_MethodContext or outer_ctxt_class is space.w_BlockContext): raise PrimitiveFailedError() - + # additionally to the smalltalk implementation, this also pushes # args and copiedValues s_new_frame = block.asContextWithSender(s_frame.w_self(), args_w) diff --git a/spyvm/squeakimage.py b/spyvm/squeakimage.py --- a/spyvm/squeakimage.py +++ b/spyvm/squeakimage.py @@ -71,7 +71,7 @@ return swapped_chrs2int(data_peek) else: return chrs2int(data_peek) - + def next(self): integer = self.peek() @@ -146,19 +146,19 @@ if sys.maxint == 2 ** 63 - 1: image_versions.update({ -0x5ff6ff0000000000: - # signed version of 0xA009010000000000: + # signed version of 0xA009010000000000: ImageVersion(68000, False, True, False, False), 0x00000000000109A2: ImageVersion(68002, True, True, True, False), -0x5df6ff0000000000: - # signed version of 0xA209010000000000: - ImageVersion(68002, False, True, True, False), + # signed version of 0xA209010000000000: + ImageVersion(68002, False, True, True, False), 0x00000000000109A3: ImageVersion(68003, True, True, True, True ), -0x5cf6ff0000000000: - # signed version of 0xA309010000000000: - ImageVersion(68003, False, True, True, True ), + # signed version of 0xA309010000000000: + ImageVersion(68003, False, True, True, True ), }) - + def version(magic): ver = image_versions.get(magic, None) if ver is None: @@ -198,8 +198,8 @@ pass # raise original error raise - - + + def reader_for_image(space, stream): ver = version_from_stream(stream) if not ver.is_big_endian: @@ -207,7 +207,7 @@ return ImageReader(space, stream, ver) class ImageReader(object): - + def __init__(self, space, stream, version): self.space = space self.stream = stream @@ -594,5 +594,3 @@ def iscompact(self): return 0 < self.classid < 32 - - diff --git a/spyvm/test/test_miniimage.py b/spyvm/test/test_miniimage.py --- a/spyvm/test/test_miniimage.py +++ b/spyvm/test/test_miniimage.py @@ -28,20 +28,20 @@ return perform(space.wrap_string(name), "asSymbol") def open_miniimage(space): - return squeakimage.reader_for_image(space, squeakimage.Stream(mini_image.open())) + return squeakimage.reader_for_image(space, squeakimage.Stream(mini_image.open(mode="rb"))) def get_reader(): return reader - + def get_image(): return image - + def get_float_class(): image = get_image() return image.special(constants.SO_FLOAT_CLASS) # ------ tests ------------------------------------------ - + def test_miniimageexists(): assert mini_image.check(dir=False) @@ -52,26 +52,26 @@ assert reader.oldbaseaddress == -1221464064 assert reader.specialobjectspointer == -1221336216 -def test_read_all_header(): +def test_read_all_header(): reader = open_miniimage(space) reader.read_header() next = reader.stream.peek() - assert next != 0 #expects object header, which must not be 0x00000000 - - + assert next != 0 #expects object header, which must not be 0x00000000 + + def test_all_pointers_are_valid(): reader = get_reader() for each in reader.chunks.itervalues(): - if each.format < 5: + if each.format < 5: for pointer in each.data: if (pointer & 1) != 1: - assert pointer in reader.chunks - - + assert pointer in reader.chunks + + def test_there_are_31_compact_classes(): reader = get_reader() assert len(reader.compactclasses) == 31 - + def test_float_class_size(): w_float_class = get_float_class() assert w_float_class.size() == 9 @@ -81,7 +81,7 @@ 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") - + def test_str_w_object(): w_float_class = get_float_class() w_float_class.as_class_get_shadow(space) @@ -102,38 +102,38 @@ w = image.special(constants.SO_TRUE) w.shadow_of_my_class(space) assert str(w) == "a True" #yes, with article - + def test_scheduler(): image = get_image() w = image.special(constants.SO_SCHEDULERASSOCIATIONPOINTER) w0 = w.fetch(space, 0) - assert str(w0) == "Processor" + assert str(w0) == "Processor" w0 = w.fetch(space, 1) w0.shadow_of_my_class(space) - assert str(w0) == "a ProcessorScheduler" - + assert str(w0) == "a ProcessorScheduler" + def test_special_classes0(): image = get_image() # w = image.special(constants.SO_BITMAP_CLASS) - # assert str(w) == "Bitmap class" + # assert str(w) == "Bitmap class" w = image.special(constants.SO_SMALLINTEGER_CLASS) - assert str(w) == "SmallInteger class" + assert str(w) == "SmallInteger class" w = image.special(constants.SO_STRING_CLASS) - assert str(w) == "String class" + assert str(w) == "String class" w = image.special(constants.SO_ARRAY_CLASS) - assert str(w) == "Array class" + assert str(w) == "Array class" w = image.special(constants.SO_FLOAT_CLASS) - assert str(w) == "Float class" + assert str(w) == "Float class" w = image.special(constants.SO_METHODCONTEXT_CLASS) - assert str(w) == "MethodContext class" + assert str(w) == "MethodContext class" w = image.special(constants.SO_BLOCKCONTEXT_CLASS) - assert str(w) == "BlockContext class" + assert str(w) == "BlockContext class" w = image.special(constants.SO_POINT_CLASS) - assert str(w) == "Point class" + assert str(w) == "Point class" w = image.special(constants.SO_LARGEPOSITIVEINTEGER_CLASS) - assert str(w) == "LargePositiveInteger class" + assert str(w) == "LargePositiveInteger class" w = image.special(constants.SO_MESSAGE_CLASS) - assert str(w) == "Message class" + assert str(w) == "Message class" # to be continued @@ -144,7 +144,7 @@ SO_LOW_SPACE_SEMAPHORE = 17 SO_SEMAPHORE_CLASS = 18 SO_CHARACTER_CLASS = 19""" - + def test_name_of_shadow_of_specials(): image = get_image() w_doesnot = image.special(constants.SO_DOES_NOT_UNDERSTAND) @@ -162,8 +162,8 @@ w = image.special(constants.SO_DOES_NOT_UNDERSTAND) assert str(w) == "doesNotUnderstand:" assert str(w.getclass(space)) == "Symbol class" # for some strange reason not a symbol - - + + """ SO_DOES_NOT_UNDERSTAND = 20 SO_CANNOT_RETURN = 21 @@ -181,7 +181,7 @@ SO_A_POINT = 33 SO_CANNOT_INTERPRET = 34 SO_A_METHODCONTEXT = 35 # deprecated in closure images - SO_BLOCKCLOSURE_CLASS = 36 + SO_BLOCKCLOSURE_CLASS = 36 SO_A_BLOCKCONTEXT = 37 # deprecated in closure images SO_EXTERNAL_OBJECTS_ARRAY = 38 SO_PSEUDOCONTEXT_CLASS = 39 @@ -209,7 +209,7 @@ assert w_true.is_same_object(space.w_true) w_false = image.special(constants.SO_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 spyvm import wrapper @@ -221,32 +221,32 @@ interp.interpret_with_w_frame(w_ctx) def test_compile_method(): - sourcecode = """fib - ^self < 2 - ifTrue: [ 1 ] + sourcecode = """fib + ^self < 2 + ifTrue: [ 1 ] ifFalse: [ (self - 1) fib + (self - 2) fib ]""" 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): +def w(any): # XXX could put this on the space? if any is None: return space.w_nil if isinstance(any, str): # assume never have strings of length 1 - if len(any) == 1: + if len(any) == 1: return space.wrap_chr(any) else: return space.wrap_string(any) if isinstance(any, bool): return space.wrap_bool(any) - if isinstance(any, int): + if isinstance(any, int): return space.wrap_int(any) if isinstance(any, float): return space.wrap_float(any) else: - raise Exception + raise Exception def test_become(): sourcecode = """ @@ -268,7 +268,7 @@ (p1 -> p2 = a) ifFalse: [^10]. (p1 == a key) ifFalse: [^11]. (p2 == a value) ifFalse: [^12]. - + ^42""" perform(w(10).getclass(space), "compile:classified:notifying:", w(sourcecode), w('pypy'), w(None)) w_result = perform(w(10), "testBecome") @@ -404,4 +404,4 @@ interp.step(s_ctx) assert s_ctx.top().value == 2 interp.step(s_ctx) - assert s_ctx.top().value == 3 \ No newline at end of file + assert s_ctx.top().value == 3 diff --git a/spyvm/tool/analyseimage.py b/spyvm/tool/analyseimage.py --- a/spyvm/tool/analyseimage.py +++ b/spyvm/tool/analyseimage.py @@ -1,8 +1,8 @@ import py -from spyvm import squeakimage -from spyvm import constants -from spyvm import model -from spyvm import interpreter +from spyvm import squeakimage +from spyvm import constants +from spyvm import model +from spyvm import interpreter import sys image_dir = py.path.local(__file__).dirpath().dirpath().dirpath('images') @@ -11,14 +11,14 @@ minitest_image = image_dir.join('minitest.image') def get_miniimage(space): - return squeakimage.reader_for_image(space, squeakimage.Stream(mini_image.open())) + return squeakimage.reader_for_image(space, squeakimage.Stream(mini_image.open(mode="rb"))) def get_minitestimage(space): - return squeakimage.reader_for_image(space, squeakimage.Stream(minitest_image.open())) + return squeakimage.reader_for_image(space, squeakimage.Stream(minitest_image.open(mode="rb"))) def create_image(space, image_reader): image_reader.initialize() - + image = squeakimage.SqueakImage() image.from_reader(space, image_reader) return image diff --git a/targetimageloadingsmalltalk.py b/targetimageloadingsmalltalk.py --- a/targetimageloadingsmalltalk.py +++ b/targetimageloadingsmalltalk.py @@ -90,7 +90,7 @@ path = "Squeak.image" try: - f = open_file_as_stream(path, buffering=0) + f = open_file_as_stream(path, mode="rb", buffering=0) except OSError as e: os.write(2, "%s -- %s (LoadError)\n" % (os.strerror(e.errno), path)) return 1 From noreply at buildbot.pypy.org Tue Apr 16 14:10:40 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Tue, 16 Apr 2013 14:10:40 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: merge with tip Message-ID: <20130416121040.C61491C1522@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r281:3d04096604cf Date: 2013-04-16 11:12 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/3d04096604cf/ Log: merge with tip diff --git a/spyvm/display.py b/spyvm/display.py --- a/spyvm/display.py +++ b/spyvm/display.py @@ -6,57 +6,26 @@ from rsdl import RSDL, RSDL_helper -class SDLEventQueue(object): - def __init__(self, default, maxlen=10): - assert default - self.default = default - self.contents = [] - self.maxlen = 10 - - def push(self, event): - contents = self.contents - assert len(contents) <= self.maxlen - if len(contents) == self.maxlen: - contents.pop(0) - contents.append(event) - - def shift(self): - contents = self.contents - assert len(contents) <= self.maxlen - if contents == []: - contents = list(self.default) - return contents.pop(0) - - def peek(self): - contents = self.contents - assert len(contents) <= self.maxlen - if contents: - return contents[0] - else: - return self.default[0] - - def size(self): - if not self.contents: - return len(self.default) - else: - return len(self.contents) - +MOUSE_BTN_RIGHT = 1 +MOUSE_BTN_MIDDLE = 2 +MOUSE_BTN_LEFT = 4 +MOD_SHIFT = 8 +MOD_CONTROL = 16 +MOD_ALT = 64 class SDLDisplay(object): _attrs_ = ["screen", "width", "height", "depth", "surface", "has_surface", - "last_mouse_position", "last_mouse_buttons", "mouse_downs", "mouse_ups", "key_ups", "key_downs"] + "mouse_position", "button", "key"] def __init__(self, title): assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 RSDL.WM_SetCaption(title, "RSqueakVM") RSDL.EnableUNICODE(1) + SDLCursor.has_display = True self.has_surface = False - self.last_mouse_position = [0, 0] - self.last_mouse_buttons = 0 - self.mouse_downs = SDLEventQueue([0]) - self.mouse_ups = SDLEventQueue([0]) - self.key_ups = SDLEventQueue([0]) - self.key_downs = SDLEventQueue([0]) + self.mouse_position = [0, 0] + self.button = 0 + self.key = 0 def set_video_mode(self, w, h, d): assert w > 0 and h > 0 @@ -68,7 +37,7 @@ assert self.screen def get_pixelbuffer(self): - return self.screen.c_pixels + return rffi.cast(rffi.ULONGP, self.screen.c_pixels) def flip(self): RSDL.Flip(self.screen) @@ -85,51 +54,110 @@ if c_type == RSDL.MOUSEBUTTONDOWN or c_type == RSDL.MOUSEBUTTONUP: b = rffi.cast(RSDL.MouseButtonEventPtr, event) btn = rffi.getintfield(b, 'c_button') - if btn == RSDL.BUTTON_LEFT: - button = 4 + if btn == RSDL.BUTTON_RIGHT: + btn = MOUSE_BTN_RIGHT elif btn == RSDL.BUTTON_MIDDLE: - button = 2 - elif btn == RSDL.BUTTON_RIGHT: - button = 1 + btn = MOUSE_BTN_MIDDLE + elif btn == RSDL.BUTTON_LEFT: + btn = MOUSE_BTN_LEFT else: assert 0 button = 0 if c_type == RSDL.MOUSEBUTTONDOWN: - self.mouse_downs.push(button) + self.button |= btn self.last_mouse_buttons |= button else: - self.mouse_ups.push(button) + self.button &= ~btn self.last_mouse_buttons &= ~button elif c_type == RSDL.MOUSEMOTION: m = rffi.cast(RSDL.MouseMotionEventPtr, event) x = rffi.getintfield(m, "c_x") y = rffi.getintfield(m, "c_y") - self.last_mouse_position = list([x, y]) + self.mouse_position = [x, y] elif c_type == RSDL.KEYUP or c_type == RSDL.KEYDOWN: p = rffi.cast(RSDL.KeyboardEventPtr, event) char = rffi.getintfield(p.c_keysym, 'c_unicode') if char != 0: - for c in unicode_encode_utf_8(unichr(char), 1, "ignore"): - if c_type == RSDL.KEYUP: - self.key_ups.push(ord(c)) + chars = unicode_encode_utf_8(unichr(char), 1, "ignore") + if len(chars) == 1: + if c_type == RSDL.KEYDOWN: + self.key = ord(chars[0]) else: - self.key_downs.push(ord(c)) + pass # XXX: Todo? + elif c_type == RSDL.QUIT: + exit(0) finally: lltype.free(event, flavor='raw') + def get_modifier_mask(self): + RSDL.PumpEvents() + mod = RSDL.GetModState() + modifier = 0 + if mod & RSDL.KMOD_CTRL != 0: + modifier |= MOD_CONTROL + if mod & RSDL.KMOD_SHIFT != 0: + modifier |= MOD_SHIFT + if mod & RSDL.KMOD_ALT != 0: + modifier |= MOD_ALT + return modifier + def mouse_point(self): self.get_next_event() - return self.last_mouse_position + return self.mouse_position def mouse_button(self): self.get_next_event() - return self.last_mouse_buttons + return self.button | self.get_modifier_mask() def next_keycode(self): - self.get_next_event() - return self.key_downs.shift() + key = self.key + self.key = 0 + return key def peek_keycode(self): self.get_next_event() - return self.key_downs.peek() + return self.key + + +class SDLCursorClass(object): + _attrs_ = ["cursor", "has_cursor", "has_display"] + + instance = None + + def __init__(self): + self.has_cursor = False + self.has_display = False + + def set(self, data_words, w, h, x, y, mask_words=None): + if not self.has_display: + return + if self.has_cursor: + RSDL.FreeCursor(self.cursor) + try: + data = self.words_to_bytes(len(data_words) * 4, data_words) + try: + mask = self.words_to_bytes(len(data_words) * 4, mask_words) + self.cursor = RSDL.CreateCursor(data, mask, w * 2, h, x, y) + self.has_cursor = True + RSDL.SetCursor(self.cursor) + finally: + lltype.free(mask, flavor="raw") + finally: + lltype.free(data, flavor="raw") + + def words_to_bytes(self, bytenum, words): + bytes = lltype.malloc(RSDL.Uint8P.TO, bytenum, flavor="raw") + if words: + for pos in range(bytenum / 4): + word = words[pos] + bytes[pos * 4] = rffi.r_uchar((word >> 24) & 0xff) + bytes[pos * 4 + 1] = rffi.r_uchar((word >> 16) & 0xff) + bytes[pos * 4 + 2] = rffi.r_uchar((word >> 8) & 0xff) + bytes[pos * 4 + 3] = rffi.r_uchar(word & 0xff) + else: + for idx in range(bytenum): + bytes[idx] = rffi.r_uchar(0) + return bytes + +SDLCursor = SDLCursorClass() diff --git a/spyvm/model.py b/spyvm/model.py --- a/spyvm/model.py +++ b/spyvm/model.py @@ -36,6 +36,11 @@ space, as memory representation varies depending on PyPy translation.""" return 0 + def instsize(self, space): + """Return the size of the object reserved for instance variables. + Only returns something non-zero for W_PointersObjects""" + return 0 + def varsize(self, space): """Return bytesize of variable-sized part. @@ -807,17 +812,15 @@ @jit.unroll_safe def setword(self, n, word): self._real_depth_buffer[n] = word - pos = n * NATIVE_DEPTH * 4 + pos = n * NATIVE_DEPTH mask = r_uint(1) mask <<= 31 for i in xrange(32): bit = mask & word - self.pixelbuffer[pos] = rffi.r_uchar(0xff * (bit == 0)) - self.pixelbuffer[pos + 1] = rffi.r_uchar(0xff * (bit == 0)) - self.pixelbuffer[pos + 2] = rffi.r_uchar(0xff * (bit == 0)) - self.pixelbuffer[pos + 3] = rffi.r_uchar(0xff) + pixel = r_uint((0x00ffffff * (bit == 0)) | r_uint(0xff000000)) + self.pixelbuffer[pos] = pixel mask >>= 1 - pos += 4 + pos += 1 # XXX Shouldn't compiledmethod have class reference for subclassed compiled diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -575,9 +575,34 @@ # in case we return normally, we have to restore the removed w_rcvr return w_rcvr - at expose_primitive(BE_CURSOR, unwrap_spec=[object]) -def func(interp, s_frame, w_rcvr): - # TODO: Use info from cursor object. + at expose_primitive(BE_CURSOR) +def func(interp, s_frame, argcount): + if not (0 <= argcount <= 1): + raise PrimitiveFailedError() + w_rcvr = s_frame.peek(argcount) + if argcount == 1: + # TODO: use mask + w_mask = s_frame.peek(0) + if not isinstance(w_mask, model.W_WordsObject): + raise PrimitiveFailedError() + else: + w_mask = None + w_bitmap = w_rcvr.fetch(interp.space, 0) + if not isinstance(w_bitmap, model.W_WordsObject): + raise PrimitiveFailedError() + width = interp.space.unwrap_int(w_rcvr.fetch(interp.space, 1)) + height = interp.space.unwrap_int(w_rcvr.fetch(interp.space, 2)) + depth = interp.space.unwrap_int(w_rcvr.fetch(interp.space, 3)) + hotpt = wrapper.PointWrapper(interp.space, w_rcvr.fetch(interp.space, 4)) + display.SDLCursor.set( + w_bitmap.words, + width, + height, + hotpt.x(), + hotpt.y(), + w_mask.words if w_mask else None + ) + interp.space.objtable['w_cursor'] = w_rcvr return w_rcvr @@ -647,8 +672,8 @@ # might be different (e.g. Symbol and ByteString) if w_rcvr.__class__ is not w_replacement.__class__: raise PrimitiveFailedError() - if (w_rcvr.size() <= stop - or w_replacement.size() < repStart + (stop - start)): + if (w_rcvr.size() - w_rcvr.instsize(interp.space) <= stop + or w_replacement.size() - w_replacement.instsize(interp.space) <= repStart + (stop - start)): raise PrimitiveFailedError() repOff = repStart - start for i0 in range(start, stop + 1): @@ -1128,7 +1153,7 @@ if not w_rcvr.getclass(interp.space).is_same_object( interp.space.w_Semaphore): raise PrimitiveFailedError() - s_frame.push(w_rcvr) # w_rcvr is the result in the old frame + # s_frame.push(w_rcvr) # w_rcvr is the result in the old frame return wrapper.SemaphoreWrapper(interp.space, w_rcvr).wait(s_frame.w_self()) @expose_primitive(RESUME, unwrap_spec=[object], result_is_new_frame=True) From noreply at buildbot.pypy.org Tue Apr 16 14:10:42 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Tue, 16 Apr 2013 14:10:42 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: merge with tip Message-ID: <20130416121042.8D8541C1522@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r282:0d1302a3c025 Date: 2013-04-16 14:10 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/0d1302a3c025/ Log: merge with tip diff --git a/.travis.yml b/.travis.yml new file mode 100644 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,22 @@ +language: python +python: + - 2.7 +env: + matrix: + - TEST_TYPE=own + - TEST_TYPE=translate +install: + - pip install rsdl --use-mirrors + - wget https://bitbucket.org/pypy/pypy/get/default.tar.bz2 -O `pwd`/../pypy.tar.bz2 || wget https://bitbucket.org/pypy/pypy/get/default.tar.bz2 -O `pwd`/../pypy.tar.bz2 + - tar -xf `pwd`/../pypy.tar.bz2 -C `pwd`/../ + - mv ../pypy-pypy* ../pypy-pypy +script: + - export PYTHONPATH=$PYTHONPATH:../pypy-pypy/:. + - "case \"$TEST_TYPE\" in + own) + py.test + ;; + translate) + python ../pypy-pypy/rpython/bin/rpython --batch targetimageloadingsmalltalk.py + ;; + esac" diff --git a/spyvm/constants.py b/spyvm/constants.py --- a/spyvm/constants.py +++ b/spyvm/constants.py @@ -183,4 +183,4 @@ # MAX_LOOP_DEPTH = 100 -INTERRUPT_COUNTER_SIZE = 1000 \ No newline at end of file +INTERRUPT_COUNTER_SIZE = 10000 diff --git a/spyvm/display.py b/spyvm/display.py --- a/spyvm/display.py +++ b/spyvm/display.py @@ -86,7 +86,9 @@ else: pass # XXX: Todo? elif c_type == RSDL.QUIT: - exit(0) + from spyvm.interpreter import ReturnFromTopLevel + print "Window closed.." + raise SystemExit() finally: lltype.free(event, flavor='raw') @@ -126,6 +128,7 @@ instance = None def __init__(self): + self.cursor = lltype.nullptr(RSDL.CursorPtr.TO) self.has_cursor = False self.has_display = False @@ -134,10 +137,10 @@ return if self.has_cursor: RSDL.FreeCursor(self.cursor) + data = self.words_to_bytes(len(data_words) * 4, data_words) try: - data = self.words_to_bytes(len(data_words) * 4, data_words) + mask = self.words_to_bytes(len(data_words) * 4, mask_words) try: - mask = self.words_to_bytes(len(data_words) * 4, mask_words) self.cursor = RSDL.CreateCursor(data, mask, w * 2, h, x, y) self.has_cursor = True RSDL.SetCursor(self.cursor) diff --git a/spyvm/model.py b/spyvm/model.py --- a/spyvm/model.py +++ b/spyvm/model.py @@ -267,15 +267,12 @@ return "W_LargePositiveInteger1Word(%d)" % r_uint(self.value) def lshift(self, space, shift): - from rpython.rlib.rarithmetic import ovfcheck, intmask, r_uint + from rpython.rlib.rarithmetic import intmask, r_uint # shift > 0, therefore the highest bit of upperbound is not set, # i.e. upperbound is positive upperbound = intmask(r_uint(-1) >> shift) if 0 <= self.value <= upperbound: - try: - shifted = intmask(ovfcheck(self.value << shift)) - except OverflowError: - raise error.PrimitiveFailedError() + shifted = intmask(self.value << shift) return space.wrap_positive_32bit_int(shifted) else: raise error.PrimitiveFailedError() diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -580,13 +580,13 @@ if not (0 <= argcount <= 1): raise PrimitiveFailedError() w_rcvr = s_frame.peek(argcount) + mask_words = None if argcount == 1: # TODO: use mask w_mask = s_frame.peek(0) if not isinstance(w_mask, model.W_WordsObject): raise PrimitiveFailedError() - else: - w_mask = None + mask_words = w_mask.words w_bitmap = w_rcvr.fetch(interp.space, 0) if not isinstance(w_bitmap, model.W_WordsObject): raise PrimitiveFailedError() @@ -600,7 +600,7 @@ height, hotpt.x(), hotpt.y(), - w_mask.words if w_mask else None + mask_words=mask_words ) interp.space.objtable['w_cursor'] = w_rcvr From noreply at buildbot.pypy.org Tue Apr 16 16:25:40 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Tue, 16 Apr 2013 16:25:40 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: merge with tip Message-ID: <20130416142540.A98931C01FD@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r283:9226d9dccea3 Date: 2013-04-16 14:20 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/9226d9dccea3/ Log: merge with tip diff --git a/.travis.yml b/.travis.yml new file mode 100644 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,22 @@ +language: python +python: + - 2.7 +env: + matrix: + - TEST_TYPE=own + - TEST_TYPE=translate +install: + - pip install rsdl --use-mirrors + - wget https://bitbucket.org/pypy/pypy/get/default.tar.bz2 -O `pwd`/../pypy.tar.bz2 || wget https://bitbucket.org/pypy/pypy/get/default.tar.bz2 -O `pwd`/../pypy.tar.bz2 + - tar -xf `pwd`/../pypy.tar.bz2 -C `pwd`/../ + - mv ../pypy-pypy* ../pypy-pypy +script: + - export PYTHONPATH=$PYTHONPATH:../pypy-pypy/:. + - "case \"$TEST_TYPE\" in + own) + py.test + ;; + translate) + python ../pypy-pypy/rpython/bin/rpython --batch targetimageloadingsmalltalk.py + ;; + esac" diff --git a/spyvm/constants.py b/spyvm/constants.py --- a/spyvm/constants.py +++ b/spyvm/constants.py @@ -183,4 +183,4 @@ # MAX_LOOP_DEPTH = 100 -INTERRUPT_COUNTER_SIZE = 1000 \ No newline at end of file +INTERRUPT_COUNTER_SIZE = 10000 diff --git a/spyvm/display.py b/spyvm/display.py --- a/spyvm/display.py +++ b/spyvm/display.py @@ -50,7 +50,6 @@ ok = rffi.cast(lltype.Signed, RSDL.PollEvent(event)) if ok == 1: c_type = rffi.getintfield(event, 'c_type') - print ' %d' % c_type, if c_type == RSDL.MOUSEBUTTONDOWN or c_type == RSDL.MOUSEBUTTONUP: b = rffi.cast(RSDL.MouseButtonEventPtr, event) btn = rffi.getintfield(b, 'c_button') @@ -60,16 +59,11 @@ btn = MOUSE_BTN_MIDDLE elif btn == RSDL.BUTTON_LEFT: btn = MOUSE_BTN_LEFT - else: - assert 0 - button = 0 - + if c_type == RSDL.MOUSEBUTTONDOWN: self.button |= btn - self.last_mouse_buttons |= button else: self.button &= ~btn - self.last_mouse_buttons &= ~button elif c_type == RSDL.MOUSEMOTION: m = rffi.cast(RSDL.MouseMotionEventPtr, event) x = rffi.getintfield(m, "c_x") @@ -86,7 +80,9 @@ else: pass # XXX: Todo? elif c_type == RSDL.QUIT: - exit(0) + from spyvm.interpreter import ReturnFromTopLevel + print "Window closed.." + raise SystemExit() finally: lltype.free(event, flavor='raw') @@ -126,6 +122,7 @@ instance = None def __init__(self): + self.cursor = lltype.nullptr(RSDL.CursorPtr.TO) self.has_cursor = False self.has_display = False @@ -134,10 +131,10 @@ return if self.has_cursor: RSDL.FreeCursor(self.cursor) + data = self.words_to_bytes(len(data_words) * 4, data_words) try: - data = self.words_to_bytes(len(data_words) * 4, data_words) + mask = self.words_to_bytes(len(data_words) * 4, mask_words) try: - mask = self.words_to_bytes(len(data_words) * 4, mask_words) self.cursor = RSDL.CreateCursor(data, mask, w * 2, h, x, y) self.has_cursor = True RSDL.SetCursor(self.cursor) diff --git a/spyvm/model.py b/spyvm/model.py --- a/spyvm/model.py +++ b/spyvm/model.py @@ -267,15 +267,12 @@ return "W_LargePositiveInteger1Word(%d)" % r_uint(self.value) def lshift(self, space, shift): - from rpython.rlib.rarithmetic import ovfcheck, intmask, r_uint + from rpython.rlib.rarithmetic import intmask, r_uint # shift > 0, therefore the highest bit of upperbound is not set, # i.e. upperbound is positive upperbound = intmask(r_uint(-1) >> shift) if 0 <= self.value <= upperbound: - try: - shifted = intmask(ovfcheck(self.value << shift)) - except OverflowError: - raise error.PrimitiveFailedError() + shifted = intmask(self.value << shift) return space.wrap_positive_32bit_int(shifted) else: raise error.PrimitiveFailedError() diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -580,13 +580,13 @@ if not (0 <= argcount <= 1): raise PrimitiveFailedError() w_rcvr = s_frame.peek(argcount) + mask_words = None if argcount == 1: # TODO: use mask w_mask = s_frame.peek(0) if not isinstance(w_mask, model.W_WordsObject): raise PrimitiveFailedError() - else: - w_mask = None + mask_words = w_mask.words w_bitmap = w_rcvr.fetch(interp.space, 0) if not isinstance(w_bitmap, model.W_WordsObject): raise PrimitiveFailedError() @@ -600,7 +600,7 @@ height, hotpt.x(), hotpt.y(), - w_mask.words if w_mask else None + mask_words=mask_words ) interp.space.objtable['w_cursor'] = w_rcvr From noreply at buildbot.pypy.org Tue Apr 16 16:25:42 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Tue, 16 Apr 2013 16:25:42 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: reverted the optimization to the copyLoop because it introduced clipping errors Message-ID: <20130416142542.50F781C3173@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r284:35b6ae515ed9 Date: 2013-04-16 16:15 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/35b6ae515ed9/ Log: reverted the optimization to the copyLoop because it introduced clipping errors diff --git a/BitBltSim.19.cs b/BitBltSim.19.cs --- a/BitBltSim.19.cs +++ b/BitBltSim.19.cs @@ -13,33 +13,33 @@ !BitBlt methodsFor: 'private'! clipRange destX >= clipX - ifTrue: + ifTrue: [simSx _ sourceX. simDx _ destX. simW _ width] - ifFalse: + ifFalse: [simSx _ sourceX + (clipX - destX). simW _ width - (clipX - destX). simDx _ clipX]. simDx + simW > (clipX + clipWidth) ifTrue: [simW _ simW - (simDx + simW - (clipX + clipWidth))]. destY >= clipY - ifTrue: + ifTrue: [simSy _ sourceY. simDy _ destY. simH _ height] - ifFalse: + ifFalse: [simSy _ sourceY + clipY - destY. simH _ height - (clipY - destY). simDy _ clipY]. simDy + simH > (clipY + clipHeight) ifTrue: [simH _ simH - (simDy + simH - (clipY + clipHeight))]. simSx < 0 - ifTrue: + ifTrue: [simDx _ simDx - simSx. simW _ simW + simSx. simSx _ 0]. simSx + simW > sourceForm width ifTrue: [simW _ simW - (simSx + simW - sourceForm width)]. simSy < 0 - ifTrue: + ifTrue: [simDy _ simDy - simSy. simH _ simH + simSy. simSy _ 0]. @@ -121,33 +121,38 @@ copyLoop | prevWord thisWord skewWord mergeMask halftoneWord mergeWord noSimSkewMask | noSimSkewMask _ simSkewMask bitInvert32. - 1 to: simH do: - [:i | + 1 to: simH do: + [:i | halftoneForm notNil - ifTrue: + ifTrue: [halftoneWord _ simHalftoneBits at: 1 + (simDy \\ simHalftoneBits size). simDy _ simDy + simVDir] ifFalse: [halftoneWord _ AllOnes]. skewWord _ halftoneWord. simPreload - ifTrue: + ifTrue: [prevWord _ simSourceBits at: simSourceIndex + 1. simSourceIndex _ simSourceIndex + simHDir] ifFalse: [prevWord _ 0]. mergeMask _ simMask1. - 1 to: simNWords do: - [:word | + 1 to: simNWords do: + [:word | sourceForm notNil - ifTrue: - [thisWord _ (simSourceIndex <= 0 or: [simSourceIndex >= simSourceBits size]) + ifTrue: + [prevWord _ prevWord bitAnd: simSkewMask. + "XXX: Hack to work around out-of-bounds access" + thisWord := (simSourceIndex < 0 or: [simSourceIndex >= simSourceBits size]) ifTrue: [simSourceBits at: 1] ifFalse: [simSourceBits at: simSourceIndex + 1]. - prevWord _ (prevWord bitAnd: simSkewMask) bitShift: simSkew. - skewWord _ prevWord bitOr: ((thisWord bitAnd: noSimSkewMask) bitShift: simSkew - WordSize). - prevWord _ thisWord]. - halftoneForm notNil - ifTrue: [mergeWord _ self merge: (skewWord bitAnd: halftoneWord) - with: (simDestBits at: simDestIndex + 1)]. + "pick up next word" + skewWord _ + prevWord bitOr: (thisWord bitAnd: simSkewMask bitInvert32). + prevWord _ thisWord. + "Change from BB: bitAnd: AllOnes to stay in word bounds" + skewWord _ ((skewWord bitShift: simSkew) bitAnd: AllOnes) bitOr: + (skewWord bitShift: simSkew - WordSize)]. + mergeWord _ self merge: (skewWord bitAnd: halftoneWord) + with: (simDestBits at: simDestIndex + 1). simDestBits at: simDestIndex + 1 put: ((mergeMask bitAnd: mergeWord) bitOr: (mergeMask bitInvert32 bitAnd: (simDestBits at: simDestIndex + 1))). simSourceIndex _ simSourceIndex + simHDir. @@ -298,19 +303,19 @@ extent: f extent clipRect: Display computeBoundingBox. "paint the gray Form on the screen for a while. " - [Sensor anyButtonPressed] whileFalse: + [Sensor anyButtonPressed] whileFalse: [aBitBlt destOrigin: Sensor cursorPoint. aBitBlt simulateCopyBits]. Display newDepth: displayDepth. "BitBlt exampleTwo"! ! !BitBlt class methodsFor: 'private' stamp: 'tfel 3/15/2013 14:32'! -exampleAt: originPoint rule: rule fillColor: mask +exampleAt: originPoint rule: rule fillColor: mask "This builds a source and destination form and copies the source to the destination using the specifed rule and mask. It is called from the method named exampleOne. Only works with Display depth of 1" - | s d border aBitBlt | + | s d border aBitBlt | border:=Form extent: 32 at 32. border fillBlack. border fill: (1 at 1 extent: 30 at 30) fillColor: Color white. @@ -326,7 +331,7 @@ d displayOn: Display at: originPoint + (s width @0). border displayOn: Display at: originPoint + (s width @0) rule: Form under. - d displayOn: Display at: originPoint + (s extent // (2 @ 1)). + d displayOn: Display at: originPoint + (s extent // (2 @ 1)). aBitBlt := BitBlt destForm: Display sourceForm: s @@ -337,7 +342,7 @@ extent: s extent clipRect: Display computeBoundingBox. aBitBlt simulateCopyBits. - border + border displayOn: Display at: originPoint + (s extent // (2 @ 1)) rule: Form under. @@ -468,7 +473,7 @@ | results | results := #( #(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) - + #(0 0 0 0 0 0 0 33554304 33554304 33554304 33554304 33554304 33554304 33554304 33554304 33554304 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) #(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 33554304 33554304 33554304 33554304 33554304 33554304 33554304 33554304 33554304 0 0 0 0 0 0 0) @@ -511,7 +516,7 @@ !BitBltSimTest methodsFor: 'running-modes' stamp: 'tfel 3/15/2013 14:37'! runTestDark: index - | s d rule | + | s d rule | rule := index - 1. s := self sourceForm. d := self destForm. @@ -530,7 +535,7 @@ !BitBltSimTest methodsFor: 'running-modes' stamp: 'tfel 3/15/2013 14:30'! runTestLarge: index - | s d aBitBlt mask rule simD originPoint destOrigin | + | s d aBitBlt mask rule simD originPoint destOrigin | originPoint := path at: index. rule := index - 1. mask := nil. @@ -553,7 +558,7 @@ extent: s extent clipRect: simD computeBoundingBox. aBitBlt simulateCopyBits. - + aBitBlt := BitBlt destForm: d sourceForm: s @@ -569,7 +574,7 @@ !BitBltSimTest methodsFor: 'running-modes' stamp: 'tfel 3/15/2013 14:43'! runTestVisual: index - | s d aBitBlt mask rule simD originPoint destOrigin | + | s d aBitBlt mask rule simD originPoint destOrigin | originPoint := path at: index. rule := index - 1. mask := nil. @@ -592,7 +597,7 @@ extent: s extent clipRect: simD computeBoundingBox. aBitBlt simulateCopyBits. - + aBitBlt := BitBlt destForm: d sourceForm: s @@ -606,7 +611,7 @@ simD displayOn: Display at: originPoint + (s width @ 0) rule: Form over. d displayOn: Display at: originPoint - (10 at 0) rule: Form over. - + d bits = simD bits ifTrue: [index asString displayAt: originPoint - 20] ifFalse: [(index asString, ' failed') displayAt: originPoint - 20. self assert: false].! ! From noreply at buildbot.pypy.org Tue Apr 16 16:25:43 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Tue, 16 Apr 2013 16:25:43 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: refactored the special nil hack to have its own closure (function extract) Message-ID: <20130416142543.BD1C41C01FD@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r285:90f0ca3c4b91 Date: 2013-04-16 16:17 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/90f0ca3c4b91/ Log: refactored the special nil hack to have its own closure (function extract) diff --git a/spyvm/objspace.py b/spyvm/objspace.py --- a/spyvm/objspace.py +++ b/spyvm/objspace.py @@ -135,9 +135,13 @@ # 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.space = self - w_nil.s_class = self.classtable['w_UndefinedObject'].as_class_get_penumbra(self) + def patch_nil(w_nil): + from spyvm.fieldtypes import nilTyper + w_nil.space = self + w_nil.fieldtypes = nilTyper + w_nil.s_class = self.classtable['w_UndefinedObject'].as_class_get_penumbra(self) + return w_nil + w_nil = self.w_nil = patch_nil(model.w_nil) w_true = self.classtable['w_True'].as_class_get_shadow(self).new() self.w_true = w_true From noreply at buildbot.pypy.org Tue Apr 16 16:25:45 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Tue, 16 Apr 2013 16:25:45 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: added primitive 129: return the special objects array which is used by VM Message-ID: <20130416142545.32EE51C01FD@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r286:6135571784b6 Date: 2013-04-16 16:18 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/6135571784b6/ Log: added primitive 129: return the special objects array which is used by VM the primitive is needed when printing methods in the mini.image diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -813,6 +813,7 @@ # ___________________________________________________________________________ # Squeak Miscellaneous Primitives (128-134) BECOME = 128 +SPECIAL_OBJECTS_ARRAY = 129 FULL_GC = 130 INC_GC = 131 INTERRUPT_SEMAPHORE = 134 @@ -838,6 +839,10 @@ def fake_bytes_left(interp): return interp.space.wrap_int(2**20) # XXX we don't know how to do this :-( + at expose_primitive(SPECIAL_OBJECTS_ARRAY, unwrap_spec=[object]) +def func(interp, s_frame, w_rcvr): + return interp.space.wrap_list(interp.image.special_objects) + @expose_primitive(INC_GC, unwrap_spec=[object]) @expose_primitive(FULL_GC, unwrap_spec=[object]) @jit.dont_look_inside From noreply at buildbot.pypy.org Tue Apr 16 16:25:46 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Tue, 16 Apr 2013 16:25:46 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: fixed (?) the semaphore errors by informing the primitive-generation that the stack should remain untouched and removing the return value pushes (self) Message-ID: <20130416142546.69A9F1C01FD@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r287:9f1e3a4bd300 Date: 2013-04-16 16:21 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/9f1e3a4bd300/ Log: fixed (?) the semaphore errors by informing the primitive-generation that the stack should remain untouched and removing the return value pushes (self) diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -1143,42 +1143,38 @@ s_frame._sendSelector(w_selector, argcount, interp, w_rcvr, w_rcvr.shadow_of_my_class(interp.space)) - at expose_primitive(SIGNAL, unwrap_spec=[object]) + at expose_primitive(SIGNAL, unwrap_spec=[object], clean_stack=False) def func(interp, s_frame, w_rcvr): # XXX we might want to disable this check if not w_rcvr.getclass(interp.space).is_same_object( interp.space.w_Semaphore): raise PrimitiveFailedError() - s_frame.push(w_rcvr) # w_rcvr is the result in the old frame return wrapper.SemaphoreWrapper(interp.space, w_rcvr).signal(s_frame.w_self()) - at expose_primitive(WAIT, unwrap_spec=[object]) + at expose_primitive(WAIT, unwrap_spec=[object], clean_stack=False) def func(interp, s_frame, w_rcvr): # XXX we might want to disable this check if not w_rcvr.getclass(interp.space).is_same_object( interp.space.w_Semaphore): raise PrimitiveFailedError() - # s_frame.push(w_rcvr) # w_rcvr is the result in the old frame return wrapper.SemaphoreWrapper(interp.space, w_rcvr).wait(s_frame.w_self()) - at expose_primitive(RESUME, unwrap_spec=[object], result_is_new_frame=True) + at expose_primitive(RESUME, unwrap_spec=[object], result_is_new_frame=True, clean_stack=False) def func(interp, s_frame, w_rcvr): # XXX we might want to disable this check if not w_rcvr.getclass(interp.space).is_same_object( interp.space.w_Process): raise PrimitiveFailedError() - s_frame.push(w_rcvr) # w_rcvr is the result in the old frame w_frame = wrapper.ProcessWrapper(interp.space, w_rcvr).resume(s_frame.w_self()) w_frame = interp.space.unwrap_pointersobject(w_frame) return w_frame.as_context_get_shadow(interp.space) - at expose_primitive(SUSPEND, unwrap_spec=[object], result_is_new_frame=True) + at expose_primitive(SUSPEND, unwrap_spec=[object], result_is_new_frame=True, clean_stack=False) def func(interp, s_frame, w_rcvr): # XXX we might want to disable this check if not w_rcvr.getclass(interp.space).is_same_object( interp.space.w_Process): raise PrimitiveFailedError() - s_frame.push(w_rcvr) # w_rcvr is the result in the old frame w_frame = wrapper.ProcessWrapper(interp.space, w_rcvr).suspend(s_frame.w_self()) w_frame = interp.space.unwrap_pointersobject(w_frame) return w_frame.as_context_get_shadow(interp.space) From noreply at buildbot.pypy.org Tue Apr 16 16:25:47 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Tue, 16 Apr 2013 16:25:47 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: removed tracing from code called by bitBlt primitive to reproduce errors of normal execution faster Message-ID: <20130416142547.AF3601C01FD@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r288:7ee37752fdbd Date: 2013-04-16 16:23 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/7ee37752fdbd/ Log: removed tracing from code called by bitBlt primitive to reproduce errors of normal execution faster diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -563,9 +563,13 @@ raise PrimitiveFailedError space = interp.space + trace = interp.trace + interp.trace = False try: s_frame._sendSelfSelector(interp.image.w_simulateCopyBits, 0, interp) + interp.trace = trace except Return: + interp.trace = trace w_dest_form = w_rcvr.fetch(space, 0) if w_dest_form.is_same_object(space.objtable['w_display']): w_bitmap = w_dest_form.fetch(space, 0) From noreply at buildbot.pypy.org Tue Apr 16 16:25:48 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Tue, 16 Apr 2013 16:25:48 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: merge with tip, again Message-ID: <20130416142548.DCD701C01FD@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r289:6f621debcab2 Date: 2013-04-16 16:25 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/6f621debcab2/ Log: merge with tip, again From noreply at buildbot.pypy.org Tue Apr 16 19:13:12 2013 From: noreply at buildbot.pypy.org (mattip) Date: Tue, 16 Apr 2013 19:13:12 +0200 (CEST) Subject: [pypy-commit] pypy win32-fixes2: invalid test skip, should just prevent running rpython.jit.backend.test.test_zll_stress with pypy Message-ID: <20130416171312.04C481C3151@cobra.cs.uni-duesseldorf.de> Author: mattip Branch: win32-fixes2 Changeset: r63408:200449276ec2 Date: 2013-04-16 01:29 +0300 http://bitbucket.org/pypy/pypy/changeset/200449276ec2/ Log: invalid test skip, should just prevent running rpython.jit.backend.test.test_zll_stress with pypy From noreply at buildbot.pypy.org Tue Apr 16 19:13:13 2013 From: noreply at buildbot.pypy.org (mattip) Date: Tue, 16 Apr 2013 19:13:13 +0200 (CEST) Subject: [pypy-commit] pypy closed-branches: Merge closed win32-fixes2 Message-ID: <20130416171313.3EF251C317E@cobra.cs.uni-duesseldorf.de> Author: mattip Branch: closed-branches Changeset: r63409:66f007f5f442 Date: 2013-04-16 01:33 +0300 http://bitbucket.org/pypy/pypy/changeset/66f007f5f442/ Log: Merge closed win32-fixes2 From noreply at buildbot.pypy.org Tue Apr 16 19:13:17 2013 From: noreply at buildbot.pypy.org (mattip) Date: Tue, 16 Apr 2013 19:13:17 +0200 (CEST) Subject: [pypy-commit] pypy default: skip syslog tests when module not available Message-ID: <20130416171317.DD6561C3182@cobra.cs.uni-duesseldorf.de> Author: mattip Branch: Changeset: r63413:41c27a4a7146 Date: 2013-04-16 18:57 +0300 http://bitbucket.org/pypy/pypy/changeset/41c27a4a7146/ Log: skip syslog tests when module not available diff --git a/pypy/module/test_lib_pypy/test_ctypes_config_cache.py b/pypy/module/test_lib_pypy/test_ctypes_config_cache.py --- a/pypy/module/test_lib_pypy/test_ctypes_config_cache.py +++ b/pypy/module/test_lib_pypy/test_ctypes_config_cache.py @@ -33,6 +33,10 @@ def test_syslog(): + try: + import lib_pypy.syslog + except ImportError: + py.test.skip('no syslog on this platform') d = run('syslog.ctc.py', '_syslog_cache.py') assert 'LOG_NOTICE' in d diff --git a/pypy/module/test_lib_pypy/test_syslog.py b/pypy/module/test_lib_pypy/test_syslog.py --- a/pypy/module/test_lib_pypy/test_syslog.py +++ b/pypy/module/test_lib_pypy/test_syslog.py @@ -1,11 +1,15 @@ from __future__ import absolute_import +import py +try: + from lib_pypy import syslog +except ImportError: + py.test.skip('no syslog on this platform') + # XXX very minimal test from lib_pypy.ctypes_config_cache import rebuild rebuild.rebuild_one('syslog.ctc.py') -from lib_pypy import syslog - def test_syslog(): assert hasattr(syslog, 'LOG_ALERT') From noreply at buildbot.pypy.org Tue Apr 16 19:13:19 2013 From: noreply at buildbot.pypy.org (mattip) Date: Tue, 16 Apr 2013 19:13:19 +0200 (CEST) Subject: [pypy-commit] pypy default: fix quotes for windows Message-ID: <20130416171319.068111C3151@cobra.cs.uni-duesseldorf.de> Author: mattip Branch: Changeset: r63414:f0d7998697a6 Date: 2013-04-16 19:17 +0300 http://bitbucket.org/pypy/pypy/changeset/f0d7998697a6/ Log: fix quotes for windows diff --git a/pypy/module/test_lib_pypy/test_site_extra.py b/pypy/module/test_lib_pypy/test_site_extra.py --- a/pypy/module/test_lib_pypy/test_site_extra.py +++ b/pypy/module/test_lib_pypy/test_site_extra.py @@ -4,7 +4,7 @@ def test_preimported_modules(): lst = ['__builtin__', '_codecs', '_warnings', 'codecs', 'encodings', 'exceptions', 'signal', 'sys', 'zipimport'] - g = os.popen("'%s' -c 'import sys; print sorted(sys.modules)'" % + g = os.popen('"%s" -c "import sys; print sorted(sys.modules)"' % (sys.executable,)) real_data = g.read() g.close() From noreply at buildbot.pypy.org Tue Apr 16 19:13:14 2013 From: noreply at buildbot.pypy.org (mattip) Date: Tue, 16 Apr 2013 19:13:14 +0200 (CEST) Subject: [pypy-commit] pypy win32-fixes3: pass more own-windows-x86 tests Message-ID: <20130416171314.78DE91C317F@cobra.cs.uni-duesseldorf.de> Author: mattip Branch: win32-fixes3 Changeset: r63410:fd463866093a Date: 2013-04-16 12:16 +0300 http://bitbucket.org/pypy/pypy/changeset/fd463866093a/ Log: pass more own-windows-x86 tests From noreply at buildbot.pypy.org Tue Apr 16 19:13:20 2013 From: noreply at buildbot.pypy.org (mattip) Date: Tue, 16 Apr 2013 19:13:20 +0200 (CEST) Subject: [pypy-commit] pypy default: skip resource tests when module not available Message-ID: <20130416171320.355D91C3151@cobra.cs.uni-duesseldorf.de> Author: mattip Branch: Changeset: r63415:740f02b99e77 Date: 2013-04-16 19:21 +0300 http://bitbucket.org/pypy/pypy/changeset/740f02b99e77/ Log: skip resource tests when module not available diff --git a/pypy/module/test_lib_pypy/test_resource.py b/pypy/module/test_lib_pypy/test_resource.py --- a/pypy/module/test_lib_pypy/test_resource.py +++ b/pypy/module/test_lib_pypy/test_resource.py @@ -1,8 +1,13 @@ from __future__ import absolute_import +import py +try: + from lib_pypy import resource +except ImportError: + py.test.skip('no resource module available') + from lib_pypy.ctypes_config_cache import rebuild rebuild.rebuild_one('resource.ctc.py') -from lib_pypy import resource def test_resource(): x = resource.getrusage(resource.RUSAGE_SELF) From noreply at buildbot.pypy.org Tue Apr 16 19:13:15 2013 From: noreply at buildbot.pypy.org (mattip) Date: Tue, 16 Apr 2013 19:13:15 +0200 (CEST) Subject: [pypy-commit] pypy win32-fixes3: corrected version of changeset 95c610ea4aed on py3k branch Message-ID: <20130416171315.99FD81C3180@cobra.cs.uni-duesseldorf.de> Author: mattip Branch: win32-fixes3 Changeset: r63411:eb462464a1d1 Date: 2013-04-16 12:31 +0300 http://bitbucket.org/pypy/pypy/changeset/eb462464a1d1/ Log: corrected version of changeset 95c610ea4aed on py3k branch diff --git a/rpython/rlib/ropenssl.py b/rpython/rlib/ropenssl.py --- a/rpython/rlib/ropenssl.py +++ b/rpython/rlib/ropenssl.py @@ -10,7 +10,7 @@ testonly_libraries = [] include_dirs = [] if sys.platform == 'win32' and platform.name != 'mingw32': - libraries = ['libeay32', 'ssleay32', + libraries = ['libeay32', 'ssleay32', 'zlib1', 'user32', 'advapi32', 'gdi32', 'msvcrt', 'ws2_32'] includes = [ # ssl.h includes winsock.h, which will conflict with our own diff --git a/rpython/rlib/rzlib.py b/rpython/rlib/rzlib.py --- a/rpython/rlib/rzlib.py +++ b/rpython/rlib/rzlib.py @@ -10,7 +10,7 @@ if compiler.name == "msvc": - libname = 'zlib' + libname = 'zlib1' # since version 1.1.4 and later, see http://www.zlib.net/DLL_FAQ.txt else: libname = 'z' eci = ExternalCompilationInfo( From noreply at buildbot.pypy.org Tue Apr 16 19:13:21 2013 From: noreply at buildbot.pypy.org (mattip) Date: Tue, 16 Apr 2013 19:13:21 +0200 (CEST) Subject: [pypy-commit] pypy default: comment out unneeded rebuild Message-ID: <20130416171321.5135E1C3151@cobra.cs.uni-duesseldorf.de> Author: mattip Branch: Changeset: r63416:7e3fde300fa3 Date: 2013-04-16 20:10 +0300 http://bitbucket.org/pypy/pypy/changeset/7e3fde300fa3/ Log: comment out unneeded rebuild diff --git a/pypy/module/test_lib_pypy/test_os_wait.py b/pypy/module/test_lib_pypy/test_os_wait.py --- a/pypy/module/test_lib_pypy/test_os_wait.py +++ b/pypy/module/test_lib_pypy/test_os_wait.py @@ -1,7 +1,7 @@ # Generates the resource cache -from __future__ import absolute_import -from lib_pypy.ctypes_config_cache import rebuild -rebuild.rebuild_one('resource.ctc.py') +#from __future__ import absolute_import +#from lib_pypy.ctypes_config_cache import rebuild +#rebuild.rebuild_one('resource.ctc.py') import os From noreply at buildbot.pypy.org Tue Apr 16 19:13:16 2013 From: noreply at buildbot.pypy.org (mattip) Date: Tue, 16 Apr 2013 19:13:16 +0200 (CEST) Subject: [pypy-commit] pypy win32-fixes3: cleaner version of changeset 17314bb8cd1a on py3k branch Message-ID: <20130416171316.BE9041C3181@cobra.cs.uni-duesseldorf.de> Author: mattip Branch: win32-fixes3 Changeset: r63412:87ac4d9b978b Date: 2013-04-16 12:34 +0300 http://bitbucket.org/pypy/pypy/changeset/87ac4d9b978b/ Log: cleaner version of changeset 17314bb8cd1a on py3k branch diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py --- a/rpython/rlib/rposix.py +++ b/rpython/rlib/rposix.py @@ -103,11 +103,10 @@ _set_errno(rffi.cast(INT, errno)) if os.name == 'nt': - is_valid_fd = rffi.llexternal( + is_valid_fd = jit.dont_look_inside(rffi.llexternal( "_PyVerify_fd", [rffi.INT], rffi.INT, compilation_info=errno_eci, - ) - @jit.dont_look_inside + )) def validate_fd(fd): if not is_valid_fd(fd): raise OSError(get_errno(), 'Bad file descriptor') From noreply at buildbot.pypy.org Tue Apr 16 19:13:22 2013 From: noreply at buildbot.pypy.org (mattip) Date: Tue, 16 Apr 2013 19:13:22 +0200 (CEST) Subject: [pypy-commit] pypy default: merge heads Message-ID: <20130416171322.82A991C3151@cobra.cs.uni-duesseldorf.de> Author: mattip Branch: Changeset: r63417:84d6ab8cc8a2 Date: 2013-04-16 20:12 +0300 http://bitbucket.org/pypy/pypy/changeset/84d6ab8cc8a2/ Log: merge heads diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -129,3 +129,5 @@ .. branch: release-2.0-beta2 .. branch: unbreak-freebsd + +.. branch: virtualref-virtualizable diff --git a/rpython/tool/logparser.py b/rpython/tool/logparser.py --- a/rpython/tool/logparser.py +++ b/rpython/tool/logparser.py @@ -70,7 +70,11 @@ time = int(int(match.group(1), 16)) time_decrase = time_decrase or time < lasttime lasttime = time - record(match.group(2), time=int(match.group(1), 16)) + try: + record(match.group(2), time=int(match.group(1), 16)) + except: + print "Line", i + raise if verbose: sys.stderr.write('loaded\n') if performance_log and time_decrase: From noreply at buildbot.pypy.org Tue Apr 16 20:28:51 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Tue, 16 Apr 2013 20:28:51 +0200 (CEST) Subject: [pypy-commit] pypy py3k: fill in missing exceptions Message-ID: <20130416182851.BC7371C01FD@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63419:fcc7e919d7eb Date: 2013-04-15 18:14 -0700 http://bitbucket.org/pypy/pypy/changeset/fcc7e919d7eb/ Log: fill in missing exceptions diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py --- a/pypy/interpreter/baseobjspace.py +++ b/pypy/interpreter/baseobjspace.py @@ -1655,11 +1655,15 @@ 'AssertionError', 'AttributeError', 'BaseException', + 'BufferError', + 'BytesWarning', 'DeprecationWarning', 'EOFError', 'EnvironmentError', 'Exception', 'FloatingPointError', + 'FutureWarning', + 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', @@ -1673,23 +1677,28 @@ 'NotImplementedError', 'OSError', 'OverflowError', + 'PendingDeprecationWarning', 'ReferenceError', + 'ResourceWarning', 'RuntimeError', + 'RuntimeWarning', 'StopIteration', 'SyntaxError', + 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', + 'UnicodeEncodeError', 'UnicodeError', - 'UnicodeEncodeError', 'UnicodeTranslateError', + 'UnicodeWarning', + 'UserWarning', 'ValueError', - 'ZeroDivisionError', - 'RuntimeWarning', - 'PendingDeprecationWarning', + 'Warning', + 'ZeroDivisionError' ] if sys.platform.startswith("win"): From noreply at buildbot.pypy.org Tue Apr 16 20:28:53 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Tue, 16 Apr 2013 20:28:53 +0200 (CEST) Subject: [pypy-commit] pypy py3k: _pickle & cStringIO are dead, kill Message-ID: <20130416182853.24DCC1C01FD@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63420:26c0fb3aa469 Date: 2013-04-16 11:26 -0700 http://bitbucket.org/pypy/pypy/changeset/26c0fb3aa469/ Log: _pickle & cStringIO are dead, kill diff --git a/pypy/module/test_lib_pypy/test__pickle.py b/pypy/module/test_lib_pypy/test__pickle.py deleted file mode 100644 --- a/pypy/module/test_lib_pypy/test__pickle.py +++ /dev/null @@ -1,6 +0,0 @@ - -class AppTestPickle: - - def test_stack_underflow(self): - import _pickle - raises(TypeError, _pickle.loads, "a string") diff --git a/pypy/module/test_lib_pypy/test_cStringIO.py b/pypy/module/test_lib_pypy/test_cStringIO.py deleted file mode 100644 --- a/pypy/module/test_lib_pypy/test_cStringIO.py +++ /dev/null @@ -1,25 +0,0 @@ -""" -Tests for the PyPy cStringIO implementation. -""" - -class AppTestcStringIO: - def setup_class(cls): - cls.w_io = cls.space.appexec([], "(): import cStringIO; return cStringIO") - cls.w_bytes = cls.space.wrap('some bytes') - - def test_reset(self): - """ - Test that the reset method of cStringIO objects sets the position - marker to the beginning of the stream. - """ - io = self.io.StringIO() - io.write(self.bytes) - assert io.read() == '' - io.reset() - assert io.read() == self.bytes - - io = self.io.StringIO(self.bytes) - assert io.read() == self.bytes - assert io.read() == '' - io.reset() - assert io.read() == self.bytes From noreply at buildbot.pypy.org Tue Apr 16 20:28:54 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Tue, 16 Apr 2013 20:28:54 +0200 (CEST) Subject: [pypy-commit] pypy py3k: slice ops aren't 'standard' descs anymore (in ObjSpace.MethodTable), move them Message-ID: <20130416182854.5D9091C01FD@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63421:0faddc5a7c23 Date: 2013-04-16 11:28 -0700 http://bitbucket.org/pypy/pypy/changeset/0faddc5a7c23/ Log: slice ops aren't 'standard' descs anymore (in ObjSpace.MethodTable), move them into baseobjspace so they show up in the FakeObjSpace diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py --- a/pypy/interpreter/baseobjspace.py +++ b/pypy/interpreter/baseobjspace.py @@ -1214,6 +1214,18 @@ else: return index + def getslice(space, w_obj, w_start, w_stop): + w_slice = space.newslice(w_start, w_stop, space.w_None) + return space.getitem(w_obj, w_slice) + + def setslice(space, w_obj, w_start, w_stop, w_sequence): + w_slice = space.newslice(w_start, w_stop, space.w_None) + return space.setitem(w_obj, w_slice, w_sequence) + + def delslice(space, w_obj, w_start, w_stop): + w_slice = space.newslice(w_start, w_stop, space.w_None) + return space.delitem(w_obj, w_slice) + def r_longlong_w(self, w_obj): bigint = self.bigint_w(w_obj) try: diff --git a/pypy/objspace/descroperation.py b/pypy/objspace/descroperation.py --- a/pypy/objspace/descroperation.py +++ b/pypy/objspace/descroperation.py @@ -332,18 +332,6 @@ typename) return space.get_and_call_function(w_descr, w_obj, w_key) - def getslice(space, w_obj, w_start, w_stop): - w_slice = space.newslice(w_start, w_stop, space.w_None) - return space.getitem(w_obj, w_slice) - - def setslice(space, w_obj, w_start, w_stop, w_sequence): - w_slice = space.newslice(w_start, w_stop, space.w_None) - return space.setitem(w_obj, w_slice, w_sequence) - - def delslice(space, w_obj, w_start, w_stop): - w_slice = space.newslice(w_start, w_stop, space.w_None) - return space.delitem(w_obj, w_slice) - def format(space, w_obj, w_format_spec): w_descr = space.lookup(w_obj, '__format__') if w_descr is None: From noreply at buildbot.pypy.org Tue Apr 16 20:33:40 2013 From: noreply at buildbot.pypy.org (matti) Date: Tue, 16 Apr 2013 20:33:40 +0200 (CEST) Subject: [pypy-commit] buildbot default: add SalsaSalsa, change win32 build to use pypy Message-ID: <20130416183340.B875A1C317E@cobra.cs.uni-duesseldorf.de> Author: matti Branch: Changeset: r785:e9baee829175 Date: 2013-04-16 21:33 +0300 http://bitbucket.org/pypy/buildbot/changeset/e9baee829175/ Log: add SalsaSalsa, change win32 build to use pypy diff --git a/bot2/pypybuildbot/master.py b/bot2/pypybuildbot/master.py --- a/bot2/pypybuildbot/master.py +++ b/bot2/pypybuildbot/master.py @@ -136,7 +136,7 @@ lib_python=True, pypyjit=True, app_tests=True, - interpreter='python', + interpreter='pypy', ) pypyJITTranslatedTestFactoryFreeBSD = pypybuilds.Translated( @@ -331,7 +331,7 @@ 'category' : 'mac64', }, {"name": WIN32, - "slavenames": ["aurora"], + "slavenames": ["aurora", "SalsaSalsa"], "builddir": WIN32, "factory": pypyOwnTestFactoryWin, "category": 'win32', @@ -343,13 +343,13 @@ "category": 'win32' }, {"name": APPLVLWIN32, - "slavenames": ["aurora"], + "slavenames": ["aurora", "SalsaSalsa"], "builddir": APPLVLWIN32, "factory": pypyTranslatedAppLevelTestFactoryWin, "category": "win32", }, {"name" : JITWIN32, - "slavenames": ["aurora"], + "slavenames": ["aurora", "SalsaSalsa"], 'builddir' : JITWIN32, 'factory' : pypyJITTranslatedTestFactoryWin, 'category' : 'win32', From noreply at buildbot.pypy.org Tue Apr 16 20:47:59 2013 From: noreply at buildbot.pypy.org (bdkearns) Date: Tue, 16 Apr 2013 20:47:59 +0200 (CEST) Subject: [pypy-commit] buildbot default: also un-force this one to python Message-ID: <20130416184759.2ADF31C3151@cobra.cs.uni-duesseldorf.de> Author: Brian Kearns Branch: Changeset: r786:8b26b8d7aba3 Date: 2013-04-16 14:47 -0400 http://bitbucket.org/pypy/buildbot/changeset/8b26b8d7aba3/ Log: also un-force this one to python diff --git a/bot2/pypybuildbot/master.py b/bot2/pypybuildbot/master.py --- a/bot2/pypybuildbot/master.py +++ b/bot2/pypybuildbot/master.py @@ -80,7 +80,7 @@ platform="win32", lib_python=True, app_tests=True, - interpreter='python') + ) jit_translation_args = ['-Ojit'] @@ -136,7 +136,6 @@ lib_python=True, pypyjit=True, app_tests=True, - interpreter='pypy', ) pypyJITTranslatedTestFactoryFreeBSD = pypybuilds.Translated( From noreply at buildbot.pypy.org Tue Apr 16 21:16:53 2013 From: noreply at buildbot.pypy.org (hodgestar) Date: Tue, 16 Apr 2013 21:16:53 +0200 (CEST) Subject: [pypy-commit] pypy remove-string-smm: Add support for func_defaults to interpdirect2app. Message-ID: <20130416191653.9EED91C01FD@cobra.cs.uni-duesseldorf.de> Author: Simon Cross Branch: remove-string-smm Changeset: r63422:264b4a12d787 Date: 2013-04-16 21:00 +0200 http://bitbucket.org/pypy/pypy/changeset/264b4a12d787/ Log: Add support for func_defaults to interpdirect2app. diff --git a/pypy/interpreter/gateway.py b/pypy/interpreter/gateway.py --- a/pypy/interpreter/gateway.py +++ b/pypy/interpreter/gateway.py @@ -809,7 +809,6 @@ args = inspect.getargs(func.func_code) if args.varargs or args.keywords: raise TypeError("Varargs and keywords not supported in unwrap_spec") - assert not func.func_defaults argspec = ', '.join([arg for arg in args.args[1:]]) func_code = py.code.Source(""" def f(w_obj, %(args)s): @@ -818,6 +817,7 @@ d = {} exec func_code.compile() in d f = d['f'] + f.func_defaults = unbound_meth.func_defaults f.__module__ = func.__module__ # necessary for unique identifiers for pickling f.func_name = func.func_name diff --git a/pypy/interpreter/test/test_gateway.py b/pypy/interpreter/test/test_gateway.py --- a/pypy/interpreter/test/test_gateway.py +++ b/pypy/interpreter/test/test_gateway.py @@ -135,18 +135,28 @@ def test_interpindirect2app(self): space = self.space + class BaseA(W_Root): def method(self, space, x): pass + def method_with_default(self, space, x=5): + pass + class A(BaseA): def method(self, space, x): return space.wrap(x + 2) + def method_with_default(self, space, x): + return space.wrap(x + 2) + class B(BaseA): def method(self, space, x): return space.wrap(x + 1) + def method_with_default(self, space, x): + return space.wrap(x + 1) + class FakeTypeDef(object): rawdict = {} bases = {} @@ -163,6 +173,15 @@ assert space.int_w(space.call_function(w_c, w_a, space.wrap(1))) == 1 + 2 assert space.int_w(space.call_function(w_c, w_b, space.wrap(-10))) == -10 + 1 + meth_with_default = gateway.interpindirect2app( + BaseA.method_with_default, {'x': int}) + w_d = space.wrap(meth_with_default) + + assert space.int_w(space.call_function(w_d, w_a, space.wrap(4))) == 4 + 2 + assert space.int_w(space.call_function(w_d, w_b, space.wrap(-10))) == -10 + 1 + assert space.int_w(space.call_function(w_d, w_a)) == 5 + 2 + assert space.int_w(space.call_function(w_d, w_b)) == 5 + 1 + def test_interp2app_unwrap_spec(self): space = self.space w = space.wrap From noreply at buildbot.pypy.org Tue Apr 16 21:16:54 2013 From: noreply at buildbot.pypy.org (hodgestar) Date: Tue, 16 Apr 2013 21:16:54 +0200 (CEST) Subject: [pypy-commit] pypy remove-string-smm: Add support for func_doc/__doc__ to interpindirect2app. Message-ID: <20130416191654.CC7501C3180@cobra.cs.uni-duesseldorf.de> Author: Simon Cross Branch: remove-string-smm Changeset: r63423:efdea0b37ab8 Date: 2013-04-16 21:07 +0200 http://bitbucket.org/pypy/pypy/changeset/efdea0b37ab8/ Log: Add support for func_doc/__doc__ to interpindirect2app. diff --git a/pypy/interpreter/gateway.py b/pypy/interpreter/gateway.py --- a/pypy/interpreter/gateway.py +++ b/pypy/interpreter/gateway.py @@ -818,6 +818,7 @@ exec func_code.compile() in d f = d['f'] f.func_defaults = unbound_meth.func_defaults + f.func_doc = unbound_meth.func_doc f.__module__ = func.__module__ # necessary for unique identifiers for pickling f.func_name = func.func_name diff --git a/pypy/interpreter/test/test_gateway.py b/pypy/interpreter/test/test_gateway.py --- a/pypy/interpreter/test/test_gateway.py +++ b/pypy/interpreter/test/test_gateway.py @@ -138,6 +138,7 @@ class BaseA(W_Root): def method(self, space, x): + "This is a method" pass def method_with_default(self, space, x=5): @@ -173,6 +174,9 @@ assert space.int_w(space.call_function(w_c, w_a, space.wrap(1))) == 1 + 2 assert space.int_w(space.call_function(w_c, w_b, space.wrap(-10))) == -10 + 1 + doc = space.str_w(space.getattr(w_c, space.wrap('__doc__'))) + assert doc == "This is a method" + meth_with_default = gateway.interpindirect2app( BaseA.method_with_default, {'x': int}) w_d = space.wrap(meth_with_default) From noreply at buildbot.pypy.org Tue Apr 16 21:16:56 2013 From: noreply at buildbot.pypy.org (hodgestar) Date: Tue, 16 Apr 2013 21:16:56 +0200 (CEST) Subject: [pypy-commit] pypy remove-string-smm: Some progress on bytearray. Message-ID: <20130416191656.16B3B1C01FD@cobra.cs.uni-duesseldorf.de> Author: Simon Cross Branch: remove-string-smm Changeset: r63424:b2a605627eba Date: 2013-04-16 21:16 +0200 http://bitbucket.org/pypy/pypy/changeset/b2a605627eba/ Log: Some progress on bytearray. diff --git a/pypy/objspace/std/bytearrayobject.py b/pypy/objspace/std/bytearrayobject.py --- a/pypy/objspace/std/bytearrayobject.py +++ b/pypy/objspace/std/bytearrayobject.py @@ -1,32 +1,23 @@ from pypy.interpreter.error import OperationError, operationerrfmt -from pypy.objspace.std.model import registerimplementation, W_Object +from pypy.objspace.std.model import registerimplementation from pypy.objspace.std.register_all import register_all from pypy.objspace.std.inttype import wrapint from pypy.objspace.std.multimethod import FailedToImplement -from pypy.objspace.std.noneobject import W_NoneObject -from rpython.rlib.rarithmetic import intmask from rpython.rlib.rstring import StringBuilder -from rpython.rlib.debug import check_annotation from pypy.objspace.std import stringobject -from pypy.objspace.std.intobject import W_IntObject -from pypy.objspace.std.listobject import get_positive_index, get_list_index -from pypy.objspace.std.sliceobject import W_SliceObject, normalize_simple_slice -from pypy.objspace.std.stringobject import W_StringObject -from pypy.objspace.std.strutil import ParseStringError -from pypy.objspace.std.strutil import string_to_float -from pypy.objspace.std.tupleobject import W_TupleObject -from pypy.objspace.std.unicodeobject import W_UnicodeObject -from pypy.objspace.std import slicetype -from pypy.interpreter import gateway +from pypy.objspace.std.listobject import get_list_index +from pypy.interpreter.gateway import unwrap_spec from pypy.interpreter.buffer import RWBuffer from pypy.interpreter.signature import Signature from pypy.objspace.std.bytearraytype import ( - makebytearraydata_w, getbytevalue, - new_bytearray -) -from rpython.tool.sourcetools import func_with_new_name -from pypy.objspace.std.contiguousstring import StringMethods + makebytearraydata_w, new_bytearray) from pypy.objspace.std.bytearraytype import W_AbstractBytearrayObject +from pypy.objspace.std.unicodeobject import W_UnicodeObject # XXX: kill this whem SMMs are dead +from pypy.objspace.std.noneobject import W_NoneObject # XXX: and this one. +from pypy.objspace.std.stringobject import W_StringObject # XXX: and this too. +from pypy.objspace.std.tupleobject import W_TupleObject # XXX: ... +from pypy.objspace.std.intobject import W_IntObject # XXX: ... +from pypy.objspace.std.sliceobject import W_SliceObject # XXX: WTF. class W_BytearrayObject(W_AbstractBytearrayObject): @@ -35,10 +26,74 @@ def __init__(w_self, data): w_self.data = data + def descr_ljust(self, space, arg, fillchar=' '): + u_self = self.data + if len(fillchar) != 1: + raise OperationError(space.w_TypeError, + space.wrap("ljust() argument 2 must be a single character")) + + d = arg - len(u_self) + if d > 0: + lst = [0] * max(arg, len(u_self)) + fillchar = fillchar[0] # annotator hint: it's a single character + lst[:len(u_self)] = u_self + for i in range(d): + lst[len(u_self) + i] = fillchar + else: + lst = u_self.data[:] + + return space.newbytearray(lst) + + def bytearray_rjust(self, space, arg, fillchar=' '): + u_self = self.data + if len(fillchar) != 1: + raise OperationError(space.w_TypeError, + space.wrap("rjust() argument 2 must be a single character")) + + d = arg - len(u_self) + if d > 0: + lst = [0] * max(arg, len(u_self)) + fillchar = fillchar[0] # annotator hint: it's a single character + for i in range(d): + lst[i] = fillchar + lst[len(u_self) - 1:] = u_self + else: + lst = u_self.data[:] + + return space.newbytearray(lst) + + def descr_insert(self, space, index, w_val): + if isinstance(val, int): + val = chr(val) + elif len(val) != 1: + raise OperationError(space.w_ValueError, + space.wrap("string must be of size 1")) + self.data.insert(index, val) + return space.w_None + + def descr_pop(self, space, index=-1): + try: + result = self.data.pop(index) + except IndexError: + if not self.data: + raise OperationError(space.w_IndexError, space.wrap( + "pop from empty bytearray")) + raise OperationError(space.w_IndexError, space.wrap( + "pop index out of range")) + return space.wrap(ord(result)) + + def descr_remove(self, space, value): + try: + self.data.remove(chr(value)) + except ValueError: + raise OperationError(space.w_ValueError, space.wrap( + "value not found in bytearray")) + def __repr__(w_self): """ representation for debugging purposes """ return "%s(%s)" % (w_self.__class__.__name__, ''.join(w_self.data)) + registerimplementation(W_BytearrayObject) init_signature = Signature(['source', 'encoding', 'errors'], None, None) diff --git a/pypy/objspace/std/bytearraytype.py b/pypy/objspace/std/bytearraytype.py --- a/pypy/objspace/std/bytearraytype.py +++ b/pypy/objspace/std/bytearraytype.py @@ -1,10 +1,8 @@ -from pypy.interpreter.baseobjspace import W_Root from pypy.objspace.std.model import W_Object from pypy.interpreter.error import OperationError -from pypy.interpreter.gateway import interp2app, unwrap_spec -from pypy.objspace.std.register_all import register_all +from pypy.interpreter.gateway import ( + interpindirect2app, interp2app, unwrap_spec) from pypy.objspace.std.stdtypedef import StdTypeDef, SMM -from pypy.objspace.std.listobject import get_positive_index from pypy.objspace.std.stringtype import ( str_decode, @@ -17,11 +15,52 @@ str_splitlines, str_translate) from rpython.rlib.objectmodel import newlist_hint, resizelist_hint -from pypy.objspace.std.bytearrayinterface import bytearray_interface_methods class W_AbstractBytearrayObject(W_Object): - pass + @unwrap_spec(arg=int, fillchar=str) + def descr_ljust(self, space, arg, fillchar=' '): + """S.ljust(width[, fillchar]) -> string + + Return S left justified in a string of length width. Padding + is done using the specified fill character (default is a space). + """ + raise NotImplementedError + + @unwrap_spec(arg=int, fillchar=str) + def descr_rjust(self, space, arg, fillchar=' '): + """S.rjust(width[, fillchar]) -> string + + Return S right justified in a string of length width. Padding + is done using the specified fill character (default is a space). + """ + raise NotImplementedError + + @unwrap_spec(index=int) + def descr_insert(self, space, index, w_val): + """B.insert(index, int) -> None + + Insert a single item into the bytearray before the given index. + """ + raise NotImplementedError + + @unwrap_spec(index=int) + def descr_pop(self, space, index=-1): + """B.pop([index]) -> int + + Remove and return a single item from B. If no index + argument is given, will pop the last value. + """ + raise NotImplementedError + + @unwrap_spec(value='index') + def descr_remove(self, space, value): + """B.remove(int) -> None + + Remove the first occurance of a value in B. + """ + raise NotImplementedError + str_join = SMM('join', 2, defaults=(None,-1)) @@ -29,103 +68,6 @@ bytearray_extend = SMM('extend', 2) - at unwrap_spec(w_self=W_Root, arg=int, fillchar=str) -def bytearray_ljust(w_self, space, arg, fillchar=' '): - """S.ljust(width[, fillchar]) -> string - - Return S left justified in a string of length width. Padding - is done using the specified fill character (default is a space). - """ - assert isinstance(w_self, W_AbstractBytearrayObject) - u_self = w_self.data - if len(fillchar) != 1: - raise OperationError(space.w_TypeError, - space.wrap("ljust() argument 2 must be a single character")) - - d = arg - len(u_self) - if d > 0: - lst = [0] * max(arg, len(u_self)) - fillchar = fillchar[0] # annotator hint: it's a single character - lst[:len(u_self)] = u_self - for i in range(d): - lst[len(u_self) + i] = fillchar - else: - lst = u_self.data[:] - - return space.newbytearray(lst) - - - at unwrap_spec(w_self=W_Root, arg=int, fillchar=str) -def bytearray_rjust(w_self, space, arg, fillchar=' '): - """S.rjust(width[, fillchar]) -> string - - Return S right justified in a string of length width. Padding - is done using the specified fill character (default is a space). - """ - u_self = w_self.data - assert isinstance(w_self, W_AbstractBytearrayObject) - if len(fillchar) != 1: - raise OperationError(space.w_TypeError, - space.wrap("rjust() argument 2 must be a single character")) - - d = arg - len(u_self) - if d > 0: - lst = [0] * max(arg, len(u_self)) - fillchar = fillchar[0] # annotator hint: it's a single character - for i in range(d): - lst[i] = fillchar - lst[len(u_self)-1:] = u_self - else: - lst = u_self.data[:] - - return space.newbytearray(lst) - - - at unwrap_spec(index=int, val='str_or_int') -def bytearray_insert(w_self, space, index, val): - """B.insert(index, int) -> None - - Insert a single item into the bytearray before the given index. - """ - if isinstance(val, int): - val = chr(val) - elif len(val) != 1: - raise OperationError(space.w_ValueError, - space.wrap("string must be of size 1")) - w_self.data.insert(index, val) - return space.w_None - - - at unwrap_spec(index=int) -def bytearray_pop(w_self, space, index=-1): - """B.pop([index]) -> int - - Remove and return a single item from B. If no index - argument is given, will pop the last value. - """ - try: - result = w_self.data.pop(index) - except IndexError: - if not w_self.data: - raise OperationError(space.w_IndexError, space.wrap( - "pop from empty bytearray")) - raise OperationError(space.w_IndexError, space.wrap( - "pop index out of range")) - return space.wrap(ord(result)) - - - at unwrap_spec(value='index') -def bytearray_remove(w_self, space, value): - """B.remove(int) -> None - - Remove the first occurance of a value in B. - """ - try: - w_self.data.remove(chr(value)) - except ValueError: - raise OperationError(space.w_ValueError, space.wrap( - "value not found in bytearray")) - bytearray_reverse = SMM('reverse', 1, doc="B.reverse() -> None\n\n" @@ -267,10 +209,10 @@ __hash__ = None, __reduce__ = interp2app(descr_bytearray__reduce__), fromhex = interp2app(descr_fromhex, as_classmethod=True), - ljust=interp2app(bytearray_ljust), - rjust=interp2app(bytearray_rjust), - insert=interp2app(bytearray_insert), - pop=interp2app(bytearray_pop), - remove=interp2app(bytearray_remove), + ljust=interpindirect2app(W_AbstractBytearrayObject.descr_ljust), + rjust=interpindirect2app(W_AbstractBytearrayObject.descr_rjust), + insert=interpindirect2app(W_AbstractBytearrayObject.descr_insert), + pop=interpindirect2app(W_AbstractBytearrayObject.descr_pop), + remove=interpindirect2app(W_AbstractBytearrayObject.descr_remove), ) bytearray_typedef.registermethods(globals()) From noreply at buildbot.pypy.org Tue Apr 16 21:33:26 2013 From: noreply at buildbot.pypy.org (hodgestar) Date: Tue, 16 Apr 2013 21:33:26 +0200 (CEST) Subject: [pypy-commit] pypy remove-string-smm: Add support for copying unwrap_spec to interpindirect2app. Message-ID: <20130416193326.9BCE71C317F@cobra.cs.uni-duesseldorf.de> Author: Simon Cross Branch: remove-string-smm Changeset: r63425:1a9a9b6917f4 Date: 2013-04-16 21:31 +0200 http://bitbucket.org/pypy/pypy/changeset/1a9a9b6917f4/ Log: Add support for copying unwrap_spec to interpindirect2app. diff --git a/pypy/interpreter/gateway.py b/pypy/interpreter/gateway.py --- a/pypy/interpreter/gateway.py +++ b/pypy/interpreter/gateway.py @@ -823,7 +823,7 @@ # necessary for unique identifiers for pickling f.func_name = func.func_name if unwrap_spec is None: - unwrap_spec = {} + unwrap_spec = getattr(unbound_meth, 'unwrap_spec', {}) else: assert isinstance(unwrap_spec, dict) unwrap_spec = unwrap_spec.copy() diff --git a/pypy/interpreter/test/test_gateway.py b/pypy/interpreter/test/test_gateway.py --- a/pypy/interpreter/test/test_gateway.py +++ b/pypy/interpreter/test/test_gateway.py @@ -144,6 +144,10 @@ def method_with_default(self, space, x=5): pass + @gateway.unwrap_spec(x=int) + def method_with_unwrap_spec(self, space, x): + pass + class A(BaseA): def method(self, space, x): return space.wrap(x + 2) @@ -151,6 +155,9 @@ def method_with_default(self, space, x): return space.wrap(x + 2) + def method_with_unwrap_spec(self, space, x): + return space.wrap(x + 2) + class B(BaseA): def method(self, space, x): return space.wrap(x + 1) @@ -158,6 +165,9 @@ def method_with_default(self, space, x): return space.wrap(x + 1) + def method_with_unwrap_spec(self, space, x): + return space.wrap(x + 1) + class FakeTypeDef(object): rawdict = {} bases = {} @@ -186,6 +196,11 @@ assert space.int_w(space.call_function(w_d, w_a)) == 5 + 2 assert space.int_w(space.call_function(w_d, w_b)) == 5 + 1 + meth_with_unwrap_spec = gateway.interpindirect2app( + BaseA.method_with_unwrap_spec) + w_e = space.wrap(meth_with_unwrap_spec) + assert space.int_w(space.call_function(w_e, w_a, space.wrap(4))) == 4 + 2 + def test_interp2app_unwrap_spec(self): space = self.space w = space.wrap From noreply at buildbot.pypy.org Tue Apr 16 21:33:27 2013 From: noreply at buildbot.pypy.org (hodgestar) Date: Tue, 16 Apr 2013 21:33:27 +0200 (CEST) Subject: [pypy-commit] pypy remove-string-smm: Fix name of implementation of descr_rjust in bytearray. Message-ID: <20130416193327.DF1E01C317F@cobra.cs.uni-duesseldorf.de> Author: Simon Cross Branch: remove-string-smm Changeset: r63426:4215711f5f45 Date: 2013-04-16 21:33 +0200 http://bitbucket.org/pypy/pypy/changeset/4215711f5f45/ Log: Fix name of implementation of descr_rjust in bytearray. diff --git a/pypy/objspace/std/bytearrayobject.py b/pypy/objspace/std/bytearrayobject.py --- a/pypy/objspace/std/bytearrayobject.py +++ b/pypy/objspace/std/bytearrayobject.py @@ -44,7 +44,7 @@ return space.newbytearray(lst) - def bytearray_rjust(self, space, arg, fillchar=' '): + def descr_rjust(self, space, arg, fillchar=' '): u_self = self.data if len(fillchar) != 1: raise OperationError(space.w_TypeError, From noreply at buildbot.pypy.org Tue Apr 16 21:38:19 2013 From: noreply at buildbot.pypy.org (hodgestar) Date: Tue, 16 Apr 2013 21:38:19 +0200 (CEST) Subject: [pypy-commit] pypy remove-string-smm: Kill str_or_int. Message-ID: <20130416193819.967F41C01FD@cobra.cs.uni-duesseldorf.de> Author: Simon Cross Branch: remove-string-smm Changeset: r63427:eed07b5588c3 Date: 2013-04-16 21:38 +0200 http://bitbucket.org/pypy/pypy/changeset/eed07b5588c3/ Log: Kill str_or_int. diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py --- a/pypy/interpreter/baseobjspace.py +++ b/pypy/interpreter/baseobjspace.py @@ -1301,11 +1301,6 @@ return None return self.str_w(w_obj) - def str_or_int_w(self, w_obj): - if self.is_true(self.isinstance(w_obj, self.w_str)): - return self.str_w(w_obj) - return self.int_w(w_obj) - def str_w(self, w_obj): return w_obj.str_w(self) diff --git a/pypy/interpreter/gateway.py b/pypy/interpreter/gateway.py --- a/pypy/interpreter/gateway.py +++ b/pypy/interpreter/gateway.py @@ -132,9 +132,6 @@ def visit_str_or_None(self, el, app_sig): self.checked_space_method(el, app_sig) - def visit_str_or_int(self, el, app_sig): - self.checked_space_method(el, app_sig) - def visit_str0(self, el, app_sig): self.checked_space_method(el, app_sig) @@ -248,9 +245,6 @@ def visit_str_or_None(self, typ): self.run_args.append("space.str_or_None_w(%s)" % (self.scopenext(),)) - def visit_str_or_int(self, typ): - self.run_args.append("space.str_or_int_w(%s)" % (self.scopenext(),)) - def visit_str0(self, typ): self.run_args.append("space.str0_w(%s)" % (self.scopenext(),)) From noreply at buildbot.pypy.org Tue Apr 16 22:07:29 2013 From: noreply at buildbot.pypy.org (hodgestar) Date: Tue, 16 Apr 2013 22:07:29 +0200 (CEST) Subject: [pypy-commit] pypy remove-string-smm: Add gateway_chr_w and 'chr' unwrap spec type (fijal, hodgestar) Message-ID: <20130416200729.158301C01FD@cobra.cs.uni-duesseldorf.de> Author: Simon Cross Branch: remove-string-smm Changeset: r63428:5446bd20e6cc Date: 2013-04-16 22:07 +0200 http://bitbucket.org/pypy/pypy/changeset/5446bd20e6cc/ Log: Add gateway_chr_w and 'chr' unwrap spec type (fijal, hodgestar) diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py --- a/pypy/interpreter/baseobjspace.py +++ b/pypy/interpreter/baseobjspace.py @@ -1367,6 +1367,26 @@ self.wrap("integer argument expected, got float")) return self.int_w(self.int(w_obj)) + def gateway_chr_w(self, w_obj): + """Accept string of length 1 or an integer that can be cast to chr + """ + if self.isinstance_w(w_obj, self.w_str): + c = self.str_w(w_obj) + if len(c) != 1: + raise OperationError(self.w_ValueError, + self.wrap("string must be of size 1")) + return c[0] + elif self.isinstance_w(w_obj, self.w_int): + i = self.int_w(w_obj) + if i < 0 or i > 255: + raise OperationError( + self.w_ValueError, + self.wrap("byte must be in range(0, 256)")) + return chr(i) + raise OperationError( + self.w_TypeError, + self.wrap("an integer or string of size 1 is required")) + def gateway_float_w(self, w_obj): return self.float_w(self.float(w_obj)) diff --git a/pypy/interpreter/gateway.py b/pypy/interpreter/gateway.py --- a/pypy/interpreter/gateway.py +++ b/pypy/interpreter/gateway.py @@ -129,6 +129,9 @@ def visit_bufferstr(self, el, app_sig): self.checked_space_method(el, app_sig) + def visit_chr(self, el, app_sig): + self.checked_space_method(el, app_sig) + def visit_str_or_None(self, el, app_sig): self.checked_space_method(el, app_sig) @@ -242,6 +245,9 @@ def visit_bufferstr(self, typ): self.run_args.append("space.bufferstr_w(%s)" % (self.scopenext(),)) + def visit_chr(self, typ): + self.run_args.append("space.gateway_chr_w(%s)" % (self.scopenext(),)) + def visit_str_or_None(self, typ): self.run_args.append("space.str_or_None_w(%s)" % (self.scopenext(),)) @@ -379,6 +385,9 @@ def visit_bufferstr(self, typ): self.unwrap.append("space.bufferstr_w(%s)" % (self.nextarg(),)) + def visit_chr(self, typ): + self.unwrap.append("space.gateway_chr_w(%s)" % (self.nextarg(),)) + def visit_str_or_None(self, typ): self.unwrap.append("space.str_or_None_w(%s)" % (self.nextarg(),)) diff --git a/pypy/interpreter/test/test_gateway.py b/pypy/interpreter/test/test_gateway.py --- a/pypy/interpreter/test/test_gateway.py +++ b/pypy/interpreter/test/test_gateway.py @@ -238,6 +238,28 @@ assert self.space.eq_w(space.call_function(w_app_g, space.wrap(True)), space.wrap(True)) + def test_interp2app_unwrap_spec_chr(self): + space = self.space + + def g(space, c): + return space.wrap(c) + + app_g = gateway.interp2app(g, unwrap_spec=[gateway.ObjSpace, 'chr']) + w_app_g = space.wrap(app_g) + assert space.str_w( + space.call_function(w_app_g, space.wrap(1))) == chr(1) + assert space.str_w( + space.call_function(w_app_g, space.wrap('a'))) == 'a' + + space.raises_w(space.w_ValueError, + space.call_function, w_app_g, space.wrap('ab')) + space.raises_w(space.w_ValueError, + space.call_function, w_app_g, space.wrap(256)) + space.raises_w(space.w_ValueError, + space.call_function, w_app_g, space.wrap(-1)) + space.raises_w(space.w_TypeError, + space.call_function, w_app_g, space.w_None) + def test_caching_methods(self): class Base(gateway.W_Root): def f(self): From noreply at buildbot.pypy.org Tue Apr 16 22:09:23 2013 From: noreply at buildbot.pypy.org (hodgestar) Date: Tue, 16 Apr 2013 22:09:23 +0200 (CEST) Subject: [pypy-commit] pypy remove-string-smm: Use new 'chr' unwrap spec to fix bytearray.insert. Message-ID: <20130416200923.B6BAA1C01FD@cobra.cs.uni-duesseldorf.de> Author: Simon Cross Branch: remove-string-smm Changeset: r63429:b969a2ea3352 Date: 2013-04-16 22:09 +0200 http://bitbucket.org/pypy/pypy/changeset/b969a2ea3352/ Log: Use new 'chr' unwrap spec to fix bytearray.insert. diff --git a/pypy/objspace/std/bytearrayobject.py b/pypy/objspace/std/bytearrayobject.py --- a/pypy/objspace/std/bytearrayobject.py +++ b/pypy/objspace/std/bytearrayobject.py @@ -62,12 +62,7 @@ return space.newbytearray(lst) - def descr_insert(self, space, index, w_val): - if isinstance(val, int): - val = chr(val) - elif len(val) != 1: - raise OperationError(space.w_ValueError, - space.wrap("string must be of size 1")) + def descr_insert(self, space, index, val): self.data.insert(index, val) return space.w_None diff --git a/pypy/objspace/std/bytearraytype.py b/pypy/objspace/std/bytearraytype.py --- a/pypy/objspace/std/bytearraytype.py +++ b/pypy/objspace/std/bytearraytype.py @@ -36,8 +36,8 @@ """ raise NotImplementedError - @unwrap_spec(index=int) - def descr_insert(self, space, index, w_val): + @unwrap_spec(index=int, val='chr') + def descr_insert(self, space, index, val): """B.insert(index, int) -> None Insert a single item into the bytearray before the given index. From noreply at buildbot.pypy.org Tue Apr 16 22:18:54 2013 From: noreply at buildbot.pypy.org (hodgestar) Date: Tue, 16 Apr 2013 22:18:54 +0200 (CEST) Subject: [pypy-commit] pypy remove-string-smm: Remove bytearray.append SMM. Message-ID: <20130416201854.4CC0F1C01FD@cobra.cs.uni-duesseldorf.de> Author: Simon Cross Branch: remove-string-smm Changeset: r63430:0e6b17820f73 Date: 2013-04-16 22:18 +0200 http://bitbucket.org/pypy/pypy/changeset/0e6b17820f73/ Log: Remove bytearray.append SMM. diff --git a/pypy/objspace/std/bytearrayobject.py b/pypy/objspace/std/bytearrayobject.py --- a/pypy/objspace/std/bytearrayobject.py +++ b/pypy/objspace/std/bytearrayobject.py @@ -84,6 +84,10 @@ raise OperationError(space.w_ValueError, space.wrap( "value not found in bytearray")) + def descr_append(self, space, val): + self.data.append(val) + return space.w_None + def __repr__(w_self): """ representation for debugging purposes """ return "%s(%s)" % (w_self.__class__.__name__, ''.join(w_self.data)) @@ -572,10 +576,6 @@ # __________________________________________________________ # Mutability methods -def bytearray_append__Bytearray_ANY(space, w_bytearray, w_item): - from pypy.objspace.std.bytearraytype import getbytevalue - w_bytearray.data.append(getbytevalue(space, w_item)) - def bytearray_extend__Bytearray_Bytearray(space, w_bytearray, w_other): w_bytearray.data += w_other.data diff --git a/pypy/objspace/std/bytearraytype.py b/pypy/objspace/std/bytearraytype.py --- a/pypy/objspace/std/bytearraytype.py +++ b/pypy/objspace/std/bytearraytype.py @@ -61,10 +61,17 @@ """ raise NotImplementedError + @unwrap_spec(val='chr') + def descr_append(self, space, val): + """B.append(int) -> None + + Append a single item to the end of B. + """ + raise NotImplementedError + str_join = SMM('join', 2, defaults=(None,-1)) -bytearray_append = SMM('append', 2) bytearray_extend = SMM('extend', 2) @@ -214,5 +221,6 @@ insert=interpindirect2app(W_AbstractBytearrayObject.descr_insert), pop=interpindirect2app(W_AbstractBytearrayObject.descr_pop), remove=interpindirect2app(W_AbstractBytearrayObject.descr_remove), + append=interpindirect2app(W_AbstractBytearrayObject.descr_append), ) bytearray_typedef.registermethods(globals()) From noreply at buildbot.pypy.org Tue Apr 16 22:26:41 2013 From: noreply at buildbot.pypy.org (hodgestar) Date: Tue, 16 Apr 2013 22:26:41 +0200 (CEST) Subject: [pypy-commit] pypy remove-string-smm: Remove bytearray.extend multi-method and some unneeded return space.w_Nones (fijal, hodgestar). Message-ID: <20130416202641.E502E1C01FD@cobra.cs.uni-duesseldorf.de> Author: Simon Cross Branch: remove-string-smm Changeset: r63431:58d8ca4f8154 Date: 2013-04-16 22:26 +0200 http://bitbucket.org/pypy/pypy/changeset/58d8ca4f8154/ Log: Remove bytearray.extend multi-method and some unneeded return space.w_Nones (fijal, hodgestar). diff --git a/pypy/objspace/std/bytearrayobject.py b/pypy/objspace/std/bytearrayobject.py --- a/pypy/objspace/std/bytearrayobject.py +++ b/pypy/objspace/std/bytearrayobject.py @@ -64,7 +64,6 @@ def descr_insert(self, space, index, val): self.data.insert(index, val) - return space.w_None def descr_pop(self, space, index=-1): try: @@ -86,7 +85,14 @@ def descr_append(self, space, val): self.data.append(val) - return space.w_None + + def descr_extend(self, space, w_iterable): + if isinstance(w_iterable, W_BytearrayObject): + self.data.extend(w_iterable.data) + return + for w_item in space.listview(w_iterable): + c = space.gateway_chr_w(w_item) + self.data.append(c) def __repr__(w_self): """ representation for debugging purposes """ @@ -576,12 +582,6 @@ # __________________________________________________________ # Mutability methods -def bytearray_extend__Bytearray_Bytearray(space, w_bytearray, w_other): - w_bytearray.data += w_other.data - -def bytearray_extend__Bytearray_ANY(space, w_bytearray, w_other): - w_bytearray.data += makebytearraydata_w(space, w_other) - def inplace_add__Bytearray_Bytearray(space, w_bytearray1, w_bytearray2): bytearray_extend__Bytearray_Bytearray(space, w_bytearray1, w_bytearray2) return w_bytearray1 diff --git a/pypy/objspace/std/bytearraytype.py b/pypy/objspace/std/bytearraytype.py --- a/pypy/objspace/std/bytearraytype.py +++ b/pypy/objspace/std/bytearraytype.py @@ -69,12 +69,16 @@ """ raise NotImplementedError + def descr_extend(self, space, w_iterable): + """B.extend(iterable int) -> None + + Append all the elements from the iterator or sequence to the + end of B. + """ + raise NotImplementedError str_join = SMM('join', 2, defaults=(None,-1)) -bytearray_extend = SMM('extend', 2) - - bytearray_reverse = SMM('reverse', 1, doc="B.reverse() -> None\n\n" @@ -222,5 +226,6 @@ pop=interpindirect2app(W_AbstractBytearrayObject.descr_pop), remove=interpindirect2app(W_AbstractBytearrayObject.descr_remove), append=interpindirect2app(W_AbstractBytearrayObject.descr_append), + extend=interpindirect2app(W_AbstractBytearrayObject.descr_extend), ) bytearray_typedef.registermethods(globals()) From noreply at buildbot.pypy.org Tue Apr 16 22:35:05 2013 From: noreply at buildbot.pypy.org (bivab) Date: Tue, 16 Apr 2013 22:35:05 +0200 (CEST) Subject: [pypy-commit] pypy default: expose ARM libffi ABI information Message-ID: <20130416203505.3154D1C3151@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63432:5be8df0b14e7 Date: 2013-04-16 22:28 +0200 http://bitbucket.org/pypy/pypy/changeset/5be8df0b14e7/ Log: expose ARM libffi ABI information diff --git a/rpython/rlib/clibffi.py b/rpython/rlib/clibffi.py --- a/rpython/rlib/clibffi.py +++ b/rpython/rlib/clibffi.py @@ -4,6 +4,7 @@ from rpython.rtyper.tool import rffi_platform from rpython.rtyper.lltypesystem import lltype, rffi +from rpython.rtyper.tool import rffi_platform from rpython.rlib.unroll import unrolling_iterable from rpython.rlib.rarithmetic import intmask, is_emulated_long from rpython.rlib.objectmodel import we_are_translated @@ -15,6 +16,7 @@ from rpython.translator.tool.cbuild import ExternalCompilationInfo from rpython.translator.platform import platform from rpython.conftest import cdir +from platform import machine import py import os import sys @@ -35,6 +37,8 @@ _LITTLE_ENDIAN = sys.byteorder == 'little' _BIG_ENDIAN = sys.byteorder == 'big' +_ARM = rffi_platform.getdefined('__arm__', '') + if _WIN32: from rpython.rlib import rwin32 @@ -154,6 +158,10 @@ if _WIN32 and not _WIN64: FFI_STDCALL = rffi_platform.ConstantInteger('FFI_STDCALL') + if _ARM: + FFI_SYSV = rffi_platform.ConstantInteger('FFI_SYSV') + FFI_VFP = rffi_platform.ConstantInteger('FFI_VFP') + FFI_TYPE_STRUCT = rffi_platform.ConstantInteger('FFI_TYPE_STRUCT') size_t = rffi_platform.SimpleType("size_t", rffi.ULONG) @@ -327,6 +335,9 @@ FFI_DEFAULT_ABI = cConfig.FFI_DEFAULT_ABI if _WIN32 and not _WIN64: FFI_STDCALL = cConfig.FFI_STDCALL +if _ARM: + FFI_SYSV = cConfig.FFI_SYSV + FFI_VFP = cConfig.FFI_VFP FFI_TYPE_STRUCT = cConfig.FFI_TYPE_STRUCT FFI_CIFP = lltype.Ptr(cConfig.ffi_cif) From noreply at buildbot.pypy.org Tue Apr 16 22:35:06 2013 From: noreply at buildbot.pypy.org (bivab) Date: Tue, 16 Apr 2013 22:35:06 +0200 (CEST) Subject: [pypy-commit] pypy default: use libffi information to detect hardfloat Message-ID: <20130416203506.5F6391C3151@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63433:193255cd7eb8 Date: 2013-04-16 22:31 +0200 http://bitbucket.org/pypy/pypy/changeset/193255cd7eb8/ Log: use libffi information to detect hardfloat diff --git a/rpython/jit/backend/arm/detect.py b/rpython/jit/backend/arm/detect.py --- a/rpython/jit/backend/arm/detect.py +++ b/rpython/jit/backend/arm/detect.py @@ -1,5 +1,5 @@ from rpython.translator.tool.cbuild import ExternalCompilationInfo -from rpython.rtyper.lltypesystem import lltype, rffi +from rpython.rlib.clibffi import FFI_DEFAULT_ABI, FFI_SYSV, FFI_VFP from rpython.rtyper.tool import rffi_platform from rpython.translator.platform import CompilationError @@ -14,10 +14,7 @@ """]) def detect_hardfloat(): - # http://gcc.gnu.org/ml/gcc-patches/2010-10/msg02419.html - if rffi_platform.getdefined('__ARM_PCS_VFP', ''): - return rffi_platform.getconstantinteger('__ARM_PCS_VFP', '') - return False + return FFI_DEFAULT_ABI == FFI_VFP def detect_float(): """Check for hardware float support From noreply at buildbot.pypy.org Tue Apr 16 22:35:07 2013 From: noreply at buildbot.pypy.org (bivab) Date: Tue, 16 Apr 2013 22:35:07 +0200 (CEST) Subject: [pypy-commit] pypy default: detect ABI at runtime and simplify the code that selects the ABI Message-ID: <20130416203507.90A371C3151@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63434:4407fb5f5f5e Date: 2013-04-16 22:33 +0200 http://bitbucket.org/pypy/pypy/changeset/4407fb5f5f5e/ Log: detect ABI at runtime and simplify the code that selects the ABI diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -13,7 +13,7 @@ operations as regalloc_operations, operations_with_guard as regalloc_operations_with_guard) from rpython.jit.backend.llsupport import jitframe -from rpython.jit.backend.llsupport.assembler import DEBUG_COUNTER, debug_bridge +from rpython.jit.backend.llsupport.assembler import DEBUG_COUNTER, debug_bridge, BaseAssembler from rpython.jit.backend.llsupport.asmmemmgr import MachineDataBlockWrapper from rpython.jit.backend.model import CompiledLoopToken from rpython.jit.codewriter.effectinfo import EffectInfo @@ -25,7 +25,7 @@ from rpython.rlib.rarithmetic import r_uint from rpython.rtyper.annlowlevel import llhelper, cast_instance_to_gcref from rpython.rtyper.lltypesystem import lltype, rffi - +from rpython.jit.backend.arm.detect import detect_hardfloat class AssemblerARM(ResOpAssembler): @@ -49,6 +49,10 @@ self.loop_run_counters = [] self.gcrootmap_retaddr_forced = 0 + def setup_once(self): + BaseAssembler.setup_once(self) + self.hf_abi = detect_hardfloat() + def setup(self, looptoken): assert self.memcpy_addr != 0, 'setup_once() not called?' if we_are_translated(): diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -3,7 +3,6 @@ from rpython.jit.backend.arm import registers as r from rpython.jit.backend.arm import shift from rpython.jit.backend.arm.arch import WORD, DOUBLE_WORD, JITFRAME_FIXED_SIZE - from rpython.jit.backend.arm.helper.assembler import (gen_emit_op_by_helper_call, gen_emit_op_unary_cmp, gen_emit_guard_unary_cmp, @@ -354,7 +353,7 @@ result_info=(-1, -1), can_collect=1, reload_frame=False): - if self.cpu.hf_abi: + if self.hf_abi: stack_args, adr = self._setup_call_hf(adr, arglocs, fcond, resloc, result_info) else: @@ -379,7 +378,7 @@ # ensure the result is wellformed and stored in the correct location if resloc is not None: - if resloc.is_vfp_reg() and not self.cpu.hf_abi: + if resloc.is_vfp_reg() and not self.hf_abi: # move result to the allocated register self.mov_to_vfp_loc(r.r0, r.r1, resloc) elif resloc.is_reg() and result_info != (-1, -1): diff --git a/rpython/jit/backend/arm/runner.py b/rpython/jit/backend/arm/runner.py --- a/rpython/jit/backend/arm/runner.py +++ b/rpython/jit/backend/arm/runner.py @@ -6,6 +6,7 @@ from rpython.jit.backend.llsupport.llmodel import AbstractLLCPU from rpython.rlib.jit_hooks import LOOP_RUN_CONTAINER from rpython.rtyper.lltypesystem import lltype, llmemory +from rpython.jit.backend.arm.detect import detect_hardfloat jitframe.STATICSIZE = JITFRAME_FIXED_SIZE @@ -16,7 +17,7 @@ supports_floats = True supports_longlong = False # XXX requires an implementation of # read_timestamp that works in user mode - supports_singlefloats = True + supports_singlefloats = not detect_hardfloat() from rpython.jit.backend.arm.arch import JITFRAME_FIXED_SIZE all_reg_indexes = range(len(all_regs)) @@ -112,22 +113,10 @@ class CPU_ARM(AbstractARMCPU): - """ARM v7 uses softfp ABI, requires vfp""" + """ARM v7""" backend_name = "armv7" - -class CPU_ARMHF(AbstractARMCPU): - """ARM v7 uses hardfp ABI, requires vfp""" - hf_abi = True - backend_name = "armv7hf" - supports_floats = True - supports_singlefloats = False - - -class CPU_ARMv6HF(AbstractARMCPU): +class CPU_ARMv6(AbstractARMCPU): """ ARM v6, uses hardfp ABI, requires vfp""" - hf_abi = True arch_version = 6 - backend_name = "armv6hf" - supports_floats = True - supports_singlefloats = False + backend_name = "armv6" diff --git a/rpython/jit/backend/detect_cpu.py b/rpython/jit/backend/detect_cpu.py --- a/rpython/jit/backend/detect_cpu.py +++ b/rpython/jit/backend/detect_cpu.py @@ -61,8 +61,6 @@ model = 'x86-without-sse2' if model.startswith('arm'): from rpython.jit.backend.arm.detect import detect_hardfloat, detect_float - if detect_hardfloat(): - model += 'hf' assert detect_float(), 'the JIT-compiler requires a vfp unit' return model @@ -77,12 +75,10 @@ return "rpython.jit.backend.x86.runner", "CPU_X86_64" elif backend_name == 'cli': return "rpython.jit.backend.cli.runner", "CliCPU" - elif backend_name == 'armv6hf': - return "rpython.jit.backend.arm.runner", "CPU_ARMv6HF" - elif backend_name == 'armv7': + elif backend_name.startswith('armv6'): + return "rpython.jit.backend.arm.runner", "CPU_ARMv6" + elif backend_name.startswith('armv7'): return "rpython.jit.backend.arm.runner", "CPU_ARM" - elif backend_name == 'armv7hf': - return "rpython.jit.backend.arm.runner", "CPU_ARMHF" else: raise ProcessorAutodetectError, ( "we have no JIT backend for this cpu: '%s'" % backend_name) From noreply at buildbot.pypy.org Tue Apr 16 22:44:52 2013 From: noreply at buildbot.pypy.org (hodgestar) Date: Tue, 16 Apr 2013 22:44:52 +0200 (CEST) Subject: [pypy-commit] pypy remove-string-smm: Replace bytearray.join multimethod (fijal, hodgestar). Message-ID: <20130416204452.C36221C3151@cobra.cs.uni-duesseldorf.de> Author: Simon Cross Branch: remove-string-smm Changeset: r63435:c66c3201fa1c Date: 2013-04-16 22:44 +0200 http://bitbucket.org/pypy/pypy/changeset/c66c3201fa1c/ Log: Replace bytearray.join multimethod (fijal, hodgestar). diff --git a/pypy/objspace/std/bytearrayobject.py b/pypy/objspace/std/bytearrayobject.py --- a/pypy/objspace/std/bytearrayobject.py +++ b/pypy/objspace/std/bytearrayobject.py @@ -94,6 +94,31 @@ c = space.gateway_chr_w(w_item) self.data.append(c) + def descr_join(self, space, w_iterable): + list_w = space.listview(w_iterable) + if not list_w: + return W_BytearrayObject([]) + newdata = [] + data = self.data + for i in range(len(list_w)): + if data and i != 0: + newdata.extend(data) + w_s = list_w[i] + if space.isinstance_w(w_s, space.w_str): + for c in space.str_w(w_s): + newdata.append(c) + elif isinstance(w_s, W_BytearrayObject): + newdata.extend(w_s.data) + elif space.isinstance(w_s, space.w_bytearray): + assert False, ("Please implement this case if you add a new" + " bytearray implementation.") + else: + raise operationerrfmt( + space.w_TypeError, + "sequence item %d: expected string, %s " + "found", i, space.type(w_s).getname(space)) + return W_BytearrayObject(newdata) + def __repr__(w_self): """ representation for debugging purposes """ return "%s(%s)" % (w_self.__class__.__name__, ''.join(w_self.data)) @@ -404,26 +429,6 @@ return stringobject.str_endswith__String_Tuple_ANY_ANY(space, w_str, w_suffix, w_start, w_stop) -def str_join__Bytearray_ANY(space, w_self, w_list): - list_w = space.listview(w_list) - if not list_w: - return W_BytearrayObject([]) - data = w_self.data - newdata = [] - for i in range(len(list_w)): - w_s = list_w[i] - if not (space.isinstance_w(w_s, space.w_str) or - space.isinstance_w(w_s, space.w_bytearray)): - raise operationerrfmt( - space.w_TypeError, - "sequence item %d: expected string, %s " - "found", i, space.type(w_s).getname(space)) - - if data and i != 0: - newdata.extend(data) - newdata.extend([c for c in space.bufferstr_new_w(w_s)]) - return W_BytearrayObject(newdata) - def str_decode__Bytearray_ANY_ANY(space, w_bytearray, w_encoding, w_errors): w_str = str__Bytearray(space, w_bytearray) return stringobject.str_decode__String_ANY_ANY(space, w_str, w_encoding, w_errors) diff --git a/pypy/objspace/std/bytearraytype.py b/pypy/objspace/std/bytearraytype.py --- a/pypy/objspace/std/bytearraytype.py +++ b/pypy/objspace/std/bytearraytype.py @@ -77,7 +77,13 @@ """ raise NotImplementedError -str_join = SMM('join', 2, defaults=(None,-1)) + def descr_join(self, space, w_iterable): + """B.join(iterable_of_bytes) -> bytes + + Concatenates any number of bytearray objects, with B in between each + pair. + """ + raise NotImplementedError bytearray_reverse = SMM('reverse', 1, @@ -227,5 +233,6 @@ remove=interpindirect2app(W_AbstractBytearrayObject.descr_remove), append=interpindirect2app(W_AbstractBytearrayObject.descr_append), extend=interpindirect2app(W_AbstractBytearrayObject.descr_extend), + join=interpindirect2app(W_AbstractBytearrayObject.descr_join), ) bytearray_typedef.registermethods(globals()) From noreply at buildbot.pypy.org Tue Apr 16 22:50:19 2013 From: noreply at buildbot.pypy.org (hodgestar) Date: Tue, 16 Apr 2013 22:50:19 +0200 (CEST) Subject: [pypy-commit] pypy remove-string-smm: Replace bytearray.reverse multimethod (fijal, hodgestar). Message-ID: <20130416205019.913231C01FD@cobra.cs.uni-duesseldorf.de> Author: Simon Cross Branch: remove-string-smm Changeset: r63436:748667f013a0 Date: 2013-04-16 22:50 +0200 http://bitbucket.org/pypy/pypy/changeset/748667f013a0/ Log: Replace bytearray.reverse multimethod (fijal, hodgestar). diff --git a/pypy/objspace/std/bytearrayobject.py b/pypy/objspace/std/bytearrayobject.py --- a/pypy/objspace/std/bytearrayobject.py +++ b/pypy/objspace/std/bytearrayobject.py @@ -119,6 +119,9 @@ "found", i, space.type(w_s).getname(space)) return W_BytearrayObject(newdata) + def descr_reverse(self, space): + self.data.reverse() + def __repr__(w_self): """ representation for debugging purposes """ return "%s(%s)" % (w_self.__class__.__name__, ''.join(w_self.data)) @@ -461,10 +464,6 @@ w_str = str__Bytearray(space, w_bytearray) return stringobject.str_isspace__String(space, w_str) -def bytearray_reverse__Bytearray(space, w_bytearray): - w_bytearray.data.reverse() - return space.w_None - _space_chars = ''.join([chr(c) for c in [9, 10, 11, 12, 13, 32]]) def bytearray_strip__Bytearray_None(space, w_bytearray, w_chars): diff --git a/pypy/objspace/std/bytearraytype.py b/pypy/objspace/std/bytearraytype.py --- a/pypy/objspace/std/bytearraytype.py +++ b/pypy/objspace/std/bytearraytype.py @@ -85,10 +85,13 @@ """ raise NotImplementedError + def descr_reverse(self, space): + """B.reverse() -> None -bytearray_reverse = SMM('reverse', 1, - doc="B.reverse() -> None\n\n" - "Reverse the order of the values in B in place.") + Reverse the order of the values in B in place. + """ + raise NotImplementedError + bytearray_strip = SMM('strip', 2, defaults=(None,), doc="B.strip([bytes]) -> bytearray\n\nStrip leading " @@ -234,5 +237,6 @@ append=interpindirect2app(W_AbstractBytearrayObject.descr_append), extend=interpindirect2app(W_AbstractBytearrayObject.descr_extend), join=interpindirect2app(W_AbstractBytearrayObject.descr_join), + reverse=interpindirect2app(W_AbstractBytearrayObject.descr_reverse), ) bytearray_typedef.registermethods(globals()) From noreply at buildbot.pypy.org Tue Apr 16 23:06:52 2013 From: noreply at buildbot.pypy.org (hodgestar) Date: Tue, 16 Apr 2013 23:06:52 +0200 (CEST) Subject: [pypy-commit] pypy remove-string-smm: Remove bytearray.{strip, lstrip, rstrip} multimethods (fijal, hodgestar). Message-ID: <20130416210652.702E31C01FD@cobra.cs.uni-duesseldorf.de> Author: Simon Cross Branch: remove-string-smm Changeset: r63437:55e0a79ff91d Date: 2013-04-16 23:06 +0200 http://bitbucket.org/pypy/pypy/changeset/55e0a79ff91d/ Log: Remove bytearray.{strip,lstrip,rstrip} multimethods (fijal, hodgestar). diff --git a/pypy/objspace/std/bytearrayobject.py b/pypy/objspace/std/bytearrayobject.py --- a/pypy/objspace/std/bytearrayobject.py +++ b/pypy/objspace/std/bytearrayobject.py @@ -122,6 +122,27 @@ def descr_reverse(self, space): self.data.reverse() + def descr_strip(self, space, w_chars=None): + if space.is_none(w_chars): + chars = _space_chars + else: + chars = space.bufferstr_new_w(w_chars) + return _strip(space, self, chars, 1, 1) + + def descr_lstrip(self, space, w_chars=None): + if space.is_none(w_chars): + chars = _space_chars + else: + chars = space.bufferstr_new_w(w_chars) + return _strip(space, self, chars, 1, 0) + + def descr_rstrip(self, space, w_chars=None): + if space.is_none(w_chars): + chars = _space_chars + else: + chars = space.bufferstr_new_w(w_chars) + return _strip(space, self, chars, 0, 1) + def __repr__(w_self): """ representation for debugging purposes """ return "%s(%s)" % (w_self.__class__.__name__, ''.join(w_self.data)) @@ -466,23 +487,6 @@ _space_chars = ''.join([chr(c) for c in [9, 10, 11, 12, 13, 32]]) -def bytearray_strip__Bytearray_None(space, w_bytearray, w_chars): - return _strip(space, w_bytearray, _space_chars, 1, 1) - -def bytearray_strip__Bytearray_ANY(space, w_bytearray, w_chars): - return _strip(space, w_bytearray, space.bufferstr_new_w(w_chars), 1, 1) - -def bytearray_lstrip__Bytearray_None(space, w_bytearray, w_chars): - return _strip(space, w_bytearray, _space_chars, 1, 0) - -def bytearray_lstrip__Bytearray_ANY(space, w_bytearray, w_chars): - return _strip(space, w_bytearray, space.bufferstr_new_w(w_chars), 1, 0) - -def bytearray_rstrip__Bytearray_None(space, w_bytearray, w_chars): - return _strip(space, w_bytearray, _space_chars, 0, 1) - -def bytearray_rstrip__Bytearray_ANY(space, w_bytearray, w_chars): - return _strip(space, w_bytearray, space.bufferstr_new_w(w_chars), 0, 1) # These methods could just delegate to the string implementation, # but they have to return a bytearray. diff --git a/pypy/objspace/std/bytearraytype.py b/pypy/objspace/std/bytearraytype.py --- a/pypy/objspace/std/bytearraytype.py +++ b/pypy/objspace/std/bytearraytype.py @@ -92,21 +92,30 @@ """ raise NotImplementedError + def descr_strip(self, space, w_chars=None): + """B.strip([bytes]) -> bytearray -bytearray_strip = SMM('strip', 2, defaults=(None,), - doc="B.strip([bytes]) -> bytearray\n\nStrip leading " - "and trailing bytes contained in the argument.\nIf " - "the argument is omitted, strip ASCII whitespace.") + Strip leading and trailing bytes contained in the argument. + If the argument is omitted, strip ASCII whitespace. + """ + raise NotImplementedError -bytearray_lstrip = SMM('lstrip', 2, defaults=(None,), - doc="B.lstrip([bytes]) -> bytearray\n\nStrip leading " - "bytes contained in the argument.\nIf the argument is " - "omitted, strip leading ASCII whitespace.") + def descr_lstrip(self, space, w_chars=None): + """B.lstrip([bytes]) -> bytearray -bytearray_rstrip = SMM('rstrip', 2, defaults=(None,), - doc="'B.rstrip([bytes]) -> bytearray\n\nStrip trailing " - "bytes contained in the argument.\nIf the argument is " - "omitted, strip trailing ASCII whitespace.") + Strip leading bytes contained in the argument. + If the argument is omitted, strip leading ASCII whitespace. + """ + raise NotImplementedError + + def descr_rstrip(self, space, w_chars=None): + """B.rstrip([bytes]) -> bytearray + + Strip trailing bytes contained in the argument. + If the argument is omitted, strip trailing ASCII whitespace. + """ + raise NotImplementedError + def getbytevalue(space, w_value): if space.isinstance_w(w_value, space.w_str): @@ -238,5 +247,8 @@ extend=interpindirect2app(W_AbstractBytearrayObject.descr_extend), join=interpindirect2app(W_AbstractBytearrayObject.descr_join), reverse=interpindirect2app(W_AbstractBytearrayObject.descr_reverse), + strip=interpindirect2app(W_AbstractBytearrayObject.descr_strip), + lstrip=interpindirect2app(W_AbstractBytearrayObject.descr_lstrip), + rstrip=interpindirect2app(W_AbstractBytearrayObject.descr_rstrip), ) bytearray_typedef.registermethods(globals()) From noreply at buildbot.pypy.org Wed Apr 17 00:01:55 2013 From: noreply at buildbot.pypy.org (hodgestar) Date: Wed, 17 Apr 2013 00:01:55 +0200 (CEST) Subject: [pypy-commit] pypy remove-string-smm: Remove bytearray.decode multimethod (fijal, hodgestar). Message-ID: <20130416220155.8C5CF1C317E@cobra.cs.uni-duesseldorf.de> Author: Simon Cross Branch: remove-string-smm Changeset: r63438:dece801042c2 Date: 2013-04-16 23:30 +0200 http://bitbucket.org/pypy/pypy/changeset/dece801042c2/ Log: Remove bytearray.decode multimethod (fijal, hodgestar). diff --git a/pypy/objspace/std/bytearrayobject.py b/pypy/objspace/std/bytearrayobject.py --- a/pypy/objspace/std/bytearrayobject.py +++ b/pypy/objspace/std/bytearrayobject.py @@ -453,10 +453,6 @@ return stringobject.str_endswith__String_Tuple_ANY_ANY(space, w_str, w_suffix, w_start, w_stop) -def str_decode__Bytearray_ANY_ANY(space, w_bytearray, w_encoding, w_errors): - w_str = str__Bytearray(space, w_bytearray) - return stringobject.str_decode__String_ANY_ANY(space, w_str, w_encoding, w_errors) - def str_islower__Bytearray(space, w_bytearray): w_str = str__Bytearray(space, w_bytearray) return stringobject.str_islower__String(space, w_str) diff --git a/pypy/objspace/std/bytearraytype.py b/pypy/objspace/std/bytearraytype.py --- a/pypy/objspace/std/bytearraytype.py +++ b/pypy/objspace/std/bytearraytype.py @@ -5,7 +5,6 @@ from pypy.objspace.std.stdtypedef import StdTypeDef, SMM from pypy.objspace.std.stringtype import ( - str_decode, str_count, str_index, str_rindex, str_find, str_rfind, str_replace, str_startswith, str_endswith, str_islower, str_isupper, str_isalpha, str_isalnum, str_isdigit, str_isspace, str_istitle, @@ -116,6 +115,22 @@ """ raise NotImplementedError + def descr_decode(self, space, w_encoding=None, w_errors=None): + """B.decode([encoding[,errors]]) -> object + + Decodes B using the codec registered for encoding. encoding defaults + to the default encoding. errors may be given to set a different error + handling scheme. Default is 'strict' meaning that encoding errors raise + a UnicodeDecodeError. Other possible values are 'ignore' and 'replace' + as well as any other name registerd with codecs.register_error that is + able to handle UnicodeDecodeErrors. + """ + from pypy.objspace.std.unicodetype import ( + _get_encoding_and_errors, decode_object) + encoding, errors = _get_encoding_and_errors( + space, w_encoding, w_errors) + return decode_object(space, self, encoding, errors) + def getbytevalue(space, w_value): if space.isinstance_w(w_value, space.w_str): @@ -250,5 +265,6 @@ strip=interpindirect2app(W_AbstractBytearrayObject.descr_strip), lstrip=interpindirect2app(W_AbstractBytearrayObject.descr_lstrip), rstrip=interpindirect2app(W_AbstractBytearrayObject.descr_rstrip), + decode=interpindirect2app(W_AbstractBytearrayObject.descr_decode), ) bytearray_typedef.registermethods(globals()) diff --git a/pypy/objspace/std/test/test_bytearrayobject.py b/pypy/objspace/std/test/test_bytearrayobject.py --- a/pypy/objspace/std/test/test_bytearrayobject.py +++ b/pypy/objspace/std/test/test_bytearrayobject.py @@ -431,8 +431,12 @@ assert b == 'abcDEFghi' def test_decode(self): + b = bytearray(u'abcdefghi\xe1'.encode('utf-8')) + u = b.decode('utf-8') + assert isinstance(u, unicode) + assert u == u'abcdefghi\xe1' b = bytearray('abcdefghi') - u = b.decode('utf-8') + u = b.decode() assert isinstance(u, unicode) assert u == u'abcdefghi' From noreply at buildbot.pypy.org Wed Apr 17 00:01:56 2013 From: noreply at buildbot.pypy.org (hodgestar) Date: Wed, 17 Apr 2013 00:01:56 +0200 (CEST) Subject: [pypy-commit] pypy remove-string-smm: Remove bytearray.__repr__ multimethod (fijal, hodgestar). Message-ID: <20130416220156.B57DE1C317E@cobra.cs.uni-duesseldorf.de> Author: Simon Cross Branch: remove-string-smm Changeset: r63439:98e3ba2a00d2 Date: 2013-04-17 00:01 +0200 http://bitbucket.org/pypy/pypy/changeset/98e3ba2a00d2/ Log: Remove bytearray.__repr__ multimethod (fijal, hodgestar). diff --git a/pypy/objspace/std/bytearrayobject.py b/pypy/objspace/std/bytearrayobject.py --- a/pypy/objspace/std/bytearrayobject.py +++ b/pypy/objspace/std/bytearrayobject.py @@ -12,6 +12,7 @@ from pypy.objspace.std.bytearraytype import ( makebytearraydata_w, new_bytearray) from pypy.objspace.std.bytearraytype import W_AbstractBytearrayObject +from pypy.objspace.std.stringobject import string_escape_encode from pypy.objspace.std.unicodeobject import W_UnicodeObject # XXX: kill this whem SMMs are dead from pypy.objspace.std.noneobject import W_NoneObject # XXX: and this one. from pypy.objspace.std.stringobject import W_StringObject # XXX: and this too. @@ -143,6 +144,14 @@ chars = space.bufferstr_new_w(w_chars) return _strip(space, self, chars, 0, 1) + def descr_repr(self, space): + s = "".join(self.data) + quote = "'" + if quote in s and '"' not in s: + quote = '"' + + return space.wrap("bytearray(b" + string_escape_encode(s, quote) + ")") + def __repr__(w_self): """ representation for debugging purposes """ return "%s(%s)" % (w_self.__class__.__name__, ''.join(w_self.data)) @@ -360,40 +369,6 @@ w_table, w_deletechars) return String2Bytearray(space, w_res) -# Mostly copied from repr__String, but without the "smart quote" -# functionality. -def repr__Bytearray(space, w_bytearray): - s = w_bytearray.data - - # Good default if there are no replacements. - buf = StringBuilder(len("bytearray(b'')") + len(s)) - - buf.append("bytearray(b'") - - for i in range(len(s)): - c = s[i] - - if c == '\\' or c == "'": - buf.append('\\') - buf.append(c) - elif c == '\t': - buf.append('\\t') - elif c == '\r': - buf.append('\\r') - elif c == '\n': - buf.append('\\n') - elif not '\x20' <= c < '\x7f': - n = ord(c) - buf.append('\\x') - buf.append("0123456789abcdef"[n>>4]) - buf.append("0123456789abcdef"[n&0xF]) - else: - buf.append(c) - - buf.append("')") - - return space.wrap(buf.build()) - def str__Bytearray(space, w_bytearray): return space.wrap(''.join(w_bytearray.data)) diff --git a/pypy/objspace/std/bytearraytype.py b/pypy/objspace/std/bytearraytype.py --- a/pypy/objspace/std/bytearraytype.py +++ b/pypy/objspace/std/bytearraytype.py @@ -131,6 +131,10 @@ space, w_encoding, w_errors) return decode_object(space, self, encoding, errors) + def descr_repr(self, space): + """x.__repr__() <==> repr(x)""" + raise NotImplementedError + def getbytevalue(space, w_value): if space.isinstance_w(w_value, space.w_str): @@ -252,6 +256,7 @@ __new__ = interp2app(descr__new__), __hash__ = None, __reduce__ = interp2app(descr_bytearray__reduce__), + __repr__=interpindirect2app(W_AbstractBytearrayObject.descr_repr), fromhex = interp2app(descr_fromhex, as_classmethod=True), ljust=interpindirect2app(W_AbstractBytearrayObject.descr_ljust), rjust=interpindirect2app(W_AbstractBytearrayObject.descr_rjust), diff --git a/pypy/objspace/std/test/test_bytearrayobject.py b/pypy/objspace/std/test/test_bytearrayobject.py --- a/pypy/objspace/std/test/test_bytearrayobject.py +++ b/pypy/objspace/std/test/test_bytearrayobject.py @@ -49,7 +49,9 @@ def test_repr(self): assert repr(bytearray()) == "bytearray(b'')" assert repr(bytearray('test')) == "bytearray(b'test')" - assert repr(bytearray("d'oh")) == r"bytearray(b'd\'oh')" + # CPython 2.7.3 produces a different repr for the test below, + # namely: 'bytearray(b"d\\\'oh")' + assert repr(bytearray("d'oh")) == 'bytearray(b"d\'oh")' def test_str(self): assert str(bytearray()) == "" From noreply at buildbot.pypy.org Wed Apr 17 08:55:41 2013 From: noreply at buildbot.pypy.org (bivab) Date: Wed, 17 Apr 2013 08:55:41 +0200 (CEST) Subject: [pypy-commit] pypy default: skip ARM tests on other architectures during collection, avoiding to load the files Message-ID: <20130417065541.CF2A31C034F@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63440:864116505c2a Date: 2013-04-17 08:55 +0200 http://bitbucket.org/pypy/pypy/changeset/864116505c2a/ Log: skip ARM tests on other architectures during collection, avoiding to load the files diff --git a/rpython/jit/backend/arm/test/conftest.py b/rpython/jit/backend/arm/test/conftest.py --- a/rpython/jit/backend/arm/test/conftest.py +++ b/rpython/jit/backend/arm/test/conftest.py @@ -16,6 +16,7 @@ dest="run_translation_tests", help="run tests that translate code") -def pytest_runtest_setup(item): +def pytest_collect_directory(path, parent): if not cpu.startswith('arm'): py.test.skip("ARM(v7) tests skipped: cpu is %r" % (cpu,)) +pytest_collect_file = pytest_collect_directory From noreply at buildbot.pypy.org Wed Apr 17 09:20:48 2013 From: noreply at buildbot.pypy.org (arigo) Date: Wed, 17 Apr 2013 09:20:48 +0200 (CEST) Subject: [pypy-commit] pypy default: Remove the temporary workaround for GCC 4.8. Properly use "[]", i.e. flexible arrays. Message-ID: <20130417072048.C8D1D1C01FD@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63441:c9bde493beba Date: 2013-04-17 09:23 +0200 http://bitbucket.org/pypy/pypy/changeset/c9bde493beba/ Log: Remove the temporary workaround for GCC 4.8. Properly use "[]", i.e. flexible arrays. diff --git a/rpython/translator/c/database.py b/rpython/translator/c/database.py --- a/rpython/translator/c/database.py +++ b/rpython/translator/c/database.py @@ -64,9 +64,8 @@ self.instrument_ncounter = 0 - def gettypedefnode(self, T, varlength=1): - if varlength <= 1: - varlength = 1 # it's C after all + def gettypedefnode(self, T, varlength=None): + if varlength is None: key = T else: key = T, varlength @@ -94,7 +93,7 @@ self.pendingsetupnodes.append(node) return node - def gettype(self, T, varlength=1, who_asks=None, argnames=[]): + def gettype(self, T, varlength=None, who_asks=None, argnames=[]): if isinstance(T, Primitive) or T == GCREF: return PrimitiveType[T] elif isinstance(T, Typedef): diff --git a/rpython/translator/c/node.py b/rpython/translator/c/node.py --- a/rpython/translator/c/node.py +++ b/rpython/translator/c/node.py @@ -47,12 +47,12 @@ typetag = 'struct' extra_union_for_varlength = True - def __init__(self, db, STRUCT, varlength=1): + def __init__(self, db, STRUCT, varlength=None): NodeWithDependencies.__init__(self, db) self.STRUCT = STRUCT self.LLTYPE = STRUCT self.varlength = varlength - if varlength == 1: + if varlength is None: basename = STRUCT._name with_number = True else: @@ -93,7 +93,7 @@ self.fields = [] db = self.db STRUCT = self.STRUCT - if self.varlength != 1: + if self.varlength is not None: self.normalizedtypename = db.gettype(STRUCT, who_asks=self) if needs_gcheader(self.STRUCT): HDR = db.gcpolicy.struct_gcheader_definition(self) @@ -120,7 +120,7 @@ rtti = getRuntimeTypeInfo(STRUCT) except ValueError: pass - if self.varlength == 1: + if self.varlength is None: self.db.gcpolicy.struct_setup(self, rtti) return self.gcinfo gcinfo = defaultproperty(computegcinfo) @@ -160,12 +160,14 @@ if typename == PrimitiveType[Void]: line = '/* %s */' % line else: + if is_empty and typename.endswith('[RPY_VARLENGTH]'): + yield '\tRPY_DUMMY_VARLENGTH' is_empty = False yield '\t' + line if is_empty: yield '\t' + 'char _dummy; /* this struct is empty */' yield '};' - if self.varlength != 1: + if self.varlength is not None: assert self.typetag == 'struct' yield 'union %su {' % self.name yield ' struct %s a;' % self.name @@ -182,7 +184,7 @@ def debug_offsets(self): # generate number exprs giving the offset of the elements in the struct - assert self.varlength == 1 + assert self.varlength is None for name in self.fieldnames: FIELD_T = self.c_struct_field_type(name) if FIELD_T is Void: @@ -196,18 +198,25 @@ yield 'offsetof(%s %s, %s)' % (self.typetag, self.name, cname) +def deflength(varlength): + if varlength is None: + return 'RPY_VARLENGTH' + elif varlength == 0: + return 'RPY_LENGTH0' + else: + return varlength class ArrayDefNode(NodeWithDependencies): typetag = 'struct' extra_union_for_varlength = True - def __init__(self, db, ARRAY, varlength=1): + def __init__(self, db, ARRAY, varlength=None): NodeWithDependencies.__init__(self, db) self.ARRAY = ARRAY self.LLTYPE = ARRAY self.gcfields = [] self.varlength = varlength - if varlength == 1: + if varlength is None: basename = 'array' with_number = True else: @@ -226,7 +235,7 @@ db = self.db ARRAY = self.ARRAY self.gcinfo # force it to be computed - if self.varlength != 1: + if self.varlength is not None: self.normalizedtypename = db.gettype(ARRAY, who_asks=self) if needs_gcheader(ARRAY): HDR = db.gcpolicy.array_gcheader_definition(self) @@ -238,7 +247,7 @@ def computegcinfo(self): # let the gcpolicy do its own setup self.gcinfo = None # unless overwritten below - if self.varlength == 1: + if self.varlength is None: self.db.gcpolicy.array_setup(self) return self.gcinfo gcinfo = defaultproperty(computegcinfo) @@ -269,21 +278,22 @@ yield '\t' + cdecl(typename, fname) + ';' if not self.ARRAY._hints.get('nolength', False): yield '\tlong length;' - line = '%s;' % cdecl(self.itemtypename, 'items[%d]'% self.varlength) + line = '%s;' % cdecl(self.itemtypename, + 'items[%s]' % deflength(self.varlength)) if self.ARRAY.OF is Void: # strange line = '/* array of void */' if self.ARRAY._hints.get('nolength', False): line = 'char _dummy; ' + line yield '\t' + line yield '};' - if self.varlength != 1: + if self.varlength is not None: yield 'union %su {' % self.name yield ' struct %s a;' % self.name yield ' %s;' % cdecl(self.normalizedtypename, 'b') yield '};' def visitor_lines(self, prefix, on_item): - assert self.varlength == 1 + assert self.varlength is None ARRAY = self.ARRAY # we need a unique name for this C variable, or at least one that does # not collide with the expression in 'prefix' @@ -310,7 +320,7 @@ def debug_offsets(self): # generate three offsets for debugging inspection - assert self.varlength == 1 + assert self.varlength is None if not self.ARRAY._hints.get('nolength', False): yield 'offsetof(struct %s, length)' % (self.name,) else: @@ -333,7 +343,7 @@ forward_decl = None extra_union_for_varlength = False - def __init__(self, db, ARRAY, varlength=1): + def __init__(self, db, ARRAY, varlength=None): NodeWithDependencies.__init__(self, db) self.ARRAY = ARRAY self.LLTYPE = ARRAY @@ -342,8 +352,8 @@ # There is no such thing as an array of voids: # we use a an array of chars instead; only the pointer can be void*. self.itemtypename = db.gettype(contained_type, who_asks=self) - self.fulltypename = self.itemtypename.replace('@', '(@)[%d]' % - (self.varlength,)) + self.fulltypename = self.itemtypename.replace('@', '(@)[%s]' % + deflength(varlength)) if ARRAY._hints.get("render_as_void"): self.fullptrtypename = 'void *@' else: @@ -493,7 +503,8 @@ Node.__init__(self, db) self.obj = obj self.typename = db.gettype(T) #, who_asks=self) - self.implementationtypename = db.gettype(T, varlength=self.getlength()) + self.implementationtypename = db.gettype( + T, varlength=self.getvarlength()) parent, parentindex = parentlink(obj) if obj in exports.EXPORTS_obj2name: self.name = exports.EXPORTS_obj2name[obj] @@ -559,8 +570,8 @@ def startupcode(self): return [] - def getlength(self): - return 1 + def getvarlength(self): + return None assert not USESLOTS or '__dict__' not in dir(ContainerNode) @@ -578,10 +589,10 @@ for name in T._names: yield getattr(self.obj, name) - def getlength(self): + def getvarlength(self): T = self.getTYPE() if T._arrayfld is None: - return 1 + return None else: array = getattr(self.obj, T._arrayfld) return len(array.items) @@ -696,7 +707,7 @@ def enum_dependencies(self): return self.obj.items - def getlength(self): + def getvarlength(self): return len(self.obj.items) def initializationexpr(self, decoration=''): @@ -765,8 +776,8 @@ for i in range(self.obj.getlength()): yield self.obj.getitem(i) - def getlength(self): - return 1 # not variable-sized! + def getvarlength(self): + return None # not variable-sized! def initializationexpr(self, decoration=''): T = self.getTYPE() diff --git a/rpython/translator/c/src/g_prerequisite.h b/rpython/translator/c/src/g_prerequisite.h --- a/rpython/translator/c/src/g_prerequisite.h +++ b/rpython/translator/c/src/g_prerequisite.h @@ -14,8 +14,14 @@ #ifdef __GNUC__ /* other platforms too, probably */ typedef _Bool bool_t; +# define RPY_VARLENGTH /* nothing: [RPY_VARLENGTH] => [] */ +# define RPY_LENGTH0 0 /* array decl [0] are ok */ +# define RPY_DUMMY_VARLENGTH char _dummy[0]; #else typedef unsigned char bool_t; +# define RPY_VARLENGTH 1 /* [RPY_VARLENGTH] => [1] */ +# define RPY_LENGTH0 1 /* array decl [0] are bad */ +# define RPY_DUMMY_VARLENGTH /* nothing */ #endif diff --git a/rpython/translator/c/src/support.h b/rpython/translator/c/src/support.h --- a/rpython/translator/c/src/support.h +++ b/rpython/translator/c/src/support.h @@ -2,16 +2,6 @@ /************************************************************/ /*** C header subsection: support functions ***/ -/* a temporary(?) workaround for GCC 4.8. See: - http://stackoverflow.com/questions/16016627/ -*/ -#ifdef __GNUC__ -# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) -# pragma GCC optimize("no-aggressive-loop-optimizations") -# endif -#endif - - #define RUNNING_ON_LLINTERP 0 #define OP_JIT_RECORD_KNOWN_CLASS(i, c, r) /* nothing */ diff --git a/rpython/translator/c/test/test_lltyped.py b/rpython/translator/c/test/test_lltyped.py --- a/rpython/translator/c/test/test_lltyped.py +++ b/rpython/translator/c/test/test_lltyped.py @@ -919,3 +919,25 @@ return x fn = self.getcompiled(llf, [int]) assert fn(5) == 42 + + def test_raw_array_field_prebuilt(self): + from rpython.rtyper.lltypesystem import rffi + S = Struct('S', ('array', rffi.CArray(Signed))) + s0 = malloc(S, 0, flavor='raw', immortal=True) + s1 = malloc(S, 1, flavor='raw', immortal=True) + s1.array[0] = 521 + s2 = malloc(S, 2, flavor='raw', immortal=True) + s2.array[0] = 12 + s2.array[1] = 34 + def llf(i): + if i == 0: s = s0 + elif i == 1: s = s1 + else: s = s2 + x = 10 + if i > 0: + x += s.array[i-1] + return x + fn = self.getcompiled(llf, [int]) + assert fn(0) == 10 + assert fn(1) == 10 + 521 + assert fn(2) == 10 + 34 From noreply at buildbot.pypy.org Wed Apr 17 14:22:40 2013 From: noreply at buildbot.pypy.org (arigo) Date: Wed, 17 Apr 2013 14:22:40 +0200 (CEST) Subject: [pypy-commit] pypy stm-gc-2: When the StmGCThreadLocalAllocator is deleted, reattach its pages Message-ID: <20130417122240.17E4E1C01FD@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: stm-gc-2 Changeset: r63442:26a92a01a8dc Date: 2013-04-16 14:43 +0200 http://bitbucket.org/pypy/pypy/changeset/26a92a01a8dc/ Log: When the StmGCThreadLocalAllocator is deleted, reattach its pages to the StmGCSharedArea. diff --git a/rpython/memory/gc/stmshared.py b/rpython/memory/gc/stmshared.py --- a/rpython/memory/gc/stmshared.py +++ b/rpython/memory/gc/stmshared.py @@ -11,8 +11,9 @@ # Linux's glibc is good at 'malloc(1023*WORD)': the blocks ("pages") it # returns are exactly 1024 words apart, reserving only one extra word -# for its internal data -TRANSLATED_PAGE_SIZE = 1023 * WORD +# for its internal data. Here we assume that even on other systems it +# will not use more than two words. +TRANSLATED_PAGE_SIZE = 1022 * WORD # This is the largest size that StmGCSharedArea will map to its internal # "pages" structures. @@ -29,11 +30,11 @@ PAGE_HEADER = lltype.Struct('PageHeader', # -- The following pointer makes a chained list of pages. ('nextpage', PAGE_PTR), - # -- XXX - ('xxx1', lltype.Signed), - ('xxx2', llmemory.Address), - # -- The structure above is 3 words, which is a good value: - # '(1023-3) % N' is zero or very small for various small N's, + # -- The following is only used when the page belongs to StmGCSharedArea. + # It makes another free list, used for various purposes. + ('secondary_free_list', llmemory.Address), + # -- The structure above is 2 words, which is a good value: + # '(1022-2) % N' is zero or very small for various small N's, # i.e. there is not much wasted space. ) PAGE_PTR.TO.become(PAGE_HEADER) @@ -46,6 +47,7 @@ _alloc_flavor_ = 'raw' def __init__(self, gc, page_size, small_request_threshold): + "NOT_RPYTHON" self.gc = gc self.page_size = page_size self.small_request_threshold = small_request_threshold @@ -58,20 +60,32 @@ # is used, or if its usage says high after a major collection, # it belongs to the lists of StmGCThreadLocalAllocator. length = small_request_threshold / WORD + 1 - self.low_usage_page = lltype.malloc(rffi.CArray(PAGE_PTR), length, - flavor='raw', zero=True, - immortal=True) + self.low_usage_pages = lltype.malloc(rffi.CArray(PAGE_PTR), length, + flavor='raw', zero=True, + immortal=True) + self.full_pages = lltype.malloc(rffi.CArray(PAGE_PTR), length, + flavor='raw', zero=True, + immortal=True) self.nblocks_for_size = lltype.malloc(rffi.CArray(lltype.Signed), - length, flavor='raw', + length, flavor='raw', zero=True, immortal=True) self.hdrsize = llmemory.raw_malloc_usage(llmemory.sizeof(PAGE_HEADER)) - self.nblocks_for_size[0] = 0 # unused for i in range(1, length): self.nblocks_for_size[i] = (page_size - self.hdrsize) // (WORD * i) assert self.nblocks_for_size[length-1] >= 1 + self.length = length + # + # Counters for statistics + self.count_global_pages = 0 def setup(self): - self.ll_low_usage_lock = rthread.allocate_ll_lock() + self.ll_global_lock = rthread.allocate_ll_lock() + + def acquire_global_lock(self): + rthread.acquire_NOAUTO(self.ll_global_lock, True) + + def release_global_lock(self): + rthread.release_NOAUTO(self.ll_global_lock) # ------------------------------------------------------------ @@ -94,10 +108,11 @@ # For each size N between WORD and 'small_request_threshold' # (included), the corresponding chained list contains pages # which store objects of size N. - length = sharedarea.small_request_threshold / WORD + 1 + length = sharedarea.length self.pages_for_size = lltype.malloc( rffi.CArray(PAGE_PTR), length, flavor='raw', zero=True, track_allocation=False) + self.count_pages = 0 # for statistics # # This array contains 'length' chained lists of free locations. self.free_loc_for_size = lltype.malloc( @@ -141,6 +156,7 @@ return NULL if not we_are_translated(): self._seen_pages.add(result) + self.count_pages += 1 llarena.arena_reserve(result, llmemory.sizeof(PAGE_HEADER)) # # Initialize the fields of the resulting page @@ -213,7 +229,27 @@ while lst.non_empty(): self.free_object(lst.pop()) + def gift_all_pages_to_shared_area(self): + """Send to the shared area all my pages. For now we don't extract + the information about which locations are free or not; we just stick + them into 'full_pages' and leave the next global GC to figure it out. + """ + stmshared = self.sharedarea + stmshared.acquire_global_lock() + i = stmshared.length - 1 + while i >= 1: + lpage = self.pages_for_size[i] + if lpage: + gpage = stmshared.full_pages[i] + gpage_addr = llmemory.cast_ptr_to_adr(gpage) + lpage.secondary_free_list = gpage_addr + stmshared.full_pages[i] = lpage + i -= 1 + stmshared.count_global_pages += self.count_pages + stmshared.release_global_lock() + def delete(self): + self.gift_all_pages_to_shared_area() lltype.free(self.free_loc_for_size, flavor='raw', track_allocation=False) lltype.free(self.pages_for_size, flavor='raw', diff --git a/rpython/memory/gc/test/test_stmshared.py b/rpython/memory/gc/test/test_stmshared.py --- a/rpython/memory/gc/test/test_stmshared.py +++ b/rpython/memory/gc/test/test_stmshared.py @@ -17,7 +17,7 @@ def test_simple(): gc = FakeGC() - shared = StmGCSharedArea(gc, 10*WORD, 2*WORD) + shared = StmGCSharedArea(gc, 9*WORD, 2*WORD) shared.setup() thl1 = StmGCThreadLocalAllocator(shared) thl1.malloc_object(2*WORD-1) @@ -32,11 +32,12 @@ assert len(thl1._seen_pages) == 3 thl1.malloc_object(2*WORD) assert len(thl1._seen_pages) == 3 + assert thl1.count_pages == 3 thl1.delete() def test_free(): gc = FakeGC() - shared = StmGCSharedArea(gc, 10*WORD, 2*WORD) + shared = StmGCSharedArea(gc, 9*WORD, 2*WORD) shared.setup() thl1 = StmGCThreadLocalAllocator(shared) obj = thl1.malloc_object(2*WORD) @@ -48,7 +49,7 @@ def test_big_object(): gc = FakeGC() - shared = StmGCSharedArea(gc, 10*WORD, 2*WORD) + shared = StmGCSharedArea(gc, 9*WORD, 2*WORD) shared.setup() thl1 = StmGCThreadLocalAllocator(shared) obj = thl1.malloc_object(3*WORD) @@ -58,7 +59,7 @@ def test_allocation_is_thread_local(): gc = FakeGC() - shared = StmGCSharedArea(gc, 10*WORD, 2*WORD) + shared = StmGCSharedArea(gc, 9*WORD, 2*WORD) shared.setup() thl1 = StmGCThreadLocalAllocator(shared) thl2 = StmGCThreadLocalAllocator(shared) @@ -73,3 +74,16 @@ # thl1.delete() thl2.delete() + +def test_dying_gift_to_shared_area(): + gc = FakeGC() + shared = StmGCSharedArea(gc, 9*WORD, 2*WORD) + shared.setup() + thl1 = StmGCThreadLocalAllocator(shared) + thl1.malloc_object(2*WORD) + assert thl1.count_pages == 1 + assert len(thl1._seen_pages) == 1 + # + assert shared.count_global_pages == 0 + thl1.delete() + assert shared.count_global_pages == 1 From noreply at buildbot.pypy.org Wed Apr 17 14:22:41 2013 From: noreply at buildbot.pypy.org (arigo) Date: Wed, 17 Apr 2013 14:22:41 +0200 (CEST) Subject: [pypy-commit] pypy stm-gc-2: tweaks Message-ID: <20130417122241.56B361C01FD@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: stm-gc-2 Changeset: r63443:27210e49f4c5 Date: 2013-04-17 14:22 +0200 http://bitbucket.org/pypy/pypy/changeset/27210e49f4c5/ Log: tweaks diff --git a/rpython/memory/gc/stmshared.py b/rpython/memory/gc/stmshared.py --- a/rpython/memory/gc/stmshared.py +++ b/rpython/memory/gc/stmshared.py @@ -63,6 +63,7 @@ self.low_usage_pages = lltype.malloc(rffi.CArray(PAGE_PTR), length, flavor='raw', zero=True, immortal=True) + # ^^^ XXX not used so far self.full_pages = lltype.malloc(rffi.CArray(PAGE_PTR), length, flavor='raw', zero=True, immortal=True) @@ -197,7 +198,8 @@ return llarena.arena_malloc( llmemory.raw_malloc_usage(totalsize), 0) - def malloc_object(self, totalsize): + def malloc_object(self, objsize): + totalsize = self.gc.gcheaderbuilder.size_gc_header + objsize addr = self.malloc_object_addr(totalsize) llarena.arena_reserve(addr, _dummy_size(totalsize)) return addr + self.gc.gcheaderbuilder.size_gc_header @@ -210,9 +212,10 @@ def free_object(self, obj): adr1 = obj - self.gc.gcheaderbuilder.size_gc_header - osize = self.gc.get_size_incl_hash(obj) - if osize <= self.sharedarea.small_request_threshold: - size_class = (osize + WORD_POWER_2 - 1) >> WORD_POWER_2 + totalsize = (self.gc.gcheaderbuilder.size_gc_header + + self.gc.get_size_incl_hash(obj)) + if totalsize <= self.sharedarea.small_request_threshold: + size_class = (totalsize + WORD_POWER_2 - 1) >> WORD_POWER_2 self._free_size_class(adr1, size_class) else: llarena.arena_free(llarena.getfakearenaaddress(adr1)) @@ -232,7 +235,8 @@ def gift_all_pages_to_shared_area(self): """Send to the shared area all my pages. For now we don't extract the information about which locations are free or not; we just stick - them into 'full_pages' and leave the next global GC to figure it out. + them into 'full_pages' and leave it to the next global GC to figure + them out. """ stmshared = self.sharedarea stmshared.acquire_global_lock() diff --git a/rpython/memory/gc/test/test_stmshared.py b/rpython/memory/gc/test/test_stmshared.py --- a/rpython/memory/gc/test/test_stmshared.py +++ b/rpython/memory/gc/test/test_stmshared.py @@ -3,9 +3,11 @@ from rpython.memory.gc.stmshared import StmGCThreadLocalAllocator +SGH = 3 + class FakeGC: class gcheaderbuilder: - size_gc_header = 3 + size_gc_header = SGH def __init__(self): self._object_sizes = {} def set_size(self, obj, size): @@ -20,17 +22,17 @@ shared = StmGCSharedArea(gc, 9*WORD, 2*WORD) shared.setup() thl1 = StmGCThreadLocalAllocator(shared) - thl1.malloc_object(2*WORD-1) + thl1.malloc_object(2*WORD-1-SGH) assert len(thl1._seen_pages) == 1 - thl1.malloc_object(2*WORD) + thl1.malloc_object(2*WORD-SGH) assert len(thl1._seen_pages) == 1 - thl1.malloc_object(1*WORD) + thl1.malloc_object(1*WORD-SGH) assert len(thl1._seen_pages) == 2 - thl1.malloc_object(2*WORD) + thl1.malloc_object(2*WORD-SGH) assert len(thl1._seen_pages) == 2 - thl1.malloc_object(2*WORD) + thl1.malloc_object(2*WORD-SGH) assert len(thl1._seen_pages) == 3 - thl1.malloc_object(2*WORD) + thl1.malloc_object(2*WORD-SGH) assert len(thl1._seen_pages) == 3 assert thl1.count_pages == 3 thl1.delete() @@ -40,10 +42,10 @@ shared = StmGCSharedArea(gc, 9*WORD, 2*WORD) shared.setup() thl1 = StmGCThreadLocalAllocator(shared) - obj = thl1.malloc_object(2*WORD) - gc.set_size(obj, 2*WORD) + obj = thl1.malloc_object(2*WORD-SGH) + gc.set_size(obj, 2*WORD-SGH) thl1.free_object(obj) - obj2 = thl1.malloc_object(2*WORD) + obj2 = thl1.malloc_object(2*WORD-SGH) assert obj2 == obj # reusing the same location thl1.delete() @@ -52,8 +54,8 @@ shared = StmGCSharedArea(gc, 9*WORD, 2*WORD) shared.setup() thl1 = StmGCThreadLocalAllocator(shared) - obj = thl1.malloc_object(3*WORD) - gc.set_size(obj, 3*WORD) + obj = thl1.malloc_object(3*WORD-SGH) + gc.set_size(obj, 3*WORD-SGH) thl1.free_object(obj) thl1.delete() @@ -65,11 +67,11 @@ thl2 = StmGCThreadLocalAllocator(shared) # assert len(thl1._seen_pages) == 0 - thl1.malloc_object(2*WORD) + thl1.malloc_object(2*WORD-SGH) assert len(thl1._seen_pages) == 1 # assert len(thl2._seen_pages) == 0 - thl2.malloc_object(2*WORD) + thl2.malloc_object(2*WORD-SGH) assert len(thl2._seen_pages) == 1 # thl1.delete() @@ -80,7 +82,7 @@ shared = StmGCSharedArea(gc, 9*WORD, 2*WORD) shared.setup() thl1 = StmGCThreadLocalAllocator(shared) - thl1.malloc_object(2*WORD) + thl1.malloc_object(2*WORD-SGH) assert thl1.count_pages == 1 assert len(thl1._seen_pages) == 1 # From noreply at buildbot.pypy.org Wed Apr 17 14:59:43 2013 From: noreply at buildbot.pypy.org (arigo) Date: Wed, 17 Apr 2013 14:59:43 +0200 (CEST) Subject: [pypy-commit] pypy stm-gc-2: Translation fixes and a "bah": can't seem to get a doubly-linked list Message-ID: <20130417125943.4B1CB1C30EE@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: stm-gc-2 Changeset: r63444:55b694882862 Date: 2013-04-17 14:57 +0200 http://bitbucket.org/pypy/pypy/changeset/55b694882862/ Log: Translation fixes and a "bah": can't seem to get a doubly-linked list implementation correct. (stm/test/test_ztranslated.test_targetdemo) diff --git a/rpython/memory/gc/stmgc.py b/rpython/memory/gc/stmgc.py --- a/rpython/memory/gc/stmgc.py +++ b/rpython/memory/gc/stmgc.py @@ -203,14 +203,17 @@ llop.nop(lltype.Void, llhelper(self.stm_operations.DUPLICATE, self._stm_duplicate)) # + self.ll_global_lock = rthread.null_ll_lock self.sharedarea.setup() # self.linked_list_stmtls = None - self.ll_global_lock = rthread.allocate_ll_lock() # self.stm_operations.descriptor_init() self.stm_operations.begin_inevitable_transaction() self.setup_thread() + # + # Now the gc is running, we can allocate this lock object + self.ll_global_lock = rthread.allocate_ll_lock() def setup_thread(self): """Build the StmGCTLS object and start a transaction at the level @@ -237,15 +240,22 @@ stmtls.delete() def acquire_global_lock(self): - rthread.acquire_NOAUTO(self.ll_global_lock, True) + if self.ll_global_lock: + rthread.acquire_NOAUTO(self.ll_global_lock, True) def release_global_lock(self): - rthread.release_NOAUTO(self.ll_global_lock) + if self.ll_global_lock: + rthread.release_NOAUTO(self.ll_global_lock) def add_in_linked_list(self, stmtls): self.acquire_global_lock() + stmnext = self.linked_list_stmtls stmtls.linked_list_prev = None - stmtls.linked_list_next = self.linked_list_stmtls + stmtls.linked_list_next = stmnext + if stmnext is not None: + ll_assert(stmnext.linked_list_prev is None, + "add_in_linked_list: bad linked list") + stmnext.linked_list_prev = stmtls self.linked_list_stmtls = stmtls self.release_global_lock() @@ -254,9 +264,9 @@ c = 0 stmprev = stmtls.linked_list_prev stmnext = stmtls.linked_list_next - if stmnext: + if stmnext is not None: stmnext.linked_list_prev = stmprev - if stmprev: + if stmprev is not None: stmprev.linked_list_next = stmnext c += 1 if stmtls is self.linked_list_stmtls: diff --git a/rpython/memory/gc/stmshared.py b/rpython/memory/gc/stmshared.py --- a/rpython/memory/gc/stmshared.py +++ b/rpython/memory/gc/stmshared.py @@ -80,13 +80,7 @@ self.count_global_pages = 0 def setup(self): - self.ll_global_lock = rthread.allocate_ll_lock() - - def acquire_global_lock(self): - rthread.acquire_NOAUTO(self.ll_global_lock, True) - - def release_global_lock(self): - rthread.release_NOAUTO(self.ll_global_lock) + pass # ------------------------------------------------------------ @@ -239,7 +233,7 @@ them out. """ stmshared = self.sharedarea - stmshared.acquire_global_lock() + stmshared.gc.acquire_global_lock() i = stmshared.length - 1 while i >= 1: lpage = self.pages_for_size[i] @@ -250,7 +244,7 @@ stmshared.full_pages[i] = lpage i -= 1 stmshared.count_global_pages += self.count_pages - stmshared.release_global_lock() + stmshared.gc.release_global_lock() def delete(self): self.gift_all_pages_to_shared_area() diff --git a/rpython/rlib/rthread.py b/rpython/rlib/rthread.py --- a/rpython/rlib/rthread.py +++ b/rpython/rlib/rthread.py @@ -200,6 +200,7 @@ res = c_thread_acquirelock_NOAUTO(ll_lock, flag) res = rffi.cast(lltype.Signed, res) return bool(res) +acquire_NOAUTO._annenforceargs_ = (None, bool) def release_NOAUTO(ll_lock): if not we_are_translated(): diff --git a/rpython/translator/c/genc.py b/rpython/translator/c/genc.py --- a/rpython/translator/c/genc.py +++ b/rpython/translator/c/genc.py @@ -355,6 +355,11 @@ def cmdexec(self, args='', env=None, err=False, expect_crash=False): assert self._compiled + if env is None: + envrepr = '' + else: + envrepr = ' [env=%r]' % (env,) + log.cmdexec('%s %s%s' % (self.executable_name, args, envrepr)) res = self.translator.platform.execute(self.executable_name, args, env=env) if res.returncode != 0: From noreply at buildbot.pypy.org Wed Apr 17 16:11:36 2013 From: noreply at buildbot.pypy.org (arigo) Date: Wed, 17 Apr 2013 16:11:36 +0200 (CEST) Subject: [pypy-commit] pypy stm-gc-2: Comments; fix allocate_object_of_size() Message-ID: <20130417141136.18A9A1C0F4B@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: stm-gc-2 Changeset: r63445:bcb33801e8ac Date: 2013-04-17 15:19 +0200 http://bitbucket.org/pypy/pypy/changeset/bcb33801e8ac/ Log: Comments; fix allocate_object_of_size() diff --git a/rpython/memory/gc/stmtls.py b/rpython/memory/gc/stmtls.py --- a/rpython/memory/gc/stmtls.py +++ b/rpython/memory/gc/stmtls.py @@ -272,16 +272,31 @@ fatalerror("malloc in a non-main thread but outside a transaction") if llmemory.raw_malloc_usage(size) > self.nursery_size // 8 * 7: fatalerror("XXX object too large to ever fit in the nursery") + # + self.local_collection(run_finalizers=True) + # + # call this here in case another thread is waiting for a global GC self.stm_operations.should_break_transaction() - step = 0 - while True: - free = self.nursery_free - top = self.nursery_top - if (top - free) >= llmemory.raw_malloc_usage(size): - return free - ll_assert(step < 2, "nursery must be empty [0]") - self.local_collection(run_finalizers=(step==0)) - step += 1 + # + # if we have now enough space, return it + free = self.nursery_free + top = self.nursery_top + if (top - free) >= llmemory.raw_malloc_usage(size): + return free + # + # no, it might be because we ran finalizers or did a global GC. + # Try again without running the finalizers. + self.local_collection(run_finalizers=False) + # + # now we must have enough space + free = self.nursery_free + top = self.nursery_top + if (top - free) >= llmemory.raw_malloc_usage(size): + return free + # + ll_assert(False, + "local_collection(run_finalizers=0) didn't free enough mem") + return NULL def is_in_nursery(self, addr): ll_assert(llmemory.cast_adr_to_int(addr) & 1 == 0, diff --git a/rpython/rlib/rstm.py b/rpython/rlib/rstm.py --- a/rpython/rlib/rstm.py +++ b/rpython/rlib/rstm.py @@ -46,12 +46,6 @@ def abort_and_retry(): stmgcintf.StmOperations.abort_and_retry() -def start_single_thread(): - stmgcintf.StmOperations.start_single_thread() - -def stop_single_thread(): - stmgcintf.StmOperations.stop_single_thread() - def before_external_call(): if not is_atomic(): e = get_errno() diff --git a/rpython/translator/stm/src_stm/et.c b/rpython/translator/stm/src_stm/et.c --- a/rpython/translator/stm/src_stm/et.c +++ b/rpython/translator/stm/src_stm/et.c @@ -75,6 +75,10 @@ static volatile revision_t next_locked_value = LOCKED + 3; /* always odd */ static __thread struct tx_descriptor *thread_descriptor = NULL; +/* a multi-reader, single-writer lock: transactions normally take a reader + lock, so don't conflict with each other; when we need to do a global GC, + we take a writer lock to "stop the world". Note the initializer here, + which should give the correct priority for reached_safe_point(). */ static pthread_rwlock_t rwlock_in_transaction = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP; diff --git a/rpython/translator/stm/src_stm/rpyintf.c b/rpython/translator/stm/src_stm/rpyintf.c --- a/rpython/translator/stm/src_stm/rpyintf.c +++ b/rpython/translator/stm/src_stm/rpyintf.c @@ -243,6 +243,8 @@ { err = pthread_rwlock_unlock(&rwlock_in_transaction); assert(err == 0); + /* another thread should be waiting in pthread_rwlock_wrlock(), + which takes priority here */ err = pthread_rwlock_rdlock(&rwlock_in_transaction); assert(err == 0); } From noreply at buildbot.pypy.org Wed Apr 17 16:11:37 2013 From: noreply at buildbot.pypy.org (arigo) Date: Wed, 17 Apr 2013 16:11:37 +0200 (CEST) Subject: [pypy-commit] pypy default: Restore the name 'tzdescr' here, as used by locals(). The tests use it, Message-ID: <20130417141137.816381C0F4B@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63446:2b6749fd7c8f Date: 2013-04-17 15:39 +0200 http://bitbucket.org/pypy/pypy/changeset/2b6749fd7c8f/ Log: Restore the name 'tzdescr' here, as used by locals(). The tests use it, but pass anyway if it's missing -- probably because parse() replaces missing descrs with None, which is (I think) useful when parsing log files. diff --git a/rpython/jit/backend/llsupport/test/test_rewrite.py b/rpython/jit/backend/llsupport/test/test_rewrite.py --- a/rpython/jit/backend/llsupport/test/test_rewrite.py +++ b/rpython/jit/backend/llsupport/test/test_rewrite.py @@ -34,7 +34,7 @@ ('t', lltype.Signed)) tdescr = get_size_descr(self.gc_ll_descr, T) tdescr.tid = 5678 - get_field_descr(self.gc_ll_descr, T, 'z') + tzdescr = get_field_descr(self.gc_ll_descr, T, 'z') # A = lltype.GcArray(lltype.Signed) adescr = get_array_descr(self.gc_ll_descr, A) From noreply at buildbot.pypy.org Wed Apr 17 16:11:38 2013 From: noreply at buildbot.pypy.org (arigo) Date: Wed, 17 Apr 2013 16:11:38 +0200 (CEST) Subject: [pypy-commit] pypy default: Extract a big portion of the __init__() into its own method, Message-ID: <20130417141138.B21E41C0F4B@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63447:88e2ae515e01 Date: 2013-04-17 15:51 +0200 http://bitbucket.org/pypy/pypy/changeset/88e2ae515e01/ Log: Extract a big portion of the __init__() into its own method, _declare_functions(). This is useful for the stm branch, which overrides the function. (The diff of this commit is confusing: what really occurs is that I moved down a lot of code, not that I moved up one page.) diff --git a/rpython/memory/gctransform/framework.py b/rpython/memory/gctransform/framework.py --- a/rpython/memory/gctransform/framework.py +++ b/rpython/memory/gctransform/framework.py @@ -129,8 +129,6 @@ def __init__(self, translator): from rpython.memory.gc.base import choose_gc_from_config - from rpython.memory.gc.base import ARRAY_TYPEID_MAP - from rpython.memory.gc import inspector super(BaseFrameworkGCTransformer, self).__init__(translator, inline=True) @@ -232,7 +230,51 @@ classdef = bk.getuniqueclassdef(GCClass) s_gc = annmodel.SomeInstance(classdef) + + self._declare_functions(GCClass, getfn, s_gc, s_typeid16) + + # thread support + if translator.config.translation.continuation: + root_walker.stacklet_support = True + root_walker.need_stacklet_support(self, getfn) + if translator.config.translation.thread: + root_walker.need_thread_support(self, getfn) + + self.layoutbuilder.encode_type_shapes_now() + + annhelper.finish() # at this point, annotate all mix-level helpers + annhelper.backend_optimize() + + self.collect_analyzer = CollectAnalyzer(self.translator) + self.collect_analyzer.analyze_all() + + s_gc = self.translator.annotator.bookkeeper.valueoftype(GCClass) + r_gc = self.translator.rtyper.getrepr(s_gc) + self.c_const_gc = rmodel.inputconst(r_gc, self.gcdata.gc) + s_gc_data = self.translator.annotator.bookkeeper.valueoftype( + gctypelayout.GCData) + r_gc_data = self.translator.rtyper.getrepr(s_gc_data) + self.c_const_gcdata = rmodel.inputconst(r_gc_data, self.gcdata) + self.malloc_zero_filled = GCClass.malloc_zero_filled + + HDR = self.HDR = self.gcdata.gc.gcheaderbuilder.HDR + + size_gc_header = self.gcdata.gc.gcheaderbuilder.size_gc_header + vtableinfo = (HDR, size_gc_header, self.gcdata.gc.typeid_is_in_field) + self.c_vtableinfo = rmodel.inputconst(lltype.Void, vtableinfo) + tig = self.layoutbuilder.type_info_group._as_ptr() + self.c_type_info_group = rmodel.inputconst(lltype.typeOf(tig), tig) + sko = llmemory.sizeof(gcdata.TYPE_INFO) + self.c_vtinfo_skip_offset = rmodel.inputconst(lltype.typeOf(sko), sko) + + + def _declare_functions(self, GCClass, getfn, s_gc, s_typeid16): + from rpython.memory.gc.base import ARRAY_TYPEID_MAP + from rpython.memory.gc import inspector + s_gcref = annmodel.SomePtr(llmemory.GCREF) + gcdata = self.gcdata + translator = self.translator malloc_fixedsize_clear_meth = GCClass.malloc_fixedsize_clear.im_func self.malloc_fixedsize_clear_ptr = getfn( @@ -466,39 +508,6 @@ [annmodel.SomeAddress()], annmodel.s_None) - # thread support - if translator.config.translation.continuation: - root_walker.stacklet_support = True - root_walker.need_stacklet_support(self, getfn) - if translator.config.translation.thread: - root_walker.need_thread_support(self, getfn) - - self.layoutbuilder.encode_type_shapes_now() - - annhelper.finish() # at this point, annotate all mix-level helpers - annhelper.backend_optimize() - - self.collect_analyzer = CollectAnalyzer(self.translator) - self.collect_analyzer.analyze_all() - - s_gc = self.translator.annotator.bookkeeper.valueoftype(GCClass) - r_gc = self.translator.rtyper.getrepr(s_gc) - self.c_const_gc = rmodel.inputconst(r_gc, self.gcdata.gc) - s_gc_data = self.translator.annotator.bookkeeper.valueoftype( - gctypelayout.GCData) - r_gc_data = self.translator.rtyper.getrepr(s_gc_data) - self.c_const_gcdata = rmodel.inputconst(r_gc_data, self.gcdata) - self.malloc_zero_filled = GCClass.malloc_zero_filled - - HDR = self.HDR = self.gcdata.gc.gcheaderbuilder.HDR - - size_gc_header = self.gcdata.gc.gcheaderbuilder.size_gc_header - vtableinfo = (HDR, size_gc_header, self.gcdata.gc.typeid_is_in_field) - self.c_vtableinfo = rmodel.inputconst(lltype.Void, vtableinfo) - tig = self.layoutbuilder.type_info_group._as_ptr() - self.c_type_info_group = rmodel.inputconst(lltype.typeOf(tig), tig) - sko = llmemory.sizeof(gcdata.TYPE_INFO) - self.c_vtinfo_skip_offset = rmodel.inputconst(lltype.typeOf(sko), sko) def consider_constant(self, TYPE, value): self.layoutbuilder.consider_constant(TYPE, value, self.gcdata.gc) From noreply at buildbot.pypy.org Wed Apr 17 17:21:42 2013 From: noreply at buildbot.pypy.org (bivab) Date: Wed, 17 Apr 2013 17:21:42 +0200 (CEST) Subject: [pypy-commit] pypy default: attempt to port a9073815e95a, 41ffa1b27b0c, 154e81a46200 and 278985f308f0 to ARM (may contain traces of pffff) Message-ID: <20130417152142.836F31C0F4B@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63449:b1bcc0680978 Date: 2013-04-17 17:21 +0200 http://bitbucket.org/pypy/pypy/changeset/b1bcc0680978/ Log: attempt to port a9073815e95a, 41ffa1b27b0c, 154e81a46200 and 278985f308f0 to ARM (may contain traces of pffff) diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -278,7 +278,7 @@ mc.CMP_ri(r.r0.value, 0) mc.B(self.propagate_exception_path, c=c.EQ) # - self._reload_frame_if_necessary(mc, align_stack=True) + self._reload_frame_if_necessary(mc) self._pop_all_regs_from_jitframe(mc, [r.r0, r.r1], self.cpu.supports_floats) # nursery_free_adr = self.cpu.gc_ll_descr.get_nursery_free_addr() @@ -293,7 +293,7 @@ rawstart = mc.materialize(self.cpu.asmmemmgr, []) self.malloc_slowpath = rawstart - def _reload_frame_if_necessary(self, mc, align_stack=False, can_collect=0): + def _reload_frame_if_necessary(self, mc): gcrootmap = self.cpu.gc_ll_descr.gcrootmap if gcrootmap and gcrootmap.is_shadow_stack: rst = gcrootmap.get_root_stack_top_addr() @@ -305,7 +305,7 @@ # frame never uses card marking, so we enforce this is not # an array self._write_barrier_fastpath(mc, wbdescr, [r.fp], array=False, - is_frame=True)#, align_stack=align_stack) + is_frame=True) def propagate_memoryerror_if_r0_is_null(self): # see ../x86/assembler.py:propagate_memoryerror_if_eax_is_null diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -350,9 +350,10 @@ return cond def _emit_call(self, adr, arglocs, fcond=c.AL, resloc=None, - result_info=(-1, -1), - can_collect=1, - reload_frame=False): + result_info=(-1, -1), + # whether to worry about a CALL that can collect; this + # is always true except in call_release_gil + can_collect=True): if self.hf_abi: stack_args, adr = self._setup_call_hf(adr, arglocs, fcond, resloc, result_info) @@ -361,7 +362,11 @@ resloc, result_info) if can_collect: + # we push *now* the gcmap, describing the status of GC registers + # after the rearrangements done just above, ignoring the return + # value eax, if necessary noregs = self.cpu.gc_ll_descr.is_shadow_stack() + assert noregs gcmap = self._regalloc.get_gcmap([r.r0], noregs=noregs) self.push_gcmap(self.mc, gcmap, store=True) #the actual call @@ -385,10 +390,8 @@ self._ensure_result_bit_extension(resloc, result_info[0], result_info[1]) if can_collect: - self._reload_frame_if_necessary(self.mc, can_collect=can_collect) + self._reload_frame_if_necessary(self.mc) self.pop_gcmap(self.mc) - elif reload_frame: - self._reload_frame_if_necessary(self.mc) return fcond def _restore_sp(self, stack_args, fcond): @@ -1259,6 +1262,7 @@ def emit_guard_call_release_gil(self, op, guard_op, arglocs, regalloc, fcond): + self._store_force_index(guard_op) # first, close the stack in the sense of the asmgcc GC root tracker gcrootmap = self.cpu.gc_ll_descr.gcrootmap numargs = op.numargs() @@ -1267,24 +1271,27 @@ resloc = arglocs[0] if gcrootmap: - noregs = self.cpu.gc_ll_descr.is_shadow_stack() - assert noregs - gcmap = self._regalloc.get_gcmap([r.r0], noregs=noregs) + # we put the gcmap now into the frame before releasing the GIL, + # and pop it below after reacquiring the GIL. The assumption + # is that this gcmap describes correctly the situation at any + # point in-between: all values containing GC pointers should + # be safely saved out of registers by now, and will not be + # manipulated by any of the following CALLs. + gcmap = self._regalloc.get_gcmap(noregs=True) self.push_gcmap(self.mc, gcmap, store=True) self.call_release_gil(gcrootmap, arglocs, regalloc, fcond) # do the call - self._store_force_index(guard_op) - # descr = op.getdescr() size = descr.get_result_size() signed = descr.is_result_signed() # self._emit_call(adr, callargs, fcond, resloc, (size, signed), - can_collect=0) + can_collect=False) # then reopen the stack if gcrootmap: self.call_reacquire_gil(gcrootmap, resloc, regalloc, fcond) + self.pop_gcmap(self.mc) # remove the gcmap saved above self._emit_guard_may_force(guard_op, arglocs[numargs+1:], numargs) return fcond @@ -1313,7 +1320,7 @@ # call the reopenstack() function (also reacquiring the GIL) with saved_registers(self.mc, regs_to_save, vfp_regs_to_save): self._emit_call(imm(self.reacqgil_addr), [], fcond, - can_collect=False, reload_frame=True) + can_collect=False) def _store_force_index(self, guard_op): faildescr = guard_op.getdescr() From noreply at buildbot.pypy.org Wed Apr 17 17:30:38 2013 From: noreply at buildbot.pypy.org (arigo) Date: Wed, 17 Apr 2013 17:30:38 +0200 (CEST) Subject: [pypy-commit] pypy stm-gc-2: Fix Message-ID: <20130417153038.223FE1C0F4B@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: stm-gc-2 Changeset: r63450:1b1193331a45 Date: 2013-04-17 17:23 +0200 http://bitbucket.org/pypy/pypy/changeset/1b1193331a45/ Log: Fix diff --git a/rpython/memory/gc/test/test_stmshared.py b/rpython/memory/gc/test/test_stmshared.py --- a/rpython/memory/gc/test/test_stmshared.py +++ b/rpython/memory/gc/test/test_stmshared.py @@ -15,6 +15,10 @@ self._object_sizes[obj] = size def get_size_incl_hash(self, obj): return self._object_sizes[obj] + def acquire_global_lock(self): + pass + def release_global_lock(self): + pass def test_simple(): From noreply at buildbot.pypy.org Wed Apr 17 17:30:39 2013 From: noreply at buildbot.pypy.org (arigo) Date: Wed, 17 Apr 2013 17:30:39 +0200 (CEST) Subject: [pypy-commit] pypy stm-gc-2: Translation fixes Message-ID: <20130417153039.518741C0F4B@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: stm-gc-2 Changeset: r63451:52ae351c7535 Date: 2013-04-17 17:28 +0200 http://bitbucket.org/pypy/pypy/changeset/52ae351c7535/ Log: Translation fixes diff --git a/rpython/memory/gctransform/framework.py b/rpython/memory/gctransform/framework.py --- a/rpython/memory/gctransform/framework.py +++ b/rpython/memory/gctransform/framework.py @@ -1258,7 +1258,7 @@ else: try: analyzer = FinalizerAnalyzer(self.translator) - light = not analyzer..analyze_light_finalizer(g) + light = not analyzer.analyze_light_finalizer(g) except lltype.DelayedPointer: light = False # XXX bah, too bad return fptr, light diff --git a/rpython/memory/gctransform/stmframework.py b/rpython/memory/gctransform/stmframework.py --- a/rpython/memory/gctransform/stmframework.py +++ b/rpython/memory/gctransform/stmframework.py @@ -115,7 +115,7 @@ gc = self.gc addr = end while True: - addr = root_iterator.nextleft(gc, addr) + addr = root_iterator.nextleft(gc, llmemory.NULL, addr) if addr.signed[0] == END_MARKER: break callback(arg, addr) From noreply at buildbot.pypy.org Wed Apr 17 17:33:06 2013 From: noreply at buildbot.pypy.org (bivab) Date: Wed, 17 Apr 2013 17:33:06 +0200 (CEST) Subject: [pypy-commit] pypy default: some pffff Message-ID: <20130417153306.A591E1C3151@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63452:116ce9cfbdcc Date: 2013-04-17 17:32 +0200 http://bitbucket.org/pypy/pypy/changeset/116ce9cfbdcc/ Log: some pffff diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -366,7 +366,6 @@ # after the rearrangements done just above, ignoring the return # value eax, if necessary noregs = self.cpu.gc_ll_descr.is_shadow_stack() - assert noregs gcmap = self._regalloc.get_gcmap([r.r0], noregs=noregs) self.push_gcmap(self.mc, gcmap, store=True) #the actual call From noreply at buildbot.pypy.org Wed Apr 17 18:20:03 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 17 Apr 2013 18:20:03 +0200 (CEST) Subject: [pypy-commit] pypy fast-newarray: Fix tests now that we're slightly more pedantic about descrs Message-ID: <20130417162003.2B4071C3151@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: fast-newarray Changeset: r63453:992520ae6986 Date: 2013-04-16 14:34 +0200 http://bitbucket.org/pypy/pypy/changeset/992520ae6986/ Log: Fix tests now that we're slightly more pedantic about descrs diff --git a/rpython/jit/backend/llsupport/test/test_rewrite.py b/rpython/jit/backend/llsupport/test/test_rewrite.py --- a/rpython/jit/backend/llsupport/test/test_rewrite.py +++ b/rpython/jit/backend/llsupport/test/test_rewrite.py @@ -109,6 +109,8 @@ class BaseFakeCPU(object): JITFRAME_FIXED_SIZE = 0 + can_inline_varsize_malloc = True + def __init__(self): self.tracker = FakeTracker() self._cache = {} diff --git a/rpython/jit/backend/test/runner_test.py b/rpython/jit/backend/test/runner_test.py --- a/rpython/jit/backend/test/runner_test.py +++ b/rpython/jit/backend/test/runner_test.py @@ -2833,7 +2833,7 @@ def test_assembler_call_propagate_exc(self): from rpython.jit.backend.llsupport.llmodel import AbstractLLCPU - + if not isinstance(self.cpu, AbstractLLCPU): py.test.skip("llgraph can't fake exceptions well enough, give up") @@ -3477,10 +3477,10 @@ ops = """ [i0] i1 = int_force_ge_zero(i0) # but forced to be in a register - finish(i1, descr=1) + finish(i1, descr=descr) """ + descr = BasicFinalDescr() loop = parse(ops, self.cpu, namespace=locals()) - descr = loop.operations[-1].getdescr() looptoken = JitCellToken() self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken) for inp, outp in [(2,2), (-3, 0)]: @@ -3493,21 +3493,20 @@ py.test.skip("pointless test on non-asm") from rpython.jit.backend.tool.viewcode import machine_code_dump import ctypes + targettoken = TargetToken() ops = """ [i2] i0 = same_as(i2) # but forced to be in a register - label(i0, descr=1) + label(i0, descr=targettoken) i1 = int_add(i0, i0) - guard_true(i1, descr=faildesr) [i1] - jump(i1, descr=1) + guard_true(i1, descr=faildescr) [i1] + jump(i1, descr=targettoken) """ faildescr = BasicFailDescr(2) loop = parse(ops, self.cpu, namespace=locals()) - faildescr = loop.operations[-2].getdescr() - jumpdescr = loop.operations[-1].getdescr() bridge_ops = """ [i0] - jump(i0, descr=jumpdescr) + jump(i0, descr=targettoken) """ bridge = parse(bridge_ops, self.cpu, namespace=locals()) looptoken = JitCellToken() diff --git a/rpython/jit/metainterp/test/test_logger.py b/rpython/jit/metainterp/test/test_logger.py --- a/rpython/jit/metainterp/test/test_logger.py +++ b/rpython/jit/metainterp/test/test_logger.py @@ -93,7 +93,7 @@ [p0] setfield_gc(p0, 3, descr=somedescr) ''' - Descr() + somedescr = Descr() self.reparse(inp, namespace=locals()) def test_guard(self): From noreply at buildbot.pypy.org Wed Apr 17 18:20:04 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 17 Apr 2013 18:20:04 +0200 (CEST) Subject: [pypy-commit] pypy fast-newarray: close to be merged branch Message-ID: <20130417162004.4AE2A1C3151@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: fast-newarray Changeset: r63454:e28a5f13c942 Date: 2013-04-17 18:16 +0200 http://bitbucket.org/pypy/pypy/changeset/e28a5f13c942/ Log: close to be merged branch From noreply at buildbot.pypy.org Wed Apr 17 18:20:05 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 17 Apr 2013 18:20:05 +0200 (CEST) Subject: [pypy-commit] pypy default: Merge fast-newarray. This inlines the fast path of newarray in the assembler. Message-ID: <20130417162005.99BB21C3151@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r63455:6bf943756133 Date: 2013-04-17 18:18 +0200 http://bitbucket.org/pypy/pypy/changeset/6bf943756133/ Log: Merge fast-newarray. This inlines the fast path of newarray in the assembler. Disabled on ARM until we fix issues. diff --git a/rpython/jit/backend/llsupport/assembler.py b/rpython/jit/backend/llsupport/assembler.py --- a/rpython/jit/backend/llsupport/assembler.py +++ b/rpython/jit/backend/llsupport/assembler.py @@ -70,6 +70,14 @@ # the address of the function called by 'new' gc_ll_descr = self.cpu.gc_ll_descr gc_ll_descr.initialize() + if hasattr(gc_ll_descr, 'minimal_size_in_nursery'): + self.gc_minimal_size_in_nursery = gc_ll_descr.minimal_size_in_nursery + else: + self.gc_minimal_size_in_nursery = 0 + if hasattr(gc_ll_descr, 'gcheaderbuilder'): + self.gc_size_of_header = gc_ll_descr.gcheaderbuilder.size_gc_header + else: + self.gc_size_of_header = WORD # for tests self.memcpy_addr = self.cpu.cast_ptr_to_int(memcpy_fn) self._build_failure_recovery(False, withfloats=False) self._build_failure_recovery(True, withfloats=False) @@ -85,7 +93,20 @@ self._build_wb_slowpath(True, withfloats=True) self._build_propagate_exception_path() if gc_ll_descr.get_malloc_slowpath_addr is not None: - self._build_malloc_slowpath() + # generate few slowpaths for various cases + self.malloc_slowpath = self._build_malloc_slowpath(kind='fixed') + self.malloc_slowpath_varsize = self._build_malloc_slowpath( + kind='var') + if hasattr(gc_ll_descr, 'malloc_str'): + self.malloc_slowpath_str = self._build_malloc_slowpath(kind='str') + else: + self.malloc_slowpath_str = None + if hasattr(gc_ll_descr, 'malloc_unicode'): + self.malloc_slowpath_unicode = self._build_malloc_slowpath( + kind='unicode') + else: + self.malloc_slowpath_unicode = None + self._build_stack_check_slowpath() if gc_ll_descr.gcrootmap: self._build_release_gil(gc_ll_descr.gcrootmap) diff --git a/rpython/jit/backend/llsupport/gc.py b/rpython/jit/backend/llsupport/gc.py --- a/rpython/jit/backend/llsupport/gc.py +++ b/rpython/jit/backend/llsupport/gc.py @@ -415,6 +415,7 @@ return llop1.do_malloc_fixedsize_clear(llmemory.GCREF, type_id, size, False, False, False) + self.generate_function('malloc_nursery', malloc_nursery_slowpath, [lltype.Signed]) @@ -567,6 +568,9 @@ def get_malloc_slowpath_addr(self): return self.get_malloc_fn_addr('malloc_nursery') + def get_malloc_slowpath_array_addr(self): + return self.get_malloc_fn_addr('malloc_array') + # ____________________________________________________________ def get_ll_description(gcdescr, translator=None, rtyper=None): diff --git a/rpython/jit/backend/llsupport/llmodel.py b/rpython/jit/backend/llsupport/llmodel.py --- a/rpython/jit/backend/llsupport/llmodel.py +++ b/rpython/jit/backend/llsupport/llmodel.py @@ -21,6 +21,8 @@ class AbstractLLCPU(AbstractCPU): from rpython.jit.metainterp.typesystem import llhelper as ts + can_inline_varsize_malloc = False + def __init__(self, rtyper, stats, opts, translate_support_code=False, gcdescr=None): assert type(opts) is not bool @@ -171,9 +173,9 @@ def pos_exc_value(): addr = llop.get_exc_value_addr(llmemory.Address) return heaptracker.adr2int(addr) - + from rpython.rlib import rstack - + STACK_CHECK_SLOWPATH = lltype.Ptr(lltype.FuncType([lltype.Signed], lltype.Void)) def insert_stack_check(): diff --git a/rpython/jit/backend/llsupport/rewrite.py b/rpython/jit/backend/llsupport/rewrite.py --- a/rpython/jit/backend/llsupport/rewrite.py +++ b/rpython/jit/backend/llsupport/rewrite.py @@ -8,19 +8,29 @@ from rpython.jit.backend.llsupport.descr import SizeDescr, ArrayDescr from rpython.jit.metainterp.history import JitCellToken +FLAG_ARRAY = 0 +FLAG_STR = 1 +FLAG_UNICODE = 2 + class GcRewriterAssembler(object): - # This class performs the following rewrites on the list of operations: - # - # - Remove the DEBUG_MERGE_POINTs. - # - # - Turn all NEW_xxx to either a CALL_MALLOC_GC, or a CALL_MALLOC_NURSERY - # followed by SETFIELDs in order to initialize their GC fields. The - # two advantages of CALL_MALLOC_NURSERY is that it inlines the common - # path, and we need only one such operation to allocate several blocks - # of memory at once. - # - # - Add COND_CALLs to the write barrier before SETFIELD_GC and - # SETARRAYITEM_GC operations. + """ This class performs the following rewrites on the list of operations: + + - Remove the DEBUG_MERGE_POINTs. + + - Turn all NEW_xxx to either a CALL_MALLOC_GC, or a CALL_MALLOC_NURSERY + followed by SETFIELDs in order to initialize their GC fields. The + two advantages of CALL_MALLOC_NURSERY is that it inlines the common + path, and we need only one such operation to allocate several blocks + of memory at once. + + - Add COND_CALLs to the write barrier before SETFIELD_GC and + SETARRAYITEM_GC operations. + + recent_mallocs contains a dictionary of variable -> None. If a variable + is in the dictionary, next setfields can be called without a write barrier, + because the variable got allocated after the last potentially collecting + resop + """ _previous_size = -1 _op_malloc_nursery = None @@ -32,7 +42,7 @@ self.cpu = cpu self.newops = [] self.known_lengths = {} - self.recent_mallocs = {} # set of variables + self.recent_mallocs = {} def rewrite(self, operations): # we can only remember one malloc since the next malloc can possibly @@ -92,9 +102,11 @@ assert isinstance(descr, ArrayDescr) self.handle_new_array(descr, op) elif opnum == rop.NEWSTR: - self.handle_new_array(self.gc_ll_descr.str_descr, op) + self.handle_new_array(self.gc_ll_descr.str_descr, op, + kind=FLAG_STR) elif opnum == rop.NEWUNICODE: - self.handle_new_array(self.gc_ll_descr.unicode_descr, op) + self.handle_new_array(self.gc_ll_descr.unicode_descr, op, + kind=FLAG_UNICODE) else: raise NotImplementedError(op.getopname()) @@ -106,7 +118,7 @@ else: self.gen_malloc_fixedsize(size, descr.tid, op.result) - def handle_new_array(self, arraydescr, op): + def handle_new_array(self, arraydescr, op, kind=FLAG_ARRAY): v_length = op.getarg(0) total_size = -1 if isinstance(v_length, ConstInt): @@ -119,6 +131,14 @@ pass # total_size is still -1 elif arraydescr.itemsize == 0: total_size = arraydescr.basesize + elif (self.gc_ll_descr.can_use_nursery_malloc(1) and + self.gen_malloc_nursery_varsize(arraydescr.itemsize, + v_length, op.result, arraydescr, kind=kind)): + # note that we cannot initialize tid here, because the array + # might end up being allocated by malloc_external or some + # stuff that initializes GC header fields differently + self.gen_initialize_len(op.result, v_length, arraydescr.lendescr) + return if (total_size >= 0 and self.gen_malloc_nursery(total_size, op.result)): self.gen_initialize_tid(op.result, arraydescr.tid) @@ -152,7 +172,7 @@ size_box, descr=descrs.jfi_frame_size) self.newops.append(op0) - self.gen_malloc_nursery_varsize(size_box, frame, is_small=True) + self.gen_malloc_nursery_varsize_small(size_box, frame) self.gen_initialize_tid(frame, descrs.arraydescr.tid) length_box = history.BoxInt() op1 = ResOperation(rop.GETFIELD_GC, [history.ConstInt(frame_info)], @@ -281,10 +301,28 @@ self._gen_call_malloc_gc([ConstInt(addr), v_num_elem], v_result, self.gc_ll_descr.malloc_unicode_descr) - def gen_malloc_nursery_varsize(self, sizebox, v_result, is_small=False): + def gen_malloc_nursery_varsize(self, itemsize, v_length, v_result, + arraydescr, kind=FLAG_ARRAY): + """ itemsize is an int, v_length and v_result are boxes + """ + if not self.cpu.can_inline_varsize_malloc: + return False # temporary, kill when ARM supports it + gc_descr = self.gc_ll_descr + if (kind == FLAG_ARRAY and + (arraydescr.basesize != gc_descr.standard_array_basesize or + arraydescr.lendescr.offset != gc_descr.standard_array_length_ofs)): + return False + self.emitting_an_operation_that_can_collect() + op = ResOperation(rop.CALL_MALLOC_NURSERY_VARSIZE, + [ConstInt(kind), ConstInt(itemsize), v_length], + v_result, descr=arraydescr) + self.newops.append(op) + self.recent_mallocs[v_result] = None + return True + + def gen_malloc_nursery_varsize_small(self, sizebox, v_result): """ Generate CALL_MALLOC_NURSERY_VARSIZE_SMALL """ - assert is_small self.emitting_an_operation_that_can_collect() op = ResOperation(rop.CALL_MALLOC_NURSERY_VARSIZE_SMALL, [sizebox], diff --git a/rpython/jit/backend/llsupport/test/test_gc_integration.py b/rpython/jit/backend/llsupport/test/test_gc_integration.py --- a/rpython/jit/backend/llsupport/test/test_gc_integration.py +++ b/rpython/jit/backend/llsupport/test/test_gc_integration.py @@ -29,11 +29,11 @@ return r[r.find('1'):] class TestRegallocGcIntegration(BaseTestRegalloc): - + cpu = CPU(None, None) cpu.gc_ll_descr = GcLLDescr_boehm(None, None, None) cpu.setup_once() - + S = lltype.GcForwardReference() S.become(lltype.GcStruct('S', ('field', lltype.Ptr(S)), ('int', lltype.Signed))) @@ -145,6 +145,7 @@ gcrootmap = None passes_frame = True write_barrier_descr = None + max_size_of_young_obj = 50 def __init__(self, callback): GcLLDescription.__init__(self, None) @@ -172,6 +173,20 @@ [lltype.Signed, jitframe.JITFRAMEPTR], lltype.Signed) + def malloc_array(itemsize, tid, num_elem): + self.calls.append((itemsize, tid, num_elem)) + return 13 + + self.malloc_slowpath_array_fnptr = llhelper_args(malloc_array, + [lltype.Signed] * 3, + lltype.Signed) + + def malloc_str(size): + self.calls.append(('str', size)) + return 13 + self.generate_function('malloc_str', malloc_str, [lltype.Signed], + lltype.Signed) + def get_nursery_free_addr(self): return rffi.cast(lltype.Signed, self.addrs) @@ -181,6 +196,9 @@ def get_malloc_slowpath_addr(self): return self.get_malloc_fn_addr('malloc_nursery') + def get_malloc_slowpath_array_addr(self): + return self.malloc_slowpath_array_fnptr + def check_nothing_in_nursery(self): # CALL_MALLOC_NURSERY should not write anything in the nursery for i in range(64): @@ -229,7 +247,7 @@ p1 = call_malloc_nursery_varsize_small(i1) p2 = call_malloc_nursery_varsize_small(i2) guard_true(i0) [p0, p1, p2] - ''' + ''' self.interpret(ops, [16, 32, 16]) # check the returned pointers gc_ll_descr = self.cpu.gc_ll_descr @@ -244,6 +262,56 @@ # slowpath never called assert gc_ll_descr.calls == [] + def test_malloc_nursery_varsize(self): + self.cpu = self.getcpu(None) + A = lltype.GcArray(lltype.Signed) + arraydescr = self.cpu.arraydescrof(A) + arraydescr.tid = 15 + ops = ''' + [i0, i1, i2] + p0 = call_malloc_nursery_varsize(0, 8, i0, descr=arraydescr) + p1 = call_malloc_nursery_varsize(0, 5, i1, descr=arraydescr) + guard_false(i0) [p0, p1] + ''' + self.interpret(ops, [1, 2, 3], + namespace={'arraydescr': arraydescr}) + # check the returned pointers + gc_ll_descr = self.cpu.gc_ll_descr + nurs_adr = rffi.cast(lltype.Signed, gc_ll_descr.nursery) + ref = lambda n: self.cpu.get_ref_value(self.deadframe, n) + assert rffi.cast(lltype.Signed, ref(0)) == nurs_adr + 0 + assert rffi.cast(lltype.Signed, ref(1)) == nurs_adr + 2*WORD + 8*1 + # check the nursery content and state + assert gc_ll_descr.nursery[0] == chr(15) + assert gc_ll_descr.nursery[2 * WORD + 8] == chr(15) + assert gc_ll_descr.addrs[0] == nurs_adr + (((4 * WORD + 8*1 + 5*2) + (WORD - 1)) & ~(WORD - 1)) + # slowpath never called + assert gc_ll_descr.calls == [] + + def test_malloc_nursery_varsize_slowpath(self): + self.cpu = self.getcpu(None) + ops = """ + [i0, i1, i2] + p0 = call_malloc_nursery_varsize(0, 8, i0, descr=arraydescr) + p1 = call_malloc_nursery_varsize(0, 5, i1, descr=arraydescr) + p3 = call_malloc_nursery_varsize(0, 5, i2, descr=arraydescr) + # overflow + p4 = call_malloc_nursery_varsize(0, 5, i2, descr=arraydescr) + # we didn't collect, so still overflow + p5 = call_malloc_nursery_varsize(1, 5, i2, descr=strdescr) + guard_false(i0) [p0, p1, p3, p4] + """ + A = lltype.GcArray(lltype.Signed) + arraydescr = self.cpu.arraydescrof(A) + arraydescr.tid = 15 + self.interpret(ops, [10, 3, 3], + namespace={'arraydescr': arraydescr, + 'strdescr': arraydescr}) + # check the returned pointers + gc_ll_descr = self.cpu.gc_ll_descr + assert gc_ll_descr.calls == [(8, 15, 10), (5, 15, 3), ('str', 3)] + # one fit, one was too large, one was not fitting + def test_malloc_slowpath(self): def check(frame): expected_size = 1 @@ -294,7 +362,7 @@ s = bin(x[0]).count('1') + bin(x[1]).count('1') assert s == 16 # all but two registers + some stuff on stack - + self.cpu = self.getcpu(check) S1 = lltype.GcStruct('S1') S2 = lltype.GcStruct('S2', ('s0', lltype.Ptr(S1)), @@ -360,7 +428,7 @@ class MockShadowStackRootMap(object): is_shadow_stack = True - + def __init__(self): TP = rffi.CArray(lltype.Signed) self.stack = lltype.malloc(TP, 10, flavor='raw') @@ -369,7 +437,7 @@ self.stack_addr[0] = rffi.cast(lltype.Signed, self.stack) def __del__(self): - lltype.free(self.stack_addr, flavor='raw') + lltype.free(self.stack_addr, flavor='raw') lltype.free(self.stack, flavor='raw') def register_asm_addr(self, start, mark): @@ -381,7 +449,7 @@ class WriteBarrierDescr(AbstractDescr): jit_wb_cards_set = 0 jit_wb_if_flag_singlebyte = 1 - + def __init__(self, gc_ll_descr): def write_barrier(frame): gc_ll_descr.write_barrier_on_frame_called = frame @@ -442,6 +510,15 @@ self.malloc_slowpath_fnptr = llhelper_args(malloc_slowpath, [lltype.Signed], lltype.Signed) + + def malloc_array(itemsize, tid, num_elem): + import pdb + pdb.set_trace() + + self.malloc_slowpath_array_fnptr = llhelper_args(malloc_array, + [lltype.Signed] * 3, + lltype.Signed) + self.all_nurseries = [] def init_nursery(self, nursery_size=None): @@ -497,6 +574,9 @@ def get_malloc_slowpath_addr(self): return self.malloc_slowpath_fnptr + def get_malloc_slowpath_array_addr(self): + return self.malloc_slowpath_array_fnptr + def get_nursery_free_addr(self): return self.nursery_addr @@ -507,7 +587,7 @@ for nursery in self.all_nurseries: lltype.free(nursery, flavor='raw', track_allocation=False) lltype.free(self.nursery_ptrs, flavor='raw') - + def unpack_gcmap(frame): res = [] val = 0 @@ -543,10 +623,10 @@ def test_shadowstack_call(self): cpu = self.cpu cpu.gc_ll_descr.init_nursery(100) - cpu.setup_once() + cpu.setup_once() S = self.S frames = [] - + def check(i): assert cpu.gc_ll_descr.gcrootmap.stack[0] == i frame = rffi.cast(JITFRAMEPTR, i) @@ -720,7 +800,7 @@ def test_call_may_force_gcmap(self): cpu = self.cpu - + def f(frame, arg, x): assert not arg assert frame.jf_gcmap[0] & 31 == 0 @@ -748,7 +828,7 @@ pdying = getarrayitem_gc(p0, 0, descr=arraydescr) px = call_may_force(ConstClass(fptr), pf, pdying, i0, descr=calldescr) guard_not_forced(descr=faildescr) [p1, p2, p3, px] - finish(px, descr=finishdescr) + finish(px, descr=finaldescr) """, namespace={'fptr': fptr, 'calldescr': calldescr, 'arraydescr': cpu.arraydescrof(A), 'faildescr': BasicFailDescr(1), @@ -760,12 +840,12 @@ cpu.compile_loop(loop.inputargs, loop.operations, token) frame = lltype.cast_opaque_ptr(JITFRAMEPTR, cpu.execute_token(token, 1, a)) - + assert getmap(frame).count('1') == 4 def test_call_gcmap_no_guard(self): cpu = self.cpu - + def f(frame, arg, x): assert not arg assert frame.jf_gcmap[0] & 31 == 0 @@ -792,7 +872,7 @@ pdying = getarrayitem_gc(p0, 0, descr=arraydescr) px = call(ConstClass(fptr), pf, pdying, i0, descr=calldescr) guard_false(i0, descr=faildescr) [p1, p2, p3, px] - finish(px, descr=finishdescr) + finish(px, descr=finaldescr) """, namespace={'fptr': fptr, 'calldescr': calldescr, 'arraydescr': cpu.arraydescrof(A), 'faildescr': BasicFailDescr(1), diff --git a/rpython/jit/backend/llsupport/test/test_regalloc_integration.py b/rpython/jit/backend/llsupport/test/test_regalloc_integration.py --- a/rpython/jit/backend/llsupport/test/test_regalloc_integration.py +++ b/rpython/jit/backend/llsupport/test/test_regalloc_integration.py @@ -93,8 +93,8 @@ type_system=self.type_system, boxkinds=boxkinds) - def interpret(self, ops, args, run=True): - loop = self.parse(ops) + def interpret(self, ops, args, run=True, namespace=None): + loop = self.parse(ops, namespace=namespace) self.loop = loop looptoken = JitCellToken() self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken) diff --git a/rpython/jit/backend/llsupport/test/test_rewrite.py b/rpython/jit/backend/llsupport/test/test_rewrite.py --- a/rpython/jit/backend/llsupport/test/test_rewrite.py +++ b/rpython/jit/backend/llsupport/test/test_rewrite.py @@ -85,6 +85,7 @@ signedframedescr = self.cpu.signedframedescr floatframedescr = self.cpu.floatframedescr casmdescr.compiled_loop_token = clt + tzdescr = None # noone cares # namespace.update(locals()) # @@ -107,7 +108,9 @@ class BaseFakeCPU(object): JITFRAME_FIXED_SIZE = 0 - + + can_inline_varsize_malloc = True + def __init__(self): self.tracker = FakeTracker() self._cache = {} @@ -121,7 +124,7 @@ def unpack_arraydescr_size(self, d): return 0, d.itemsize, 0 - + def arraydescrof(self, ARRAY): try: return self._cache[ARRAY] @@ -129,7 +132,7 @@ r = ArrayDescr(1, 2, FieldDescr('len', 0, 0, 0), 0) self._cache[ARRAY] = r return r - + def fielddescrof(self, STRUCT, fname): key = (STRUCT, fname) try: @@ -407,12 +410,23 @@ jump(i0) """, """ [i0] - p0 = call_malloc_gc(ConstClass(malloc_array), 1, \ - %(bdescr.tid)d, i0, \ - descr=malloc_array_descr) + p0 = call_malloc_nursery_varsize(0, 1, i0, descr=bdescr) + setfield_gc(p0, i0, descr=blendescr) jump(i0) """) + def test_rewrite_new_string(self): + self.check_rewrite(""" + [i0] + p0 = newstr(i0) + jump(i0) + """, """ + [i0] + p0 = call_malloc_nursery_varsize(1, 1, i0, descr=strdescr) + setfield_gc(p0, i0, descr=strlendescr) + jump(i0) + """) + def test_rewrite_assembler_nonstandard_array(self): # a non-standard array is a bit hard to get; e.g. GcArray(Float) # is like that on Win32, but not on Linux. Build one manually... @@ -533,10 +547,12 @@ p1 = int_add(p0, %(strdescr.basesize + 16 * strdescr.itemsize)d) setfield_gc(p1, %(unicodedescr.tid)d, descr=tiddescr) setfield_gc(p1, 10, descr=unicodelendescr) - p2 = call_malloc_gc(ConstClass(malloc_unicode), i2, \ - descr=malloc_unicode_descr) - p3 = call_malloc_gc(ConstClass(malloc_str), i2, \ - descr=malloc_str_descr) + p2 = call_malloc_nursery_varsize(2, 4, i2, \ + descr=unicodedescr) + setfield_gc(p2, i2, descr=unicodelendescr) + p3 = call_malloc_nursery_varsize(1, 1, i2, \ + descr=strdescr) + setfield_gc(p3, i2, descr=strlendescr) jump() """) @@ -716,8 +732,9 @@ [i0] p0 = call_malloc_nursery(%(tdescr.size)d) setfield_gc(p0, 5678, descr=tiddescr) - p1 = call_malloc_gc(ConstClass(malloc_str), i0, \ - descr=malloc_str_descr) + p1 = call_malloc_nursery_varsize(1, 1, i0, \ + descr=strdescr) + setfield_gc(p1, i0, descr=strlendescr) cond_call_gc_wb(p0, p1, descr=wbdescr) setfield_raw(p0, p1, descr=tzdescr) jump() diff --git a/rpython/jit/backend/test/runner_test.py b/rpython/jit/backend/test/runner_test.py --- a/rpython/jit/backend/test/runner_test.py +++ b/rpython/jit/backend/test/runner_test.py @@ -2833,7 +2833,7 @@ def test_assembler_call_propagate_exc(self): from rpython.jit.backend.llsupport.llmodel import AbstractLLCPU - + if not isinstance(self.cpu, AbstractLLCPU): py.test.skip("llgraph can't fake exceptions well enough, give up") @@ -3477,10 +3477,10 @@ ops = """ [i0] i1 = int_force_ge_zero(i0) # but forced to be in a register - finish(i1, descr=1) + finish(i1, descr=descr) """ + descr = BasicFinalDescr() loop = parse(ops, self.cpu, namespace=locals()) - descr = loop.operations[-1].getdescr() looptoken = JitCellToken() self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken) for inp, outp in [(2,2), (-3, 0)]: @@ -3493,21 +3493,20 @@ py.test.skip("pointless test on non-asm") from rpython.jit.backend.tool.viewcode import machine_code_dump import ctypes + targettoken = TargetToken() ops = """ [i2] i0 = same_as(i2) # but forced to be in a register - label(i0, descr=1) + label(i0, descr=targettoken) i1 = int_add(i0, i0) - guard_true(i1, descr=faildesr) [i1] - jump(i1, descr=1) + guard_true(i1, descr=faildescr) [i1] + jump(i1, descr=targettoken) """ faildescr = BasicFailDescr(2) loop = parse(ops, self.cpu, namespace=locals()) - faildescr = loop.operations[-2].getdescr() - jumpdescr = loop.operations[-1].getdescr() bridge_ops = """ [i0] - jump(i0, descr=jumpdescr) + jump(i0, descr=targettoken) """ bridge = parse(bridge_ops, self.cpu, namespace=locals()) looptoken = JitCellToken() diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -1,7 +1,7 @@ import sys import os -from rpython.jit.backend.llsupport import symbolic, jitframe +from rpython.jit.backend.llsupport import symbolic, jitframe, rewrite from rpython.jit.backend.llsupport.assembler import (GuardToken, BaseAssembler, DEBUG_COUNTER, debug_bridge) from rpython.jit.backend.llsupport.asmmemmgr import MachineDataBlockWrapper @@ -60,6 +60,7 @@ self.float_const_neg_addr = 0 self.float_const_abs_addr = 0 self.malloc_slowpath = 0 + self.malloc_slowpath_varsize = 0 self.wb_slowpath = [0, 0, 0, 0, 0] self.setup_failure_recovery() self.datablockwrapper = None @@ -158,27 +159,56 @@ mc.RET() self._frame_realloc_slowpath = mc.materialize(self.cpu.asmmemmgr, []) - def _build_malloc_slowpath(self): + def _build_malloc_slowpath(self, kind): """ While arriving on slowpath, we have a gcpattern on stack, nursery_head in eax and the size in edi - eax """ + assert kind in ['fixed', 'str', 'unicode', 'var'] mc = codebuf.MachineCodeBlockWrapper() self._push_all_regs_to_frame(mc, [eax, edi], self.cpu.supports_floats) ofs = self.cpu.get_ofs_of_frame_field('jf_gcmap') # store the gc pattern mc.MOV_rs(ecx.value, WORD) mc.MOV_br(ofs, ecx.value) - addr = self.cpu.gc_ll_descr.get_malloc_slowpath_addr() - mc.SUB_rr(edi.value, eax.value) # compute the size we want - # the arg is already in edi + if kind == 'fixed': + addr = self.cpu.gc_ll_descr.get_malloc_slowpath_addr() + elif kind == 'str': + addr = self.cpu.gc_ll_descr.get_malloc_fn_addr('malloc_str') + elif kind == 'unicode': + addr = self.cpu.gc_ll_descr.get_malloc_fn_addr('malloc_unicode') + else: + addr = self.cpu.gc_ll_descr.get_malloc_slowpath_array_addr() mc.SUB_ri(esp.value, 16 - WORD) - if IS_X86_32: - mc.MOV_sr(0, edi.value) - if hasattr(self.cpu.gc_ll_descr, 'passes_frame'): - mc.MOV_sr(WORD, ebp.value) - elif hasattr(self.cpu.gc_ll_descr, 'passes_frame'): - # for tests only - mc.MOV_rr(esi.value, ebp.value) + if kind == 'fixed': + mc.SUB_rr(edi.value, eax.value) # compute the size we want + # the arg is already in edi + if IS_X86_32: + mc.MOV_sr(0, edi.value) + if hasattr(self.cpu.gc_ll_descr, 'passes_frame'): + mc.MOV_sr(WORD, ebp.value) + elif hasattr(self.cpu.gc_ll_descr, 'passes_frame'): + # for tests only + mc.MOV_rr(esi.value, ebp.value) + elif kind == 'str' or kind == 'unicode': + if IS_X86_32: + # 1 for return value, 3 for alignment + mc.MOV_rs(edi.value, WORD * (3 + 1 + 1)) + mc.MOV_sr(0, edi.value) + else: + mc.MOV_rs(edi.value, WORD * 3) + else: + if IS_X86_32: + mc.MOV_rs(edi.value, WORD * (3 + 1 + 1)) # itemsize + mc.MOV_sr(0, edi.value) + mc.MOV_rs(edi.value, WORD * (3 + 3 + 1)) + mc.MOV_sr(WORD, edi.value) # tid + mc.MOV_rs(edi.value, WORD * (3 + 2 + 1)) + mc.MOV_sr(2 * WORD, edi.value) # length + else: + # offset is 1 extra for call + 1 for SUB above + mc.MOV_rs(edi.value, WORD * 3) # itemsize + mc.MOV_rs(esi.value, WORD * 5) # tid + mc.MOV_rs(edx.value, WORD * 4) # length self.set_extra_stack_depth(mc, 16) mc.CALL(imm(addr)) mc.ADD_ri(esp.value, 16 - WORD) @@ -205,7 +235,7 @@ mc.JMP(imm(self.propagate_exception_path)) # rawstart = mc.materialize(self.cpu.asmmemmgr, []) - self.malloc_slowpath = rawstart + return rawstart def _build_propagate_exception_path(self): if not self.cpu.propagate_exception_descr: @@ -2352,6 +2382,51 @@ self.mc.overwrite(jmp_adr-1, chr(offset)) self.mc.MOV(heap(nursery_free_adr), edi) + def malloc_cond_varsize(self, kind, nursery_free_adr, nursery_top_adr, + lengthloc, itemsize, maxlength, gcmap, + arraydescr): + from rpython.jit.backend.llsupport.descr import ArrayDescr + assert isinstance(arraydescr, ArrayDescr) + + self.mc.CMP(lengthloc, imm(maxlength)) + self.mc.J_il8(rx86.Conditions['G'], 0) # patched later + jmp_adr0 = self.mc.get_relative_pos() + self.mc.MOV(eax, heap(nursery_free_adr)) + self.mc.MOV(edi, lengthloc) + assert arraydescr.basesize >= self.gc_minimal_size_in_nursery + self.mc.IMUL_ri(edi.value, itemsize) + header_size = self.gc_size_of_header + self.mc.ADD_ri(edi.value, arraydescr.basesize + header_size + WORD - 1) + self.mc.AND_ri(edi.value, ~(WORD - 1)) + self.mc.ADD(edi, heap(nursery_free_adr)) + self.mc.CMP(edi, heap(nursery_top_adr)) + # write down the tid + self.mc.MOV(mem(eax, 0), imm(arraydescr.tid)) + self.mc.J_il8(rx86.Conditions['NA'], 0) # patched later + jmp_adr1 = self.mc.get_relative_pos() + offset = self.mc.get_relative_pos() - jmp_adr0 + assert 0 < offset <= 127 + self.mc.overwrite(jmp_adr0-1, chr(offset)) + if kind == rewrite.FLAG_ARRAY: + self.mc.MOV_si(WORD, itemsize) + self.mc.MOV(RawEspLoc(WORD * 2, INT), lengthloc) + self.mc.MOV_si(WORD * 3, arraydescr.tid) + addr = self.malloc_slowpath_varsize + else: + if kind == rewrite.FLAG_STR: + addr = self.malloc_slowpath_str + else: + assert kind == rewrite.FLAG_UNICODE + addr = self.malloc_slowpath_unicode + self.mc.MOV(RawEspLoc(WORD, INT), lengthloc) + # save the gcmap + self.push_gcmap(self.mc, gcmap, mov=True) + self.mc.CALL(imm(addr)) + offset = self.mc.get_relative_pos() - jmp_adr1 + assert 0 < offset <= 127 + self.mc.overwrite(jmp_adr1-1, chr(offset)) + self.mc.MOV(heap(nursery_free_adr), edi) + def force_token(self, reg): # XXX kill me assert isinstance(reg, RegLoc) diff --git a/rpython/jit/backend/x86/regalloc.py b/rpython/jit/backend/x86/regalloc.py --- a/rpython/jit/backend/x86/regalloc.py +++ b/rpython/jit/backend/x86/regalloc.py @@ -54,7 +54,7 @@ class X86_64_RegisterManager(X86RegisterManager): # r11 omitted because it's used as scratch all_regs = [ecx, eax, edx, ebx, esi, edi, r8, r9, r10, r12, r13, r14, r15] - + no_lower_byte_regs = [] save_around_call_regs = [eax, ecx, edx, esi, edi, r8, r9, r10] @@ -103,7 +103,7 @@ def __init__(self, base_ofs): FrameManager.__init__(self) self.base_ofs = base_ofs - + def frame_pos(self, i, box_type): return FrameLoc(i, get_ebp_ofs(self.base_ofs, i), box_type) @@ -870,6 +870,33 @@ gc_ll_descr.get_nursery_top_addr(), sizeloc, gcmap) + def consider_call_malloc_nursery_varsize(self, op): + gc_ll_descr = self.assembler.cpu.gc_ll_descr + if not hasattr(gc_ll_descr, 'max_size_of_young_obj'): + raise Exception("unreachable code") + # for boehm, this function should never be called + length_box = op.getarg(2) + arraydescr = op.getdescr() + assert isinstance(length_box, BoxInt) # we cannot have a const here! + # looking at the result + self.rm.force_allocate_reg(op.result, selected_reg=eax) + # + # We need edx as a temporary, but otherwise don't save any more + # register. See comments in _build_malloc_slowpath(). + tmp_box = TempBox() + self.rm.force_allocate_reg(tmp_box, selected_reg=edi) + lengthloc = self.rm.make_sure_var_in_reg(length_box, [op.result, tmp_box]) + gcmap = self.get_gcmap([eax, edi]) # allocate the gcmap *before* + self.rm.possibly_free_var(tmp_box) + # + itemsize = op.getarg(1).getint() + maxlength = (gc_ll_descr.max_size_of_young_obj - WORD * 2) / itemsize + self.assembler.malloc_cond_varsize( + op.getarg(0).getint(), + gc_ll_descr.get_nursery_free_addr(), + gc_ll_descr.get_nursery_top_addr(), + lengthloc, itemsize, maxlength, gcmap, arraydescr) + def get_gcmap(self, forbidden_regs=[], noregs=False): frame_depth = self.fm.get_frame_depth() gcmap = allocate_gcmap(self.assembler, frame_depth, JITFRAME_FIXED_SIZE) @@ -1313,7 +1340,7 @@ #jump_op = self.final_jump_op #if jump_op is not None and jump_op.getdescr() is descr: # self._compute_hint_frame_locations_from_descr(descr) - + def consider_keepalive(self, op): pass diff --git a/rpython/jit/backend/x86/runner.py b/rpython/jit/backend/x86/runner.py --- a/rpython/jit/backend/x86/runner.py +++ b/rpython/jit/backend/x86/runner.py @@ -23,6 +23,8 @@ with_threads = False frame_reg = regloc.ebp + can_inline_varsize_malloc = True + from rpython.jit.backend.x86.arch import JITFRAME_FIXED_SIZE all_reg_indexes = gpr_reg_mgr_cls.all_reg_indexes gen_regs = gpr_reg_mgr_cls.all_regs diff --git a/rpython/jit/metainterp/executor.py b/rpython/jit/metainterp/executor.py --- a/rpython/jit/metainterp/executor.py +++ b/rpython/jit/metainterp/executor.py @@ -354,6 +354,7 @@ rop.QUASIIMMUT_FIELD, rop.CALL_MALLOC_GC, rop.CALL_MALLOC_NURSERY, + rop.CALL_MALLOC_NURSERY_VARSIZE, rop.CALL_MALLOC_NURSERY_VARSIZE_SMALL, rop.LABEL, ): # list of opcodes never executed by pyjitpl diff --git a/rpython/jit/metainterp/resoperation.py b/rpython/jit/metainterp/resoperation.py --- a/rpython/jit/metainterp/resoperation.py +++ b/rpython/jit/metainterp/resoperation.py @@ -525,6 +525,7 @@ 'CALL_PURE/*d', # removed before it's passed to the backend 'CALL_MALLOC_GC/*d', # like CALL, but NULL => propagate MemoryError 'CALL_MALLOC_NURSERY/1', # nursery malloc, const number of bytes, zeroed + 'CALL_MALLOC_NURSERY_VARSIZE/3d', 'CALL_MALLOC_NURSERY_VARSIZE_SMALL/1', # nursery malloc, non-const number of bytes, zeroed # note that the number of bytes must be well known to be small enough diff --git a/rpython/jit/metainterp/test/test_logger.py b/rpython/jit/metainterp/test/test_logger.py --- a/rpython/jit/metainterp/test/test_logger.py +++ b/rpython/jit/metainterp/test/test_logger.py @@ -93,7 +93,7 @@ [p0] setfield_gc(p0, 3, descr=somedescr) ''' - Descr() + somedescr = Descr() self.reparse(inp, namespace=locals()) def test_guard(self): diff --git a/rpython/jit/tool/oparser.py b/rpython/jit/tool/oparser.py --- a/rpython/jit/tool/oparser.py +++ b/rpython/jit/tool/oparser.py @@ -106,6 +106,8 @@ tt = self.model.TargetToken(token) self._consts[poss_descr] = tt return tt + else: + raise def box_for_var(self, elem): try: From noreply at buildbot.pypy.org Wed Apr 17 18:20:06 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 17 Apr 2013 18:20:06 +0200 (CEST) Subject: [pypy-commit] pypy default: merge Message-ID: <20130417162006.F316B1C3151@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r63456:2207377f4cc9 Date: 2013-04-17 18:19 +0200 http://bitbucket.org/pypy/pypy/changeset/2207377f4cc9/ Log: merge diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -13,7 +13,7 @@ operations as regalloc_operations, operations_with_guard as regalloc_operations_with_guard) from rpython.jit.backend.llsupport import jitframe -from rpython.jit.backend.llsupport.assembler import DEBUG_COUNTER, debug_bridge +from rpython.jit.backend.llsupport.assembler import DEBUG_COUNTER, debug_bridge, BaseAssembler from rpython.jit.backend.llsupport.asmmemmgr import MachineDataBlockWrapper from rpython.jit.backend.model import CompiledLoopToken from rpython.jit.codewriter.effectinfo import EffectInfo @@ -25,7 +25,7 @@ from rpython.rlib.rarithmetic import r_uint from rpython.rtyper.annlowlevel import llhelper, cast_instance_to_gcref from rpython.rtyper.lltypesystem import lltype, rffi - +from rpython.jit.backend.arm.detect import detect_hardfloat class AssemblerARM(ResOpAssembler): @@ -49,6 +49,10 @@ self.loop_run_counters = [] self.gcrootmap_retaddr_forced = 0 + def setup_once(self): + BaseAssembler.setup_once(self) + self.hf_abi = detect_hardfloat() + def setup(self, looptoken): assert self.memcpy_addr != 0, 'setup_once() not called?' if we_are_translated(): @@ -274,7 +278,7 @@ mc.CMP_ri(r.r0.value, 0) mc.B(self.propagate_exception_path, c=c.EQ) # - self._reload_frame_if_necessary(mc, align_stack=True) + self._reload_frame_if_necessary(mc) self._pop_all_regs_from_jitframe(mc, [r.r0, r.r1], self.cpu.supports_floats) # nursery_free_adr = self.cpu.gc_ll_descr.get_nursery_free_addr() @@ -289,7 +293,7 @@ rawstart = mc.materialize(self.cpu.asmmemmgr, []) self.malloc_slowpath = rawstart - def _reload_frame_if_necessary(self, mc, align_stack=False, can_collect=0): + def _reload_frame_if_necessary(self, mc): gcrootmap = self.cpu.gc_ll_descr.gcrootmap if gcrootmap and gcrootmap.is_shadow_stack: rst = gcrootmap.get_root_stack_top_addr() @@ -301,7 +305,7 @@ # frame never uses card marking, so we enforce this is not # an array self._write_barrier_fastpath(mc, wbdescr, [r.fp], array=False, - is_frame=True)#, align_stack=align_stack) + is_frame=True) def propagate_memoryerror_if_r0_is_null(self): # see ../x86/assembler.py:propagate_memoryerror_if_eax_is_null diff --git a/rpython/jit/backend/arm/detect.py b/rpython/jit/backend/arm/detect.py --- a/rpython/jit/backend/arm/detect.py +++ b/rpython/jit/backend/arm/detect.py @@ -1,5 +1,5 @@ from rpython.translator.tool.cbuild import ExternalCompilationInfo -from rpython.rtyper.lltypesystem import lltype, rffi +from rpython.rlib.clibffi import FFI_DEFAULT_ABI, FFI_SYSV, FFI_VFP from rpython.rtyper.tool import rffi_platform from rpython.translator.platform import CompilationError @@ -14,10 +14,7 @@ """]) def detect_hardfloat(): - # http://gcc.gnu.org/ml/gcc-patches/2010-10/msg02419.html - if rffi_platform.getdefined('__ARM_PCS_VFP', ''): - return rffi_platform.getconstantinteger('__ARM_PCS_VFP', '') - return False + return FFI_DEFAULT_ABI == FFI_VFP def detect_float(): """Check for hardware float support diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -3,7 +3,6 @@ from rpython.jit.backend.arm import registers as r from rpython.jit.backend.arm import shift from rpython.jit.backend.arm.arch import WORD, DOUBLE_WORD, JITFRAME_FIXED_SIZE - from rpython.jit.backend.arm.helper.assembler import (gen_emit_op_by_helper_call, gen_emit_op_unary_cmp, gen_emit_guard_unary_cmp, @@ -351,10 +350,11 @@ return cond def _emit_call(self, adr, arglocs, fcond=c.AL, resloc=None, - result_info=(-1, -1), - can_collect=1, - reload_frame=False): - if self.cpu.hf_abi: + result_info=(-1, -1), + # whether to worry about a CALL that can collect; this + # is always true except in call_release_gil + can_collect=True): + if self.hf_abi: stack_args, adr = self._setup_call_hf(adr, arglocs, fcond, resloc, result_info) else: @@ -362,6 +362,9 @@ resloc, result_info) if can_collect: + # we push *now* the gcmap, describing the status of GC registers + # after the rearrangements done just above, ignoring the return + # value eax, if necessary noregs = self.cpu.gc_ll_descr.is_shadow_stack() gcmap = self._regalloc.get_gcmap([r.r0], noregs=noregs) self.push_gcmap(self.mc, gcmap, store=True) @@ -379,17 +382,15 @@ # ensure the result is wellformed and stored in the correct location if resloc is not None: - if resloc.is_vfp_reg() and not self.cpu.hf_abi: + if resloc.is_vfp_reg() and not self.hf_abi: # move result to the allocated register self.mov_to_vfp_loc(r.r0, r.r1, resloc) elif resloc.is_reg() and result_info != (-1, -1): self._ensure_result_bit_extension(resloc, result_info[0], result_info[1]) if can_collect: - self._reload_frame_if_necessary(self.mc, can_collect=can_collect) + self._reload_frame_if_necessary(self.mc) self.pop_gcmap(self.mc) - elif reload_frame: - self._reload_frame_if_necessary(self.mc) return fcond def _restore_sp(self, stack_args, fcond): @@ -1260,6 +1261,7 @@ def emit_guard_call_release_gil(self, op, guard_op, arglocs, regalloc, fcond): + self._store_force_index(guard_op) # first, close the stack in the sense of the asmgcc GC root tracker gcrootmap = self.cpu.gc_ll_descr.gcrootmap numargs = op.numargs() @@ -1268,24 +1270,27 @@ resloc = arglocs[0] if gcrootmap: - noregs = self.cpu.gc_ll_descr.is_shadow_stack() - assert noregs - gcmap = self._regalloc.get_gcmap([r.r0], noregs=noregs) + # we put the gcmap now into the frame before releasing the GIL, + # and pop it below after reacquiring the GIL. The assumption + # is that this gcmap describes correctly the situation at any + # point in-between: all values containing GC pointers should + # be safely saved out of registers by now, and will not be + # manipulated by any of the following CALLs. + gcmap = self._regalloc.get_gcmap(noregs=True) self.push_gcmap(self.mc, gcmap, store=True) self.call_release_gil(gcrootmap, arglocs, regalloc, fcond) # do the call - self._store_force_index(guard_op) - # descr = op.getdescr() size = descr.get_result_size() signed = descr.is_result_signed() # self._emit_call(adr, callargs, fcond, resloc, (size, signed), - can_collect=0) + can_collect=False) # then reopen the stack if gcrootmap: self.call_reacquire_gil(gcrootmap, resloc, regalloc, fcond) + self.pop_gcmap(self.mc) # remove the gcmap saved above self._emit_guard_may_force(guard_op, arglocs[numargs+1:], numargs) return fcond @@ -1314,7 +1319,7 @@ # call the reopenstack() function (also reacquiring the GIL) with saved_registers(self.mc, regs_to_save, vfp_regs_to_save): self._emit_call(imm(self.reacqgil_addr), [], fcond, - can_collect=False, reload_frame=True) + can_collect=False) def _store_force_index(self, guard_op): faildescr = guard_op.getdescr() diff --git a/rpython/jit/backend/arm/runner.py b/rpython/jit/backend/arm/runner.py --- a/rpython/jit/backend/arm/runner.py +++ b/rpython/jit/backend/arm/runner.py @@ -6,6 +6,7 @@ from rpython.jit.backend.llsupport.llmodel import AbstractLLCPU from rpython.rlib.jit_hooks import LOOP_RUN_CONTAINER from rpython.rtyper.lltypesystem import lltype, llmemory +from rpython.jit.backend.arm.detect import detect_hardfloat jitframe.STATICSIZE = JITFRAME_FIXED_SIZE @@ -16,7 +17,7 @@ supports_floats = True supports_longlong = False # XXX requires an implementation of # read_timestamp that works in user mode - supports_singlefloats = True + supports_singlefloats = not detect_hardfloat() from rpython.jit.backend.arm.arch import JITFRAME_FIXED_SIZE all_reg_indexes = range(len(all_regs)) @@ -112,22 +113,10 @@ class CPU_ARM(AbstractARMCPU): - """ARM v7 uses softfp ABI, requires vfp""" + """ARM v7""" backend_name = "armv7" - -class CPU_ARMHF(AbstractARMCPU): - """ARM v7 uses hardfp ABI, requires vfp""" - hf_abi = True - backend_name = "armv7hf" - supports_floats = True - supports_singlefloats = False - - -class CPU_ARMv6HF(AbstractARMCPU): +class CPU_ARMv6(AbstractARMCPU): """ ARM v6, uses hardfp ABI, requires vfp""" - hf_abi = True arch_version = 6 - backend_name = "armv6hf" - supports_floats = True - supports_singlefloats = False + backend_name = "armv6" diff --git a/rpython/jit/backend/arm/test/conftest.py b/rpython/jit/backend/arm/test/conftest.py --- a/rpython/jit/backend/arm/test/conftest.py +++ b/rpython/jit/backend/arm/test/conftest.py @@ -16,6 +16,7 @@ dest="run_translation_tests", help="run tests that translate code") -def pytest_runtest_setup(item): +def pytest_collect_directory(path, parent): if not cpu.startswith('arm'): py.test.skip("ARM(v7) tests skipped: cpu is %r" % (cpu,)) +pytest_collect_file = pytest_collect_directory diff --git a/rpython/jit/backend/detect_cpu.py b/rpython/jit/backend/detect_cpu.py --- a/rpython/jit/backend/detect_cpu.py +++ b/rpython/jit/backend/detect_cpu.py @@ -61,8 +61,6 @@ model = 'x86-without-sse2' if model.startswith('arm'): from rpython.jit.backend.arm.detect import detect_hardfloat, detect_float - if detect_hardfloat(): - model += 'hf' assert detect_float(), 'the JIT-compiler requires a vfp unit' return model @@ -77,12 +75,10 @@ return "rpython.jit.backend.x86.runner", "CPU_X86_64" elif backend_name == 'cli': return "rpython.jit.backend.cli.runner", "CliCPU" - elif backend_name == 'armv6hf': - return "rpython.jit.backend.arm.runner", "CPU_ARMv6HF" - elif backend_name == 'armv7': + elif backend_name.startswith('armv6'): + return "rpython.jit.backend.arm.runner", "CPU_ARMv6" + elif backend_name.startswith('armv7'): return "rpython.jit.backend.arm.runner", "CPU_ARM" - elif backend_name == 'armv7hf': - return "rpython.jit.backend.arm.runner", "CPU_ARMHF" else: raise ProcessorAutodetectError, ( "we have no JIT backend for this cpu: '%s'" % backend_name) diff --git a/rpython/jit/backend/llsupport/test/test_rewrite.py b/rpython/jit/backend/llsupport/test/test_rewrite.py --- a/rpython/jit/backend/llsupport/test/test_rewrite.py +++ b/rpython/jit/backend/llsupport/test/test_rewrite.py @@ -34,7 +34,7 @@ ('t', lltype.Signed)) tdescr = get_size_descr(self.gc_ll_descr, T) tdescr.tid = 5678 - get_field_descr(self.gc_ll_descr, T, 'z') + tzdescr = get_field_descr(self.gc_ll_descr, T, 'z') # A = lltype.GcArray(lltype.Signed) adescr = get_array_descr(self.gc_ll_descr, A) diff --git a/rpython/memory/gctransform/framework.py b/rpython/memory/gctransform/framework.py --- a/rpython/memory/gctransform/framework.py +++ b/rpython/memory/gctransform/framework.py @@ -129,8 +129,6 @@ def __init__(self, translator): from rpython.memory.gc.base import choose_gc_from_config - from rpython.memory.gc.base import ARRAY_TYPEID_MAP - from rpython.memory.gc import inspector super(BaseFrameworkGCTransformer, self).__init__(translator, inline=True) @@ -232,7 +230,51 @@ classdef = bk.getuniqueclassdef(GCClass) s_gc = annmodel.SomeInstance(classdef) + + self._declare_functions(GCClass, getfn, s_gc, s_typeid16) + + # thread support + if translator.config.translation.continuation: + root_walker.stacklet_support = True + root_walker.need_stacklet_support(self, getfn) + if translator.config.translation.thread: + root_walker.need_thread_support(self, getfn) + + self.layoutbuilder.encode_type_shapes_now() + + annhelper.finish() # at this point, annotate all mix-level helpers + annhelper.backend_optimize() + + self.collect_analyzer = CollectAnalyzer(self.translator) + self.collect_analyzer.analyze_all() + + s_gc = self.translator.annotator.bookkeeper.valueoftype(GCClass) + r_gc = self.translator.rtyper.getrepr(s_gc) + self.c_const_gc = rmodel.inputconst(r_gc, self.gcdata.gc) + s_gc_data = self.translator.annotator.bookkeeper.valueoftype( + gctypelayout.GCData) + r_gc_data = self.translator.rtyper.getrepr(s_gc_data) + self.c_const_gcdata = rmodel.inputconst(r_gc_data, self.gcdata) + self.malloc_zero_filled = GCClass.malloc_zero_filled + + HDR = self.HDR = self.gcdata.gc.gcheaderbuilder.HDR + + size_gc_header = self.gcdata.gc.gcheaderbuilder.size_gc_header + vtableinfo = (HDR, size_gc_header, self.gcdata.gc.typeid_is_in_field) + self.c_vtableinfo = rmodel.inputconst(lltype.Void, vtableinfo) + tig = self.layoutbuilder.type_info_group._as_ptr() + self.c_type_info_group = rmodel.inputconst(lltype.typeOf(tig), tig) + sko = llmemory.sizeof(gcdata.TYPE_INFO) + self.c_vtinfo_skip_offset = rmodel.inputconst(lltype.typeOf(sko), sko) + + + def _declare_functions(self, GCClass, getfn, s_gc, s_typeid16): + from rpython.memory.gc.base import ARRAY_TYPEID_MAP + from rpython.memory.gc import inspector + s_gcref = annmodel.SomePtr(llmemory.GCREF) + gcdata = self.gcdata + translator = self.translator malloc_fixedsize_clear_meth = GCClass.malloc_fixedsize_clear.im_func self.malloc_fixedsize_clear_ptr = getfn( @@ -466,39 +508,6 @@ [annmodel.SomeAddress()], annmodel.s_None) - # thread support - if translator.config.translation.continuation: - root_walker.stacklet_support = True - root_walker.need_stacklet_support(self, getfn) - if translator.config.translation.thread: - root_walker.need_thread_support(self, getfn) - - self.layoutbuilder.encode_type_shapes_now() - - annhelper.finish() # at this point, annotate all mix-level helpers - annhelper.backend_optimize() - - self.collect_analyzer = CollectAnalyzer(self.translator) - self.collect_analyzer.analyze_all() - - s_gc = self.translator.annotator.bookkeeper.valueoftype(GCClass) - r_gc = self.translator.rtyper.getrepr(s_gc) - self.c_const_gc = rmodel.inputconst(r_gc, self.gcdata.gc) - s_gc_data = self.translator.annotator.bookkeeper.valueoftype( - gctypelayout.GCData) - r_gc_data = self.translator.rtyper.getrepr(s_gc_data) - self.c_const_gcdata = rmodel.inputconst(r_gc_data, self.gcdata) - self.malloc_zero_filled = GCClass.malloc_zero_filled - - HDR = self.HDR = self.gcdata.gc.gcheaderbuilder.HDR - - size_gc_header = self.gcdata.gc.gcheaderbuilder.size_gc_header - vtableinfo = (HDR, size_gc_header, self.gcdata.gc.typeid_is_in_field) - self.c_vtableinfo = rmodel.inputconst(lltype.Void, vtableinfo) - tig = self.layoutbuilder.type_info_group._as_ptr() - self.c_type_info_group = rmodel.inputconst(lltype.typeOf(tig), tig) - sko = llmemory.sizeof(gcdata.TYPE_INFO) - self.c_vtinfo_skip_offset = rmodel.inputconst(lltype.typeOf(sko), sko) def consider_constant(self, TYPE, value): self.layoutbuilder.consider_constant(TYPE, value, self.gcdata.gc) diff --git a/rpython/rlib/clibffi.py b/rpython/rlib/clibffi.py --- a/rpython/rlib/clibffi.py +++ b/rpython/rlib/clibffi.py @@ -4,6 +4,7 @@ from rpython.rtyper.tool import rffi_platform from rpython.rtyper.lltypesystem import lltype, rffi +from rpython.rtyper.tool import rffi_platform from rpython.rlib.unroll import unrolling_iterable from rpython.rlib.rarithmetic import intmask, is_emulated_long from rpython.rlib.objectmodel import we_are_translated @@ -15,6 +16,7 @@ from rpython.translator.tool.cbuild import ExternalCompilationInfo from rpython.translator.platform import platform from rpython.conftest import cdir +from platform import machine import py import os import sys @@ -35,6 +37,8 @@ _LITTLE_ENDIAN = sys.byteorder == 'little' _BIG_ENDIAN = sys.byteorder == 'big' +_ARM = rffi_platform.getdefined('__arm__', '') + if _WIN32: from rpython.rlib import rwin32 @@ -154,6 +158,10 @@ if _WIN32 and not _WIN64: FFI_STDCALL = rffi_platform.ConstantInteger('FFI_STDCALL') + if _ARM: + FFI_SYSV = rffi_platform.ConstantInteger('FFI_SYSV') + FFI_VFP = rffi_platform.ConstantInteger('FFI_VFP') + FFI_TYPE_STRUCT = rffi_platform.ConstantInteger('FFI_TYPE_STRUCT') size_t = rffi_platform.SimpleType("size_t", rffi.ULONG) @@ -327,6 +335,9 @@ FFI_DEFAULT_ABI = cConfig.FFI_DEFAULT_ABI if _WIN32 and not _WIN64: FFI_STDCALL = cConfig.FFI_STDCALL +if _ARM: + FFI_SYSV = cConfig.FFI_SYSV + FFI_VFP = cConfig.FFI_VFP FFI_TYPE_STRUCT = cConfig.FFI_TYPE_STRUCT FFI_CIFP = lltype.Ptr(cConfig.ffi_cif) diff --git a/rpython/translator/c/database.py b/rpython/translator/c/database.py --- a/rpython/translator/c/database.py +++ b/rpython/translator/c/database.py @@ -64,9 +64,8 @@ self.instrument_ncounter = 0 - def gettypedefnode(self, T, varlength=1): - if varlength <= 1: - varlength = 1 # it's C after all + def gettypedefnode(self, T, varlength=None): + if varlength is None: key = T else: key = T, varlength @@ -94,7 +93,7 @@ self.pendingsetupnodes.append(node) return node - def gettype(self, T, varlength=1, who_asks=None, argnames=[]): + def gettype(self, T, varlength=None, who_asks=None, argnames=[]): if isinstance(T, Primitive) or T == GCREF: return PrimitiveType[T] elif isinstance(T, Typedef): diff --git a/rpython/translator/c/node.py b/rpython/translator/c/node.py --- a/rpython/translator/c/node.py +++ b/rpython/translator/c/node.py @@ -47,12 +47,12 @@ typetag = 'struct' extra_union_for_varlength = True - def __init__(self, db, STRUCT, varlength=1): + def __init__(self, db, STRUCT, varlength=None): NodeWithDependencies.__init__(self, db) self.STRUCT = STRUCT self.LLTYPE = STRUCT self.varlength = varlength - if varlength == 1: + if varlength is None: basename = STRUCT._name with_number = True else: @@ -93,7 +93,7 @@ self.fields = [] db = self.db STRUCT = self.STRUCT - if self.varlength != 1: + if self.varlength is not None: self.normalizedtypename = db.gettype(STRUCT, who_asks=self) if needs_gcheader(self.STRUCT): HDR = db.gcpolicy.struct_gcheader_definition(self) @@ -120,7 +120,7 @@ rtti = getRuntimeTypeInfo(STRUCT) except ValueError: pass - if self.varlength == 1: + if self.varlength is None: self.db.gcpolicy.struct_setup(self, rtti) return self.gcinfo gcinfo = defaultproperty(computegcinfo) @@ -160,12 +160,14 @@ if typename == PrimitiveType[Void]: line = '/* %s */' % line else: + if is_empty and typename.endswith('[RPY_VARLENGTH]'): + yield '\tRPY_DUMMY_VARLENGTH' is_empty = False yield '\t' + line if is_empty: yield '\t' + 'char _dummy; /* this struct is empty */' yield '};' - if self.varlength != 1: + if self.varlength is not None: assert self.typetag == 'struct' yield 'union %su {' % self.name yield ' struct %s a;' % self.name @@ -182,7 +184,7 @@ def debug_offsets(self): # generate number exprs giving the offset of the elements in the struct - assert self.varlength == 1 + assert self.varlength is None for name in self.fieldnames: FIELD_T = self.c_struct_field_type(name) if FIELD_T is Void: @@ -196,18 +198,25 @@ yield 'offsetof(%s %s, %s)' % (self.typetag, self.name, cname) +def deflength(varlength): + if varlength is None: + return 'RPY_VARLENGTH' + elif varlength == 0: + return 'RPY_LENGTH0' + else: + return varlength class ArrayDefNode(NodeWithDependencies): typetag = 'struct' extra_union_for_varlength = True - def __init__(self, db, ARRAY, varlength=1): + def __init__(self, db, ARRAY, varlength=None): NodeWithDependencies.__init__(self, db) self.ARRAY = ARRAY self.LLTYPE = ARRAY self.gcfields = [] self.varlength = varlength - if varlength == 1: + if varlength is None: basename = 'array' with_number = True else: @@ -226,7 +235,7 @@ db = self.db ARRAY = self.ARRAY self.gcinfo # force it to be computed - if self.varlength != 1: + if self.varlength is not None: self.normalizedtypename = db.gettype(ARRAY, who_asks=self) if needs_gcheader(ARRAY): HDR = db.gcpolicy.array_gcheader_definition(self) @@ -238,7 +247,7 @@ def computegcinfo(self): # let the gcpolicy do its own setup self.gcinfo = None # unless overwritten below - if self.varlength == 1: + if self.varlength is None: self.db.gcpolicy.array_setup(self) return self.gcinfo gcinfo = defaultproperty(computegcinfo) @@ -269,21 +278,22 @@ yield '\t' + cdecl(typename, fname) + ';' if not self.ARRAY._hints.get('nolength', False): yield '\tlong length;' - line = '%s;' % cdecl(self.itemtypename, 'items[%d]'% self.varlength) + line = '%s;' % cdecl(self.itemtypename, + 'items[%s]' % deflength(self.varlength)) if self.ARRAY.OF is Void: # strange line = '/* array of void */' if self.ARRAY._hints.get('nolength', False): line = 'char _dummy; ' + line yield '\t' + line yield '};' - if self.varlength != 1: + if self.varlength is not None: yield 'union %su {' % self.name yield ' struct %s a;' % self.name yield ' %s;' % cdecl(self.normalizedtypename, 'b') yield '};' def visitor_lines(self, prefix, on_item): - assert self.varlength == 1 + assert self.varlength is None ARRAY = self.ARRAY # we need a unique name for this C variable, or at least one that does # not collide with the expression in 'prefix' @@ -310,7 +320,7 @@ def debug_offsets(self): # generate three offsets for debugging inspection - assert self.varlength == 1 + assert self.varlength is None if not self.ARRAY._hints.get('nolength', False): yield 'offsetof(struct %s, length)' % (self.name,) else: @@ -333,7 +343,7 @@ forward_decl = None extra_union_for_varlength = False - def __init__(self, db, ARRAY, varlength=1): + def __init__(self, db, ARRAY, varlength=None): NodeWithDependencies.__init__(self, db) self.ARRAY = ARRAY self.LLTYPE = ARRAY @@ -342,8 +352,8 @@ # There is no such thing as an array of voids: # we use a an array of chars instead; only the pointer can be void*. self.itemtypename = db.gettype(contained_type, who_asks=self) - self.fulltypename = self.itemtypename.replace('@', '(@)[%d]' % - (self.varlength,)) + self.fulltypename = self.itemtypename.replace('@', '(@)[%s]' % + deflength(varlength)) if ARRAY._hints.get("render_as_void"): self.fullptrtypename = 'void *@' else: @@ -493,7 +503,8 @@ Node.__init__(self, db) self.obj = obj self.typename = db.gettype(T) #, who_asks=self) - self.implementationtypename = db.gettype(T, varlength=self.getlength()) + self.implementationtypename = db.gettype( + T, varlength=self.getvarlength()) parent, parentindex = parentlink(obj) if obj in exports.EXPORTS_obj2name: self.name = exports.EXPORTS_obj2name[obj] @@ -559,8 +570,8 @@ def startupcode(self): return [] - def getlength(self): - return 1 + def getvarlength(self): + return None assert not USESLOTS or '__dict__' not in dir(ContainerNode) @@ -578,10 +589,10 @@ for name in T._names: yield getattr(self.obj, name) - def getlength(self): + def getvarlength(self): T = self.getTYPE() if T._arrayfld is None: - return 1 + return None else: array = getattr(self.obj, T._arrayfld) return len(array.items) @@ -696,7 +707,7 @@ def enum_dependencies(self): return self.obj.items - def getlength(self): + def getvarlength(self): return len(self.obj.items) def initializationexpr(self, decoration=''): @@ -765,8 +776,8 @@ for i in range(self.obj.getlength()): yield self.obj.getitem(i) - def getlength(self): - return 1 # not variable-sized! + def getvarlength(self): + return None # not variable-sized! def initializationexpr(self, decoration=''): T = self.getTYPE() diff --git a/rpython/translator/c/src/g_prerequisite.h b/rpython/translator/c/src/g_prerequisite.h --- a/rpython/translator/c/src/g_prerequisite.h +++ b/rpython/translator/c/src/g_prerequisite.h @@ -14,8 +14,14 @@ #ifdef __GNUC__ /* other platforms too, probably */ typedef _Bool bool_t; +# define RPY_VARLENGTH /* nothing: [RPY_VARLENGTH] => [] */ +# define RPY_LENGTH0 0 /* array decl [0] are ok */ +# define RPY_DUMMY_VARLENGTH char _dummy[0]; #else typedef unsigned char bool_t; +# define RPY_VARLENGTH 1 /* [RPY_VARLENGTH] => [1] */ +# define RPY_LENGTH0 1 /* array decl [0] are bad */ +# define RPY_DUMMY_VARLENGTH /* nothing */ #endif diff --git a/rpython/translator/c/src/support.h b/rpython/translator/c/src/support.h --- a/rpython/translator/c/src/support.h +++ b/rpython/translator/c/src/support.h @@ -2,16 +2,6 @@ /************************************************************/ /*** C header subsection: support functions ***/ -/* a temporary(?) workaround for GCC 4.8. See: - http://stackoverflow.com/questions/16016627/ -*/ -#ifdef __GNUC__ -# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) -# pragma GCC optimize("no-aggressive-loop-optimizations") -# endif -#endif - - #define RUNNING_ON_LLINTERP 0 #define OP_JIT_RECORD_KNOWN_CLASS(i, c, r) /* nothing */ diff --git a/rpython/translator/c/test/test_lltyped.py b/rpython/translator/c/test/test_lltyped.py --- a/rpython/translator/c/test/test_lltyped.py +++ b/rpython/translator/c/test/test_lltyped.py @@ -919,3 +919,25 @@ return x fn = self.getcompiled(llf, [int]) assert fn(5) == 42 + + def test_raw_array_field_prebuilt(self): + from rpython.rtyper.lltypesystem import rffi + S = Struct('S', ('array', rffi.CArray(Signed))) + s0 = malloc(S, 0, flavor='raw', immortal=True) + s1 = malloc(S, 1, flavor='raw', immortal=True) + s1.array[0] = 521 + s2 = malloc(S, 2, flavor='raw', immortal=True) + s2.array[0] = 12 + s2.array[1] = 34 + def llf(i): + if i == 0: s = s0 + elif i == 1: s = s1 + else: s = s2 + x = 10 + if i > 0: + x += s.array[i-1] + return x + fn = self.getcompiled(llf, [int]) + assert fn(0) == 10 + assert fn(1) == 10 + 521 + assert fn(2) == 10 + 34 From noreply at buildbot.pypy.org Wed Apr 17 18:22:11 2013 From: noreply at buildbot.pypy.org (arigo) Date: Wed, 17 Apr 2013 18:22:11 +0200 (CEST) Subject: [pypy-commit] benchmarks default: Improve the output in case of error Message-ID: <20130417162211.74AEF1C3151@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r205:4a34e2726d88 Date: 2013-04-17 18:21 +0200 http://bitbucket.org/pypy/benchmarks/changeset/4a34e2726d88/ Log: Improve the output in case of error diff --git a/benchmarks.py b/benchmarks.py --- a/benchmarks.py +++ b/benchmarks.py @@ -159,9 +159,13 @@ out, err = proc.communicate() retcode = proc.poll() if retcode != 0: - print out - print err - raise Exception("translate.py failed") + if out is not None: + print '---------- stdout ----------' + print out + if err is not None: + print '---------- stderr ----------' + print err + raise Exception("translate.py failed, retcode %r" % (retcode,)) lines = err.splitlines() timings = parse_timer(lines) From noreply at buildbot.pypy.org Wed Apr 17 18:27:47 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Wed, 17 Apr 2013 18:27:47 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: added tracing for doesNotUnderstand-calls, padding is done with # instead of ' ' to alleviate backwards search Message-ID: <20130417162747.6B3021C01FD@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r290:ea0276a64497 Date: 2013-04-17 09:27 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/ea0276a64497/ Log: added tracing for doesNotUnderstand-calls, padding is done with # instead of ' ' to alleviate backwards search diff --git a/spyvm/interpreter.py b/spyvm/interpreter.py --- a/spyvm/interpreter.py +++ b/spyvm/interpreter.py @@ -236,7 +236,7 @@ # ___________________________________________________________________________ # Bytecode Implementations: # -# "self" is always a ContextPartShadow instance. +# "self" is always a ContextPartShadow instance. # __extend__ adds new methods to the ContextPartShadow class class __extend__(ContextPartShadow): @@ -389,6 +389,12 @@ raise s_frame = s_method.create_frame(self.space, receiver, [w_message], self) self.pop() + + # ###################################################################### + if interp.trace: + padding = '#' * (interp.max_stack_depth - interp.remaining_stack_depth) + print padding + s_frame.short_str(1) + return interp.stack_frame(s_frame) def _return(self, return_value, interp, s_return_to): @@ -397,7 +403,7 @@ raise ReturnFromTopLevel(return_value) # unfortunately, the assert below is not true for some tests # assert self._stack_ptr == self.tempsize() - + raise Return(return_value, s_return_to) def returnReceiver(self, interp, current_bytecode): @@ -441,7 +447,7 @@ self.push(association.value()) else: assert 0 - + def extendedStoreBytecode(self, interp, current_bytecode): variableType, variableIndex = self.extendedVariableTypeAndIndex() if variableType == 0: @@ -571,7 +577,7 @@ i = self.getbytecode() blockSize = (j << 8) | i #create new instance of BlockClosure - w_closure = space.newClosure(self.w_self(), self.pc(), numArgs, + w_closure = space.newClosure(self.w_self(), self.pc(), numArgs, self.pop_and_return_n(numCopied)) self.push(w_closure) self.jump(blockSize) From noreply at buildbot.pypy.org Wed Apr 17 18:27:48 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Wed, 17 Apr 2013 18:27:48 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: identified error of maximizing/scrolling and took some first steps to alleviate it Message-ID: <20130417162748.D42CD1C01FD@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r291:85602aa57b8f Date: 2013-04-17 17:08 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/85602aa57b8f/ Log: identified error of maximizing/scrolling and took some first steps to alleviate it diff --git a/BitBltSim.19.cs b/BitBltSim.19.cs --- a/BitBltSim.19.cs +++ b/BitBltSim.19.cs @@ -165,23 +165,53 @@ !BitBlt methodsFor: 'simulation' stamp: 'tfel 3/17/2013 16:17'! merge: srcWord with: dstWord - "These are the 16 combination rules." - combinationRule = 0 ifTrue: [^ 0]. - combinationRule = 1 ifTrue: [^ srcWord bitAnd: dstWord]. - combinationRule = 2 ifTrue: [^ srcWord bitAnd: dstWord bitInvert32]. - combinationRule = 3 ifTrue: [^ srcWord]. - combinationRule = 4 ifTrue: [^ srcWord bitInvert32 bitAnd: dstWord]. - combinationRule = 5 ifTrue: [^ dstWord]. - combinationRule = 6 ifTrue: [^ srcWord bitXor: dstWord]. - combinationRule = 7 ifTrue: [^ srcWord bitOr: dstWord]. - combinationRule = 8 ifTrue: [^ srcWord bitInvert32 bitAnd: dstWord bitInvert32]. - combinationRule = 9 ifTrue: [^ srcWord bitInvert32 bitXor: dstWord]. - combinationRule = 10 ifTrue: [^ dstWord bitInvert32]. - combinationRule = 11 ifTrue: [^ srcWord bitOr: dstWord bitInvert32]. - combinationRule = 12 ifTrue: [^ srcWord bitInvert32]. - combinationRule = 13 ifTrue: [^ srcWord bitInvert32 bitOr: dstWord]. - combinationRule = 14 ifTrue: [^ srcWord bitInvert32 bitOr: dstWord bitInvert32]. - combinationRule = 15 ifTrue: [^ dstWord]! ! + + combinationRule < 16 + ifTrue: [ "These are the 16 basic combination rules." + combinationRule = 0 ifTrue: [^ 0]. + combinationRule = 1 ifTrue: [^ srcWord bitAnd: dstWord]. + combinationRule = 2 ifTrue: [^ srcWord bitAnd: dstWord bitInvert32]. + combinationRule = 3 ifTrue: [^ srcWord]. + combinationRule = 4 ifTrue: [^ srcWord bitInvert32 bitAnd: dstWord]. + combinationRule = 5 ifTrue: [^ dstWord]. + combinationRule = 6 ifTrue: [^ srcWord bitXor: dstWord]. + combinationRule = 7 ifTrue: [^ srcWord bitOr: dstWord]. + combinationRule = 8 ifTrue: [^ srcWord bitInvert32 bitAnd: dstWord bitInvert32]. + combinationRule = 9 ifTrue: [^ srcWord bitInvert32 bitXor: dstWord]. + combinationRule = 10 ifTrue: [^ dstWord bitInvert32]. + combinationRule = 11 ifTrue: [^ srcWord bitOr: dstWord bitInvert32]. + combinationRule = 12 ifTrue: [^ srcWord bitInvert32]. + combinationRule = 13 ifTrue: [^ srcWord bitInvert32 bitOr: dstWord]. + combinationRule = 14 ifTrue: [^ srcWord bitInvert32 bitOr: dstWord bitInvert32]. + combinationRule = 15 ifTrue: [^ dstWord].] + ifFalse: [ "These are newer combination rules. (BitBltSimulation class>>#initializeRuleTable)" + combinationRule = 16 ifTrue: [^ dstWord]. "unused - was old paint" + combinationRule = 17 ifTrue: [^ dstWord]. "unused - was old mask" + combinationRule = 18 ifTrue: [^ dstWord]. "addWord" + combinationRule = 19 ifTrue: [^ dstWord]. "subWord" + combinationRule = 20 ifTrue: [^ dstWord]. "rgbAdd" + combinationRule = 21 ifTrue: [^ dstWord]. "rgbSub" + combinationRule = 22 ifTrue: [^ dstWord]. "OLDrgbDiff" + combinationRule = 23 ifTrue: [^ dstWord]. "OLDtallyIntoMap" + combinationRule = 24 ifTrue: [^ dstWord]. "alphaBlend" + combinationRule = 25 ifTrue: [^ dstWord]. "pixPaint" + combinationRule = 26 ifTrue: [^ dstWord]. "pixMask" + combinationRule = 27 ifTrue: [^ dstWord]. "rgbMax" + combinationRule = 28 ifTrue: [^ dstWord]. "rgbMin" + combinationRule = 29 ifTrue: [^ dstWord]. "rgbMinInvert" + combinationRule = 30 ifTrue: [^ dstWord]. "alphaBlendConst" + combinationRule = 31 ifTrue: [^ dstWord]. "alphaPaintConst" + combinationRule = 32 ifTrue: [^ dstWord]. "rgbDiff" + combinationRule = 33 ifTrue: [^ dstWord]. "tallyIntoMap" + combinationRule = 34 ifTrue: [^ dstWord]. "alphaBlendScaled" + combinationRule = 35 ifTrue: [^ dstWord]. "unused here - only used by FXBlt" + combinationRule = 36 ifTrue: [^ dstWord]. "unused here - only used by FXBlt" + combinationRule = 37 ifTrue: [^ dstWord]. "rgbMul" + combinationRule = 38 ifTrue: [^ dstWord]. "pixSwap" + combinationRule = 39 ifTrue: [^ dstWord]. "pixClear" + combinationRule = 40 ifTrue: [^ dstWord]. "fixAlpha" + combinationRule = 41 ifTrue: [^ dstWord]. "rgbComponentAlpha"]. + self error: 'Combination Rule is not supported.'! ! !BitBlt methodsFor: 'simulation' stamp: 'tfel 3/15/2013 14:49'! sanitizeInput diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -562,6 +562,10 @@ if not isinstance(w_rcvr, model.W_PointersObject) or w_rcvr.size() < 15: raise PrimitiveFailedError + # only allow combinationRules 0-15 + if interp.space.unwrap_positive_32bit_int(w_rcvr.fetch(interp.space, 3)) > 41: + raise PrimitiveFailedError + space = interp.space trace = interp.trace interp.trace = False From noreply at buildbot.pypy.org Wed Apr 17 18:27:49 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Wed, 17 Apr 2013 18:27:49 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: merge the different approaches to exiting using a new exception: Exit Message-ID: <20130417162749.EB5291C01FD@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r292:0cff3f71df5a Date: 2013-04-17 17:11 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/0cff3f71df5a/ Log: merge the different approaches to exiting using a new exception: Exit implemented Quit-Primitive (139) diff --git a/spyvm/display.py b/spyvm/display.py --- a/spyvm/display.py +++ b/spyvm/display.py @@ -80,9 +80,8 @@ else: pass # XXX: Todo? elif c_type == RSDL.QUIT: - from spyvm.interpreter import ReturnFromTopLevel - print "Window closed.." - raise SystemExit() + from spyvm.error import Exit + raise Exit("Window closed..") finally: lltype.free(event, flavor='raw') diff --git a/spyvm/error.py b/spyvm/error.py --- a/spyvm/error.py +++ b/spyvm/error.py @@ -24,4 +24,8 @@ self.msg = msg class BlockCannotReturnError(SmalltalkException): - pass \ No newline at end of file + pass + +class Exit(Exception): + def __init__(self, msg): + self.msg = msg diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -325,10 +325,9 @@ @expose_primitive(FAIL) def func(interp, s_frame, argcount): - from spyvm.interpreter import ReturnFromTopLevel + from spyvm.error import Exit if s_frame.w_method()._likely_methodname == 'doesNotUnderstand:': - print 'Probably Debugger called...' - raise ReturnFromTopLevel(interp.space.wrap_string("debugger called")) + raise Exit('Probably Debugger called...') raise PrimitiveFailedError() # ___________________________________________________________________________ @@ -743,10 +742,14 @@ @expose_primitive(QUIT, unwrap_spec=[object]) def func(interp, s_frame, w_rcvr): - raise PrimitiveNotYetWrittenError() + from spyvm.error import Exit + raise Exit('Quit-Primitive called..') @expose_primitive(EXIT_TO_DEBUGGER, unwrap_spec=[object]) def func(interp, s_frame, w_rcvr): + from rpython.rlib import objectmodel + if not objectmodel.we_are_translated(): + import pdb; pdb.set_trace() raise PrimitiveNotYetWrittenError() @expose_primitive(CHANGE_CLASS, unwrap_spec=[object, object], no_result=True) diff --git a/targetimageloadingsmalltalk.py b/targetimageloadingsmalltalk.py --- a/targetimageloadingsmalltalk.py +++ b/targetimageloadingsmalltalk.py @@ -4,7 +4,8 @@ from rpython.rlib.streamio import open_file_as_stream from rpython.rlib import jit -from spyvm import model, interpreter, squeakimage, objspace, wrapper, model +from spyvm import model, interpreter, squeakimage, objspace, wrapper, model, \ + error from spyvm.tool.analyseimage import create_image @@ -15,6 +16,8 @@ w_result = interp.perform(w_object, benchmark) except interpreter.ReturnFromTopLevel, e: w_result = e.object + except error.Exit, e: + print e.msg t2 = time.time() if w_result: if isinstance(w_result, model.W_BytesObject): @@ -30,7 +33,10 @@ w_ctx = ap.suspended_context() assert isinstance(w_ctx, model.W_PointersObject) ap.store_suspended_context(space.w_nil) - interp.interpret_with_w_frame(w_ctx) + try: + interp.interpret_with_w_frame(w_ctx) + except error.Exit, e: + print e.msg return 0 From noreply at buildbot.pypy.org Wed Apr 17 18:27:51 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Wed, 17 Apr 2013 18:27:51 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: updated the doesNotUnderstand tracing code to give more information and halt in case interpretation Message-ID: <20130417162751.11E3F1C01FD@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r293:a9cbe7ad9fdc Date: 2013-04-17 17:12 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/a9cbe7ad9fdc/ Log: updated the doesNotUnderstand tracing code to give more information and halt in case interpretation diff --git a/spyvm/interpreter.py b/spyvm/interpreter.py --- a/spyvm/interpreter.py +++ b/spyvm/interpreter.py @@ -393,7 +393,9 @@ # ###################################################################### if interp.trace: padding = '#' * (interp.max_stack_depth - interp.remaining_stack_depth) - print padding + s_frame.short_str(1) + print '%s%s missing: #%s' % (padding, s_frame.short_str(0), w_selector.as_string()) + if not objectmodel.we_are_translated(): + import pdb; pdb.set_trace() return interp.stack_frame(s_frame) From noreply at buildbot.pypy.org Wed Apr 17 18:27:52 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Wed, 17 Apr 2013 18:27:52 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: fix translation error Message-ID: <20130417162752.1B7531C01FD@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r294:f7ea8305ebe2 Date: 2013-04-17 18:17 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/f7ea8305ebe2/ Log: fix translation error diff --git a/targetimageloadingsmalltalk.py b/targetimageloadingsmalltalk.py --- a/targetimageloadingsmalltalk.py +++ b/targetimageloadingsmalltalk.py @@ -18,6 +18,7 @@ w_result = e.object except error.Exit, e: print e.msg + w_result = None t2 = time.time() if w_result: if isinstance(w_result, model.W_BytesObject): From noreply at buildbot.pypy.org Wed Apr 17 18:27:53 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Wed, 17 Apr 2013 18:27:53 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: added more concrete rule for pixPaint (combinationRule 25) Message-ID: <20130417162753.7DCD71C01FD@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r295:a284054344a3 Date: 2013-04-17 18:26 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/a284054344a3/ Log: added more concrete rule for pixPaint (combinationRule 25) the effect is still of though diff --git a/BitBltSim.19.cs b/BitBltSim.19.cs --- a/BitBltSim.19.cs +++ b/BitBltSim.19.cs @@ -141,7 +141,7 @@ ifTrue: [prevWord _ prevWord bitAnd: simSkewMask. "XXX: Hack to work around out-of-bounds access" - thisWord := (simSourceIndex < 0 or: [simSourceIndex >= simSourceBits size]) + thisWord _ (simSourceIndex < 0 or: [simSourceIndex >= simSourceBits size]) ifTrue: [simSourceBits at: 1] ifFalse: [simSourceBits at: simSourceIndex + 1]. "pick up next word" @@ -194,7 +194,7 @@ combinationRule = 22 ifTrue: [^ dstWord]. "OLDrgbDiff" combinationRule = 23 ifTrue: [^ dstWord]. "OLDtallyIntoMap" combinationRule = 24 ifTrue: [^ dstWord]. "alphaBlend" - combinationRule = 25 ifTrue: [^ dstWord]. "pixPaint" + combinationRule = 25 ifTrue: [^ self pixPaint: srcWord with: dstWord]. combinationRule = 26 ifTrue: [^ dstWord]. "pixMask" combinationRule = 27 ifTrue: [^ dstWord]. "rgbMax" combinationRule = 28 ifTrue: [^ dstWord]. "rgbMin" @@ -213,6 +213,11 @@ combinationRule = 41 ifTrue: [^ dstWord]. "rgbComponentAlpha"]. self error: 'Combination Rule is not supported.'! ! +!BitBlt methodsFor: 'simulation' stamp: 'tfel 1/1/1981 00:00'! +pixPaint: srcWord with: dstWord + srcWord = 0 ifTrue: [^ dstWord]. + ^ srcWord bitOr: (dstWord bitAnd: srcWord bitInvert32)! ! + !BitBlt methodsFor: 'simulation' stamp: 'tfel 3/15/2013 14:49'! sanitizeInput From noreply at buildbot.pypy.org Wed Apr 17 18:27:54 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Wed, 17 Apr 2013 18:27:54 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: added tracing when entering t into image, and deactivating tracing when typing s Message-ID: <20130417162754.74AB81C01FD@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r296:0e904d8d20dc Date: 2013-04-17 18:27 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/0e904d8d20dc/ Log: added tracing when entering t into image, and deactivating tracing when typing s diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -561,18 +561,14 @@ if not isinstance(w_rcvr, model.W_PointersObject) or w_rcvr.size() < 15: raise PrimitiveFailedError - # only allow combinationRules 0-15 + # only allow combinationRules 0-41 if interp.space.unwrap_positive_32bit_int(w_rcvr.fetch(interp.space, 3)) > 41: raise PrimitiveFailedError space = interp.space - trace = interp.trace - interp.trace = False try: s_frame._sendSelfSelector(interp.image.w_simulateCopyBits, 0, interp) - interp.trace = trace except Return: - interp.trace = trace w_dest_form = w_rcvr.fetch(space, 0) if w_dest_form.is_same_object(space.objtable['w_display']): w_bitmap = w_dest_form.fetch(space, 0) @@ -704,6 +700,10 @@ @expose_primitive(KBD_NEXT, unwrap_spec=[object]) def func(interp, s_frame, w_rcvr): code = interp.space.get_display().next_keycode() + if code == ord('t'): + interp.trace = True + elif code == ord('s'): + interp.trace = False if code == 0: return interp.space.w_nil else: From noreply at buildbot.pypy.org Wed Apr 17 18:36:40 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Wed, 17 Apr 2013 18:36:40 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: updated minibluebookdebug.image to include the code of BitBltSim.19.cs Message-ID: <20130417163640.6BDEC1C01FD@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r297:4a7e6857957c Date: 2013-04-17 18:36 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/4a7e6857957c/ Log: updated minibluebookdebug.image to include the code of BitBltSim.19.cs diff --git a/BitBltSim.19.cs b/BitBltSim.19.cs --- a/BitBltSim.19.cs +++ b/BitBltSim.19.cs @@ -146,7 +146,7 @@ ifFalse: [simSourceBits at: simSourceIndex + 1]. "pick up next word" skewWord _ - prevWord bitOr: (thisWord bitAnd: simSkewMask bitInvert32). + prevWord bitOr: (thisWord bitAnd: noSimSkewMask). prevWord _ thisWord. "Change from BB: bitAnd: AllOnes to stay in word bounds" skewWord _ ((skewWord bitShift: simSkew) bitAnd: AllOnes) bitOr: @@ -211,7 +211,7 @@ combinationRule = 39 ifTrue: [^ dstWord]. "pixClear" combinationRule = 40 ifTrue: [^ dstWord]. "fixAlpha" combinationRule = 41 ifTrue: [^ dstWord]. "rgbComponentAlpha"]. - self error: 'Combination Rule is not supported.'! ! + self error: 'The Combination Rule(', combinationRule,') is not supported.'! ! !BitBlt methodsFor: 'simulation' stamp: 'tfel 1/1/1981 00:00'! pixPaint: srcWord with: dstWord diff --git a/images/minibluebookdebug.image b/images/minibluebookdebug.image index 72834c73d01e0d5de097c1c824971bd952d0e6e8..e14767581ade29ce25d0c0fa8bdd3aef9ebc6a51 GIT binary patch [cut] From noreply at buildbot.pypy.org Wed Apr 17 19:20:09 2013 From: noreply at buildbot.pypy.org (arigo) Date: Wed, 17 Apr 2013 19:20:09 +0200 (CEST) Subject: [pypy-commit] pypy default: Rename 'call_malloc_nursery_varsize_small' to '..varsize_frame', to Message-ID: <20130417172009.883D81C3151@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63457:b2f26450c5a6 Date: 2013-04-17 19:10 +0200 http://bitbucket.org/pypy/pypy/changeset/b2f26450c5a6/ Log: Rename 'call_malloc_nursery_varsize_small' to '..varsize_frame', to match more precisely its only usage. Optimize a bit the code generation of this operation. diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -1348,7 +1348,7 @@ ) self._alignment_check() return fcond - emit_op_call_malloc_nursery_varsize_small = emit_op_call_malloc_nursery + emit_op_call_malloc_nursery_varsize_frame = emit_op_call_malloc_nursery def _alignment_check(self): diff --git a/rpython/jit/backend/arm/regalloc.py b/rpython/jit/backend/arm/regalloc.py --- a/rpython/jit/backend/arm/regalloc.py +++ b/rpython/jit/backend/arm/regalloc.py @@ -1014,7 +1014,7 @@ self.possibly_free_var(t) return [imm(size)] - def prepare_op_call_malloc_nursery_varsize_small(self, op, fcond): + def prepare_op_call_malloc_nursery_varsize_frame(self, op, fcond): size_box = op.getarg(0) assert isinstance(size_box, BoxInt) diff --git a/rpython/jit/backend/llsupport/rewrite.py b/rpython/jit/backend/llsupport/rewrite.py --- a/rpython/jit/backend/llsupport/rewrite.py +++ b/rpython/jit/backend/llsupport/rewrite.py @@ -172,7 +172,7 @@ size_box, descr=descrs.jfi_frame_size) self.newops.append(op0) - self.gen_malloc_nursery_varsize_small(size_box, frame) + self.gen_malloc_nursery_varsize_frame(size_box, frame) self.gen_initialize_tid(frame, descrs.arraydescr.tid) length_box = history.BoxInt() op1 = ResOperation(rop.GETFIELD_GC, [history.ConstInt(frame_info)], @@ -320,11 +320,11 @@ self.recent_mallocs[v_result] = None return True - def gen_malloc_nursery_varsize_small(self, sizebox, v_result): - """ Generate CALL_MALLOC_NURSERY_VARSIZE_SMALL + def gen_malloc_nursery_varsize_frame(self, sizebox, v_result): + """ Generate CALL_MALLOC_NURSERY_VARSIZE_FRAME """ self.emitting_an_operation_that_can_collect() - op = ResOperation(rop.CALL_MALLOC_NURSERY_VARSIZE_SMALL, + op = ResOperation(rop.CALL_MALLOC_NURSERY_VARSIZE_FRAME, [sizebox], v_result) diff --git a/rpython/jit/backend/llsupport/test/test_gc_integration.py b/rpython/jit/backend/llsupport/test/test_gc_integration.py --- a/rpython/jit/backend/llsupport/test/test_gc_integration.py +++ b/rpython/jit/backend/llsupport/test/test_gc_integration.py @@ -239,13 +239,13 @@ # slowpath never called assert gc_ll_descr.calls == [] - def test_malloc_nursery_varsize_small(self): + def test_malloc_nursery_varsize_frame(self): self.cpu = self.getcpu(None) ops = ''' [i0, i1, i2] - p0 = call_malloc_nursery_varsize_small(i0) - p1 = call_malloc_nursery_varsize_small(i1) - p2 = call_malloc_nursery_varsize_small(i2) + p0 = call_malloc_nursery_varsize_frame(i0) + p1 = call_malloc_nursery_varsize_frame(i1) + p2 = call_malloc_nursery_varsize_frame(i2) guard_true(i0) [p0, p1, p2] ''' self.interpret(ops, [16, 32, 16]) diff --git a/rpython/jit/backend/llsupport/test/test_rewrite.py b/rpython/jit/backend/llsupport/test/test_rewrite.py --- a/rpython/jit/backend/llsupport/test/test_rewrite.py +++ b/rpython/jit/backend/llsupport/test/test_rewrite.py @@ -764,7 +764,7 @@ """, """ [i0, f0] i1 = getfield_gc(ConstClass(frame_info), descr=jfi_frame_size) - p1 = call_malloc_nursery_varsize_small(i1) + p1 = call_malloc_nursery_varsize_frame(i1) setfield_gc(p1, 0, descr=tiddescr) i2 = getfield_gc(ConstClass(frame_info), descr=jfi_frame_depth) setfield_gc(p1, i2, descr=framelendescr) diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -2366,11 +2366,16 @@ self.mc.overwrite(jmp_adr-1, chr(offset)) self.mc.MOV(heap(nursery_free_adr), edi) - def malloc_cond_varsize_small(self, nursery_free_adr, nursery_top_adr, + def malloc_cond_varsize_frame(self, nursery_free_adr, nursery_top_adr, sizeloc, gcmap): - self.mc.MOV(edi, heap(nursery_free_adr)) - self.mc.MOV(eax, edi) - self.mc.ADD(edi, sizeloc) + if not isinstance(sizeloc, RegLoc) or sizeloc is eax: + self.mc.MOV(edi, sizeloc) + sizeloc = edi + self.mc.MOV(eax, heap(nursery_free_adr)) + if sizeloc is edi: + self.mc.ADD_rr(edi.value, eax.value) + else: + self.mc.LEA_ra(edi.value, (eax.value, sizeloc.value, 0, 0)) self.mc.CMP(edi, heap(nursery_top_adr)) self.mc.J_il8(rx86.Conditions['NA'], 0) # patched later jmp_adr = self.mc.get_relative_pos() @@ -2389,7 +2394,7 @@ assert isinstance(arraydescr, ArrayDescr) self.mc.CMP(lengthloc, imm(maxlength)) - self.mc.J_il8(rx86.Conditions['G'], 0) # patched later + self.mc.J_il8(rx86.Conditions['A'], 0) # patched later jmp_adr0 = self.mc.get_relative_pos() self.mc.MOV(eax, heap(nursery_free_adr)) self.mc.MOV(edi, lengthloc) diff --git a/rpython/jit/backend/x86/regalloc.py b/rpython/jit/backend/x86/regalloc.py --- a/rpython/jit/backend/x86/regalloc.py +++ b/rpython/jit/backend/x86/regalloc.py @@ -837,7 +837,7 @@ # looking at the result self.rm.force_allocate_reg(op.result, selected_reg=eax) # - # We need edx as a temporary, but otherwise don't save any more + # We need edi as a temporary, but otherwise don't save any more # register. See comments in _build_malloc_slowpath(). tmp_box = TempBox() self.rm.force_allocate_reg(tmp_box, selected_reg=edi) @@ -850,22 +850,22 @@ gc_ll_descr.get_nursery_top_addr(), size, gcmap) - def consider_call_malloc_nursery_varsize_small(self, op): + def consider_call_malloc_nursery_varsize_frame(self, op): size_box = op.getarg(0) assert isinstance(size_box, BoxInt) # we cannot have a const here! - # looking at the result + # size_box can be anywhere (including the stack, or eax, or edi) + sizeloc = self.rm.loc(size_box) + self.rm.possibly_free_var(size_box) + # the result will be in eax self.rm.force_allocate_reg(op.result, selected_reg=eax) - # - # We need edx as a temporary, but otherwise don't save any more - # register. See comments in _build_malloc_slowpath(). + # we need edi as a temporary tmp_box = TempBox() self.rm.force_allocate_reg(tmp_box, selected_reg=edi) - sizeloc = self.rm.make_sure_var_in_reg(size_box, [op.result, tmp_box]) gcmap = self.get_gcmap([eax, edi]) # allocate the gcmap *before* self.rm.possibly_free_var(tmp_box) # gc_ll_descr = self.assembler.cpu.gc_ll_descr - self.assembler.malloc_cond_varsize_small( + self.assembler.malloc_cond_varsize_frame( gc_ll_descr.get_nursery_free_addr(), gc_ll_descr.get_nursery_top_addr(), sizeloc, gcmap) diff --git a/rpython/jit/metainterp/executor.py b/rpython/jit/metainterp/executor.py --- a/rpython/jit/metainterp/executor.py +++ b/rpython/jit/metainterp/executor.py @@ -355,7 +355,7 @@ rop.CALL_MALLOC_GC, rop.CALL_MALLOC_NURSERY, rop.CALL_MALLOC_NURSERY_VARSIZE, - rop.CALL_MALLOC_NURSERY_VARSIZE_SMALL, + rop.CALL_MALLOC_NURSERY_VARSIZE_FRAME, rop.LABEL, ): # list of opcodes never executed by pyjitpl continue diff --git a/rpython/jit/metainterp/resoperation.py b/rpython/jit/metainterp/resoperation.py --- a/rpython/jit/metainterp/resoperation.py +++ b/rpython/jit/metainterp/resoperation.py @@ -526,7 +526,7 @@ 'CALL_MALLOC_GC/*d', # like CALL, but NULL => propagate MemoryError 'CALL_MALLOC_NURSERY/1', # nursery malloc, const number of bytes, zeroed 'CALL_MALLOC_NURSERY_VARSIZE/3d', - 'CALL_MALLOC_NURSERY_VARSIZE_SMALL/1', + 'CALL_MALLOC_NURSERY_VARSIZE_FRAME/1', # nursery malloc, non-const number of bytes, zeroed # note that the number of bytes must be well known to be small enough # to fulfill allocating in the nursery rules (and no card markings) From noreply at buildbot.pypy.org Wed Apr 17 19:50:28 2013 From: noreply at buildbot.pypy.org (arigo) Date: Wed, 17 Apr 2013 19:50:28 +0200 (CEST) Subject: [pypy-commit] pypy default: Oups, sorry. Message-ID: <20130417175028.CC9531C034F@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63458:5fc401548386 Date: 2013-04-17 19:50 +0200 http://bitbucket.org/pypy/pypy/changeset/5fc401548386/ Log: Oups, sorry. diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -2368,7 +2368,7 @@ def malloc_cond_varsize_frame(self, nursery_free_adr, nursery_top_adr, sizeloc, gcmap): - if not isinstance(sizeloc, RegLoc) or sizeloc is eax: + if sizeloc is eax: self.mc.MOV(edi, sizeloc) sizeloc = edi self.mc.MOV(eax, heap(nursery_free_adr)) diff --git a/rpython/jit/backend/x86/regalloc.py b/rpython/jit/backend/x86/regalloc.py --- a/rpython/jit/backend/x86/regalloc.py +++ b/rpython/jit/backend/x86/regalloc.py @@ -853,8 +853,9 @@ def consider_call_malloc_nursery_varsize_frame(self, op): size_box = op.getarg(0) assert isinstance(size_box, BoxInt) # we cannot have a const here! - # size_box can be anywhere (including the stack, or eax, or edi) - sizeloc = self.rm.loc(size_box) + # sizeloc must be in a register, but we can free it now + # (we take care explicitly of conflicts with eax or edi) + sizeloc = self.rm.make_sure_var_in_reg(size_box) self.rm.possibly_free_var(size_box) # the result will be in eax self.rm.force_allocate_reg(op.result, selected_reg=eax) From noreply at buildbot.pypy.org Wed Apr 17 20:48:21 2013 From: noreply at buildbot.pypy.org (arigo) Date: Wed, 17 Apr 2013 20:48:21 +0200 (CEST) Subject: [pypy-commit] pypy default: Expand the comments. No actual change in the code. Message-ID: <20130417184821.6C4FB1C01FD@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63459:a1173abdf19e Date: 2013-04-17 20:48 +0200 http://bitbucket.org/pypy/pypy/changeset/a1173abdf19e/ Log: Expand the comments. No actual change in the code. diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -178,7 +178,8 @@ addr = self.cpu.gc_ll_descr.get_malloc_fn_addr('malloc_unicode') else: addr = self.cpu.gc_ll_descr.get_malloc_slowpath_array_addr() - mc.SUB_ri(esp.value, 16 - WORD) + mc.SUB_ri(esp.value, 16 - WORD) # restore 16-byte alignment + # magically, the above is enough on X86_32 to reserve 3 stack places if kind == 'fixed': mc.SUB_rr(edi.value, eax.value) # compute the size we want # the arg is already in edi @@ -191,21 +192,23 @@ mc.MOV_rr(esi.value, ebp.value) elif kind == 'str' or kind == 'unicode': if IS_X86_32: - # 1 for return value, 3 for alignment - mc.MOV_rs(edi.value, WORD * (3 + 1 + 1)) + # stack layout: [---][---][---][ret][gcmap][length]... + mc.MOV_rs(edi.value, WORD * 5) # pick 'length' mc.MOV_sr(0, edi.value) else: + # stack layout: [---][ret][gcmap][length]... mc.MOV_rs(edi.value, WORD * 3) else: if IS_X86_32: - mc.MOV_rs(edi.value, WORD * (3 + 1 + 1)) # itemsize + # stack layout: [--][--][--][ret][gcmap][itemsize][length][tid] + mc.MOV_rs(edi.value, WORD * 5) # pick 'itemsize' mc.MOV_sr(0, edi.value) - mc.MOV_rs(edi.value, WORD * (3 + 3 + 1)) - mc.MOV_sr(WORD, edi.value) # tid - mc.MOV_rs(edi.value, WORD * (3 + 2 + 1)) - mc.MOV_sr(2 * WORD, edi.value) # length + mc.MOV_rs(edi.value, WORD * 7) # pick 'tid' + mc.MOV_sr(WORD, edi.value) + mc.MOV_rs(edi.value, WORD * 6) # pick 'length' + mc.MOV_sr(2 * WORD, edi.value) else: - # offset is 1 extra for call + 1 for SUB above + # stack layout: [---][ret][gcmap][itemsize][length][tid]... mc.MOV_rs(edi.value, WORD * 3) # itemsize mc.MOV_rs(esi.value, WORD * 5) # tid mc.MOV_rs(edx.value, WORD * 4) # length @@ -2425,7 +2428,7 @@ addr = self.malloc_slowpath_unicode self.mc.MOV(RawEspLoc(WORD, INT), lengthloc) # save the gcmap - self.push_gcmap(self.mc, gcmap, mov=True) + self.push_gcmap(self.mc, gcmap, mov=True) # mov into RawEspLoc(0) self.mc.CALL(imm(addr)) offset = self.mc.get_relative_pos() - jmp_adr1 assert 0 < offset <= 127 From noreply at buildbot.pypy.org Wed Apr 17 21:30:26 2013 From: noreply at buildbot.pypy.org (matti) Date: Wed, 17 Apr 2013 21:30:26 +0200 (CEST) Subject: [pypy-commit] buildbot default: limit concurrent builds for windows slaves on virtual machines Message-ID: <20130417193026.173C11C30AF@cobra.cs.uni-duesseldorf.de> Author: matti Branch: Changeset: r787:6ff7e31751c9 Date: 2013-04-17 22:30 +0300 http://bitbucket.org/pypy/buildbot/changeset/6ff7e31751c9/ Log: limit concurrent builds for windows slaves on virtual machines diff --git a/bot2/pypybuildbot/master.py b/bot2/pypybuildbot/master.py --- a/bot2/pypybuildbot/master.py +++ b/bot2/pypybuildbot/master.py @@ -191,7 +191,10 @@ CPYTHON_64 = "cpython-2-benchmark-x86-64" -extra_opts= {'xerxes': {'keepalive_interval': 15}} +extra_opts= {'xerxes': {'keepalive_interval': 15}, + 'aurora': {'max_builds': 1}, + 'salsa': {'max_builds': 1}, + } BuildmasterConfig = { 'slavePortnum': slavePortnum, From noreply at buildbot.pypy.org Wed Apr 17 21:39:30 2013 From: noreply at buildbot.pypy.org (arigo) Date: Wed, 17 Apr 2013 21:39:30 +0200 (CEST) Subject: [pypy-commit] pypy default: Phew. Rewrite carefully to generate less code. I hope it was careful Message-ID: <20130417193930.D0E8E1C01FD@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63460:f61197c64f0c Date: 2013-04-17 21:33 +0200 http://bitbucket.org/pypy/pypy/changeset/f61197c64f0c/ Log: Phew. Rewrite carefully to generate less code. I hope it was careful enough (the tests are happy at least). diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -160,16 +160,26 @@ self._frame_realloc_slowpath = mc.materialize(self.cpu.asmmemmgr, []) def _build_malloc_slowpath(self, kind): - """ While arriving on slowpath, we have a gcpattern on stack, - nursery_head in eax and the size in edi - eax + """ While arriving on slowpath, we have a gcpattern on stack 0. + The arguments are passed in eax and edi, as follows: + + kind == 'fixed': nursery_head in eax and the size in edi - eax. + + kind == 'str/unicode': length of the string to allocate in edi. + + kind == 'var': length to allocate in edi, tid in eax, + and itemsize in the stack 1 (position esp+WORD). + + This function must preserve all registers apart from eax and edi. """ assert kind in ['fixed', 'str', 'unicode', 'var'] mc = codebuf.MachineCodeBlockWrapper() self._push_all_regs_to_frame(mc, [eax, edi], self.cpu.supports_floats) + # store the gc pattern ofs = self.cpu.get_ofs_of_frame_field('jf_gcmap') - # store the gc pattern mc.MOV_rs(ecx.value, WORD) mc.MOV_br(ofs, ecx.value) + # if kind == 'fixed': addr = self.cpu.gc_ll_descr.get_malloc_slowpath_addr() elif kind == 'str': @@ -192,26 +202,22 @@ mc.MOV_rr(esi.value, ebp.value) elif kind == 'str' or kind == 'unicode': if IS_X86_32: - # stack layout: [---][---][---][ret][gcmap][length]... - mc.MOV_rs(edi.value, WORD * 5) # pick 'length' - mc.MOV_sr(0, edi.value) + # stack layout: [---][---][---][ret].. with 3 free stack places + mc.MOV_sr(0, edi.value) # store the length else: - # stack layout: [---][ret][gcmap][length]... - mc.MOV_rs(edi.value, WORD * 3) + pass # length already in edi else: if IS_X86_32: - # stack layout: [--][--][--][ret][gcmap][itemsize][length][tid] - mc.MOV_rs(edi.value, WORD * 5) # pick 'itemsize' - mc.MOV_sr(0, edi.value) - mc.MOV_rs(edi.value, WORD * 7) # pick 'tid' - mc.MOV_sr(WORD, edi.value) - mc.MOV_rs(edi.value, WORD * 6) # pick 'length' - mc.MOV_sr(2 * WORD, edi.value) + # stack layout: [---][---][---][ret][gcmap][itemsize]... + mc.MOV_sr(WORD * 2, edi.value) # store the length + mc.MOV_sr(WORD * 1, eax.value) # store the tid + mc.MOV_rs(edi.value, WORD * 5) # load the itemsize + mc.MOV_sr(WORD * 0, edi.value) # store the itemsize else: - # stack layout: [---][ret][gcmap][itemsize][length][tid]... - mc.MOV_rs(edi.value, WORD * 3) # itemsize - mc.MOV_rs(esi.value, WORD * 5) # tid - mc.MOV_rs(edx.value, WORD * 4) # length + # stack layout: [---][ret][gcmap][itemsize]... + mc.MOV_rr(edx.value, edi.value) # length + mc.MOV_rr(esi.value, eax.value) # tid + mc.MOV_rs(edi.value, WORD * 3) # load the itemsize self.set_extra_stack_depth(mc, 16) mc.CALL(imm(addr)) mc.ADD_ri(esp.value, 16 - WORD) @@ -2396,29 +2402,50 @@ from rpython.jit.backend.llsupport.descr import ArrayDescr assert isinstance(arraydescr, ArrayDescr) - self.mc.CMP(lengthloc, imm(maxlength)) + # lengthloc is the length of the array, which we must not modify! + assert lengthloc is not eax and lengthloc is not edi + if isinstance(lengthloc, RegLoc): + varsizeloc = lengthloc + else: + self.mc.MOV(edi, lengthloc) + varsizeloc = edi + + self.mc.CMP(varsizeloc, imm(maxlength)) self.mc.J_il8(rx86.Conditions['A'], 0) # patched later jmp_adr0 = self.mc.get_relative_pos() + self.mc.MOV(eax, heap(nursery_free_adr)) - self.mc.MOV(edi, lengthloc) + shift = size2shift(itemsize) + if shift < 0: + self.mc.IMUL_rri(edi.value, varsizeloc.value, itemsize) + varsizeloc = edi + shift = 0 + # now varsizeloc is a register != eax. The size of + # the variable part of the array is (varsizeloc << shift) assert arraydescr.basesize >= self.gc_minimal_size_in_nursery - self.mc.IMUL_ri(edi.value, itemsize) - header_size = self.gc_size_of_header - self.mc.ADD_ri(edi.value, arraydescr.basesize + header_size + WORD - 1) - self.mc.AND_ri(edi.value, ~(WORD - 1)) - self.mc.ADD(edi, heap(nursery_free_adr)) + constsize = arraydescr.basesize + self.gc_size_of_header + force_realignment = (itemsize % WORD) != 0 + if force_realignment: + constsize += WORD - 1 + self.mc.LEA_ra(edi.value, (eax.value, varsizeloc.value, shift, + constsize)) + if force_realignment: + self.mc.AND_ri(edi.value, ~(WORD - 1)) + # now edi contains the total size in bytes, rounded up to a multiple + # of WORD, plus nursery_free_adr self.mc.CMP(edi, heap(nursery_top_adr)) - # write down the tid - self.mc.MOV(mem(eax, 0), imm(arraydescr.tid)) self.mc.J_il8(rx86.Conditions['NA'], 0) # patched later jmp_adr1 = self.mc.get_relative_pos() + # offset = self.mc.get_relative_pos() - jmp_adr0 assert 0 < offset <= 127 self.mc.overwrite(jmp_adr0-1, chr(offset)) + # save the gcmap + self.push_gcmap(self.mc, gcmap, mov=True) # mov into RawEspLoc(0) if kind == rewrite.FLAG_ARRAY: self.mc.MOV_si(WORD, itemsize) - self.mc.MOV(RawEspLoc(WORD * 2, INT), lengthloc) - self.mc.MOV_si(WORD * 3, arraydescr.tid) + self.mc.MOV(edi, lengthloc) + self.mc.MOV_ri(eax.value, arraydescr.tid) addr = self.malloc_slowpath_varsize else: if kind == rewrite.FLAG_STR: @@ -2426,14 +2453,22 @@ else: assert kind == rewrite.FLAG_UNICODE addr = self.malloc_slowpath_unicode - self.mc.MOV(RawEspLoc(WORD, INT), lengthloc) - # save the gcmap - self.push_gcmap(self.mc, gcmap, mov=True) # mov into RawEspLoc(0) + self.mc.MOV(edi, lengthloc) self.mc.CALL(imm(addr)) + self.mc.JMP_l8(0) # jump to done, patched later + jmp_location = self.mc.get_relative_pos() + # offset = self.mc.get_relative_pos() - jmp_adr1 assert 0 < offset <= 127 self.mc.overwrite(jmp_adr1-1, chr(offset)) + # write down the tid, but not if it's the result of the CALL + self.mc.MOV(mem(eax, 0), imm(arraydescr.tid)) + # while we're at it, this line is not needed if we've done the CALL self.mc.MOV(heap(nursery_free_adr), edi) + # + offset = self.mc.get_relative_pos() - jmp_location + assert 0 < offset <= 127 + self.mc.overwrite(jmp_location - 1, chr(offset)) def force_token(self, reg): # XXX kill me @@ -2488,5 +2523,13 @@ os.write(2, '[x86/asm] %s\n' % msg) raise NotImplementedError(msg) +def size2shift(size): + "Return a result 0..3 such that (1< Author: mattip Branch: Changeset: r63461:06cef90a9ede Date: 2013-04-17 23:53 +0300 http://bitbucket.org/pypy/pypy/changeset/06cef90a9ede/ Log: document merged branch diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -53,6 +53,11 @@ .. branch: improve-docs-2 Improve documents and straighten out links +.. branch: fast-newarray +Inline the fast path of newarray in the assembler. +Disabled on ARM until we fix issues. + + .. branches we don't care about .. branch: autoreds .. branch: reflex-support From noreply at buildbot.pypy.org Wed Apr 17 22:54:34 2013 From: noreply at buildbot.pypy.org (mattip) Date: Wed, 17 Apr 2013 22:54:34 +0200 (CEST) Subject: [pypy-commit] pypy win32-fixes3: merge default into branch Message-ID: <20130417205434.8A1211C30AF@cobra.cs.uni-duesseldorf.de> Author: mattip Branch: win32-fixes3 Changeset: r63462:7349482407d1 Date: 2013-04-17 23:54 +0300 http://bitbucket.org/pypy/pypy/changeset/7349482407d1/ Log: merge default into branch diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -53,6 +53,11 @@ .. branch: improve-docs-2 Improve documents and straighten out links +.. branch: fast-newarray +Inline the fast path of newarray in the assembler. +Disabled on ARM until we fix issues. + + .. branches we don't care about .. branch: autoreds .. branch: reflex-support @@ -129,3 +134,5 @@ .. branch: release-2.0-beta2 .. branch: unbreak-freebsd + +.. branch: virtualref-virtualizable diff --git a/pypy/module/test_lib_pypy/test_ctypes_config_cache.py b/pypy/module/test_lib_pypy/test_ctypes_config_cache.py --- a/pypy/module/test_lib_pypy/test_ctypes_config_cache.py +++ b/pypy/module/test_lib_pypy/test_ctypes_config_cache.py @@ -33,6 +33,10 @@ def test_syslog(): + try: + import lib_pypy.syslog + except ImportError: + py.test.skip('no syslog on this platform') d = run('syslog.ctc.py', '_syslog_cache.py') assert 'LOG_NOTICE' in d diff --git a/pypy/module/test_lib_pypy/test_os_wait.py b/pypy/module/test_lib_pypy/test_os_wait.py --- a/pypy/module/test_lib_pypy/test_os_wait.py +++ b/pypy/module/test_lib_pypy/test_os_wait.py @@ -1,7 +1,7 @@ # Generates the resource cache -from __future__ import absolute_import -from lib_pypy.ctypes_config_cache import rebuild -rebuild.rebuild_one('resource.ctc.py') +#from __future__ import absolute_import +#from lib_pypy.ctypes_config_cache import rebuild +#rebuild.rebuild_one('resource.ctc.py') import os diff --git a/pypy/module/test_lib_pypy/test_resource.py b/pypy/module/test_lib_pypy/test_resource.py --- a/pypy/module/test_lib_pypy/test_resource.py +++ b/pypy/module/test_lib_pypy/test_resource.py @@ -1,8 +1,13 @@ from __future__ import absolute_import +import py +try: + from lib_pypy import resource +except ImportError: + py.test.skip('no resource module available') + from lib_pypy.ctypes_config_cache import rebuild rebuild.rebuild_one('resource.ctc.py') -from lib_pypy import resource def test_resource(): x = resource.getrusage(resource.RUSAGE_SELF) diff --git a/pypy/module/test_lib_pypy/test_site_extra.py b/pypy/module/test_lib_pypy/test_site_extra.py --- a/pypy/module/test_lib_pypy/test_site_extra.py +++ b/pypy/module/test_lib_pypy/test_site_extra.py @@ -4,7 +4,7 @@ def test_preimported_modules(): lst = ['__builtin__', '_codecs', '_warnings', 'codecs', 'encodings', 'exceptions', 'signal', 'sys', 'zipimport'] - g = os.popen("'%s' -c 'import sys; print sorted(sys.modules)'" % + g = os.popen('"%s" -c "import sys; print sorted(sys.modules)"' % (sys.executable,)) real_data = g.read() g.close() diff --git a/pypy/module/test_lib_pypy/test_syslog.py b/pypy/module/test_lib_pypy/test_syslog.py --- a/pypy/module/test_lib_pypy/test_syslog.py +++ b/pypy/module/test_lib_pypy/test_syslog.py @@ -1,11 +1,15 @@ from __future__ import absolute_import +import py +try: + from lib_pypy import syslog +except ImportError: + py.test.skip('no syslog on this platform') + # XXX very minimal test from lib_pypy.ctypes_config_cache import rebuild rebuild.rebuild_one('syslog.ctc.py') -from lib_pypy import syslog - def test_syslog(): assert hasattr(syslog, 'LOG_ALERT') diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -13,7 +13,7 @@ operations as regalloc_operations, operations_with_guard as regalloc_operations_with_guard) from rpython.jit.backend.llsupport import jitframe -from rpython.jit.backend.llsupport.assembler import DEBUG_COUNTER, debug_bridge +from rpython.jit.backend.llsupport.assembler import DEBUG_COUNTER, debug_bridge, BaseAssembler from rpython.jit.backend.llsupport.asmmemmgr import MachineDataBlockWrapper from rpython.jit.backend.model import CompiledLoopToken from rpython.jit.codewriter.effectinfo import EffectInfo @@ -25,7 +25,7 @@ from rpython.rlib.rarithmetic import r_uint from rpython.rtyper.annlowlevel import llhelper, cast_instance_to_gcref from rpython.rtyper.lltypesystem import lltype, rffi - +from rpython.jit.backend.arm.detect import detect_hardfloat class AssemblerARM(ResOpAssembler): @@ -49,6 +49,10 @@ self.loop_run_counters = [] self.gcrootmap_retaddr_forced = 0 + def setup_once(self): + BaseAssembler.setup_once(self) + self.hf_abi = detect_hardfloat() + def setup(self, looptoken): assert self.memcpy_addr != 0, 'setup_once() not called?' if we_are_translated(): @@ -274,7 +278,7 @@ mc.CMP_ri(r.r0.value, 0) mc.B(self.propagate_exception_path, c=c.EQ) # - self._reload_frame_if_necessary(mc, align_stack=True) + self._reload_frame_if_necessary(mc) self._pop_all_regs_from_jitframe(mc, [r.r0, r.r1], self.cpu.supports_floats) # nursery_free_adr = self.cpu.gc_ll_descr.get_nursery_free_addr() @@ -289,7 +293,7 @@ rawstart = mc.materialize(self.cpu.asmmemmgr, []) self.malloc_slowpath = rawstart - def _reload_frame_if_necessary(self, mc, align_stack=False, can_collect=0): + def _reload_frame_if_necessary(self, mc): gcrootmap = self.cpu.gc_ll_descr.gcrootmap if gcrootmap and gcrootmap.is_shadow_stack: rst = gcrootmap.get_root_stack_top_addr() @@ -301,7 +305,7 @@ # frame never uses card marking, so we enforce this is not # an array self._write_barrier_fastpath(mc, wbdescr, [r.fp], array=False, - is_frame=True)#, align_stack=align_stack) + is_frame=True) def propagate_memoryerror_if_r0_is_null(self): # see ../x86/assembler.py:propagate_memoryerror_if_eax_is_null diff --git a/rpython/jit/backend/arm/detect.py b/rpython/jit/backend/arm/detect.py --- a/rpython/jit/backend/arm/detect.py +++ b/rpython/jit/backend/arm/detect.py @@ -1,5 +1,5 @@ from rpython.translator.tool.cbuild import ExternalCompilationInfo -from rpython.rtyper.lltypesystem import lltype, rffi +from rpython.rlib.clibffi import FFI_DEFAULT_ABI, FFI_SYSV, FFI_VFP from rpython.rtyper.tool import rffi_platform from rpython.translator.platform import CompilationError @@ -14,10 +14,7 @@ """]) def detect_hardfloat(): - # http://gcc.gnu.org/ml/gcc-patches/2010-10/msg02419.html - if rffi_platform.getdefined('__ARM_PCS_VFP', ''): - return rffi_platform.getconstantinteger('__ARM_PCS_VFP', '') - return False + return FFI_DEFAULT_ABI == FFI_VFP def detect_float(): """Check for hardware float support diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -3,7 +3,6 @@ from rpython.jit.backend.arm import registers as r from rpython.jit.backend.arm import shift from rpython.jit.backend.arm.arch import WORD, DOUBLE_WORD, JITFRAME_FIXED_SIZE - from rpython.jit.backend.arm.helper.assembler import (gen_emit_op_by_helper_call, gen_emit_op_unary_cmp, gen_emit_guard_unary_cmp, @@ -351,10 +350,11 @@ return cond def _emit_call(self, adr, arglocs, fcond=c.AL, resloc=None, - result_info=(-1, -1), - can_collect=1, - reload_frame=False): - if self.cpu.hf_abi: + result_info=(-1, -1), + # whether to worry about a CALL that can collect; this + # is always true except in call_release_gil + can_collect=True): + if self.hf_abi: stack_args, adr = self._setup_call_hf(adr, arglocs, fcond, resloc, result_info) else: @@ -362,6 +362,9 @@ resloc, result_info) if can_collect: + # we push *now* the gcmap, describing the status of GC registers + # after the rearrangements done just above, ignoring the return + # value eax, if necessary noregs = self.cpu.gc_ll_descr.is_shadow_stack() gcmap = self._regalloc.get_gcmap([r.r0], noregs=noregs) self.push_gcmap(self.mc, gcmap, store=True) @@ -379,17 +382,15 @@ # ensure the result is wellformed and stored in the correct location if resloc is not None: - if resloc.is_vfp_reg() and not self.cpu.hf_abi: + if resloc.is_vfp_reg() and not self.hf_abi: # move result to the allocated register self.mov_to_vfp_loc(r.r0, r.r1, resloc) elif resloc.is_reg() and result_info != (-1, -1): self._ensure_result_bit_extension(resloc, result_info[0], result_info[1]) if can_collect: - self._reload_frame_if_necessary(self.mc, can_collect=can_collect) + self._reload_frame_if_necessary(self.mc) self.pop_gcmap(self.mc) - elif reload_frame: - self._reload_frame_if_necessary(self.mc) return fcond def _restore_sp(self, stack_args, fcond): @@ -1260,6 +1261,7 @@ def emit_guard_call_release_gil(self, op, guard_op, arglocs, regalloc, fcond): + self._store_force_index(guard_op) # first, close the stack in the sense of the asmgcc GC root tracker gcrootmap = self.cpu.gc_ll_descr.gcrootmap numargs = op.numargs() @@ -1268,24 +1270,27 @@ resloc = arglocs[0] if gcrootmap: - noregs = self.cpu.gc_ll_descr.is_shadow_stack() - assert noregs - gcmap = self._regalloc.get_gcmap([r.r0], noregs=noregs) + # we put the gcmap now into the frame before releasing the GIL, + # and pop it below after reacquiring the GIL. The assumption + # is that this gcmap describes correctly the situation at any + # point in-between: all values containing GC pointers should + # be safely saved out of registers by now, and will not be + # manipulated by any of the following CALLs. + gcmap = self._regalloc.get_gcmap(noregs=True) self.push_gcmap(self.mc, gcmap, store=True) self.call_release_gil(gcrootmap, arglocs, regalloc, fcond) # do the call - self._store_force_index(guard_op) - # descr = op.getdescr() size = descr.get_result_size() signed = descr.is_result_signed() # self._emit_call(adr, callargs, fcond, resloc, (size, signed), - can_collect=0) + can_collect=False) # then reopen the stack if gcrootmap: self.call_reacquire_gil(gcrootmap, resloc, regalloc, fcond) + self.pop_gcmap(self.mc) # remove the gcmap saved above self._emit_guard_may_force(guard_op, arglocs[numargs+1:], numargs) return fcond @@ -1314,7 +1319,7 @@ # call the reopenstack() function (also reacquiring the GIL) with saved_registers(self.mc, regs_to_save, vfp_regs_to_save): self._emit_call(imm(self.reacqgil_addr), [], fcond, - can_collect=False, reload_frame=True) + can_collect=False) def _store_force_index(self, guard_op): faildescr = guard_op.getdescr() @@ -1343,7 +1348,7 @@ ) self._alignment_check() return fcond - emit_op_call_malloc_nursery_varsize_small = emit_op_call_malloc_nursery + emit_op_call_malloc_nursery_varsize_frame = emit_op_call_malloc_nursery def _alignment_check(self): diff --git a/rpython/jit/backend/arm/regalloc.py b/rpython/jit/backend/arm/regalloc.py --- a/rpython/jit/backend/arm/regalloc.py +++ b/rpython/jit/backend/arm/regalloc.py @@ -1014,7 +1014,7 @@ self.possibly_free_var(t) return [imm(size)] - def prepare_op_call_malloc_nursery_varsize_small(self, op, fcond): + def prepare_op_call_malloc_nursery_varsize_frame(self, op, fcond): size_box = op.getarg(0) assert isinstance(size_box, BoxInt) diff --git a/rpython/jit/backend/arm/runner.py b/rpython/jit/backend/arm/runner.py --- a/rpython/jit/backend/arm/runner.py +++ b/rpython/jit/backend/arm/runner.py @@ -6,6 +6,7 @@ from rpython.jit.backend.llsupport.llmodel import AbstractLLCPU from rpython.rlib.jit_hooks import LOOP_RUN_CONTAINER from rpython.rtyper.lltypesystem import lltype, llmemory +from rpython.jit.backend.arm.detect import detect_hardfloat jitframe.STATICSIZE = JITFRAME_FIXED_SIZE @@ -16,7 +17,7 @@ supports_floats = True supports_longlong = False # XXX requires an implementation of # read_timestamp that works in user mode - supports_singlefloats = True + supports_singlefloats = not detect_hardfloat() from rpython.jit.backend.arm.arch import JITFRAME_FIXED_SIZE all_reg_indexes = range(len(all_regs)) @@ -112,22 +113,10 @@ class CPU_ARM(AbstractARMCPU): - """ARM v7 uses softfp ABI, requires vfp""" + """ARM v7""" backend_name = "armv7" - -class CPU_ARMHF(AbstractARMCPU): - """ARM v7 uses hardfp ABI, requires vfp""" - hf_abi = True - backend_name = "armv7hf" - supports_floats = True - supports_singlefloats = False - - -class CPU_ARMv6HF(AbstractARMCPU): +class CPU_ARMv6(AbstractARMCPU): """ ARM v6, uses hardfp ABI, requires vfp""" - hf_abi = True arch_version = 6 - backend_name = "armv6hf" - supports_floats = True - supports_singlefloats = False + backend_name = "armv6" diff --git a/rpython/jit/backend/arm/test/conftest.py b/rpython/jit/backend/arm/test/conftest.py --- a/rpython/jit/backend/arm/test/conftest.py +++ b/rpython/jit/backend/arm/test/conftest.py @@ -16,6 +16,7 @@ dest="run_translation_tests", help="run tests that translate code") -def pytest_runtest_setup(item): +def pytest_collect_directory(path, parent): if not cpu.startswith('arm'): py.test.skip("ARM(v7) tests skipped: cpu is %r" % (cpu,)) +pytest_collect_file = pytest_collect_directory diff --git a/rpython/jit/backend/detect_cpu.py b/rpython/jit/backend/detect_cpu.py --- a/rpython/jit/backend/detect_cpu.py +++ b/rpython/jit/backend/detect_cpu.py @@ -61,8 +61,6 @@ model = 'x86-without-sse2' if model.startswith('arm'): from rpython.jit.backend.arm.detect import detect_hardfloat, detect_float - if detect_hardfloat(): - model += 'hf' assert detect_float(), 'the JIT-compiler requires a vfp unit' return model @@ -77,12 +75,10 @@ return "rpython.jit.backend.x86.runner", "CPU_X86_64" elif backend_name == 'cli': return "rpython.jit.backend.cli.runner", "CliCPU" - elif backend_name == 'armv6hf': - return "rpython.jit.backend.arm.runner", "CPU_ARMv6HF" - elif backend_name == 'armv7': + elif backend_name.startswith('armv6'): + return "rpython.jit.backend.arm.runner", "CPU_ARMv6" + elif backend_name.startswith('armv7'): return "rpython.jit.backend.arm.runner", "CPU_ARM" - elif backend_name == 'armv7hf': - return "rpython.jit.backend.arm.runner", "CPU_ARMHF" else: raise ProcessorAutodetectError, ( "we have no JIT backend for this cpu: '%s'" % backend_name) diff --git a/rpython/jit/backend/llsupport/assembler.py b/rpython/jit/backend/llsupport/assembler.py --- a/rpython/jit/backend/llsupport/assembler.py +++ b/rpython/jit/backend/llsupport/assembler.py @@ -70,6 +70,14 @@ # the address of the function called by 'new' gc_ll_descr = self.cpu.gc_ll_descr gc_ll_descr.initialize() + if hasattr(gc_ll_descr, 'minimal_size_in_nursery'): + self.gc_minimal_size_in_nursery = gc_ll_descr.minimal_size_in_nursery + else: + self.gc_minimal_size_in_nursery = 0 + if hasattr(gc_ll_descr, 'gcheaderbuilder'): + self.gc_size_of_header = gc_ll_descr.gcheaderbuilder.size_gc_header + else: + self.gc_size_of_header = WORD # for tests self.memcpy_addr = self.cpu.cast_ptr_to_int(memcpy_fn) self._build_failure_recovery(False, withfloats=False) self._build_failure_recovery(True, withfloats=False) @@ -85,7 +93,20 @@ self._build_wb_slowpath(True, withfloats=True) self._build_propagate_exception_path() if gc_ll_descr.get_malloc_slowpath_addr is not None: - self._build_malloc_slowpath() + # generate few slowpaths for various cases + self.malloc_slowpath = self._build_malloc_slowpath(kind='fixed') + self.malloc_slowpath_varsize = self._build_malloc_slowpath( + kind='var') + if hasattr(gc_ll_descr, 'malloc_str'): + self.malloc_slowpath_str = self._build_malloc_slowpath(kind='str') + else: + self.malloc_slowpath_str = None + if hasattr(gc_ll_descr, 'malloc_unicode'): + self.malloc_slowpath_unicode = self._build_malloc_slowpath( + kind='unicode') + else: + self.malloc_slowpath_unicode = None + self._build_stack_check_slowpath() if gc_ll_descr.gcrootmap: self._build_release_gil(gc_ll_descr.gcrootmap) diff --git a/rpython/jit/backend/llsupport/gc.py b/rpython/jit/backend/llsupport/gc.py --- a/rpython/jit/backend/llsupport/gc.py +++ b/rpython/jit/backend/llsupport/gc.py @@ -415,6 +415,7 @@ return llop1.do_malloc_fixedsize_clear(llmemory.GCREF, type_id, size, False, False, False) + self.generate_function('malloc_nursery', malloc_nursery_slowpath, [lltype.Signed]) @@ -567,6 +568,9 @@ def get_malloc_slowpath_addr(self): return self.get_malloc_fn_addr('malloc_nursery') + def get_malloc_slowpath_array_addr(self): + return self.get_malloc_fn_addr('malloc_array') + # ____________________________________________________________ def get_ll_description(gcdescr, translator=None, rtyper=None): diff --git a/rpython/jit/backend/llsupport/llmodel.py b/rpython/jit/backend/llsupport/llmodel.py --- a/rpython/jit/backend/llsupport/llmodel.py +++ b/rpython/jit/backend/llsupport/llmodel.py @@ -21,6 +21,8 @@ class AbstractLLCPU(AbstractCPU): from rpython.jit.metainterp.typesystem import llhelper as ts + can_inline_varsize_malloc = False + def __init__(self, rtyper, stats, opts, translate_support_code=False, gcdescr=None): assert type(opts) is not bool @@ -171,9 +173,9 @@ def pos_exc_value(): addr = llop.get_exc_value_addr(llmemory.Address) return heaptracker.adr2int(addr) - + from rpython.rlib import rstack - + STACK_CHECK_SLOWPATH = lltype.Ptr(lltype.FuncType([lltype.Signed], lltype.Void)) def insert_stack_check(): diff --git a/rpython/jit/backend/llsupport/rewrite.py b/rpython/jit/backend/llsupport/rewrite.py --- a/rpython/jit/backend/llsupport/rewrite.py +++ b/rpython/jit/backend/llsupport/rewrite.py @@ -8,19 +8,29 @@ from rpython.jit.backend.llsupport.descr import SizeDescr, ArrayDescr from rpython.jit.metainterp.history import JitCellToken +FLAG_ARRAY = 0 +FLAG_STR = 1 +FLAG_UNICODE = 2 + class GcRewriterAssembler(object): - # This class performs the following rewrites on the list of operations: - # - # - Remove the DEBUG_MERGE_POINTs. - # - # - Turn all NEW_xxx to either a CALL_MALLOC_GC, or a CALL_MALLOC_NURSERY - # followed by SETFIELDs in order to initialize their GC fields. The - # two advantages of CALL_MALLOC_NURSERY is that it inlines the common - # path, and we need only one such operation to allocate several blocks - # of memory at once. - # - # - Add COND_CALLs to the write barrier before SETFIELD_GC and - # SETARRAYITEM_GC operations. + """ This class performs the following rewrites on the list of operations: + + - Remove the DEBUG_MERGE_POINTs. + + - Turn all NEW_xxx to either a CALL_MALLOC_GC, or a CALL_MALLOC_NURSERY + followed by SETFIELDs in order to initialize their GC fields. The + two advantages of CALL_MALLOC_NURSERY is that it inlines the common + path, and we need only one such operation to allocate several blocks + of memory at once. + + - Add COND_CALLs to the write barrier before SETFIELD_GC and + SETARRAYITEM_GC operations. + + recent_mallocs contains a dictionary of variable -> None. If a variable + is in the dictionary, next setfields can be called without a write barrier, + because the variable got allocated after the last potentially collecting + resop + """ _previous_size = -1 _op_malloc_nursery = None @@ -32,7 +42,7 @@ self.cpu = cpu self.newops = [] self.known_lengths = {} - self.recent_mallocs = {} # set of variables + self.recent_mallocs = {} def rewrite(self, operations): # we can only remember one malloc since the next malloc can possibly @@ -92,9 +102,11 @@ assert isinstance(descr, ArrayDescr) self.handle_new_array(descr, op) elif opnum == rop.NEWSTR: - self.handle_new_array(self.gc_ll_descr.str_descr, op) + self.handle_new_array(self.gc_ll_descr.str_descr, op, + kind=FLAG_STR) elif opnum == rop.NEWUNICODE: - self.handle_new_array(self.gc_ll_descr.unicode_descr, op) + self.handle_new_array(self.gc_ll_descr.unicode_descr, op, + kind=FLAG_UNICODE) else: raise NotImplementedError(op.getopname()) @@ -106,7 +118,7 @@ else: self.gen_malloc_fixedsize(size, descr.tid, op.result) - def handle_new_array(self, arraydescr, op): + def handle_new_array(self, arraydescr, op, kind=FLAG_ARRAY): v_length = op.getarg(0) total_size = -1 if isinstance(v_length, ConstInt): @@ -119,6 +131,14 @@ pass # total_size is still -1 elif arraydescr.itemsize == 0: total_size = arraydescr.basesize + elif (self.gc_ll_descr.can_use_nursery_malloc(1) and + self.gen_malloc_nursery_varsize(arraydescr.itemsize, + v_length, op.result, arraydescr, kind=kind)): + # note that we cannot initialize tid here, because the array + # might end up being allocated by malloc_external or some + # stuff that initializes GC header fields differently + self.gen_initialize_len(op.result, v_length, arraydescr.lendescr) + return if (total_size >= 0 and self.gen_malloc_nursery(total_size, op.result)): self.gen_initialize_tid(op.result, arraydescr.tid) @@ -152,7 +172,7 @@ size_box, descr=descrs.jfi_frame_size) self.newops.append(op0) - self.gen_malloc_nursery_varsize(size_box, frame, is_small=True) + self.gen_malloc_nursery_varsize_frame(size_box, frame) self.gen_initialize_tid(frame, descrs.arraydescr.tid) length_box = history.BoxInt() op1 = ResOperation(rop.GETFIELD_GC, [history.ConstInt(frame_info)], @@ -281,12 +301,30 @@ self._gen_call_malloc_gc([ConstInt(addr), v_num_elem], v_result, self.gc_ll_descr.malloc_unicode_descr) - def gen_malloc_nursery_varsize(self, sizebox, v_result, is_small=False): - """ Generate CALL_MALLOC_NURSERY_VARSIZE_SMALL + def gen_malloc_nursery_varsize(self, itemsize, v_length, v_result, + arraydescr, kind=FLAG_ARRAY): + """ itemsize is an int, v_length and v_result are boxes """ - assert is_small + if not self.cpu.can_inline_varsize_malloc: + return False # temporary, kill when ARM supports it + gc_descr = self.gc_ll_descr + if (kind == FLAG_ARRAY and + (arraydescr.basesize != gc_descr.standard_array_basesize or + arraydescr.lendescr.offset != gc_descr.standard_array_length_ofs)): + return False self.emitting_an_operation_that_can_collect() - op = ResOperation(rop.CALL_MALLOC_NURSERY_VARSIZE_SMALL, + op = ResOperation(rop.CALL_MALLOC_NURSERY_VARSIZE, + [ConstInt(kind), ConstInt(itemsize), v_length], + v_result, descr=arraydescr) + self.newops.append(op) + self.recent_mallocs[v_result] = None + return True + + def gen_malloc_nursery_varsize_frame(self, sizebox, v_result): + """ Generate CALL_MALLOC_NURSERY_VARSIZE_FRAME + """ + self.emitting_an_operation_that_can_collect() + op = ResOperation(rop.CALL_MALLOC_NURSERY_VARSIZE_FRAME, [sizebox], v_result) diff --git a/rpython/jit/backend/llsupport/test/test_gc_integration.py b/rpython/jit/backend/llsupport/test/test_gc_integration.py --- a/rpython/jit/backend/llsupport/test/test_gc_integration.py +++ b/rpython/jit/backend/llsupport/test/test_gc_integration.py @@ -29,11 +29,11 @@ return r[r.find('1'):] class TestRegallocGcIntegration(BaseTestRegalloc): - + cpu = CPU(None, None) cpu.gc_ll_descr = GcLLDescr_boehm(None, None, None) cpu.setup_once() - + S = lltype.GcForwardReference() S.become(lltype.GcStruct('S', ('field', lltype.Ptr(S)), ('int', lltype.Signed))) @@ -145,6 +145,7 @@ gcrootmap = None passes_frame = True write_barrier_descr = None + max_size_of_young_obj = 50 def __init__(self, callback): GcLLDescription.__init__(self, None) @@ -172,6 +173,20 @@ [lltype.Signed, jitframe.JITFRAMEPTR], lltype.Signed) + def malloc_array(itemsize, tid, num_elem): + self.calls.append((itemsize, tid, num_elem)) + return 13 + + self.malloc_slowpath_array_fnptr = llhelper_args(malloc_array, + [lltype.Signed] * 3, + lltype.Signed) + + def malloc_str(size): + self.calls.append(('str', size)) + return 13 + self.generate_function('malloc_str', malloc_str, [lltype.Signed], + lltype.Signed) + def get_nursery_free_addr(self): return rffi.cast(lltype.Signed, self.addrs) @@ -181,6 +196,9 @@ def get_malloc_slowpath_addr(self): return self.get_malloc_fn_addr('malloc_nursery') + def get_malloc_slowpath_array_addr(self): + return self.malloc_slowpath_array_fnptr + def check_nothing_in_nursery(self): # CALL_MALLOC_NURSERY should not write anything in the nursery for i in range(64): @@ -221,15 +239,15 @@ # slowpath never called assert gc_ll_descr.calls == [] - def test_malloc_nursery_varsize_small(self): + def test_malloc_nursery_varsize_frame(self): self.cpu = self.getcpu(None) ops = ''' [i0, i1, i2] - p0 = call_malloc_nursery_varsize_small(i0) - p1 = call_malloc_nursery_varsize_small(i1) - p2 = call_malloc_nursery_varsize_small(i2) + p0 = call_malloc_nursery_varsize_frame(i0) + p1 = call_malloc_nursery_varsize_frame(i1) + p2 = call_malloc_nursery_varsize_frame(i2) guard_true(i0) [p0, p1, p2] - ''' + ''' self.interpret(ops, [16, 32, 16]) # check the returned pointers gc_ll_descr = self.cpu.gc_ll_descr @@ -244,6 +262,56 @@ # slowpath never called assert gc_ll_descr.calls == [] + def test_malloc_nursery_varsize(self): + self.cpu = self.getcpu(None) + A = lltype.GcArray(lltype.Signed) + arraydescr = self.cpu.arraydescrof(A) + arraydescr.tid = 15 + ops = ''' + [i0, i1, i2] + p0 = call_malloc_nursery_varsize(0, 8, i0, descr=arraydescr) + p1 = call_malloc_nursery_varsize(0, 5, i1, descr=arraydescr) + guard_false(i0) [p0, p1] + ''' + self.interpret(ops, [1, 2, 3], + namespace={'arraydescr': arraydescr}) + # check the returned pointers + gc_ll_descr = self.cpu.gc_ll_descr + nurs_adr = rffi.cast(lltype.Signed, gc_ll_descr.nursery) + ref = lambda n: self.cpu.get_ref_value(self.deadframe, n) + assert rffi.cast(lltype.Signed, ref(0)) == nurs_adr + 0 + assert rffi.cast(lltype.Signed, ref(1)) == nurs_adr + 2*WORD + 8*1 + # check the nursery content and state + assert gc_ll_descr.nursery[0] == chr(15) + assert gc_ll_descr.nursery[2 * WORD + 8] == chr(15) + assert gc_ll_descr.addrs[0] == nurs_adr + (((4 * WORD + 8*1 + 5*2) + (WORD - 1)) & ~(WORD - 1)) + # slowpath never called + assert gc_ll_descr.calls == [] + + def test_malloc_nursery_varsize_slowpath(self): + self.cpu = self.getcpu(None) + ops = """ + [i0, i1, i2] + p0 = call_malloc_nursery_varsize(0, 8, i0, descr=arraydescr) + p1 = call_malloc_nursery_varsize(0, 5, i1, descr=arraydescr) + p3 = call_malloc_nursery_varsize(0, 5, i2, descr=arraydescr) + # overflow + p4 = call_malloc_nursery_varsize(0, 5, i2, descr=arraydescr) + # we didn't collect, so still overflow + p5 = call_malloc_nursery_varsize(1, 5, i2, descr=strdescr) + guard_false(i0) [p0, p1, p3, p4] + """ + A = lltype.GcArray(lltype.Signed) + arraydescr = self.cpu.arraydescrof(A) + arraydescr.tid = 15 + self.interpret(ops, [10, 3, 3], + namespace={'arraydescr': arraydescr, + 'strdescr': arraydescr}) + # check the returned pointers + gc_ll_descr = self.cpu.gc_ll_descr + assert gc_ll_descr.calls == [(8, 15, 10), (5, 15, 3), ('str', 3)] + # one fit, one was too large, one was not fitting + def test_malloc_slowpath(self): def check(frame): expected_size = 1 @@ -294,7 +362,7 @@ s = bin(x[0]).count('1') + bin(x[1]).count('1') assert s == 16 # all but two registers + some stuff on stack - + self.cpu = self.getcpu(check) S1 = lltype.GcStruct('S1') S2 = lltype.GcStruct('S2', ('s0', lltype.Ptr(S1)), @@ -360,7 +428,7 @@ class MockShadowStackRootMap(object): is_shadow_stack = True - + def __init__(self): TP = rffi.CArray(lltype.Signed) self.stack = lltype.malloc(TP, 10, flavor='raw') @@ -369,7 +437,7 @@ self.stack_addr[0] = rffi.cast(lltype.Signed, self.stack) def __del__(self): - lltype.free(self.stack_addr, flavor='raw') + lltype.free(self.stack_addr, flavor='raw') lltype.free(self.stack, flavor='raw') def register_asm_addr(self, start, mark): @@ -381,7 +449,7 @@ class WriteBarrierDescr(AbstractDescr): jit_wb_cards_set = 0 jit_wb_if_flag_singlebyte = 1 - + def __init__(self, gc_ll_descr): def write_barrier(frame): gc_ll_descr.write_barrier_on_frame_called = frame @@ -442,6 +510,15 @@ self.malloc_slowpath_fnptr = llhelper_args(malloc_slowpath, [lltype.Signed], lltype.Signed) + + def malloc_array(itemsize, tid, num_elem): + import pdb + pdb.set_trace() + + self.malloc_slowpath_array_fnptr = llhelper_args(malloc_array, + [lltype.Signed] * 3, + lltype.Signed) + self.all_nurseries = [] def init_nursery(self, nursery_size=None): @@ -497,6 +574,9 @@ def get_malloc_slowpath_addr(self): return self.malloc_slowpath_fnptr + def get_malloc_slowpath_array_addr(self): + return self.malloc_slowpath_array_fnptr + def get_nursery_free_addr(self): return self.nursery_addr @@ -507,7 +587,7 @@ for nursery in self.all_nurseries: lltype.free(nursery, flavor='raw', track_allocation=False) lltype.free(self.nursery_ptrs, flavor='raw') - + def unpack_gcmap(frame): res = [] val = 0 @@ -543,10 +623,10 @@ def test_shadowstack_call(self): cpu = self.cpu cpu.gc_ll_descr.init_nursery(100) - cpu.setup_once() + cpu.setup_once() S = self.S frames = [] - + def check(i): assert cpu.gc_ll_descr.gcrootmap.stack[0] == i frame = rffi.cast(JITFRAMEPTR, i) @@ -720,7 +800,7 @@ def test_call_may_force_gcmap(self): cpu = self.cpu - + def f(frame, arg, x): assert not arg assert frame.jf_gcmap[0] & 31 == 0 @@ -748,7 +828,7 @@ pdying = getarrayitem_gc(p0, 0, descr=arraydescr) px = call_may_force(ConstClass(fptr), pf, pdying, i0, descr=calldescr) guard_not_forced(descr=faildescr) [p1, p2, p3, px] - finish(px, descr=finishdescr) + finish(px, descr=finaldescr) """, namespace={'fptr': fptr, 'calldescr': calldescr, 'arraydescr': cpu.arraydescrof(A), 'faildescr': BasicFailDescr(1), @@ -760,12 +840,12 @@ cpu.compile_loop(loop.inputargs, loop.operations, token) frame = lltype.cast_opaque_ptr(JITFRAMEPTR, cpu.execute_token(token, 1, a)) - + assert getmap(frame).count('1') == 4 def test_call_gcmap_no_guard(self): cpu = self.cpu - + def f(frame, arg, x): assert not arg assert frame.jf_gcmap[0] & 31 == 0 @@ -792,7 +872,7 @@ pdying = getarrayitem_gc(p0, 0, descr=arraydescr) px = call(ConstClass(fptr), pf, pdying, i0, descr=calldescr) guard_false(i0, descr=faildescr) [p1, p2, p3, px] - finish(px, descr=finishdescr) + finish(px, descr=finaldescr) """, namespace={'fptr': fptr, 'calldescr': calldescr, 'arraydescr': cpu.arraydescrof(A), 'faildescr': BasicFailDescr(1), diff --git a/rpython/jit/backend/llsupport/test/test_regalloc_integration.py b/rpython/jit/backend/llsupport/test/test_regalloc_integration.py --- a/rpython/jit/backend/llsupport/test/test_regalloc_integration.py +++ b/rpython/jit/backend/llsupport/test/test_regalloc_integration.py @@ -93,8 +93,8 @@ type_system=self.type_system, boxkinds=boxkinds) - def interpret(self, ops, args, run=True): - loop = self.parse(ops) + def interpret(self, ops, args, run=True, namespace=None): + loop = self.parse(ops, namespace=namespace) self.loop = loop looptoken = JitCellToken() self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken) diff --git a/rpython/jit/backend/llsupport/test/test_rewrite.py b/rpython/jit/backend/llsupport/test/test_rewrite.py --- a/rpython/jit/backend/llsupport/test/test_rewrite.py +++ b/rpython/jit/backend/llsupport/test/test_rewrite.py @@ -34,7 +34,7 @@ ('t', lltype.Signed)) tdescr = get_size_descr(self.gc_ll_descr, T) tdescr.tid = 5678 - get_field_descr(self.gc_ll_descr, T, 'z') + tzdescr = get_field_descr(self.gc_ll_descr, T, 'z') # A = lltype.GcArray(lltype.Signed) adescr = get_array_descr(self.gc_ll_descr, A) @@ -85,6 +85,7 @@ signedframedescr = self.cpu.signedframedescr floatframedescr = self.cpu.floatframedescr casmdescr.compiled_loop_token = clt + tzdescr = None # noone cares # namespace.update(locals()) # @@ -107,7 +108,9 @@ class BaseFakeCPU(object): JITFRAME_FIXED_SIZE = 0 - + + can_inline_varsize_malloc = True + def __init__(self): self.tracker = FakeTracker() self._cache = {} @@ -121,7 +124,7 @@ def unpack_arraydescr_size(self, d): return 0, d.itemsize, 0 - + def arraydescrof(self, ARRAY): try: return self._cache[ARRAY] @@ -129,7 +132,7 @@ r = ArrayDescr(1, 2, FieldDescr('len', 0, 0, 0), 0) self._cache[ARRAY] = r return r - + def fielddescrof(self, STRUCT, fname): key = (STRUCT, fname) try: @@ -407,12 +410,23 @@ jump(i0) """, """ [i0] - p0 = call_malloc_gc(ConstClass(malloc_array), 1, \ - %(bdescr.tid)d, i0, \ - descr=malloc_array_descr) + p0 = call_malloc_nursery_varsize(0, 1, i0, descr=bdescr) + setfield_gc(p0, i0, descr=blendescr) jump(i0) """) + def test_rewrite_new_string(self): + self.check_rewrite(""" + [i0] + p0 = newstr(i0) + jump(i0) + """, """ + [i0] + p0 = call_malloc_nursery_varsize(1, 1, i0, descr=strdescr) + setfield_gc(p0, i0, descr=strlendescr) + jump(i0) + """) + def test_rewrite_assembler_nonstandard_array(self): # a non-standard array is a bit hard to get; e.g. GcArray(Float) # is like that on Win32, but not on Linux. Build one manually... @@ -533,10 +547,12 @@ p1 = int_add(p0, %(strdescr.basesize + 16 * strdescr.itemsize)d) setfield_gc(p1, %(unicodedescr.tid)d, descr=tiddescr) setfield_gc(p1, 10, descr=unicodelendescr) - p2 = call_malloc_gc(ConstClass(malloc_unicode), i2, \ - descr=malloc_unicode_descr) - p3 = call_malloc_gc(ConstClass(malloc_str), i2, \ - descr=malloc_str_descr) + p2 = call_malloc_nursery_varsize(2, 4, i2, \ + descr=unicodedescr) + setfield_gc(p2, i2, descr=unicodelendescr) + p3 = call_malloc_nursery_varsize(1, 1, i2, \ + descr=strdescr) + setfield_gc(p3, i2, descr=strlendescr) jump() """) @@ -716,8 +732,9 @@ [i0] p0 = call_malloc_nursery(%(tdescr.size)d) setfield_gc(p0, 5678, descr=tiddescr) - p1 = call_malloc_gc(ConstClass(malloc_str), i0, \ - descr=malloc_str_descr) + p1 = call_malloc_nursery_varsize(1, 1, i0, \ + descr=strdescr) + setfield_gc(p1, i0, descr=strlendescr) cond_call_gc_wb(p0, p1, descr=wbdescr) setfield_raw(p0, p1, descr=tzdescr) jump() @@ -747,7 +764,7 @@ """, """ [i0, f0] i1 = getfield_gc(ConstClass(frame_info), descr=jfi_frame_size) - p1 = call_malloc_nursery_varsize_small(i1) + p1 = call_malloc_nursery_varsize_frame(i1) setfield_gc(p1, 0, descr=tiddescr) i2 = getfield_gc(ConstClass(frame_info), descr=jfi_frame_depth) setfield_gc(p1, i2, descr=framelendescr) diff --git a/rpython/jit/backend/test/runner_test.py b/rpython/jit/backend/test/runner_test.py --- a/rpython/jit/backend/test/runner_test.py +++ b/rpython/jit/backend/test/runner_test.py @@ -2833,7 +2833,7 @@ def test_assembler_call_propagate_exc(self): from rpython.jit.backend.llsupport.llmodel import AbstractLLCPU - + if not isinstance(self.cpu, AbstractLLCPU): py.test.skip("llgraph can't fake exceptions well enough, give up") @@ -3477,10 +3477,10 @@ ops = """ [i0] i1 = int_force_ge_zero(i0) # but forced to be in a register - finish(i1, descr=1) + finish(i1, descr=descr) """ + descr = BasicFinalDescr() loop = parse(ops, self.cpu, namespace=locals()) - descr = loop.operations[-1].getdescr() looptoken = JitCellToken() self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken) for inp, outp in [(2,2), (-3, 0)]: @@ -3493,21 +3493,20 @@ py.test.skip("pointless test on non-asm") from rpython.jit.backend.tool.viewcode import machine_code_dump import ctypes + targettoken = TargetToken() ops = """ [i2] i0 = same_as(i2) # but forced to be in a register - label(i0, descr=1) + label(i0, descr=targettoken) i1 = int_add(i0, i0) - guard_true(i1, descr=faildesr) [i1] - jump(i1, descr=1) + guard_true(i1, descr=faildescr) [i1] + jump(i1, descr=targettoken) """ faildescr = BasicFailDescr(2) loop = parse(ops, self.cpu, namespace=locals()) - faildescr = loop.operations[-2].getdescr() - jumpdescr = loop.operations[-1].getdescr() bridge_ops = """ [i0] - jump(i0, descr=jumpdescr) + jump(i0, descr=targettoken) """ bridge = parse(bridge_ops, self.cpu, namespace=locals()) looptoken = JitCellToken() diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -1,7 +1,7 @@ import sys import os -from rpython.jit.backend.llsupport import symbolic, jitframe +from rpython.jit.backend.llsupport import symbolic, jitframe, rewrite from rpython.jit.backend.llsupport.assembler import (GuardToken, BaseAssembler, DEBUG_COUNTER, debug_bridge) from rpython.jit.backend.llsupport.asmmemmgr import MachineDataBlockWrapper @@ -60,6 +60,7 @@ self.float_const_neg_addr = 0 self.float_const_abs_addr = 0 self.malloc_slowpath = 0 + self.malloc_slowpath_varsize = 0 self.wb_slowpath = [0, 0, 0, 0, 0] self.setup_failure_recovery() self.datablockwrapper = None @@ -158,27 +159,65 @@ mc.RET() self._frame_realloc_slowpath = mc.materialize(self.cpu.asmmemmgr, []) - def _build_malloc_slowpath(self): - """ While arriving on slowpath, we have a gcpattern on stack, - nursery_head in eax and the size in edi - eax + def _build_malloc_slowpath(self, kind): + """ While arriving on slowpath, we have a gcpattern on stack 0. + The arguments are passed in eax and edi, as follows: + + kind == 'fixed': nursery_head in eax and the size in edi - eax. + + kind == 'str/unicode': length of the string to allocate in edi. + + kind == 'var': length to allocate in edi, tid in eax, + and itemsize in the stack 1 (position esp+WORD). + + This function must preserve all registers apart from eax and edi. """ + assert kind in ['fixed', 'str', 'unicode', 'var'] mc = codebuf.MachineCodeBlockWrapper() self._push_all_regs_to_frame(mc, [eax, edi], self.cpu.supports_floats) + # store the gc pattern ofs = self.cpu.get_ofs_of_frame_field('jf_gcmap') - # store the gc pattern mc.MOV_rs(ecx.value, WORD) mc.MOV_br(ofs, ecx.value) - addr = self.cpu.gc_ll_descr.get_malloc_slowpath_addr() - mc.SUB_rr(edi.value, eax.value) # compute the size we want - # the arg is already in edi - mc.SUB_ri(esp.value, 16 - WORD) - if IS_X86_32: - mc.MOV_sr(0, edi.value) - if hasattr(self.cpu.gc_ll_descr, 'passes_frame'): - mc.MOV_sr(WORD, ebp.value) - elif hasattr(self.cpu.gc_ll_descr, 'passes_frame'): - # for tests only - mc.MOV_rr(esi.value, ebp.value) + # + if kind == 'fixed': + addr = self.cpu.gc_ll_descr.get_malloc_slowpath_addr() + elif kind == 'str': + addr = self.cpu.gc_ll_descr.get_malloc_fn_addr('malloc_str') + elif kind == 'unicode': + addr = self.cpu.gc_ll_descr.get_malloc_fn_addr('malloc_unicode') + else: + addr = self.cpu.gc_ll_descr.get_malloc_slowpath_array_addr() + mc.SUB_ri(esp.value, 16 - WORD) # restore 16-byte alignment + # magically, the above is enough on X86_32 to reserve 3 stack places + if kind == 'fixed': + mc.SUB_rr(edi.value, eax.value) # compute the size we want + # the arg is already in edi + if IS_X86_32: + mc.MOV_sr(0, edi.value) + if hasattr(self.cpu.gc_ll_descr, 'passes_frame'): + mc.MOV_sr(WORD, ebp.value) + elif hasattr(self.cpu.gc_ll_descr, 'passes_frame'): + # for tests only + mc.MOV_rr(esi.value, ebp.value) + elif kind == 'str' or kind == 'unicode': + if IS_X86_32: + # stack layout: [---][---][---][ret].. with 3 free stack places + mc.MOV_sr(0, edi.value) # store the length + else: + pass # length already in edi + else: + if IS_X86_32: + # stack layout: [---][---][---][ret][gcmap][itemsize]... + mc.MOV_sr(WORD * 2, edi.value) # store the length + mc.MOV_sr(WORD * 1, eax.value) # store the tid + mc.MOV_rs(edi.value, WORD * 5) # load the itemsize + mc.MOV_sr(WORD * 0, edi.value) # store the itemsize + else: + # stack layout: [---][ret][gcmap][itemsize]... + mc.MOV_rr(edx.value, edi.value) # length + mc.MOV_rr(esi.value, eax.value) # tid + mc.MOV_rs(edi.value, WORD * 3) # load the itemsize self.set_extra_stack_depth(mc, 16) mc.CALL(imm(addr)) mc.ADD_ri(esp.value, 16 - WORD) @@ -205,7 +244,7 @@ mc.JMP(imm(self.propagate_exception_path)) # rawstart = mc.materialize(self.cpu.asmmemmgr, []) - self.malloc_slowpath = rawstart + return rawstart def _build_propagate_exception_path(self): if not self.cpu.propagate_exception_descr: @@ -2336,11 +2375,16 @@ self.mc.overwrite(jmp_adr-1, chr(offset)) self.mc.MOV(heap(nursery_free_adr), edi) - def malloc_cond_varsize_small(self, nursery_free_adr, nursery_top_adr, + def malloc_cond_varsize_frame(self, nursery_free_adr, nursery_top_adr, sizeloc, gcmap): - self.mc.MOV(edi, heap(nursery_free_adr)) - self.mc.MOV(eax, edi) - self.mc.ADD(edi, sizeloc) + if sizeloc is eax: + self.mc.MOV(edi, sizeloc) + sizeloc = edi + self.mc.MOV(eax, heap(nursery_free_adr)) + if sizeloc is edi: + self.mc.ADD_rr(edi.value, eax.value) + else: + self.mc.LEA_ra(edi.value, (eax.value, sizeloc.value, 0, 0)) self.mc.CMP(edi, heap(nursery_top_adr)) self.mc.J_il8(rx86.Conditions['NA'], 0) # patched later jmp_adr = self.mc.get_relative_pos() @@ -2352,6 +2396,80 @@ self.mc.overwrite(jmp_adr-1, chr(offset)) self.mc.MOV(heap(nursery_free_adr), edi) + def malloc_cond_varsize(self, kind, nursery_free_adr, nursery_top_adr, + lengthloc, itemsize, maxlength, gcmap, + arraydescr): + from rpython.jit.backend.llsupport.descr import ArrayDescr + assert isinstance(arraydescr, ArrayDescr) + + # lengthloc is the length of the array, which we must not modify! + assert lengthloc is not eax and lengthloc is not edi + if isinstance(lengthloc, RegLoc): + varsizeloc = lengthloc + else: + self.mc.MOV(edi, lengthloc) + varsizeloc = edi + + self.mc.CMP(varsizeloc, imm(maxlength)) + self.mc.J_il8(rx86.Conditions['A'], 0) # patched later + jmp_adr0 = self.mc.get_relative_pos() + + self.mc.MOV(eax, heap(nursery_free_adr)) + shift = size2shift(itemsize) + if shift < 0: + self.mc.IMUL_rri(edi.value, varsizeloc.value, itemsize) + varsizeloc = edi + shift = 0 + # now varsizeloc is a register != eax. The size of + # the variable part of the array is (varsizeloc << shift) + assert arraydescr.basesize >= self.gc_minimal_size_in_nursery + constsize = arraydescr.basesize + self.gc_size_of_header + force_realignment = (itemsize % WORD) != 0 + if force_realignment: + constsize += WORD - 1 + self.mc.LEA_ra(edi.value, (eax.value, varsizeloc.value, shift, + constsize)) + if force_realignment: + self.mc.AND_ri(edi.value, ~(WORD - 1)) + # now edi contains the total size in bytes, rounded up to a multiple + # of WORD, plus nursery_free_adr + self.mc.CMP(edi, heap(nursery_top_adr)) + self.mc.J_il8(rx86.Conditions['NA'], 0) # patched later + jmp_adr1 = self.mc.get_relative_pos() + # + offset = self.mc.get_relative_pos() - jmp_adr0 + assert 0 < offset <= 127 + self.mc.overwrite(jmp_adr0-1, chr(offset)) + # save the gcmap + self.push_gcmap(self.mc, gcmap, mov=True) # mov into RawEspLoc(0) + if kind == rewrite.FLAG_ARRAY: + self.mc.MOV_si(WORD, itemsize) + self.mc.MOV(edi, lengthloc) + self.mc.MOV_ri(eax.value, arraydescr.tid) + addr = self.malloc_slowpath_varsize + else: + if kind == rewrite.FLAG_STR: + addr = self.malloc_slowpath_str + else: + assert kind == rewrite.FLAG_UNICODE + addr = self.malloc_slowpath_unicode + self.mc.MOV(edi, lengthloc) + self.mc.CALL(imm(addr)) + self.mc.JMP_l8(0) # jump to done, patched later + jmp_location = self.mc.get_relative_pos() + # + offset = self.mc.get_relative_pos() - jmp_adr1 + assert 0 < offset <= 127 + self.mc.overwrite(jmp_adr1-1, chr(offset)) + # write down the tid, but not if it's the result of the CALL + self.mc.MOV(mem(eax, 0), imm(arraydescr.tid)) + # while we're at it, this line is not needed if we've done the CALL + self.mc.MOV(heap(nursery_free_adr), edi) + # + offset = self.mc.get_relative_pos() - jmp_location + assert 0 < offset <= 127 + self.mc.overwrite(jmp_location - 1, chr(offset)) + def force_token(self, reg): # XXX kill me assert isinstance(reg, RegLoc) @@ -2405,5 +2523,13 @@ os.write(2, '[x86/asm] %s\n' % msg) raise NotImplementedError(msg) +def size2shift(size): + "Return a result 0..3 such that (1< propagate MemoryError 'CALL_MALLOC_NURSERY/1', # nursery malloc, const number of bytes, zeroed - 'CALL_MALLOC_NURSERY_VARSIZE_SMALL/1', + 'CALL_MALLOC_NURSERY_VARSIZE/3d', + 'CALL_MALLOC_NURSERY_VARSIZE_FRAME/1', # nursery malloc, non-const number of bytes, zeroed # note that the number of bytes must be well known to be small enough # to fulfill allocating in the nursery rules (and no card markings) diff --git a/rpython/jit/metainterp/test/test_logger.py b/rpython/jit/metainterp/test/test_logger.py --- a/rpython/jit/metainterp/test/test_logger.py +++ b/rpython/jit/metainterp/test/test_logger.py @@ -93,7 +93,7 @@ [p0] setfield_gc(p0, 3, descr=somedescr) ''' - Descr() + somedescr = Descr() self.reparse(inp, namespace=locals()) def test_guard(self): diff --git a/rpython/jit/tool/oparser.py b/rpython/jit/tool/oparser.py --- a/rpython/jit/tool/oparser.py +++ b/rpython/jit/tool/oparser.py @@ -106,6 +106,8 @@ tt = self.model.TargetToken(token) self._consts[poss_descr] = tt return tt + else: + raise def box_for_var(self, elem): try: diff --git a/rpython/memory/gctransform/framework.py b/rpython/memory/gctransform/framework.py --- a/rpython/memory/gctransform/framework.py +++ b/rpython/memory/gctransform/framework.py @@ -129,8 +129,6 @@ def __init__(self, translator): from rpython.memory.gc.base import choose_gc_from_config - from rpython.memory.gc.base import ARRAY_TYPEID_MAP - from rpython.memory.gc import inspector super(BaseFrameworkGCTransformer, self).__init__(translator, inline=True) @@ -232,7 +230,51 @@ classdef = bk.getuniqueclassdef(GCClass) s_gc = annmodel.SomeInstance(classdef) + + self._declare_functions(GCClass, getfn, s_gc, s_typeid16) + + # thread support + if translator.config.translation.continuation: + root_walker.stacklet_support = True + root_walker.need_stacklet_support(self, getfn) + if translator.config.translation.thread: + root_walker.need_thread_support(self, getfn) + + self.layoutbuilder.encode_type_shapes_now() + + annhelper.finish() # at this point, annotate all mix-level helpers + annhelper.backend_optimize() + + self.collect_analyzer = CollectAnalyzer(self.translator) + self.collect_analyzer.analyze_all() + + s_gc = self.translator.annotator.bookkeeper.valueoftype(GCClass) + r_gc = self.translator.rtyper.getrepr(s_gc) + self.c_const_gc = rmodel.inputconst(r_gc, self.gcdata.gc) + s_gc_data = self.translator.annotator.bookkeeper.valueoftype( + gctypelayout.GCData) + r_gc_data = self.translator.rtyper.getrepr(s_gc_data) + self.c_const_gcdata = rmodel.inputconst(r_gc_data, self.gcdata) + self.malloc_zero_filled = GCClass.malloc_zero_filled + + HDR = self.HDR = self.gcdata.gc.gcheaderbuilder.HDR + + size_gc_header = self.gcdata.gc.gcheaderbuilder.size_gc_header + vtableinfo = (HDR, size_gc_header, self.gcdata.gc.typeid_is_in_field) + self.c_vtableinfo = rmodel.inputconst(lltype.Void, vtableinfo) + tig = self.layoutbuilder.type_info_group._as_ptr() + self.c_type_info_group = rmodel.inputconst(lltype.typeOf(tig), tig) + sko = llmemory.sizeof(gcdata.TYPE_INFO) + self.c_vtinfo_skip_offset = rmodel.inputconst(lltype.typeOf(sko), sko) + + + def _declare_functions(self, GCClass, getfn, s_gc, s_typeid16): + from rpython.memory.gc.base import ARRAY_TYPEID_MAP + from rpython.memory.gc import inspector + s_gcref = annmodel.SomePtr(llmemory.GCREF) + gcdata = self.gcdata + translator = self.translator malloc_fixedsize_clear_meth = GCClass.malloc_fixedsize_clear.im_func self.malloc_fixedsize_clear_ptr = getfn( @@ -466,39 +508,6 @@ [annmodel.SomeAddress()], annmodel.s_None) - # thread support - if translator.config.translation.continuation: - root_walker.stacklet_support = True - root_walker.need_stacklet_support(self, getfn) - if translator.config.translation.thread: - root_walker.need_thread_support(self, getfn) - - self.layoutbuilder.encode_type_shapes_now() - - annhelper.finish() # at this point, annotate all mix-level helpers - annhelper.backend_optimize() - - self.collect_analyzer = CollectAnalyzer(self.translator) - self.collect_analyzer.analyze_all() - - s_gc = self.translator.annotator.bookkeeper.valueoftype(GCClass) - r_gc = self.translator.rtyper.getrepr(s_gc) - self.c_const_gc = rmodel.inputconst(r_gc, self.gcdata.gc) - s_gc_data = self.translator.annotator.bookkeeper.valueoftype( - gctypelayout.GCData) - r_gc_data = self.translator.rtyper.getrepr(s_gc_data) - self.c_const_gcdata = rmodel.inputconst(r_gc_data, self.gcdata) - self.malloc_zero_filled = GCClass.malloc_zero_filled - - HDR = self.HDR = self.gcdata.gc.gcheaderbuilder.HDR - - size_gc_header = self.gcdata.gc.gcheaderbuilder.size_gc_header - vtableinfo = (HDR, size_gc_header, self.gcdata.gc.typeid_is_in_field) - self.c_vtableinfo = rmodel.inputconst(lltype.Void, vtableinfo) - tig = self.layoutbuilder.type_info_group._as_ptr() - self.c_type_info_group = rmodel.inputconst(lltype.typeOf(tig), tig) - sko = llmemory.sizeof(gcdata.TYPE_INFO) - self.c_vtinfo_skip_offset = rmodel.inputconst(lltype.typeOf(sko), sko) def consider_constant(self, TYPE, value): self.layoutbuilder.consider_constant(TYPE, value, self.gcdata.gc) diff --git a/rpython/rlib/clibffi.py b/rpython/rlib/clibffi.py --- a/rpython/rlib/clibffi.py +++ b/rpython/rlib/clibffi.py @@ -4,6 +4,7 @@ from rpython.rtyper.tool import rffi_platform from rpython.rtyper.lltypesystem import lltype, rffi +from rpython.rtyper.tool import rffi_platform from rpython.rlib.unroll import unrolling_iterable from rpython.rlib.rarithmetic import intmask, is_emulated_long from rpython.rlib.objectmodel import we_are_translated @@ -15,6 +16,7 @@ from rpython.translator.tool.cbuild import ExternalCompilationInfo from rpython.translator.platform import platform from rpython.conftest import cdir +from platform import machine import py import os import sys @@ -35,6 +37,8 @@ _LITTLE_ENDIAN = sys.byteorder == 'little' _BIG_ENDIAN = sys.byteorder == 'big' +_ARM = rffi_platform.getdefined('__arm__', '') + if _WIN32: from rpython.rlib import rwin32 @@ -154,6 +158,10 @@ if _WIN32 and not _WIN64: FFI_STDCALL = rffi_platform.ConstantInteger('FFI_STDCALL') + if _ARM: + FFI_SYSV = rffi_platform.ConstantInteger('FFI_SYSV') + FFI_VFP = rffi_platform.ConstantInteger('FFI_VFP') + FFI_TYPE_STRUCT = rffi_platform.ConstantInteger('FFI_TYPE_STRUCT') size_t = rffi_platform.SimpleType("size_t", rffi.ULONG) @@ -327,6 +335,9 @@ FFI_DEFAULT_ABI = cConfig.FFI_DEFAULT_ABI if _WIN32 and not _WIN64: FFI_STDCALL = cConfig.FFI_STDCALL +if _ARM: + FFI_SYSV = cConfig.FFI_SYSV + FFI_VFP = cConfig.FFI_VFP FFI_TYPE_STRUCT = cConfig.FFI_TYPE_STRUCT FFI_CIFP = lltype.Ptr(cConfig.ffi_cif) diff --git a/rpython/tool/logparser.py b/rpython/tool/logparser.py --- a/rpython/tool/logparser.py +++ b/rpython/tool/logparser.py @@ -70,7 +70,11 @@ time = int(int(match.group(1), 16)) time_decrase = time_decrase or time < lasttime lasttime = time - record(match.group(2), time=int(match.group(1), 16)) + try: + record(match.group(2), time=int(match.group(1), 16)) + except: + print "Line", i + raise if verbose: sys.stderr.write('loaded\n') if performance_log and time_decrase: diff --git a/rpython/translator/c/database.py b/rpython/translator/c/database.py --- a/rpython/translator/c/database.py +++ b/rpython/translator/c/database.py @@ -64,9 +64,8 @@ self.instrument_ncounter = 0 - def gettypedefnode(self, T, varlength=1): - if varlength <= 1: - varlength = 1 # it's C after all + def gettypedefnode(self, T, varlength=None): + if varlength is None: key = T else: key = T, varlength @@ -94,7 +93,7 @@ self.pendingsetupnodes.append(node) return node - def gettype(self, T, varlength=1, who_asks=None, argnames=[]): + def gettype(self, T, varlength=None, who_asks=None, argnames=[]): if isinstance(T, Primitive) or T == GCREF: return PrimitiveType[T] elif isinstance(T, Typedef): diff --git a/rpython/translator/c/node.py b/rpython/translator/c/node.py --- a/rpython/translator/c/node.py +++ b/rpython/translator/c/node.py @@ -47,12 +47,12 @@ typetag = 'struct' extra_union_for_varlength = True - def __init__(self, db, STRUCT, varlength=1): + def __init__(self, db, STRUCT, varlength=None): NodeWithDependencies.__init__(self, db) self.STRUCT = STRUCT self.LLTYPE = STRUCT self.varlength = varlength - if varlength == 1: + if varlength is None: basename = STRUCT._name with_number = True else: @@ -93,7 +93,7 @@ self.fields = [] db = self.db STRUCT = self.STRUCT - if self.varlength != 1: + if self.varlength is not None: self.normalizedtypename = db.gettype(STRUCT, who_asks=self) if needs_gcheader(self.STRUCT): HDR = db.gcpolicy.struct_gcheader_definition(self) @@ -120,7 +120,7 @@ rtti = getRuntimeTypeInfo(STRUCT) except ValueError: pass - if self.varlength == 1: + if self.varlength is None: self.db.gcpolicy.struct_setup(self, rtti) return self.gcinfo gcinfo = defaultproperty(computegcinfo) @@ -160,12 +160,14 @@ if typename == PrimitiveType[Void]: line = '/* %s */' % line else: + if is_empty and typename.endswith('[RPY_VARLENGTH]'): + yield '\tRPY_DUMMY_VARLENGTH' is_empty = False yield '\t' + line if is_empty: yield '\t' + 'char _dummy; /* this struct is empty */' yield '};' - if self.varlength != 1: + if self.varlength is not None: assert self.typetag == 'struct' yield 'union %su {' % self.name yield ' struct %s a;' % self.name @@ -182,7 +184,7 @@ def debug_offsets(self): # generate number exprs giving the offset of the elements in the struct - assert self.varlength == 1 + assert self.varlength is None for name in self.fieldnames: FIELD_T = self.c_struct_field_type(name) if FIELD_T is Void: @@ -196,18 +198,25 @@ yield 'offsetof(%s %s, %s)' % (self.typetag, self.name, cname) +def deflength(varlength): + if varlength is None: + return 'RPY_VARLENGTH' + elif varlength == 0: + return 'RPY_LENGTH0' + else: + return varlength class ArrayDefNode(NodeWithDependencies): typetag = 'struct' extra_union_for_varlength = True - def __init__(self, db, ARRAY, varlength=1): + def __init__(self, db, ARRAY, varlength=None): NodeWithDependencies.__init__(self, db) self.ARRAY = ARRAY self.LLTYPE = ARRAY self.gcfields = [] self.varlength = varlength - if varlength == 1: + if varlength is None: basename = 'array' with_number = True else: @@ -226,7 +235,7 @@ db = self.db ARRAY = self.ARRAY self.gcinfo # force it to be computed - if self.varlength != 1: + if self.varlength is not None: self.normalizedtypename = db.gettype(ARRAY, who_asks=self) if needs_gcheader(ARRAY): HDR = db.gcpolicy.array_gcheader_definition(self) @@ -238,7 +247,7 @@ def computegcinfo(self): # let the gcpolicy do its own setup self.gcinfo = None # unless overwritten below - if self.varlength == 1: + if self.varlength is None: self.db.gcpolicy.array_setup(self) return self.gcinfo gcinfo = defaultproperty(computegcinfo) @@ -269,21 +278,22 @@ yield '\t' + cdecl(typename, fname) + ';' if not self.ARRAY._hints.get('nolength', False): yield '\tlong length;' - line = '%s;' % cdecl(self.itemtypename, 'items[%d]'% self.varlength) + line = '%s;' % cdecl(self.itemtypename, + 'items[%s]' % deflength(self.varlength)) if self.ARRAY.OF is Void: # strange line = '/* array of void */' if self.ARRAY._hints.get('nolength', False): line = 'char _dummy; ' + line yield '\t' + line yield '};' - if self.varlength != 1: + if self.varlength is not None: yield 'union %su {' % self.name yield ' struct %s a;' % self.name yield ' %s;' % cdecl(self.normalizedtypename, 'b') yield '};' def visitor_lines(self, prefix, on_item): - assert self.varlength == 1 + assert self.varlength is None ARRAY = self.ARRAY # we need a unique name for this C variable, or at least one that does # not collide with the expression in 'prefix' @@ -310,7 +320,7 @@ def debug_offsets(self): # generate three offsets for debugging inspection - assert self.varlength == 1 + assert self.varlength is None if not self.ARRAY._hints.get('nolength', False): yield 'offsetof(struct %s, length)' % (self.name,) else: @@ -333,7 +343,7 @@ forward_decl = None extra_union_for_varlength = False - def __init__(self, db, ARRAY, varlength=1): + def __init__(self, db, ARRAY, varlength=None): NodeWithDependencies.__init__(self, db) self.ARRAY = ARRAY self.LLTYPE = ARRAY @@ -342,8 +352,8 @@ # There is no such thing as an array of voids: # we use a an array of chars instead; only the pointer can be void*. self.itemtypename = db.gettype(contained_type, who_asks=self) - self.fulltypename = self.itemtypename.replace('@', '(@)[%d]' % - (self.varlength,)) + self.fulltypename = self.itemtypename.replace('@', '(@)[%s]' % + deflength(varlength)) if ARRAY._hints.get("render_as_void"): self.fullptrtypename = 'void *@' else: @@ -493,7 +503,8 @@ Node.__init__(self, db) self.obj = obj self.typename = db.gettype(T) #, who_asks=self) - self.implementationtypename = db.gettype(T, varlength=self.getlength()) + self.implementationtypename = db.gettype( + T, varlength=self.getvarlength()) parent, parentindex = parentlink(obj) if obj in exports.EXPORTS_obj2name: self.name = exports.EXPORTS_obj2name[obj] @@ -559,8 +570,8 @@ def startupcode(self): return [] - def getlength(self): - return 1 + def getvarlength(self): + return None assert not USESLOTS or '__dict__' not in dir(ContainerNode) @@ -578,10 +589,10 @@ for name in T._names: yield getattr(self.obj, name) - def getlength(self): + def getvarlength(self): T = self.getTYPE() if T._arrayfld is None: - return 1 + return None else: array = getattr(self.obj, T._arrayfld) return len(array.items) @@ -696,7 +707,7 @@ def enum_dependencies(self): return self.obj.items - def getlength(self): + def getvarlength(self): return len(self.obj.items) def initializationexpr(self, decoration=''): @@ -765,8 +776,8 @@ for i in range(self.obj.getlength()): yield self.obj.getitem(i) - def getlength(self): - return 1 # not variable-sized! + def getvarlength(self): + return None # not variable-sized! def initializationexpr(self, decoration=''): T = self.getTYPE() diff --git a/rpython/translator/c/src/g_prerequisite.h b/rpython/translator/c/src/g_prerequisite.h --- a/rpython/translator/c/src/g_prerequisite.h +++ b/rpython/translator/c/src/g_prerequisite.h @@ -14,8 +14,14 @@ #ifdef __GNUC__ /* other platforms too, probably */ typedef _Bool bool_t; +# define RPY_VARLENGTH /* nothing: [RPY_VARLENGTH] => [] */ +# define RPY_LENGTH0 0 /* array decl [0] are ok */ +# define RPY_DUMMY_VARLENGTH char _dummy[0]; #else typedef unsigned char bool_t; +# define RPY_VARLENGTH 1 /* [RPY_VARLENGTH] => [1] */ +# define RPY_LENGTH0 1 /* array decl [0] are bad */ +# define RPY_DUMMY_VARLENGTH /* nothing */ #endif diff --git a/rpython/translator/c/src/support.h b/rpython/translator/c/src/support.h --- a/rpython/translator/c/src/support.h +++ b/rpython/translator/c/src/support.h @@ -2,16 +2,6 @@ /************************************************************/ /*** C header subsection: support functions ***/ -/* a temporary(?) workaround for GCC 4.8. See: - http://stackoverflow.com/questions/16016627/ -*/ -#ifdef __GNUC__ -# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) -# pragma GCC optimize("no-aggressive-loop-optimizations") -# endif -#endif - - #define RUNNING_ON_LLINTERP 0 #define OP_JIT_RECORD_KNOWN_CLASS(i, c, r) /* nothing */ diff --git a/rpython/translator/c/test/test_lltyped.py b/rpython/translator/c/test/test_lltyped.py --- a/rpython/translator/c/test/test_lltyped.py +++ b/rpython/translator/c/test/test_lltyped.py @@ -919,3 +919,25 @@ return x fn = self.getcompiled(llf, [int]) assert fn(5) == 42 + + def test_raw_array_field_prebuilt(self): + from rpython.rtyper.lltypesystem import rffi + S = Struct('S', ('array', rffi.CArray(Signed))) + s0 = malloc(S, 0, flavor='raw', immortal=True) + s1 = malloc(S, 1, flavor='raw', immortal=True) + s1.array[0] = 521 + s2 = malloc(S, 2, flavor='raw', immortal=True) + s2.array[0] = 12 + s2.array[1] = 34 + def llf(i): + if i == 0: s = s0 + elif i == 1: s = s1 + else: s = s2 + x = 10 + if i > 0: + x += s.array[i-1] + return x + fn = self.getcompiled(llf, [int]) + assert fn(0) == 10 + assert fn(1) == 10 + 521 + assert fn(2) == 10 + 34 From noreply at buildbot.pypy.org Thu Apr 18 00:57:25 2013 From: noreply at buildbot.pypy.org (mattip) Date: Thu, 18 Apr 2013 00:57:25 +0200 (CEST) Subject: [pypy-commit] pypy win32-fixes3: skip resource test in windows Message-ID: <20130417225725.772701C317D@cobra.cs.uni-duesseldorf.de> Author: mattip Branch: win32-fixes3 Changeset: r63464:3a0dfa5bca98 Date: 2013-04-18 01:29 +0300 http://bitbucket.org/pypy/pypy/changeset/3a0dfa5bca98/ Log: skip resource test in windows diff --git a/pypy/module/test_lib_pypy/test_ctypes_config_cache.py b/pypy/module/test_lib_pypy/test_ctypes_config_cache.py --- a/pypy/module/test_lib_pypy/test_ctypes_config_cache.py +++ b/pypy/module/test_lib_pypy/test_ctypes_config_cache.py @@ -41,6 +41,10 @@ assert 'LOG_NOTICE' in d def test_resource(): + try: + import lib_pypy.resource + except ImportError: + py.test.skip('no syslog on this platform') d = run('resource.ctc.py', '_resource_cache.py') assert 'RLIM_NLIMITS' in d From noreply at buildbot.pypy.org Thu Apr 18 00:57:24 2013 From: noreply at buildbot.pypy.org (mattip) Date: Thu, 18 Apr 2013 00:57:24 +0200 (CEST) Subject: [pypy-commit] pypy win32-fixes3: create export library Message-ID: <20130417225724.36A301C30AF@cobra.cs.uni-duesseldorf.de> Author: mattip Branch: win32-fixes3 Changeset: r63463:beb4c026320d Date: 2013-04-18 01:25 +0300 http://bitbucket.org/pypy/pypy/changeset/beb4c026320d/ Log: create export library diff --git a/rpython/jit/backend/x86/codebuf.py b/rpython/jit/backend/x86/codebuf.py --- a/rpython/jit/backend/x86/codebuf.py +++ b/rpython/jit/backend/x86/codebuf.py @@ -7,7 +7,6 @@ from rpython.jit.backend.x86.regloc import LocationCodeBuilder from rpython.jit.backend.x86.arch import IS_X86_32, IS_X86_64, WORD from rpython.jit.backend.x86 import valgrind - # XXX: Seems nasty to change the superclass of MachineCodeBlockWrapper # like this if IS_X86_32: diff --git a/rpython/jit/backend/x86/test/test_fficall.py b/rpython/jit/backend/x86/test/test_fficall.py --- a/rpython/jit/backend/x86/test/test_fficall.py +++ b/rpython/jit/backend/x86/test/test_fficall.py @@ -2,6 +2,7 @@ from rpython.jit.metainterp.test import test_fficall from rpython.jit.backend.x86.test.test_basic import Jit386Mixin + class TestFfiCall(Jit386Mixin, test_fficall.FfiCallTests): # for the individual tests see # ====> ../../../metainterp/test/test_fficall.py diff --git a/rpython/jit/metainterp/test/test_fficall.py b/rpython/jit/metainterp/test/test_fficall.py --- a/rpython/jit/metainterp/test/test_fficall.py +++ b/rpython/jit/metainterp/test/test_fficall.py @@ -109,7 +109,6 @@ assert res == rvalue or (res, rvalue) == (654321, None) self.check_operations_history(call_may_force=0, call_release_gil=expected_call_release_gil) - def test_simple_call_int(self): self._run([types.signed] * 2, types.signed, [456, 789], -42) diff --git a/rpython/rtyper/tool/test/test_rffi_platform.py b/rpython/rtyper/tool/test/test_rffi_platform.py --- a/rpython/rtyper/tool/test/test_rffi_platform.py +++ b/rpython/rtyper/tool/test/test_rffi_platform.py @@ -281,9 +281,6 @@ assert a % struct.calcsize("P") == 0 def test_external_lib(): - # XXX this one seems to be a bit too platform-specific. Check - # how to test it on windows correctly (using so_prefix?) - # and what are alternatives to LD_LIBRARY_PATH eci = ExternalCompilationInfo() c_source = """ int f(int a, int b) @@ -291,12 +288,17 @@ return (a + b); } """ + if platform.cc == 'cl.exe': + c_source = '__declspec(dllexport) ' + c_source + libname = 'libc_lib' + else: + libname = 'c_lib' tmpdir = udir.join('external_lib').ensure(dir=1) c_file = tmpdir.join('libc_lib.c') c_file.write(c_source) l = platform.compile([c_file], eci, standalone=False) eci = ExternalCompilationInfo( - libraries = ['c_lib'], + libraries = [libname], library_dirs = [str(tmpdir)] ) rffi_platform.verify_eci(eci) From noreply at buildbot.pypy.org Thu Apr 18 00:57:26 2013 From: noreply at buildbot.pypy.org (mattip) Date: Thu, 18 Apr 2013 00:57:26 +0200 (CEST) Subject: [pypy-commit] pypy win32-fixes3: revert unintentional formatting changes Message-ID: <20130417225726.9DBDD1C30AF@cobra.cs.uni-duesseldorf.de> Author: mattip Branch: win32-fixes3 Changeset: r63465:bf7b125023b5 Date: 2013-04-18 01:55 +0300 http://bitbucket.org/pypy/pypy/changeset/bf7b125023b5/ Log: revert unintentional formatting changes diff --git a/rpython/jit/backend/x86/codebuf.py b/rpython/jit/backend/x86/codebuf.py --- a/rpython/jit/backend/x86/codebuf.py +++ b/rpython/jit/backend/x86/codebuf.py @@ -7,6 +7,7 @@ from rpython.jit.backend.x86.regloc import LocationCodeBuilder from rpython.jit.backend.x86.arch import IS_X86_32, IS_X86_64, WORD from rpython.jit.backend.x86 import valgrind + # XXX: Seems nasty to change the superclass of MachineCodeBlockWrapper # like this if IS_X86_32: diff --git a/rpython/jit/backend/x86/test/test_fficall.py b/rpython/jit/backend/x86/test/test_fficall.py --- a/rpython/jit/backend/x86/test/test_fficall.py +++ b/rpython/jit/backend/x86/test/test_fficall.py @@ -2,7 +2,6 @@ from rpython.jit.metainterp.test import test_fficall from rpython.jit.backend.x86.test.test_basic import Jit386Mixin - class TestFfiCall(Jit386Mixin, test_fficall.FfiCallTests): # for the individual tests see # ====> ../../../metainterp/test/test_fficall.py diff --git a/rpython/jit/metainterp/test/test_fficall.py b/rpython/jit/metainterp/test/test_fficall.py --- a/rpython/jit/metainterp/test/test_fficall.py +++ b/rpython/jit/metainterp/test/test_fficall.py @@ -109,6 +109,7 @@ assert res == rvalue or (res, rvalue) == (654321, None) self.check_operations_history(call_may_force=0, call_release_gil=expected_call_release_gil) + def test_simple_call_int(self): self._run([types.signed] * 2, types.signed, [456, 789], -42) From noreply at buildbot.pypy.org Thu Apr 18 00:59:29 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Thu, 18 Apr 2013 00:59:29 +0200 (CEST) Subject: [pypy-commit] pypy py3k: terrible hack/workaround for a bogus test_ztranslation failure Message-ID: <20130417225929.5DF771C30AF@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63466:086682bc42b6 Date: 2013-04-17 15:48 -0700 http://bitbucket.org/pypy/pypy/changeset/086682bc42b6/ Log: terrible hack/workaround for a bogus test_ztranslation failure diff --git a/pypy/module/_io/test/test_ztranslation.py b/pypy/module/_io/test/test_ztranslation.py --- a/pypy/module/_io/test/test_ztranslation.py +++ b/pypy/module/_io/test/test_ztranslation.py @@ -1,4 +1,15 @@ +from pypy.interpreter.typedef import GetSetProperty +from pypy.module.exceptions.interp_exceptions import W_BaseException from pypy.objspace.fake.checkmodule import checkmodule def test_checkmodule(): + # XXX: PyTraceback usage in these methods blows up checkmodule + def descr_gettraceback(self, space): + return space.w_None + def descr_settraceback(self, space, w_newtraceback): + pass + W_BaseException.descr_gettraceback = descr_gettraceback + W_BaseException.descr_settraceback = descr_settraceback + W_BaseException.typedef.add_entries( + __traceback__=GetSetProperty(descr_gettraceback, descr_settraceback)) checkmodule('_io') From noreply at buildbot.pypy.org Thu Apr 18 00:59:30 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Thu, 18 Apr 2013 00:59:30 +0200 (CEST) Subject: [pypy-commit] pypy default: whitespace/pep8 Message-ID: <20130417225930.A0B2B1C30AF@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: Changeset: r63467:36dd84c6a8ba Date: 2013-04-17 15:56 -0700 http://bitbucket.org/pypy/pypy/changeset/36dd84c6a8ba/ Log: whitespace/pep8 diff --git a/rpython/rtyper/module/ll_os_environ.py b/rpython/rtyper/module/ll_os_environ.py --- a/rpython/rtyper/module/ll_os_environ.py +++ b/rpython/rtyper/module/ll_os_environ.py @@ -1,4 +1,5 @@ -import os, sys +import os +import sys from rpython.annotator import model as annmodel from rpython.rtyper.controllerentry import Controller from rpython.rtyper.extfunc import register_external @@ -10,27 +11,32 @@ # ____________________________________________________________ # -# Annotation support to control access to 'os.environ' in the RPython program +# Annotation support to control access to 'os.environ' in the RPython +# program class OsEnvironController(Controller): knowntype = os.environ.__class__ def convert(self, obj): - return None # 'None' is good enough, there is only one os.environ + # 'None' is good enough, there is only one os.environ + return None def getitem(self, obj, key): - # in the RPython program reads of 'os.environ[key]' are redirected here + # in the RPython program reads of 'os.environ[key]' are + # redirected here result = r_getenv(key) if result is None: raise KeyError return result def setitem(self, obj, key, value): - # in the RPython program, 'os.environ[key] = value' is redirected here + # in the RPython program, 'os.environ[key] = value' is + # redirected here r_putenv(key, value) def delitem(self, obj, key): - # in the RPython program, 'del os.environ[key]' is redirected here + # in the RPython program, 'del os.environ[key]' is redirected + # here absent = r_getenv(key) is None # Always call unsetenv(), to get eventual OSErrors r_unsetenv(key) @@ -38,16 +44,18 @@ raise KeyError def get_keys(self, obj): - # 'os.environ.keys' is redirected here - note that it's the getattr - # that arrives here, not the actual method call! + # 'os.environ.keys' is redirected here - note that it's the + # getattr that arrives here, not the actual method call! return r_envkeys def get_items(self, obj): - # 'os.environ.items' is redirected here (not the actual method call!) + # 'os.environ.items' is redirected here (not the actual method + # call!) return r_envitems def get_get(self, obj): - # 'os.environ.get' is redirected here (not the actual method call!) + # 'os.environ.get' is redirected here (not the actual method + # call!) return r_getenv # ____________________________________________________________ @@ -57,7 +65,8 @@ def r_getenv(name): just_a_placeholder # should return None if name not found -os_getenv = rffi.llexternal('getenv', [rffi.CCHARP], rffi.CCHARP, threadsafe=False) +os_getenv = rffi.llexternal('getenv', [rffi.CCHARP], rffi.CCHARP, + threadsafe=False) def getenv_llimpl(name): l_name = rffi.str2charp(name) @@ -69,7 +78,8 @@ rffi.free_charp(l_name) return result -register_external(r_getenv, [str0], annmodel.SomeString(can_be_None=True, no_nul=True), +register_external(r_getenv, [str0], + annmodel.SomeString(can_be_None=True, no_nul=True), export_name='ll_os.ll_os_getenv', llimpl=getenv_llimpl) @@ -148,9 +158,8 @@ '_environ', ExternalCompilationInfo(includes=['stdlib.h'])) else: - os_get_environ, _os_set_environ = rffi.CExternVariable(rffi.CCHARPP, - 'environ', - ExternalCompilationInfo()) + os_get_environ, _os_set_environ = rffi.CExternVariable( + rffi.CCHARPP, 'environ', ExternalCompilationInfo()) # ____________________________________________________________ From noreply at buildbot.pypy.org Thu Apr 18 00:59:31 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Thu, 18 Apr 2013 00:59:31 +0200 (CEST) Subject: [pypy-commit] pypy default: utilize scoped_str2charp Message-ID: <20130417225931.D253D1C30AF@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: Changeset: r63468:39aca6fca541 Date: 2013-04-17 15:57 -0700 http://bitbucket.org/pypy/pypy/changeset/39aca6fca541/ Log: utilize scoped_str2charp diff --git a/rpython/rtyper/module/ll_os_environ.py b/rpython/rtyper/module/ll_os_environ.py --- a/rpython/rtyper/module/ll_os_environ.py +++ b/rpython/rtyper/module/ll_os_environ.py @@ -69,14 +69,9 @@ threadsafe=False) def getenv_llimpl(name): - l_name = rffi.str2charp(name) - l_result = os_getenv(l_name) - if l_result: - result = rffi.charp2str(l_result) - else: - result = None - rffi.free_charp(l_name) - return result + with rffi.scoped_str2charp(name) as l_name: + l_result = os_getenv(l_name) + return rffi.charp2str(l_result) if l_result else None register_external(r_getenv, [str0], annmodel.SomeString(can_be_None=True, no_nul=True), @@ -122,9 +117,8 @@ os_unsetenv = rffi.llexternal('unsetenv', [rffi.CCHARP], rffi.INT) def unsetenv_llimpl(name): - l_name = rffi.str2charp(name) - error = rffi.cast(lltype.Signed, os_unsetenv(l_name)) - rffi.free_charp(l_name) + with rffi.scoped_str2charp(name) as l_name: + error = rffi.cast(lltype.Signed, os_unsetenv(l_name)) if error: raise OSError(rposix.get_errno(), "os_unsetenv failed") try: From noreply at buildbot.pypy.org Thu Apr 18 01:01:50 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Thu, 18 Apr 2013 01:01:50 +0200 (CEST) Subject: [pypy-commit] pypy py3k: merge default Message-ID: <20130417230150.A370B1C3151@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63469:bc9dbaddceb6 Date: 2013-04-17 16:01 -0700 http://bitbucket.org/pypy/pypy/changeset/bc9dbaddceb6/ Log: merge default diff too long, truncating to 2000 out of 2113 lines diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -53,6 +53,11 @@ .. branch: improve-docs-2 Improve documents and straighten out links +.. branch: fast-newarray +Inline the fast path of newarray in the assembler. +Disabled on ARM until we fix issues. + + .. branches we don't care about .. branch: autoreds .. branch: reflex-support @@ -129,3 +134,5 @@ .. branch: release-2.0-beta2 .. branch: unbreak-freebsd + +.. branch: virtualref-virtualizable diff --git a/pypy/module/__pypy__/test/test_signal.py b/pypy/module/__pypy__/test/test_signal.py --- a/pypy/module/__pypy__/test/test_signal.py +++ b/pypy/module/__pypy__/test/test_signal.py @@ -25,7 +25,7 @@ __pypy__.thread._signals_enter() def test_enable_signals(self): - import __pypy__, _thread, signal, time + import __pypy__, _thread, signal, time, sys def subthread(): try: @@ -42,12 +42,16 @@ # This is normally called by app_main.py signal.signal(signal.SIGINT, signal.default_int_handler) + if sys.platform.startswith('win'): + # Windows seems to hang on _setmode when the first print comes from + # a thread, so make sure we've initialized io + sys.stdout + for i in range(10): __pypy__.thread._signals_exit() try: done = [] interrupted = [] - print('starting',i) _thread.start_new_thread(subthread, ()) for j in range(10): if len(done): break @@ -101,7 +105,7 @@ py.test.skip("this is only a test for -A runs on top of pypy") def test_enable_signals(self): - import __pypy__, _thread, signal, time + import __pypy__, _thread, time interrupted = [] lock = _thread.allocate_lock() diff --git a/pypy/module/test_lib_pypy/test_ctypes_config_cache.py b/pypy/module/test_lib_pypy/test_ctypes_config_cache.py --- a/pypy/module/test_lib_pypy/test_ctypes_config_cache.py +++ b/pypy/module/test_lib_pypy/test_ctypes_config_cache.py @@ -33,6 +33,10 @@ def test_syslog(): + try: + import lib_pypy.syslog + except ImportError: + py.test.skip('no syslog on this platform') d = run('syslog.ctc.py', '_syslog_cache.py') assert 'LOG_NOTICE' in d diff --git a/pypy/module/test_lib_pypy/test_os_wait.py b/pypy/module/test_lib_pypy/test_os_wait.py --- a/pypy/module/test_lib_pypy/test_os_wait.py +++ b/pypy/module/test_lib_pypy/test_os_wait.py @@ -1,6 +1,6 @@ # Generates the resource cache -from lib_pypy.ctypes_config_cache import rebuild -rebuild.rebuild_one('resource.ctc.py') +#from lib_pypy.ctypes_config_cache import rebuild +#rebuild.rebuild_one('resource.ctc.py') import os diff --git a/pypy/module/test_lib_pypy/test_resource.py b/pypy/module/test_lib_pypy/test_resource.py --- a/pypy/module/test_lib_pypy/test_resource.py +++ b/pypy/module/test_lib_pypy/test_resource.py @@ -1,7 +1,12 @@ +import py +try: + from lib_pypy import resource +except ImportError: + py.test.skip('no resource module available') + from lib_pypy.ctypes_config_cache import rebuild rebuild.rebuild_one('resource.ctc.py') -from lib_pypy import resource def test_resource(): x = resource.getrusage(resource.RUSAGE_SELF) diff --git a/pypy/module/test_lib_pypy/test_site_extra.py b/pypy/module/test_lib_pypy/test_site_extra.py --- a/pypy/module/test_lib_pypy/test_site_extra.py +++ b/pypy/module/test_lib_pypy/test_site_extra.py @@ -4,7 +4,7 @@ def test_preimported_modules(): lst = ['__builtin__', '_codecs', '_warnings', 'codecs', 'encodings', 'exceptions', 'signal', 'sys', 'zipimport'] - g = os.popen("'%s' -c 'import sys; print sorted(sys.modules)'" % + g = os.popen('"%s" -c "import sys; print sorted(sys.modules)"' % (sys.executable,)) real_data = g.read() g.close() diff --git a/pypy/module/test_lib_pypy/test_sqlite3.py b/pypy/module/test_lib_pypy/test_sqlite3.py --- a/pypy/module/test_lib_pypy/test_sqlite3.py +++ b/pypy/module/test_lib_pypy/test_sqlite3.py @@ -136,7 +136,7 @@ resource.setrlimit(resource.RLIMIT_NOFILE, limit) def test_on_conflict_rollback_executemany(con): - major, minor, micro = _sqlite3.sqlite_version.split('.') + major, minor, micro = _sqlite3.sqlite_version.split('.')[:3] if (int(major), int(minor), int(micro)) < (3, 2, 2): pytest.skip("requires sqlite3 version >= 3.2.2") con.execute("create table foo(x, unique(x) on conflict rollback)") diff --git a/pypy/module/test_lib_pypy/test_syslog.py b/pypy/module/test_lib_pypy/test_syslog.py --- a/pypy/module/test_lib_pypy/test_syslog.py +++ b/pypy/module/test_lib_pypy/test_syslog.py @@ -1,10 +1,14 @@ +import py +try: + from lib_pypy import syslog +except ImportError: + py.test.skip('no syslog on this platform') + # XXX very minimal test from lib_pypy.ctypes_config_cache import rebuild rebuild.rebuild_one('syslog.ctc.py') -from lib_pypy import syslog - def test_syslog(): assert hasattr(syslog, 'LOG_ALERT') diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -13,7 +13,7 @@ operations as regalloc_operations, operations_with_guard as regalloc_operations_with_guard) from rpython.jit.backend.llsupport import jitframe -from rpython.jit.backend.llsupport.assembler import DEBUG_COUNTER, debug_bridge +from rpython.jit.backend.llsupport.assembler import DEBUG_COUNTER, debug_bridge, BaseAssembler from rpython.jit.backend.llsupport.asmmemmgr import MachineDataBlockWrapper from rpython.jit.backend.model import CompiledLoopToken from rpython.jit.codewriter.effectinfo import EffectInfo @@ -25,7 +25,7 @@ from rpython.rlib.rarithmetic import r_uint from rpython.rtyper.annlowlevel import llhelper, cast_instance_to_gcref from rpython.rtyper.lltypesystem import lltype, rffi - +from rpython.jit.backend.arm.detect import detect_hardfloat class AssemblerARM(ResOpAssembler): @@ -49,6 +49,10 @@ self.loop_run_counters = [] self.gcrootmap_retaddr_forced = 0 + def setup_once(self): + BaseAssembler.setup_once(self) + self.hf_abi = detect_hardfloat() + def setup(self, looptoken): assert self.memcpy_addr != 0, 'setup_once() not called?' if we_are_translated(): @@ -274,7 +278,7 @@ mc.CMP_ri(r.r0.value, 0) mc.B(self.propagate_exception_path, c=c.EQ) # - self._reload_frame_if_necessary(mc, align_stack=True) + self._reload_frame_if_necessary(mc) self._pop_all_regs_from_jitframe(mc, [r.r0, r.r1], self.cpu.supports_floats) # nursery_free_adr = self.cpu.gc_ll_descr.get_nursery_free_addr() @@ -289,7 +293,7 @@ rawstart = mc.materialize(self.cpu.asmmemmgr, []) self.malloc_slowpath = rawstart - def _reload_frame_if_necessary(self, mc, align_stack=False, can_collect=0): + def _reload_frame_if_necessary(self, mc): gcrootmap = self.cpu.gc_ll_descr.gcrootmap if gcrootmap and gcrootmap.is_shadow_stack: rst = gcrootmap.get_root_stack_top_addr() @@ -301,7 +305,7 @@ # frame never uses card marking, so we enforce this is not # an array self._write_barrier_fastpath(mc, wbdescr, [r.fp], array=False, - is_frame=True)#, align_stack=align_stack) + is_frame=True) def propagate_memoryerror_if_r0_is_null(self): # see ../x86/assembler.py:propagate_memoryerror_if_eax_is_null diff --git a/rpython/jit/backend/arm/detect.py b/rpython/jit/backend/arm/detect.py --- a/rpython/jit/backend/arm/detect.py +++ b/rpython/jit/backend/arm/detect.py @@ -1,5 +1,5 @@ from rpython.translator.tool.cbuild import ExternalCompilationInfo -from rpython.rtyper.lltypesystem import lltype, rffi +from rpython.rlib.clibffi import FFI_DEFAULT_ABI, FFI_SYSV, FFI_VFP from rpython.rtyper.tool import rffi_platform from rpython.translator.platform import CompilationError @@ -14,10 +14,7 @@ """]) def detect_hardfloat(): - # http://gcc.gnu.org/ml/gcc-patches/2010-10/msg02419.html - if rffi_platform.getdefined('__ARM_PCS_VFP', ''): - return rffi_platform.getconstantinteger('__ARM_PCS_VFP', '') - return False + return FFI_DEFAULT_ABI == FFI_VFP def detect_float(): """Check for hardware float support diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -3,7 +3,6 @@ from rpython.jit.backend.arm import registers as r from rpython.jit.backend.arm import shift from rpython.jit.backend.arm.arch import WORD, DOUBLE_WORD, JITFRAME_FIXED_SIZE - from rpython.jit.backend.arm.helper.assembler import (gen_emit_op_by_helper_call, gen_emit_op_unary_cmp, gen_emit_guard_unary_cmp, @@ -351,10 +350,11 @@ return cond def _emit_call(self, adr, arglocs, fcond=c.AL, resloc=None, - result_info=(-1, -1), - can_collect=1, - reload_frame=False): - if self.cpu.hf_abi: + result_info=(-1, -1), + # whether to worry about a CALL that can collect; this + # is always true except in call_release_gil + can_collect=True): + if self.hf_abi: stack_args, adr = self._setup_call_hf(adr, arglocs, fcond, resloc, result_info) else: @@ -362,6 +362,9 @@ resloc, result_info) if can_collect: + # we push *now* the gcmap, describing the status of GC registers + # after the rearrangements done just above, ignoring the return + # value eax, if necessary noregs = self.cpu.gc_ll_descr.is_shadow_stack() gcmap = self._regalloc.get_gcmap([r.r0], noregs=noregs) self.push_gcmap(self.mc, gcmap, store=True) @@ -379,17 +382,15 @@ # ensure the result is wellformed and stored in the correct location if resloc is not None: - if resloc.is_vfp_reg() and not self.cpu.hf_abi: + if resloc.is_vfp_reg() and not self.hf_abi: # move result to the allocated register self.mov_to_vfp_loc(r.r0, r.r1, resloc) elif resloc.is_reg() and result_info != (-1, -1): self._ensure_result_bit_extension(resloc, result_info[0], result_info[1]) if can_collect: - self._reload_frame_if_necessary(self.mc, can_collect=can_collect) + self._reload_frame_if_necessary(self.mc) self.pop_gcmap(self.mc) - elif reload_frame: - self._reload_frame_if_necessary(self.mc) return fcond def _restore_sp(self, stack_args, fcond): @@ -1260,6 +1261,7 @@ def emit_guard_call_release_gil(self, op, guard_op, arglocs, regalloc, fcond): + self._store_force_index(guard_op) # first, close the stack in the sense of the asmgcc GC root tracker gcrootmap = self.cpu.gc_ll_descr.gcrootmap numargs = op.numargs() @@ -1268,24 +1270,27 @@ resloc = arglocs[0] if gcrootmap: - noregs = self.cpu.gc_ll_descr.is_shadow_stack() - assert noregs - gcmap = self._regalloc.get_gcmap([r.r0], noregs=noregs) + # we put the gcmap now into the frame before releasing the GIL, + # and pop it below after reacquiring the GIL. The assumption + # is that this gcmap describes correctly the situation at any + # point in-between: all values containing GC pointers should + # be safely saved out of registers by now, and will not be + # manipulated by any of the following CALLs. + gcmap = self._regalloc.get_gcmap(noregs=True) self.push_gcmap(self.mc, gcmap, store=True) self.call_release_gil(gcrootmap, arglocs, regalloc, fcond) # do the call - self._store_force_index(guard_op) - # descr = op.getdescr() size = descr.get_result_size() signed = descr.is_result_signed() # self._emit_call(adr, callargs, fcond, resloc, (size, signed), - can_collect=0) + can_collect=False) # then reopen the stack if gcrootmap: self.call_reacquire_gil(gcrootmap, resloc, regalloc, fcond) + self.pop_gcmap(self.mc) # remove the gcmap saved above self._emit_guard_may_force(guard_op, arglocs[numargs+1:], numargs) return fcond @@ -1314,7 +1319,7 @@ # call the reopenstack() function (also reacquiring the GIL) with saved_registers(self.mc, regs_to_save, vfp_regs_to_save): self._emit_call(imm(self.reacqgil_addr), [], fcond, - can_collect=False, reload_frame=True) + can_collect=False) def _store_force_index(self, guard_op): faildescr = guard_op.getdescr() @@ -1343,7 +1348,7 @@ ) self._alignment_check() return fcond - emit_op_call_malloc_nursery_varsize_small = emit_op_call_malloc_nursery + emit_op_call_malloc_nursery_varsize_frame = emit_op_call_malloc_nursery def _alignment_check(self): diff --git a/rpython/jit/backend/arm/regalloc.py b/rpython/jit/backend/arm/regalloc.py --- a/rpython/jit/backend/arm/regalloc.py +++ b/rpython/jit/backend/arm/regalloc.py @@ -1014,7 +1014,7 @@ self.possibly_free_var(t) return [imm(size)] - def prepare_op_call_malloc_nursery_varsize_small(self, op, fcond): + def prepare_op_call_malloc_nursery_varsize_frame(self, op, fcond): size_box = op.getarg(0) assert isinstance(size_box, BoxInt) diff --git a/rpython/jit/backend/arm/runner.py b/rpython/jit/backend/arm/runner.py --- a/rpython/jit/backend/arm/runner.py +++ b/rpython/jit/backend/arm/runner.py @@ -6,6 +6,7 @@ from rpython.jit.backend.llsupport.llmodel import AbstractLLCPU from rpython.rlib.jit_hooks import LOOP_RUN_CONTAINER from rpython.rtyper.lltypesystem import lltype, llmemory +from rpython.jit.backend.arm.detect import detect_hardfloat jitframe.STATICSIZE = JITFRAME_FIXED_SIZE @@ -16,7 +17,7 @@ supports_floats = True supports_longlong = False # XXX requires an implementation of # read_timestamp that works in user mode - supports_singlefloats = True + supports_singlefloats = not detect_hardfloat() from rpython.jit.backend.arm.arch import JITFRAME_FIXED_SIZE all_reg_indexes = range(len(all_regs)) @@ -112,22 +113,10 @@ class CPU_ARM(AbstractARMCPU): - """ARM v7 uses softfp ABI, requires vfp""" + """ARM v7""" backend_name = "armv7" - -class CPU_ARMHF(AbstractARMCPU): - """ARM v7 uses hardfp ABI, requires vfp""" - hf_abi = True - backend_name = "armv7hf" - supports_floats = True - supports_singlefloats = False - - -class CPU_ARMv6HF(AbstractARMCPU): +class CPU_ARMv6(AbstractARMCPU): """ ARM v6, uses hardfp ABI, requires vfp""" - hf_abi = True arch_version = 6 - backend_name = "armv6hf" - supports_floats = True - supports_singlefloats = False + backend_name = "armv6" diff --git a/rpython/jit/backend/arm/test/conftest.py b/rpython/jit/backend/arm/test/conftest.py --- a/rpython/jit/backend/arm/test/conftest.py +++ b/rpython/jit/backend/arm/test/conftest.py @@ -16,6 +16,7 @@ dest="run_translation_tests", help="run tests that translate code") -def pytest_runtest_setup(item): +def pytest_collect_directory(path, parent): if not cpu.startswith('arm'): py.test.skip("ARM(v7) tests skipped: cpu is %r" % (cpu,)) +pytest_collect_file = pytest_collect_directory diff --git a/rpython/jit/backend/detect_cpu.py b/rpython/jit/backend/detect_cpu.py --- a/rpython/jit/backend/detect_cpu.py +++ b/rpython/jit/backend/detect_cpu.py @@ -61,8 +61,6 @@ model = 'x86-without-sse2' if model.startswith('arm'): from rpython.jit.backend.arm.detect import detect_hardfloat, detect_float - if detect_hardfloat(): - model += 'hf' assert detect_float(), 'the JIT-compiler requires a vfp unit' return model @@ -77,12 +75,10 @@ return "rpython.jit.backend.x86.runner", "CPU_X86_64" elif backend_name == 'cli': return "rpython.jit.backend.cli.runner", "CliCPU" - elif backend_name == 'armv6hf': - return "rpython.jit.backend.arm.runner", "CPU_ARMv6HF" - elif backend_name == 'armv7': + elif backend_name.startswith('armv6'): + return "rpython.jit.backend.arm.runner", "CPU_ARMv6" + elif backend_name.startswith('armv7'): return "rpython.jit.backend.arm.runner", "CPU_ARM" - elif backend_name == 'armv7hf': - return "rpython.jit.backend.arm.runner", "CPU_ARMHF" else: raise ProcessorAutodetectError, ( "we have no JIT backend for this cpu: '%s'" % backend_name) diff --git a/rpython/jit/backend/llsupport/assembler.py b/rpython/jit/backend/llsupport/assembler.py --- a/rpython/jit/backend/llsupport/assembler.py +++ b/rpython/jit/backend/llsupport/assembler.py @@ -70,6 +70,14 @@ # the address of the function called by 'new' gc_ll_descr = self.cpu.gc_ll_descr gc_ll_descr.initialize() + if hasattr(gc_ll_descr, 'minimal_size_in_nursery'): + self.gc_minimal_size_in_nursery = gc_ll_descr.minimal_size_in_nursery + else: + self.gc_minimal_size_in_nursery = 0 + if hasattr(gc_ll_descr, 'gcheaderbuilder'): + self.gc_size_of_header = gc_ll_descr.gcheaderbuilder.size_gc_header + else: + self.gc_size_of_header = WORD # for tests self.memcpy_addr = self.cpu.cast_ptr_to_int(memcpy_fn) self._build_failure_recovery(False, withfloats=False) self._build_failure_recovery(True, withfloats=False) @@ -85,7 +93,20 @@ self._build_wb_slowpath(True, withfloats=True) self._build_propagate_exception_path() if gc_ll_descr.get_malloc_slowpath_addr is not None: - self._build_malloc_slowpath() + # generate few slowpaths for various cases + self.malloc_slowpath = self._build_malloc_slowpath(kind='fixed') + self.malloc_slowpath_varsize = self._build_malloc_slowpath( + kind='var') + if hasattr(gc_ll_descr, 'malloc_str'): + self.malloc_slowpath_str = self._build_malloc_slowpath(kind='str') + else: + self.malloc_slowpath_str = None + if hasattr(gc_ll_descr, 'malloc_unicode'): + self.malloc_slowpath_unicode = self._build_malloc_slowpath( + kind='unicode') + else: + self.malloc_slowpath_unicode = None + self._build_stack_check_slowpath() if gc_ll_descr.gcrootmap: self._build_release_gil(gc_ll_descr.gcrootmap) diff --git a/rpython/jit/backend/llsupport/gc.py b/rpython/jit/backend/llsupport/gc.py --- a/rpython/jit/backend/llsupport/gc.py +++ b/rpython/jit/backend/llsupport/gc.py @@ -415,6 +415,7 @@ return llop1.do_malloc_fixedsize_clear(llmemory.GCREF, type_id, size, False, False, False) + self.generate_function('malloc_nursery', malloc_nursery_slowpath, [lltype.Signed]) @@ -567,6 +568,9 @@ def get_malloc_slowpath_addr(self): return self.get_malloc_fn_addr('malloc_nursery') + def get_malloc_slowpath_array_addr(self): + return self.get_malloc_fn_addr('malloc_array') + # ____________________________________________________________ def get_ll_description(gcdescr, translator=None, rtyper=None): diff --git a/rpython/jit/backend/llsupport/llmodel.py b/rpython/jit/backend/llsupport/llmodel.py --- a/rpython/jit/backend/llsupport/llmodel.py +++ b/rpython/jit/backend/llsupport/llmodel.py @@ -21,6 +21,8 @@ class AbstractLLCPU(AbstractCPU): from rpython.jit.metainterp.typesystem import llhelper as ts + can_inline_varsize_malloc = False + def __init__(self, rtyper, stats, opts, translate_support_code=False, gcdescr=None): assert type(opts) is not bool @@ -171,9 +173,9 @@ def pos_exc_value(): addr = llop.get_exc_value_addr(llmemory.Address) return heaptracker.adr2int(addr) - + from rpython.rlib import rstack - + STACK_CHECK_SLOWPATH = lltype.Ptr(lltype.FuncType([lltype.Signed], lltype.Void)) def insert_stack_check(): diff --git a/rpython/jit/backend/llsupport/rewrite.py b/rpython/jit/backend/llsupport/rewrite.py --- a/rpython/jit/backend/llsupport/rewrite.py +++ b/rpython/jit/backend/llsupport/rewrite.py @@ -8,19 +8,29 @@ from rpython.jit.backend.llsupport.descr import SizeDescr, ArrayDescr from rpython.jit.metainterp.history import JitCellToken +FLAG_ARRAY = 0 +FLAG_STR = 1 +FLAG_UNICODE = 2 + class GcRewriterAssembler(object): - # This class performs the following rewrites on the list of operations: - # - # - Remove the DEBUG_MERGE_POINTs. - # - # - Turn all NEW_xxx to either a CALL_MALLOC_GC, or a CALL_MALLOC_NURSERY - # followed by SETFIELDs in order to initialize their GC fields. The - # two advantages of CALL_MALLOC_NURSERY is that it inlines the common - # path, and we need only one such operation to allocate several blocks - # of memory at once. - # - # - Add COND_CALLs to the write barrier before SETFIELD_GC and - # SETARRAYITEM_GC operations. + """ This class performs the following rewrites on the list of operations: + + - Remove the DEBUG_MERGE_POINTs. + + - Turn all NEW_xxx to either a CALL_MALLOC_GC, or a CALL_MALLOC_NURSERY + followed by SETFIELDs in order to initialize their GC fields. The + two advantages of CALL_MALLOC_NURSERY is that it inlines the common + path, and we need only one such operation to allocate several blocks + of memory at once. + + - Add COND_CALLs to the write barrier before SETFIELD_GC and + SETARRAYITEM_GC operations. + + recent_mallocs contains a dictionary of variable -> None. If a variable + is in the dictionary, next setfields can be called without a write barrier, + because the variable got allocated after the last potentially collecting + resop + """ _previous_size = -1 _op_malloc_nursery = None @@ -32,7 +42,7 @@ self.cpu = cpu self.newops = [] self.known_lengths = {} - self.recent_mallocs = {} # set of variables + self.recent_mallocs = {} def rewrite(self, operations): # we can only remember one malloc since the next malloc can possibly @@ -92,9 +102,11 @@ assert isinstance(descr, ArrayDescr) self.handle_new_array(descr, op) elif opnum == rop.NEWSTR: - self.handle_new_array(self.gc_ll_descr.str_descr, op) + self.handle_new_array(self.gc_ll_descr.str_descr, op, + kind=FLAG_STR) elif opnum == rop.NEWUNICODE: - self.handle_new_array(self.gc_ll_descr.unicode_descr, op) + self.handle_new_array(self.gc_ll_descr.unicode_descr, op, + kind=FLAG_UNICODE) else: raise NotImplementedError(op.getopname()) @@ -106,7 +118,7 @@ else: self.gen_malloc_fixedsize(size, descr.tid, op.result) - def handle_new_array(self, arraydescr, op): + def handle_new_array(self, arraydescr, op, kind=FLAG_ARRAY): v_length = op.getarg(0) total_size = -1 if isinstance(v_length, ConstInt): @@ -119,6 +131,14 @@ pass # total_size is still -1 elif arraydescr.itemsize == 0: total_size = arraydescr.basesize + elif (self.gc_ll_descr.can_use_nursery_malloc(1) and + self.gen_malloc_nursery_varsize(arraydescr.itemsize, + v_length, op.result, arraydescr, kind=kind)): + # note that we cannot initialize tid here, because the array + # might end up being allocated by malloc_external or some + # stuff that initializes GC header fields differently + self.gen_initialize_len(op.result, v_length, arraydescr.lendescr) + return if (total_size >= 0 and self.gen_malloc_nursery(total_size, op.result)): self.gen_initialize_tid(op.result, arraydescr.tid) @@ -152,7 +172,7 @@ size_box, descr=descrs.jfi_frame_size) self.newops.append(op0) - self.gen_malloc_nursery_varsize(size_box, frame, is_small=True) + self.gen_malloc_nursery_varsize_frame(size_box, frame) self.gen_initialize_tid(frame, descrs.arraydescr.tid) length_box = history.BoxInt() op1 = ResOperation(rop.GETFIELD_GC, [history.ConstInt(frame_info)], @@ -281,12 +301,30 @@ self._gen_call_malloc_gc([ConstInt(addr), v_num_elem], v_result, self.gc_ll_descr.malloc_unicode_descr) - def gen_malloc_nursery_varsize(self, sizebox, v_result, is_small=False): - """ Generate CALL_MALLOC_NURSERY_VARSIZE_SMALL + def gen_malloc_nursery_varsize(self, itemsize, v_length, v_result, + arraydescr, kind=FLAG_ARRAY): + """ itemsize is an int, v_length and v_result are boxes """ - assert is_small + if not self.cpu.can_inline_varsize_malloc: + return False # temporary, kill when ARM supports it + gc_descr = self.gc_ll_descr + if (kind == FLAG_ARRAY and + (arraydescr.basesize != gc_descr.standard_array_basesize or + arraydescr.lendescr.offset != gc_descr.standard_array_length_ofs)): + return False self.emitting_an_operation_that_can_collect() - op = ResOperation(rop.CALL_MALLOC_NURSERY_VARSIZE_SMALL, + op = ResOperation(rop.CALL_MALLOC_NURSERY_VARSIZE, + [ConstInt(kind), ConstInt(itemsize), v_length], + v_result, descr=arraydescr) + self.newops.append(op) + self.recent_mallocs[v_result] = None + return True + + def gen_malloc_nursery_varsize_frame(self, sizebox, v_result): + """ Generate CALL_MALLOC_NURSERY_VARSIZE_FRAME + """ + self.emitting_an_operation_that_can_collect() + op = ResOperation(rop.CALL_MALLOC_NURSERY_VARSIZE_FRAME, [sizebox], v_result) diff --git a/rpython/jit/backend/llsupport/test/test_gc_integration.py b/rpython/jit/backend/llsupport/test/test_gc_integration.py --- a/rpython/jit/backend/llsupport/test/test_gc_integration.py +++ b/rpython/jit/backend/llsupport/test/test_gc_integration.py @@ -29,11 +29,11 @@ return r[r.find('1'):] class TestRegallocGcIntegration(BaseTestRegalloc): - + cpu = CPU(None, None) cpu.gc_ll_descr = GcLLDescr_boehm(None, None, None) cpu.setup_once() - + S = lltype.GcForwardReference() S.become(lltype.GcStruct('S', ('field', lltype.Ptr(S)), ('int', lltype.Signed))) @@ -145,6 +145,7 @@ gcrootmap = None passes_frame = True write_barrier_descr = None + max_size_of_young_obj = 50 def __init__(self, callback): GcLLDescription.__init__(self, None) @@ -172,6 +173,20 @@ [lltype.Signed, jitframe.JITFRAMEPTR], lltype.Signed) + def malloc_array(itemsize, tid, num_elem): + self.calls.append((itemsize, tid, num_elem)) + return 13 + + self.malloc_slowpath_array_fnptr = llhelper_args(malloc_array, + [lltype.Signed] * 3, + lltype.Signed) + + def malloc_str(size): + self.calls.append(('str', size)) + return 13 + self.generate_function('malloc_str', malloc_str, [lltype.Signed], + lltype.Signed) + def get_nursery_free_addr(self): return rffi.cast(lltype.Signed, self.addrs) @@ -181,6 +196,9 @@ def get_malloc_slowpath_addr(self): return self.get_malloc_fn_addr('malloc_nursery') + def get_malloc_slowpath_array_addr(self): + return self.malloc_slowpath_array_fnptr + def check_nothing_in_nursery(self): # CALL_MALLOC_NURSERY should not write anything in the nursery for i in range(64): @@ -221,15 +239,15 @@ # slowpath never called assert gc_ll_descr.calls == [] - def test_malloc_nursery_varsize_small(self): + def test_malloc_nursery_varsize_frame(self): self.cpu = self.getcpu(None) ops = ''' [i0, i1, i2] - p0 = call_malloc_nursery_varsize_small(i0) - p1 = call_malloc_nursery_varsize_small(i1) - p2 = call_malloc_nursery_varsize_small(i2) + p0 = call_malloc_nursery_varsize_frame(i0) + p1 = call_malloc_nursery_varsize_frame(i1) + p2 = call_malloc_nursery_varsize_frame(i2) guard_true(i0) [p0, p1, p2] - ''' + ''' self.interpret(ops, [16, 32, 16]) # check the returned pointers gc_ll_descr = self.cpu.gc_ll_descr @@ -244,6 +262,56 @@ # slowpath never called assert gc_ll_descr.calls == [] + def test_malloc_nursery_varsize(self): + self.cpu = self.getcpu(None) + A = lltype.GcArray(lltype.Signed) + arraydescr = self.cpu.arraydescrof(A) + arraydescr.tid = 15 + ops = ''' + [i0, i1, i2] + p0 = call_malloc_nursery_varsize(0, 8, i0, descr=arraydescr) + p1 = call_malloc_nursery_varsize(0, 5, i1, descr=arraydescr) + guard_false(i0) [p0, p1] + ''' + self.interpret(ops, [1, 2, 3], + namespace={'arraydescr': arraydescr}) + # check the returned pointers + gc_ll_descr = self.cpu.gc_ll_descr + nurs_adr = rffi.cast(lltype.Signed, gc_ll_descr.nursery) + ref = lambda n: self.cpu.get_ref_value(self.deadframe, n) + assert rffi.cast(lltype.Signed, ref(0)) == nurs_adr + 0 + assert rffi.cast(lltype.Signed, ref(1)) == nurs_adr + 2*WORD + 8*1 + # check the nursery content and state + assert gc_ll_descr.nursery[0] == chr(15) + assert gc_ll_descr.nursery[2 * WORD + 8] == chr(15) + assert gc_ll_descr.addrs[0] == nurs_adr + (((4 * WORD + 8*1 + 5*2) + (WORD - 1)) & ~(WORD - 1)) + # slowpath never called + assert gc_ll_descr.calls == [] + + def test_malloc_nursery_varsize_slowpath(self): + self.cpu = self.getcpu(None) + ops = """ + [i0, i1, i2] + p0 = call_malloc_nursery_varsize(0, 8, i0, descr=arraydescr) + p1 = call_malloc_nursery_varsize(0, 5, i1, descr=arraydescr) + p3 = call_malloc_nursery_varsize(0, 5, i2, descr=arraydescr) + # overflow + p4 = call_malloc_nursery_varsize(0, 5, i2, descr=arraydescr) + # we didn't collect, so still overflow + p5 = call_malloc_nursery_varsize(1, 5, i2, descr=strdescr) + guard_false(i0) [p0, p1, p3, p4] + """ + A = lltype.GcArray(lltype.Signed) + arraydescr = self.cpu.arraydescrof(A) + arraydescr.tid = 15 + self.interpret(ops, [10, 3, 3], + namespace={'arraydescr': arraydescr, + 'strdescr': arraydescr}) + # check the returned pointers + gc_ll_descr = self.cpu.gc_ll_descr + assert gc_ll_descr.calls == [(8, 15, 10), (5, 15, 3), ('str', 3)] + # one fit, one was too large, one was not fitting + def test_malloc_slowpath(self): def check(frame): expected_size = 1 @@ -294,7 +362,7 @@ s = bin(x[0]).count('1') + bin(x[1]).count('1') assert s == 16 # all but two registers + some stuff on stack - + self.cpu = self.getcpu(check) S1 = lltype.GcStruct('S1') S2 = lltype.GcStruct('S2', ('s0', lltype.Ptr(S1)), @@ -360,7 +428,7 @@ class MockShadowStackRootMap(object): is_shadow_stack = True - + def __init__(self): TP = rffi.CArray(lltype.Signed) self.stack = lltype.malloc(TP, 10, flavor='raw') @@ -369,7 +437,7 @@ self.stack_addr[0] = rffi.cast(lltype.Signed, self.stack) def __del__(self): - lltype.free(self.stack_addr, flavor='raw') + lltype.free(self.stack_addr, flavor='raw') lltype.free(self.stack, flavor='raw') def register_asm_addr(self, start, mark): @@ -381,7 +449,7 @@ class WriteBarrierDescr(AbstractDescr): jit_wb_cards_set = 0 jit_wb_if_flag_singlebyte = 1 - + def __init__(self, gc_ll_descr): def write_barrier(frame): gc_ll_descr.write_barrier_on_frame_called = frame @@ -442,6 +510,15 @@ self.malloc_slowpath_fnptr = llhelper_args(malloc_slowpath, [lltype.Signed], lltype.Signed) + + def malloc_array(itemsize, tid, num_elem): + import pdb + pdb.set_trace() + + self.malloc_slowpath_array_fnptr = llhelper_args(malloc_array, + [lltype.Signed] * 3, + lltype.Signed) + self.all_nurseries = [] def init_nursery(self, nursery_size=None): @@ -497,6 +574,9 @@ def get_malloc_slowpath_addr(self): return self.malloc_slowpath_fnptr + def get_malloc_slowpath_array_addr(self): + return self.malloc_slowpath_array_fnptr + def get_nursery_free_addr(self): return self.nursery_addr @@ -507,7 +587,7 @@ for nursery in self.all_nurseries: lltype.free(nursery, flavor='raw', track_allocation=False) lltype.free(self.nursery_ptrs, flavor='raw') - + def unpack_gcmap(frame): res = [] val = 0 @@ -543,10 +623,10 @@ def test_shadowstack_call(self): cpu = self.cpu cpu.gc_ll_descr.init_nursery(100) - cpu.setup_once() + cpu.setup_once() S = self.S frames = [] - + def check(i): assert cpu.gc_ll_descr.gcrootmap.stack[0] == i frame = rffi.cast(JITFRAMEPTR, i) @@ -720,7 +800,7 @@ def test_call_may_force_gcmap(self): cpu = self.cpu - + def f(frame, arg, x): assert not arg assert frame.jf_gcmap[0] & 31 == 0 @@ -748,7 +828,7 @@ pdying = getarrayitem_gc(p0, 0, descr=arraydescr) px = call_may_force(ConstClass(fptr), pf, pdying, i0, descr=calldescr) guard_not_forced(descr=faildescr) [p1, p2, p3, px] - finish(px, descr=finishdescr) + finish(px, descr=finaldescr) """, namespace={'fptr': fptr, 'calldescr': calldescr, 'arraydescr': cpu.arraydescrof(A), 'faildescr': BasicFailDescr(1), @@ -760,12 +840,12 @@ cpu.compile_loop(loop.inputargs, loop.operations, token) frame = lltype.cast_opaque_ptr(JITFRAMEPTR, cpu.execute_token(token, 1, a)) - + assert getmap(frame).count('1') == 4 def test_call_gcmap_no_guard(self): cpu = self.cpu - + def f(frame, arg, x): assert not arg assert frame.jf_gcmap[0] & 31 == 0 @@ -792,7 +872,7 @@ pdying = getarrayitem_gc(p0, 0, descr=arraydescr) px = call(ConstClass(fptr), pf, pdying, i0, descr=calldescr) guard_false(i0, descr=faildescr) [p1, p2, p3, px] - finish(px, descr=finishdescr) + finish(px, descr=finaldescr) """, namespace={'fptr': fptr, 'calldescr': calldescr, 'arraydescr': cpu.arraydescrof(A), 'faildescr': BasicFailDescr(1), diff --git a/rpython/jit/backend/llsupport/test/test_regalloc_integration.py b/rpython/jit/backend/llsupport/test/test_regalloc_integration.py --- a/rpython/jit/backend/llsupport/test/test_regalloc_integration.py +++ b/rpython/jit/backend/llsupport/test/test_regalloc_integration.py @@ -93,8 +93,8 @@ type_system=self.type_system, boxkinds=boxkinds) - def interpret(self, ops, args, run=True): - loop = self.parse(ops) + def interpret(self, ops, args, run=True, namespace=None): + loop = self.parse(ops, namespace=namespace) self.loop = loop looptoken = JitCellToken() self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken) diff --git a/rpython/jit/backend/llsupport/test/test_rewrite.py b/rpython/jit/backend/llsupport/test/test_rewrite.py --- a/rpython/jit/backend/llsupport/test/test_rewrite.py +++ b/rpython/jit/backend/llsupport/test/test_rewrite.py @@ -34,7 +34,7 @@ ('t', lltype.Signed)) tdescr = get_size_descr(self.gc_ll_descr, T) tdescr.tid = 5678 - get_field_descr(self.gc_ll_descr, T, 'z') + tzdescr = get_field_descr(self.gc_ll_descr, T, 'z') # A = lltype.GcArray(lltype.Signed) adescr = get_array_descr(self.gc_ll_descr, A) @@ -85,6 +85,7 @@ signedframedescr = self.cpu.signedframedescr floatframedescr = self.cpu.floatframedescr casmdescr.compiled_loop_token = clt + tzdescr = None # noone cares # namespace.update(locals()) # @@ -107,7 +108,9 @@ class BaseFakeCPU(object): JITFRAME_FIXED_SIZE = 0 - + + can_inline_varsize_malloc = True + def __init__(self): self.tracker = FakeTracker() self._cache = {} @@ -121,7 +124,7 @@ def unpack_arraydescr_size(self, d): return 0, d.itemsize, 0 - + def arraydescrof(self, ARRAY): try: return self._cache[ARRAY] @@ -129,7 +132,7 @@ r = ArrayDescr(1, 2, FieldDescr('len', 0, 0, 0), 0) self._cache[ARRAY] = r return r - + def fielddescrof(self, STRUCT, fname): key = (STRUCT, fname) try: @@ -407,12 +410,23 @@ jump(i0) """, """ [i0] - p0 = call_malloc_gc(ConstClass(malloc_array), 1, \ - %(bdescr.tid)d, i0, \ - descr=malloc_array_descr) + p0 = call_malloc_nursery_varsize(0, 1, i0, descr=bdescr) + setfield_gc(p0, i0, descr=blendescr) jump(i0) """) + def test_rewrite_new_string(self): + self.check_rewrite(""" + [i0] + p0 = newstr(i0) + jump(i0) + """, """ + [i0] + p0 = call_malloc_nursery_varsize(1, 1, i0, descr=strdescr) + setfield_gc(p0, i0, descr=strlendescr) + jump(i0) + """) + def test_rewrite_assembler_nonstandard_array(self): # a non-standard array is a bit hard to get; e.g. GcArray(Float) # is like that on Win32, but not on Linux. Build one manually... @@ -533,10 +547,12 @@ p1 = int_add(p0, %(strdescr.basesize + 16 * strdescr.itemsize)d) setfield_gc(p1, %(unicodedescr.tid)d, descr=tiddescr) setfield_gc(p1, 10, descr=unicodelendescr) - p2 = call_malloc_gc(ConstClass(malloc_unicode), i2, \ - descr=malloc_unicode_descr) - p3 = call_malloc_gc(ConstClass(malloc_str), i2, \ - descr=malloc_str_descr) + p2 = call_malloc_nursery_varsize(2, 4, i2, \ + descr=unicodedescr) + setfield_gc(p2, i2, descr=unicodelendescr) + p3 = call_malloc_nursery_varsize(1, 1, i2, \ + descr=strdescr) + setfield_gc(p3, i2, descr=strlendescr) jump() """) @@ -716,8 +732,9 @@ [i0] p0 = call_malloc_nursery(%(tdescr.size)d) setfield_gc(p0, 5678, descr=tiddescr) - p1 = call_malloc_gc(ConstClass(malloc_str), i0, \ - descr=malloc_str_descr) + p1 = call_malloc_nursery_varsize(1, 1, i0, \ + descr=strdescr) + setfield_gc(p1, i0, descr=strlendescr) cond_call_gc_wb(p0, p1, descr=wbdescr) setfield_raw(p0, p1, descr=tzdescr) jump() @@ -747,7 +764,7 @@ """, """ [i0, f0] i1 = getfield_gc(ConstClass(frame_info), descr=jfi_frame_size) - p1 = call_malloc_nursery_varsize_small(i1) + p1 = call_malloc_nursery_varsize_frame(i1) setfield_gc(p1, 0, descr=tiddescr) i2 = getfield_gc(ConstClass(frame_info), descr=jfi_frame_depth) setfield_gc(p1, i2, descr=framelendescr) diff --git a/rpython/jit/backend/test/runner_test.py b/rpython/jit/backend/test/runner_test.py --- a/rpython/jit/backend/test/runner_test.py +++ b/rpython/jit/backend/test/runner_test.py @@ -2833,7 +2833,7 @@ def test_assembler_call_propagate_exc(self): from rpython.jit.backend.llsupport.llmodel import AbstractLLCPU - + if not isinstance(self.cpu, AbstractLLCPU): py.test.skip("llgraph can't fake exceptions well enough, give up") @@ -3477,10 +3477,10 @@ ops = """ [i0] i1 = int_force_ge_zero(i0) # but forced to be in a register - finish(i1, descr=1) + finish(i1, descr=descr) """ + descr = BasicFinalDescr() loop = parse(ops, self.cpu, namespace=locals()) - descr = loop.operations[-1].getdescr() looptoken = JitCellToken() self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken) for inp, outp in [(2,2), (-3, 0)]: @@ -3493,21 +3493,20 @@ py.test.skip("pointless test on non-asm") from rpython.jit.backend.tool.viewcode import machine_code_dump import ctypes + targettoken = TargetToken() ops = """ [i2] i0 = same_as(i2) # but forced to be in a register - label(i0, descr=1) + label(i0, descr=targettoken) i1 = int_add(i0, i0) - guard_true(i1, descr=faildesr) [i1] - jump(i1, descr=1) + guard_true(i1, descr=faildescr) [i1] + jump(i1, descr=targettoken) """ faildescr = BasicFailDescr(2) loop = parse(ops, self.cpu, namespace=locals()) - faildescr = loop.operations[-2].getdescr() - jumpdescr = loop.operations[-1].getdescr() bridge_ops = """ [i0] - jump(i0, descr=jumpdescr) + jump(i0, descr=targettoken) """ bridge = parse(bridge_ops, self.cpu, namespace=locals()) looptoken = JitCellToken() diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -1,7 +1,7 @@ import sys import os -from rpython.jit.backend.llsupport import symbolic, jitframe +from rpython.jit.backend.llsupport import symbolic, jitframe, rewrite from rpython.jit.backend.llsupport.assembler import (GuardToken, BaseAssembler, DEBUG_COUNTER, debug_bridge) from rpython.jit.backend.llsupport.asmmemmgr import MachineDataBlockWrapper @@ -60,6 +60,7 @@ self.float_const_neg_addr = 0 self.float_const_abs_addr = 0 self.malloc_slowpath = 0 + self.malloc_slowpath_varsize = 0 self.wb_slowpath = [0, 0, 0, 0, 0] self.setup_failure_recovery() self.datablockwrapper = None @@ -158,27 +159,65 @@ mc.RET() self._frame_realloc_slowpath = mc.materialize(self.cpu.asmmemmgr, []) - def _build_malloc_slowpath(self): - """ While arriving on slowpath, we have a gcpattern on stack, - nursery_head in eax and the size in edi - eax + def _build_malloc_slowpath(self, kind): + """ While arriving on slowpath, we have a gcpattern on stack 0. + The arguments are passed in eax and edi, as follows: + + kind == 'fixed': nursery_head in eax and the size in edi - eax. + + kind == 'str/unicode': length of the string to allocate in edi. + + kind == 'var': length to allocate in edi, tid in eax, + and itemsize in the stack 1 (position esp+WORD). + + This function must preserve all registers apart from eax and edi. """ + assert kind in ['fixed', 'str', 'unicode', 'var'] mc = codebuf.MachineCodeBlockWrapper() self._push_all_regs_to_frame(mc, [eax, edi], self.cpu.supports_floats) + # store the gc pattern ofs = self.cpu.get_ofs_of_frame_field('jf_gcmap') - # store the gc pattern mc.MOV_rs(ecx.value, WORD) mc.MOV_br(ofs, ecx.value) - addr = self.cpu.gc_ll_descr.get_malloc_slowpath_addr() - mc.SUB_rr(edi.value, eax.value) # compute the size we want - # the arg is already in edi - mc.SUB_ri(esp.value, 16 - WORD) - if IS_X86_32: - mc.MOV_sr(0, edi.value) - if hasattr(self.cpu.gc_ll_descr, 'passes_frame'): - mc.MOV_sr(WORD, ebp.value) - elif hasattr(self.cpu.gc_ll_descr, 'passes_frame'): - # for tests only - mc.MOV_rr(esi.value, ebp.value) + # + if kind == 'fixed': + addr = self.cpu.gc_ll_descr.get_malloc_slowpath_addr() + elif kind == 'str': + addr = self.cpu.gc_ll_descr.get_malloc_fn_addr('malloc_str') + elif kind == 'unicode': + addr = self.cpu.gc_ll_descr.get_malloc_fn_addr('malloc_unicode') + else: + addr = self.cpu.gc_ll_descr.get_malloc_slowpath_array_addr() + mc.SUB_ri(esp.value, 16 - WORD) # restore 16-byte alignment + # magically, the above is enough on X86_32 to reserve 3 stack places + if kind == 'fixed': + mc.SUB_rr(edi.value, eax.value) # compute the size we want + # the arg is already in edi + if IS_X86_32: + mc.MOV_sr(0, edi.value) + if hasattr(self.cpu.gc_ll_descr, 'passes_frame'): + mc.MOV_sr(WORD, ebp.value) + elif hasattr(self.cpu.gc_ll_descr, 'passes_frame'): + # for tests only + mc.MOV_rr(esi.value, ebp.value) + elif kind == 'str' or kind == 'unicode': + if IS_X86_32: + # stack layout: [---][---][---][ret].. with 3 free stack places + mc.MOV_sr(0, edi.value) # store the length + else: + pass # length already in edi + else: + if IS_X86_32: + # stack layout: [---][---][---][ret][gcmap][itemsize]... + mc.MOV_sr(WORD * 2, edi.value) # store the length + mc.MOV_sr(WORD * 1, eax.value) # store the tid + mc.MOV_rs(edi.value, WORD * 5) # load the itemsize + mc.MOV_sr(WORD * 0, edi.value) # store the itemsize + else: + # stack layout: [---][ret][gcmap][itemsize]... + mc.MOV_rr(edx.value, edi.value) # length + mc.MOV_rr(esi.value, eax.value) # tid + mc.MOV_rs(edi.value, WORD * 3) # load the itemsize self.set_extra_stack_depth(mc, 16) mc.CALL(imm(addr)) mc.ADD_ri(esp.value, 16 - WORD) @@ -205,7 +244,7 @@ mc.JMP(imm(self.propagate_exception_path)) # rawstart = mc.materialize(self.cpu.asmmemmgr, []) - self.malloc_slowpath = rawstart + return rawstart def _build_propagate_exception_path(self): if not self.cpu.propagate_exception_descr: @@ -2336,11 +2375,16 @@ self.mc.overwrite(jmp_adr-1, chr(offset)) self.mc.MOV(heap(nursery_free_adr), edi) - def malloc_cond_varsize_small(self, nursery_free_adr, nursery_top_adr, + def malloc_cond_varsize_frame(self, nursery_free_adr, nursery_top_adr, sizeloc, gcmap): - self.mc.MOV(edi, heap(nursery_free_adr)) - self.mc.MOV(eax, edi) - self.mc.ADD(edi, sizeloc) + if sizeloc is eax: + self.mc.MOV(edi, sizeloc) + sizeloc = edi + self.mc.MOV(eax, heap(nursery_free_adr)) + if sizeloc is edi: + self.mc.ADD_rr(edi.value, eax.value) + else: + self.mc.LEA_ra(edi.value, (eax.value, sizeloc.value, 0, 0)) self.mc.CMP(edi, heap(nursery_top_adr)) self.mc.J_il8(rx86.Conditions['NA'], 0) # patched later jmp_adr = self.mc.get_relative_pos() @@ -2352,6 +2396,80 @@ self.mc.overwrite(jmp_adr-1, chr(offset)) self.mc.MOV(heap(nursery_free_adr), edi) + def malloc_cond_varsize(self, kind, nursery_free_adr, nursery_top_adr, + lengthloc, itemsize, maxlength, gcmap, + arraydescr): + from rpython.jit.backend.llsupport.descr import ArrayDescr + assert isinstance(arraydescr, ArrayDescr) + + # lengthloc is the length of the array, which we must not modify! + assert lengthloc is not eax and lengthloc is not edi + if isinstance(lengthloc, RegLoc): + varsizeloc = lengthloc + else: + self.mc.MOV(edi, lengthloc) + varsizeloc = edi + + self.mc.CMP(varsizeloc, imm(maxlength)) + self.mc.J_il8(rx86.Conditions['A'], 0) # patched later + jmp_adr0 = self.mc.get_relative_pos() + + self.mc.MOV(eax, heap(nursery_free_adr)) + shift = size2shift(itemsize) + if shift < 0: + self.mc.IMUL_rri(edi.value, varsizeloc.value, itemsize) + varsizeloc = edi + shift = 0 + # now varsizeloc is a register != eax. The size of + # the variable part of the array is (varsizeloc << shift) + assert arraydescr.basesize >= self.gc_minimal_size_in_nursery + constsize = arraydescr.basesize + self.gc_size_of_header + force_realignment = (itemsize % WORD) != 0 + if force_realignment: + constsize += WORD - 1 + self.mc.LEA_ra(edi.value, (eax.value, varsizeloc.value, shift, + constsize)) + if force_realignment: + self.mc.AND_ri(edi.value, ~(WORD - 1)) + # now edi contains the total size in bytes, rounded up to a multiple + # of WORD, plus nursery_free_adr + self.mc.CMP(edi, heap(nursery_top_adr)) + self.mc.J_il8(rx86.Conditions['NA'], 0) # patched later + jmp_adr1 = self.mc.get_relative_pos() + # + offset = self.mc.get_relative_pos() - jmp_adr0 + assert 0 < offset <= 127 + self.mc.overwrite(jmp_adr0-1, chr(offset)) + # save the gcmap + self.push_gcmap(self.mc, gcmap, mov=True) # mov into RawEspLoc(0) + if kind == rewrite.FLAG_ARRAY: + self.mc.MOV_si(WORD, itemsize) + self.mc.MOV(edi, lengthloc) + self.mc.MOV_ri(eax.value, arraydescr.tid) + addr = self.malloc_slowpath_varsize + else: + if kind == rewrite.FLAG_STR: + addr = self.malloc_slowpath_str + else: + assert kind == rewrite.FLAG_UNICODE + addr = self.malloc_slowpath_unicode + self.mc.MOV(edi, lengthloc) + self.mc.CALL(imm(addr)) + self.mc.JMP_l8(0) # jump to done, patched later + jmp_location = self.mc.get_relative_pos() + # + offset = self.mc.get_relative_pos() - jmp_adr1 + assert 0 < offset <= 127 + self.mc.overwrite(jmp_adr1-1, chr(offset)) + # write down the tid, but not if it's the result of the CALL + self.mc.MOV(mem(eax, 0), imm(arraydescr.tid)) + # while we're at it, this line is not needed if we've done the CALL + self.mc.MOV(heap(nursery_free_adr), edi) + # + offset = self.mc.get_relative_pos() - jmp_location + assert 0 < offset <= 127 + self.mc.overwrite(jmp_location - 1, chr(offset)) + def force_token(self, reg): # XXX kill me assert isinstance(reg, RegLoc) @@ -2405,5 +2523,13 @@ os.write(2, '[x86/asm] %s\n' % msg) raise NotImplementedError(msg) +def size2shift(size): + "Return a result 0..3 such that (1< propagate MemoryError 'CALL_MALLOC_NURSERY/1', # nursery malloc, const number of bytes, zeroed - 'CALL_MALLOC_NURSERY_VARSIZE_SMALL/1', + 'CALL_MALLOC_NURSERY_VARSIZE/3d', + 'CALL_MALLOC_NURSERY_VARSIZE_FRAME/1', # nursery malloc, non-const number of bytes, zeroed # note that the number of bytes must be well known to be small enough # to fulfill allocating in the nursery rules (and no card markings) diff --git a/rpython/jit/metainterp/test/test_logger.py b/rpython/jit/metainterp/test/test_logger.py --- a/rpython/jit/metainterp/test/test_logger.py +++ b/rpython/jit/metainterp/test/test_logger.py @@ -93,7 +93,7 @@ [p0] setfield_gc(p0, 3, descr=somedescr) ''' - Descr() + somedescr = Descr() self.reparse(inp, namespace=locals()) def test_guard(self): diff --git a/rpython/jit/tool/oparser.py b/rpython/jit/tool/oparser.py --- a/rpython/jit/tool/oparser.py +++ b/rpython/jit/tool/oparser.py @@ -106,6 +106,8 @@ tt = self.model.TargetToken(token) self._consts[poss_descr] = tt return tt + else: + raise def box_for_var(self, elem): try: diff --git a/rpython/memory/gctransform/framework.py b/rpython/memory/gctransform/framework.py --- a/rpython/memory/gctransform/framework.py +++ b/rpython/memory/gctransform/framework.py @@ -129,8 +129,6 @@ def __init__(self, translator): from rpython.memory.gc.base import choose_gc_from_config - from rpython.memory.gc.base import ARRAY_TYPEID_MAP - from rpython.memory.gc import inspector super(BaseFrameworkGCTransformer, self).__init__(translator, inline=True) @@ -232,7 +230,51 @@ classdef = bk.getuniqueclassdef(GCClass) s_gc = annmodel.SomeInstance(classdef) + + self._declare_functions(GCClass, getfn, s_gc, s_typeid16) + + # thread support + if translator.config.translation.continuation: + root_walker.stacklet_support = True + root_walker.need_stacklet_support(self, getfn) + if translator.config.translation.thread: + root_walker.need_thread_support(self, getfn) + + self.layoutbuilder.encode_type_shapes_now() + + annhelper.finish() # at this point, annotate all mix-level helpers + annhelper.backend_optimize() + + self.collect_analyzer = CollectAnalyzer(self.translator) + self.collect_analyzer.analyze_all() + + s_gc = self.translator.annotator.bookkeeper.valueoftype(GCClass) + r_gc = self.translator.rtyper.getrepr(s_gc) + self.c_const_gc = rmodel.inputconst(r_gc, self.gcdata.gc) + s_gc_data = self.translator.annotator.bookkeeper.valueoftype( + gctypelayout.GCData) + r_gc_data = self.translator.rtyper.getrepr(s_gc_data) + self.c_const_gcdata = rmodel.inputconst(r_gc_data, self.gcdata) + self.malloc_zero_filled = GCClass.malloc_zero_filled + + HDR = self.HDR = self.gcdata.gc.gcheaderbuilder.HDR + + size_gc_header = self.gcdata.gc.gcheaderbuilder.size_gc_header + vtableinfo = (HDR, size_gc_header, self.gcdata.gc.typeid_is_in_field) + self.c_vtableinfo = rmodel.inputconst(lltype.Void, vtableinfo) + tig = self.layoutbuilder.type_info_group._as_ptr() + self.c_type_info_group = rmodel.inputconst(lltype.typeOf(tig), tig) + sko = llmemory.sizeof(gcdata.TYPE_INFO) + self.c_vtinfo_skip_offset = rmodel.inputconst(lltype.typeOf(sko), sko) + + + def _declare_functions(self, GCClass, getfn, s_gc, s_typeid16): + from rpython.memory.gc.base import ARRAY_TYPEID_MAP + from rpython.memory.gc import inspector + s_gcref = annmodel.SomePtr(llmemory.GCREF) + gcdata = self.gcdata + translator = self.translator malloc_fixedsize_clear_meth = GCClass.malloc_fixedsize_clear.im_func self.malloc_fixedsize_clear_ptr = getfn( @@ -466,39 +508,6 @@ [annmodel.SomeAddress()], annmodel.s_None) - # thread support - if translator.config.translation.continuation: - root_walker.stacklet_support = True - root_walker.need_stacklet_support(self, getfn) - if translator.config.translation.thread: - root_walker.need_thread_support(self, getfn) - - self.layoutbuilder.encode_type_shapes_now() - - annhelper.finish() # at this point, annotate all mix-level helpers - annhelper.backend_optimize() - - self.collect_analyzer = CollectAnalyzer(self.translator) - self.collect_analyzer.analyze_all() - - s_gc = self.translator.annotator.bookkeeper.valueoftype(GCClass) - r_gc = self.translator.rtyper.getrepr(s_gc) - self.c_const_gc = rmodel.inputconst(r_gc, self.gcdata.gc) - s_gc_data = self.translator.annotator.bookkeeper.valueoftype( - gctypelayout.GCData) - r_gc_data = self.translator.rtyper.getrepr(s_gc_data) - self.c_const_gcdata = rmodel.inputconst(r_gc_data, self.gcdata) - self.malloc_zero_filled = GCClass.malloc_zero_filled - - HDR = self.HDR = self.gcdata.gc.gcheaderbuilder.HDR - - size_gc_header = self.gcdata.gc.gcheaderbuilder.size_gc_header - vtableinfo = (HDR, size_gc_header, self.gcdata.gc.typeid_is_in_field) - self.c_vtableinfo = rmodel.inputconst(lltype.Void, vtableinfo) - tig = self.layoutbuilder.type_info_group._as_ptr() - self.c_type_info_group = rmodel.inputconst(lltype.typeOf(tig), tig) - sko = llmemory.sizeof(gcdata.TYPE_INFO) - self.c_vtinfo_skip_offset = rmodel.inputconst(lltype.typeOf(sko), sko) def consider_constant(self, TYPE, value): self.layoutbuilder.consider_constant(TYPE, value, self.gcdata.gc) diff --git a/rpython/rlib/clibffi.py b/rpython/rlib/clibffi.py --- a/rpython/rlib/clibffi.py +++ b/rpython/rlib/clibffi.py @@ -4,6 +4,7 @@ from rpython.rtyper.tool import rffi_platform from rpython.rtyper.lltypesystem import lltype, rffi +from rpython.rtyper.tool import rffi_platform from rpython.rlib.unroll import unrolling_iterable from rpython.rlib.rarithmetic import intmask, is_emulated_long from rpython.rlib.objectmodel import we_are_translated @@ -15,6 +16,7 @@ from rpython.translator.tool.cbuild import ExternalCompilationInfo from rpython.translator.platform import platform from rpython.conftest import cdir +from platform import machine import py import os import sys @@ -35,6 +37,8 @@ _LITTLE_ENDIAN = sys.byteorder == 'little' _BIG_ENDIAN = sys.byteorder == 'big' +_ARM = rffi_platform.getdefined('__arm__', '') + if _WIN32: from rpython.rlib import rwin32 @@ -154,6 +158,10 @@ if _WIN32 and not _WIN64: FFI_STDCALL = rffi_platform.ConstantInteger('FFI_STDCALL') + if _ARM: + FFI_SYSV = rffi_platform.ConstantInteger('FFI_SYSV') + FFI_VFP = rffi_platform.ConstantInteger('FFI_VFP') + FFI_TYPE_STRUCT = rffi_platform.ConstantInteger('FFI_TYPE_STRUCT') size_t = rffi_platform.SimpleType("size_t", rffi.ULONG) @@ -327,6 +335,9 @@ FFI_DEFAULT_ABI = cConfig.FFI_DEFAULT_ABI if _WIN32 and not _WIN64: FFI_STDCALL = cConfig.FFI_STDCALL +if _ARM: + FFI_SYSV = cConfig.FFI_SYSV + FFI_VFP = cConfig.FFI_VFP FFI_TYPE_STRUCT = cConfig.FFI_TYPE_STRUCT FFI_CIFP = lltype.Ptr(cConfig.ffi_cif) diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py --- a/rpython/rlib/rposix.py +++ b/rpython/rlib/rposix.py @@ -266,4 +266,3 @@ os_kill = rwin32.os_kill else: os_kill = os.kill - diff --git a/rpython/rlib/streamio.py b/rpython/rlib/streamio.py --- a/rpython/rlib/streamio.py +++ b/rpython/rlib/streamio.py @@ -89,7 +89,7 @@ def _setfd_binary(fd): pass - + def fdopen_as_stream(fd, mode, buffering=-1): # XXX XXX XXX you want do check whether the modes are compatible # otherwise you get funny results diff --git a/rpython/rtyper/module/ll_os_environ.py b/rpython/rtyper/module/ll_os_environ.py --- a/rpython/rtyper/module/ll_os_environ.py +++ b/rpython/rtyper/module/ll_os_environ.py @@ -1,4 +1,5 @@ -import os, sys +import os +import sys from rpython.annotator import model as annmodel from rpython.rtyper.controllerentry import Controller from rpython.rtyper.extfunc import register_external @@ -10,27 +11,32 @@ # ____________________________________________________________ # -# Annotation support to control access to 'os.environ' in the RPython program +# Annotation support to control access to 'os.environ' in the RPython +# program class OsEnvironController(Controller): knowntype = os.environ.__class__ def convert(self, obj): - return None # 'None' is good enough, there is only one os.environ + # 'None' is good enough, there is only one os.environ + return None def getitem(self, obj, key): - # in the RPython program reads of 'os.environ[key]' are redirected here + # in the RPython program reads of 'os.environ[key]' are + # redirected here result = r_getenv(key) if result is None: raise KeyError return result def setitem(self, obj, key, value): - # in the RPython program, 'os.environ[key] = value' is redirected here + # in the RPython program, 'os.environ[key] = value' is + # redirected here r_putenv(key, value) def delitem(self, obj, key): - # in the RPython program, 'del os.environ[key]' is redirected here + # in the RPython program, 'del os.environ[key]' is redirected + # here absent = r_getenv(key) is None # Always call unsetenv(), to get eventual OSErrors r_unsetenv(key) @@ -38,16 +44,18 @@ raise KeyError def get_keys(self, obj): - # 'os.environ.keys' is redirected here - note that it's the getattr - # that arrives here, not the actual method call! + # 'os.environ.keys' is redirected here - note that it's the + # getattr that arrives here, not the actual method call! return r_envkeys def get_items(self, obj): - # 'os.environ.items' is redirected here (not the actual method call!) + # 'os.environ.items' is redirected here (not the actual method + # call!) return r_envitems def get_get(self, obj): - # 'os.environ.get' is redirected here (not the actual method call!) + # 'os.environ.get' is redirected here (not the actual method + # call!) return r_getenv # ____________________________________________________________ @@ -57,19 +65,16 @@ def r_getenv(name): just_a_placeholder # should return None if name not found -os_getenv = rffi.llexternal('getenv', [rffi.CCHARP], rffi.CCHARP, threadsafe=False) +os_getenv = rffi.llexternal('getenv', [rffi.CCHARP], rffi.CCHARP, + threadsafe=False) def getenv_llimpl(name): - l_name = rffi.str2charp(name) - l_result = os_getenv(l_name) - if l_result: - result = rffi.charp2str(l_result) - else: - result = None - rffi.free_charp(l_name) - return result + with rffi.scoped_str2charp(name) as l_name: + l_result = os_getenv(l_name) + return rffi.charp2str(l_result) if l_result else None -register_external(r_getenv, [str0], annmodel.SomeString(can_be_None=True, no_nul=True), +register_external(r_getenv, [str0], + annmodel.SomeString(can_be_None=True, no_nul=True), export_name='ll_os.ll_os_getenv', llimpl=getenv_llimpl) @@ -112,9 +117,8 @@ os_unsetenv = rffi.llexternal('unsetenv', [rffi.CCHARP], rffi.INT) def unsetenv_llimpl(name): - l_name = rffi.str2charp(name) - error = rffi.cast(lltype.Signed, os_unsetenv(l_name)) - rffi.free_charp(l_name) + with rffi.scoped_str2charp(name) as l_name: + error = rffi.cast(lltype.Signed, os_unsetenv(l_name)) if error: raise OSError(rposix.get_errno(), "os_unsetenv failed") try: @@ -148,9 +152,8 @@ '_environ', ExternalCompilationInfo(includes=['stdlib.h'])) else: - os_get_environ, _os_set_environ = rffi.CExternVariable(rffi.CCHARPP, - 'environ', - ExternalCompilationInfo()) + os_get_environ, _os_set_environ = rffi.CExternVariable( + rffi.CCHARPP, 'environ', ExternalCompilationInfo()) # ____________________________________________________________ diff --git a/rpython/tool/logparser.py b/rpython/tool/logparser.py --- a/rpython/tool/logparser.py +++ b/rpython/tool/logparser.py @@ -70,7 +70,11 @@ time = int(int(match.group(1), 16)) time_decrase = time_decrase or time < lasttime lasttime = time - record(match.group(2), time=int(match.group(1), 16)) + try: + record(match.group(2), time=int(match.group(1), 16)) + except: + print "Line", i + raise if verbose: sys.stderr.write('loaded\n') if performance_log and time_decrase: diff --git a/rpython/translator/c/database.py b/rpython/translator/c/database.py --- a/rpython/translator/c/database.py +++ b/rpython/translator/c/database.py @@ -64,9 +64,8 @@ self.instrument_ncounter = 0 - def gettypedefnode(self, T, varlength=1): - if varlength <= 1: - varlength = 1 # it's C after all + def gettypedefnode(self, T, varlength=None): + if varlength is None: key = T else: key = T, varlength @@ -94,7 +93,7 @@ self.pendingsetupnodes.append(node) return node - def gettype(self, T, varlength=1, who_asks=None, argnames=[]): + def gettype(self, T, varlength=None, who_asks=None, argnames=[]): if isinstance(T, Primitive) or T == GCREF: return PrimitiveType[T] elif isinstance(T, Typedef): diff --git a/rpython/translator/c/node.py b/rpython/translator/c/node.py --- a/rpython/translator/c/node.py +++ b/rpython/translator/c/node.py @@ -47,12 +47,12 @@ typetag = 'struct' extra_union_for_varlength = True - def __init__(self, db, STRUCT, varlength=1): + def __init__(self, db, STRUCT, varlength=None): NodeWithDependencies.__init__(self, db) self.STRUCT = STRUCT self.LLTYPE = STRUCT self.varlength = varlength - if varlength == 1: + if varlength is None: basename = STRUCT._name with_number = True else: @@ -93,7 +93,7 @@ self.fields = [] db = self.db STRUCT = self.STRUCT - if self.varlength != 1: + if self.varlength is not None: self.normalizedtypename = db.gettype(STRUCT, who_asks=self) if needs_gcheader(self.STRUCT): HDR = db.gcpolicy.struct_gcheader_definition(self) @@ -120,7 +120,7 @@ rtti = getRuntimeTypeInfo(STRUCT) except ValueError: pass - if self.varlength == 1: + if self.varlength is None: self.db.gcpolicy.struct_setup(self, rtti) return self.gcinfo gcinfo = defaultproperty(computegcinfo) @@ -160,12 +160,14 @@ if typename == PrimitiveType[Void]: line = '/* %s */' % line else: + if is_empty and typename.endswith('[RPY_VARLENGTH]'): + yield '\tRPY_DUMMY_VARLENGTH' is_empty = False yield '\t' + line if is_empty: yield '\t' + 'char _dummy; /* this struct is empty */' yield '};' - if self.varlength != 1: + if self.varlength is not None: assert self.typetag == 'struct' yield 'union %su {' % self.name yield ' struct %s a;' % self.name @@ -182,7 +184,7 @@ def debug_offsets(self): # generate number exprs giving the offset of the elements in the struct - assert self.varlength == 1 + assert self.varlength is None for name in self.fieldnames: FIELD_T = self.c_struct_field_type(name) if FIELD_T is Void: @@ -196,18 +198,25 @@ yield 'offsetof(%s %s, %s)' % (self.typetag, self.name, cname) +def deflength(varlength): + if varlength is None: + return 'RPY_VARLENGTH' + elif varlength == 0: + return 'RPY_LENGTH0' + else: + return varlength class ArrayDefNode(NodeWithDependencies): typetag = 'struct' extra_union_for_varlength = True - def __init__(self, db, ARRAY, varlength=1): + def __init__(self, db, ARRAY, varlength=None): NodeWithDependencies.__init__(self, db) self.ARRAY = ARRAY self.LLTYPE = ARRAY self.gcfields = [] self.varlength = varlength - if varlength == 1: + if varlength is None: basename = 'array' with_number = True else: @@ -226,7 +235,7 @@ db = self.db ARRAY = self.ARRAY self.gcinfo # force it to be computed - if self.varlength != 1: + if self.varlength is not None: self.normalizedtypename = db.gettype(ARRAY, who_asks=self) if needs_gcheader(ARRAY): HDR = db.gcpolicy.array_gcheader_definition(self) @@ -238,7 +247,7 @@ def computegcinfo(self): # let the gcpolicy do its own setup self.gcinfo = None # unless overwritten below - if self.varlength == 1: + if self.varlength is None: self.db.gcpolicy.array_setup(self) return self.gcinfo gcinfo = defaultproperty(computegcinfo) @@ -269,21 +278,22 @@ yield '\t' + cdecl(typename, fname) + ';' if not self.ARRAY._hints.get('nolength', False): yield '\tlong length;' - line = '%s;' % cdecl(self.itemtypename, 'items[%d]'% self.varlength) + line = '%s;' % cdecl(self.itemtypename, + 'items[%s]' % deflength(self.varlength)) if self.ARRAY.OF is Void: # strange line = '/* array of void */' if self.ARRAY._hints.get('nolength', False): line = 'char _dummy; ' + line yield '\t' + line yield '};' - if self.varlength != 1: + if self.varlength is not None: yield 'union %su {' % self.name yield ' struct %s a;' % self.name yield ' %s;' % cdecl(self.normalizedtypename, 'b') yield '};' def visitor_lines(self, prefix, on_item): - assert self.varlength == 1 + assert self.varlength is None ARRAY = self.ARRAY # we need a unique name for this C variable, or at least one that does # not collide with the expression in 'prefix' @@ -310,7 +320,7 @@ def debug_offsets(self): # generate three offsets for debugging inspection - assert self.varlength == 1 + assert self.varlength is None if not self.ARRAY._hints.get('nolength', False): yield 'offsetof(struct %s, length)' % (self.name,) else: @@ -333,7 +343,7 @@ forward_decl = None extra_union_for_varlength = False - def __init__(self, db, ARRAY, varlength=1): + def __init__(self, db, ARRAY, varlength=None): NodeWithDependencies.__init__(self, db) self.ARRAY = ARRAY self.LLTYPE = ARRAY @@ -342,8 +352,8 @@ # There is no such thing as an array of voids: # we use a an array of chars instead; only the pointer can be void*. self.itemtypename = db.gettype(contained_type, who_asks=self) - self.fulltypename = self.itemtypename.replace('@', '(@)[%d]' % - (self.varlength,)) + self.fulltypename = self.itemtypename.replace('@', '(@)[%s]' % + deflength(varlength)) if ARRAY._hints.get("render_as_void"): self.fullptrtypename = 'void *@' else: @@ -493,7 +503,8 @@ Node.__init__(self, db) self.obj = obj self.typename = db.gettype(T) #, who_asks=self) - self.implementationtypename = db.gettype(T, varlength=self.getlength()) + self.implementationtypename = db.gettype( + T, varlength=self.getvarlength()) parent, parentindex = parentlink(obj) From noreply at buildbot.pypy.org Thu Apr 18 03:57:45 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Thu, 18 Apr 2013 03:57:45 +0200 (CEST) Subject: [pypy-commit] pypy default: the annotator has deemed these necessary Message-ID: <20130418015745.353A11C317D@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: Changeset: r63470:09b70e01d3c6 Date: 2013-04-17 18:56 -0700 http://bitbucket.org/pypy/pypy/changeset/09b70e01d3c6/ Log: the annotator has deemed these necessary diff --git a/rpython/rtyper/lltypesystem/rffi.py b/rpython/rtyper/lltypesystem/rffi.py --- a/rpython/rtyper/lltypesystem/rffi.py +++ b/rpython/rtyper/lltypesystem/rffi.py @@ -1059,6 +1059,7 @@ self.buf = str2charp(value) else: self.buf = lltype.nullptr(CCHARP.TO) + __init__._annenforceargs_ = [None, str] def __enter__(self): return self.buf def __exit__(self, *args): @@ -1072,6 +1073,7 @@ self.buf = unicode2wcharp(value) else: self.buf = lltype.nullptr(CWCHARP.TO) + __init__._annenforceargs_ = [None, unicode] def __enter__(self): return self.buf def __exit__(self, *args): From noreply at buildbot.pypy.org Thu Apr 18 03:57:46 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Thu, 18 Apr 2013 03:57:46 +0200 (CEST) Subject: [pypy-commit] pypy py3k: merge default Message-ID: <20130418015746.639321C317D@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63471:0b3850fd3bfe Date: 2013-04-17 18:57 -0700 http://bitbucket.org/pypy/pypy/changeset/0b3850fd3bfe/ Log: merge default diff --git a/rpython/rtyper/lltypesystem/rffi.py b/rpython/rtyper/lltypesystem/rffi.py --- a/rpython/rtyper/lltypesystem/rffi.py +++ b/rpython/rtyper/lltypesystem/rffi.py @@ -1059,6 +1059,7 @@ self.buf = str2charp(value) else: self.buf = lltype.nullptr(CCHARP.TO) + __init__._annenforceargs_ = [None, str] def __enter__(self): return self.buf def __exit__(self, *args): @@ -1072,6 +1073,7 @@ self.buf = unicode2wcharp(value) else: self.buf = lltype.nullptr(CWCHARP.TO) + __init__._annenforceargs_ = [None, unicode] def __enter__(self): return self.buf def __exit__(self, *args): From noreply at buildbot.pypy.org Thu Apr 18 05:40:58 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Thu, 18 Apr 2013 05:40:58 +0200 (CEST) Subject: [pypy-commit] pypy default: allow Nones Message-ID: <20130418034058.E309B1C01FD@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: Changeset: r63472:0147ac3c2583 Date: 2013-04-17 20:31 -0700 http://bitbucket.org/pypy/pypy/changeset/0147ac3c2583/ Log: allow Nones diff --git a/rpython/rtyper/lltypesystem/rffi.py b/rpython/rtyper/lltypesystem/rffi.py --- a/rpython/rtyper/lltypesystem/rffi.py +++ b/rpython/rtyper/lltypesystem/rffi.py @@ -1059,7 +1059,7 @@ self.buf = str2charp(value) else: self.buf = lltype.nullptr(CCHARP.TO) - __init__._annenforceargs_ = [None, str] + __init__._annenforceargs_ = [None, annmodel.SomeString(can_be_None=True)] def __enter__(self): return self.buf def __exit__(self, *args): @@ -1073,7 +1073,8 @@ self.buf = unicode2wcharp(value) else: self.buf = lltype.nullptr(CWCHARP.TO) - __init__._annenforceargs_ = [None, unicode] + __init__._annenforceargs_ = [None, + annmodel.SomeUnicodeString(can_be_None=True)] def __enter__(self): return self.buf def __exit__(self, *args): From noreply at buildbot.pypy.org Thu Apr 18 05:41:00 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Thu, 18 Apr 2013 05:41:00 +0200 (CEST) Subject: [pypy-commit] pypy py3k: merge default Message-ID: <20130418034100.3D3961C01FD@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63473:b9501c954681 Date: 2013-04-17 20:33 -0700 http://bitbucket.org/pypy/pypy/changeset/b9501c954681/ Log: merge default diff --git a/rpython/rtyper/lltypesystem/rffi.py b/rpython/rtyper/lltypesystem/rffi.py --- a/rpython/rtyper/lltypesystem/rffi.py +++ b/rpython/rtyper/lltypesystem/rffi.py @@ -1059,7 +1059,7 @@ self.buf = str2charp(value) else: self.buf = lltype.nullptr(CCHARP.TO) - __init__._annenforceargs_ = [None, str] + __init__._annenforceargs_ = [None, annmodel.SomeString(can_be_None=True)] def __enter__(self): return self.buf def __exit__(self, *args): @@ -1073,7 +1073,8 @@ self.buf = unicode2wcharp(value) else: self.buf = lltype.nullptr(CWCHARP.TO) - __init__._annenforceargs_ = [None, unicode] + __init__._annenforceargs_ = [None, + annmodel.SomeUnicodeString(can_be_None=True)] def __enter__(self): return self.buf def __exit__(self, *args): From noreply at buildbot.pypy.org Thu Apr 18 07:56:30 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Thu, 18 Apr 2013 07:56:30 +0200 (CEST) Subject: [pypy-commit] pypy py3k: fix getfunc on windows Message-ID: <20130418055630.65B671C04BB@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63474:ac3fd5644f1d Date: 2013-04-17 22:55 -0700 http://bitbucket.org/pypy/pypy/changeset/ac3fd5644f1d/ Log: fix getfunc on windows diff --git a/pypy/module/_ffi/interp_funcptr.py b/pypy/module/_ffi/interp_funcptr.py --- a/pypy/module/_ffi/interp_funcptr.py +++ b/pypy/module/_ffi/interp_funcptr.py @@ -21,7 +21,8 @@ def _getfunc(space, CDLL, w_name, w_argtypes, w_restype): argtypes_w, argtypes, w_restype, restype = unpack_argtypes( space, w_argtypes, w_restype) - if space.isinstance_w(w_name, space.w_str): + if space.isinstance_w(w_name, space.w_unicode): + # XXX: support LoadLibraryW name = space.str_w(w_name) try: func = CDLL.cdll.getpointer(name, argtypes, restype, From noreply at buildbot.pypy.org Thu Apr 18 09:13:03 2013 From: noreply at buildbot.pypy.org (arigo) Date: Thu, 18 Apr 2013 09:13:03 +0200 (CEST) Subject: [pypy-commit] pypy default: typos (thanks kirma) Message-ID: <20130418071303.111121C3206@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63475:f4d28fb34dc2 Date: 2013-04-18 09:12 +0200 http://bitbucket.org/pypy/pypy/changeset/f4d28fb34dc2/ Log: typos (thanks kirma) diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -43,11 +43,11 @@ Rudimentary support for bytearray in RPython .. branch: refactor-call_release_gil -Fix a bug which casused cffi to return the wrong result when calling a C +Fix a bug which caused cffi to return the wrong result when calling a C function which calls a Python callback which forces the frames .. branch: virtual-raw-mallocs -JIT optimizations which makes cffi calls even faster, by removing the need to +JIT optimizations which make cffi calls even faster, by removing the need to allocate a temporary buffer where to store the arguments. .. branch: improve-docs-2 From noreply at buildbot.pypy.org Thu Apr 18 09:30:34 2013 From: noreply at buildbot.pypy.org (arigo) Date: Thu, 18 Apr 2013 09:30:34 +0200 (CEST) Subject: [pypy-commit] pypy.org extradoc: Update the version number of CPython that we follow. Message-ID: <20130418073034.55C161C3207@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: extradoc Changeset: r403:ed89fe5e5c7b Date: 2013-04-18 09:30 +0200 http://bitbucket.org/pypy/pypy.org/changeset/ed89fe5e5c7b/ Log: Update the version number of CPython that we follow. diff --git a/index.html b/index.html --- a/index.html +++ b/index.html @@ -47,7 +47,7 @@

          PyPy

          PyPy is a fast, compliant alternative implementation of the Python -language (2.7.2). It has several advantages and distinct features:

          +language (2.7.3). It has several advantages and distinct features:

          • Speed: thanks to its Just-in-Time compiler, Python programs diff --git a/source/index.txt b/source/index.txt --- a/source/index.txt +++ b/source/index.txt @@ -4,7 +4,7 @@ --- PyPy is a `fast`_, `compliant`_ alternative implementation of the `Python`_ -language (2.7.2). It has several advantages and distinct features: +language (2.7.3). It has several advantages and distinct features: * **Speed:** thanks to its Just-in-Time compiler, Python programs often run `faster`_ on PyPy. `(What is a JIT compiler?)`_ From noreply at buildbot.pypy.org Thu Apr 18 10:30:47 2013 From: noreply at buildbot.pypy.org (arigo) Date: Thu, 18 Apr 2013 10:30:47 +0200 (CEST) Subject: [pypy-commit] pypy default: size2shift() already exists as _get_scale(). Message-ID: <20130418083047.229A31C034F@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63476:c9796f6f5eeb Date: 2013-04-18 10:30 +0200 http://bitbucket.org/pypy/pypy/changeset/c9796f6f5eeb/ Log: size2shift() already exists as _get_scale(). diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -2415,8 +2415,9 @@ jmp_adr0 = self.mc.get_relative_pos() self.mc.MOV(eax, heap(nursery_free_adr)) - shift = size2shift(itemsize) - if shift < 0: + if _valid_addressing_size(itemsize): + shift = _get_scale(itemsize) + else: self.mc.IMUL_rri(edi.value, varsizeloc.value, itemsize) varsizeloc = edi shift = 0 @@ -2523,13 +2524,5 @@ os.write(2, '[x86/asm] %s\n' % msg) raise NotImplementedError(msg) -def size2shift(size): - "Return a result 0..3 such that (1< Author: Armin Rigo Branch: Changeset: r63477:793a48310a42 Date: 2013-04-18 11:06 +0200 http://bitbucket.org/pypy/pypy/changeset/793a48310a42/ Log: Fix: "XXX should not use IMUL in more cases, it can use a clever LEA" diff --git a/rpython/jit/backend/test/runner_test.py b/rpython/jit/backend/test/runner_test.py --- a/rpython/jit/backend/test/runner_test.py +++ b/rpython/jit/backend/test/runner_test.py @@ -1057,6 +1057,28 @@ r = self.cpu.bh_getinteriorfield_gc_i(a_box.getref_base(), 4, vsdescr) assert r == 4 + def test_array_of_structs_all_sizes(self): + # x86 has special support that can be used for sizes + # 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 16, 18, 20, 24, 32, 36, 40, 64, 72 + for length in range(1, 75): + ITEM = lltype.FixedSizeArray(lltype.Char, length) + a_box, A = self.alloc_array_of(ITEM, 5) + a = a_box.getref(lltype.Ptr(A)) + middle = length // 2 + a[3][middle] = chr(65 + length) + fdescr = self.cpu.interiorfielddescrof(A, 'item%d' % middle) + r = self.execute_operation(rop.GETINTERIORFIELD_GC, + [a_box, BoxInt(3)], + 'int', descr=fdescr) + r = r.getint() + assert r == 65 + length + self.execute_operation(rop.SETINTERIORFIELD_GC, + [a_box, BoxInt(2), BoxInt(r + 1)], + 'void', descr=fdescr) + r1 = self.cpu.bh_getinteriorfield_gc_i(a_box.getref_base(), 2, + fdescr) + assert r1 == r + 1 + def test_string_basic(self): s_box = self.alloc_string("hello\xfe") r = self.execute_operation(rop.STRLEN, [s_box], 'int') diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -1537,22 +1537,50 @@ src_addr = addr_add(base_loc, ofs_loc, ofs.value, 0) self.load_from_mem(resloc, src_addr, size_loc, sign_loc) + def _imul_const_scaled(self, mc, targetreg, sourcereg, itemsize): + """Produce one operation to do roughly + targetreg = sourcereg * itemsize + except that the targetreg may still need shifting by 0,1,2,3. + """ + if (itemsize & 7) == 0: + shift = 3 + elif (itemsize & 3) == 0: + shift = 2 + elif (itemsize & 1) == 0: + shift = 1 + else: + shift = 0 + itemsize >>= shift + # + if _valid_addressing_size(itemsize - 1): + mc.LEA_ra(targetreg, (sourcereg, sourcereg, + _get_scale(itemsize - 1), 0)) + elif _valid_addressing_size(itemsize): + mc.LEA_ra(targetreg, (rx86.NO_BASE_REGISTER, sourcereg, + _get_scale(itemsize), 0)) + else: + mc.IMUL_rri(targetreg, sourcereg, itemsize) + # + return shift + def _get_interiorfield_addr(self, temp_loc, index_loc, itemsize_loc, base_loc, ofs_loc): assert isinstance(itemsize_loc, ImmedLoc) + itemsize = itemsize_loc.value if isinstance(index_loc, ImmedLoc): - temp_loc = imm(index_loc.value * itemsize_loc.value) - elif _valid_addressing_size(itemsize_loc.value): - return AddressLoc(base_loc, index_loc, _get_scale(itemsize_loc.value), ofs_loc.value) + temp_loc = imm(index_loc.value * itemsize) + shift = 0 + elif _valid_addressing_size(itemsize): + temp_loc = index_loc + shift = _get_scale(itemsize) else: - # XXX should not use IMUL in more cases, it can use a clever LEA + assert isinstance(index_loc, RegLoc) assert isinstance(temp_loc, RegLoc) - assert isinstance(index_loc, RegLoc) assert not temp_loc.is_xmm - self.mc.IMUL_rri(temp_loc.value, index_loc.value, - itemsize_loc.value) + shift = self._imul_const_scaled(self.mc, temp_loc.value, + index_loc.value, itemsize) assert isinstance(ofs_loc, ImmedLoc) - return AddressLoc(base_loc, temp_loc, 0, ofs_loc.value) + return AddressLoc(base_loc, temp_loc, shift, ofs_loc.value) def genop_getinteriorfield_gc(self, op, arglocs, resloc): (base_loc, ofs_loc, itemsize_loc, fieldsize_loc, @@ -2418,9 +2446,9 @@ if _valid_addressing_size(itemsize): shift = _get_scale(itemsize) else: - self.mc.IMUL_rri(edi.value, varsizeloc.value, itemsize) + shift = self._imul_const_scaled(self.mc, edi.value, + varsizeloc.value, itemsize) varsizeloc = edi - shift = 0 # now varsizeloc is a register != eax. The size of # the variable part of the array is (varsizeloc << shift) assert arraydescr.basesize >= self.gc_minimal_size_in_nursery From noreply at buildbot.pypy.org Thu Apr 18 14:39:05 2013 From: noreply at buildbot.pypy.org (bivab) Date: Thu, 18 Apr 2013 14:39:05 +0200 (CEST) Subject: [pypy-commit] buildbot default: update the buildslave information a bit Message-ID: <20130418123905.2DC361C01FD@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r788:820ec55d214f Date: 2013-04-18 14:38 +0200 http://bitbucket.org/pypy/buildbot/changeset/820ec55d214f/ Log: update the buildslave information a bit diff --git a/README_BUILDSLAVE b/README_BUILDSLAVE --- a/README_BUILDSLAVE +++ b/README_BUILDSLAVE @@ -5,9 +5,9 @@ pip install buildbot_buildslave The next step is to create a buildslave configuration file. Based on version -0.7.12 of buildbot you need to execute the following command. +0.8.7 of buildbot you need to execute the following command. -buildbot create-slave BASEDIR MASTERHOST:PORT SLAVENAME PASSWORD +buildslave create-slave BASEDIR MASTERHOST:PORT SLAVENAME PASSWORD For PyPy the MASTERHOST currently is ``buildbot.pypy.org``. The value for PORT is ``10407``. @@ -28,13 +28,10 @@ To run the buildslave execute ============================= -First you will need to copy the file Makefile.sample to Makefile and -update it as necessary. - To start the buildslave just run - make start + buildslave start BASEDIR and to stop it run - make stop + buildslave stop BASEDIR From noreply at buildbot.pypy.org Thu Apr 18 15:24:49 2013 From: noreply at buildbot.pypy.org (bivab) Date: Thu, 18 Apr 2013 15:24:49 +0200 (CEST) Subject: [pypy-commit] pypy default: add a special check for ARM when detecting l2 cache size. Message-ID: <20130418132449.A61721C034F@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63478:f20ec7bb60c8 Date: 2013-04-18 15:23 +0200 http://bitbucket.org/pypy/pypy/changeset/f20ec7bb60c8/ Log: add a special check for ARM when detecting l2 cache size. On ARM /proc/cpuinfo does not contain any usable information diff --git a/rpython/memory/gc/env.py b/rpython/memory/gc/env.py --- a/rpython/memory/gc/env.py +++ b/rpython/memory/gc/env.py @@ -149,6 +149,10 @@ else: data = ''.join(data) linepos = 0 + # Currently on ARM-linux we won't find any information about caches in + # cpuinfo + if _detect_arm_cpu(data): + return -1 while True: start = _findend(data, '\ncache size', linepos) if start < 0: @@ -201,6 +205,18 @@ pos += 1 return pos +def _detect_arm_cpu(data): + # check for the presence of a 'Processor' entry + start = _findend(data, 'Processor', 0) + if start >= 0: + # *** data[start:linepos] == " : ARMv6-compatible processor rev 7\n" + start = _skipspace(data, start) + if data[start] == ':': + # *** data[start:linepos] == ": ARMv6-compatible processor rev 7\n" + start = _skipspace(data, start + 1) + return data[start], data[start + 1], data[start + 2] == 'A','R','M' + return False + # ---------- Darwin ---------- sysctlbyname = rffi.llexternal('sysctlbyname', diff --git a/rpython/memory/gc/test/test_env.py b/rpython/memory/gc/test/test_env.py --- a/rpython/memory/gc/test/test_env.py +++ b/rpython/memory/gc/test/test_env.py @@ -161,3 +161,14 @@ """) result = env.get_L2cache_linux2(str(filepath)) assert result == 3072 * 1024 + +def test_estimate_best_nursery_size_linux2_arm(): + filepath = udir.join('estimate_best_nursery_size_linux2') + filepath.write("""\ +Processor : ARMv6-compatible processor rev 7 (v6l) +# this is not actually from cpuinfo, but here for the test +cache size : 3072 KB +... +""") + result = env.get_L2cache_linux2(str(filepath)) + assert result == -1 From noreply at buildbot.pypy.org Thu Apr 18 16:03:34 2013 From: noreply at buildbot.pypy.org (timfel) Date: Thu, 18 Apr 2013 16:03:34 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: add an image that we'll use for benchmarks Message-ID: <20130418140334.684D61C101D@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: Changeset: r298:60cd9f01256a Date: 2013-04-18 15:54 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/60cd9f01256a/ Log: add an image that we'll use for benchmarks diff --git a/images/benchmark.image b/images/benchmark.image new file mode 100644 index 0000000000000000000000000000000000000000..ae4f960b429414aa696e51a7e821a56b71850564 GIT binary patch [cut] From noreply at buildbot.pypy.org Thu Apr 18 16:35:24 2013 From: noreply at buildbot.pypy.org (timfel) Date: Thu, 18 Apr 2013 16:35:24 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: update benchmark method to generate CSV output Message-ID: <20130418143524.714D61C31C8@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: Changeset: r299:9dffcbc3647c Date: 2013-04-18 16:30 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/9dffcbc3647c/ Log: update benchmark method to generate CSV output diff --git a/images/benchmark.image b/images/benchmark.image index ae4f960b429414aa696e51a7e821a56b71850564..848cffbe175dbf07a5d4bdc4f958ce92779dd171 GIT binary patch [cut] From noreply at buildbot.pypy.org Thu Apr 18 18:05:06 2013 From: noreply at buildbot.pypy.org (bivab) Date: Thu, 18 Apr 2013 18:05:06 +0200 (CEST) Subject: [pypy-commit] pypy default: ARM architecture autodetection based on /proc/cpuinfo Message-ID: <20130418160506.9BC781C31A5@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63479:7cf11fdfb221 Date: 2013-04-18 18:01 +0200 http://bitbucket.org/pypy/pypy/changeset/7cf11fdfb221/ Log: ARM architecture autodetection based on /proc/cpuinfo diff --git a/rpython/jit/backend/arm/detect.py b/rpython/jit/backend/arm/detect.py --- a/rpython/jit/backend/arm/detect.py +++ b/rpython/jit/backend/arm/detect.py @@ -1,7 +1,10 @@ +import os + from rpython.translator.tool.cbuild import ExternalCompilationInfo from rpython.rlib.clibffi import FFI_DEFAULT_ABI, FFI_SYSV, FFI_VFP from rpython.rtyper.tool import rffi_platform from rpython.translator.platform import CompilationError +from rpython.rlib.debug import debug_print, debug_start, debug_stop eci = ExternalCompilationInfo( post_include_bits=[""" @@ -26,3 +29,35 @@ return True except CompilationError: return False + + +def detect_arch_version(filename="/proc/cpuinfo"): + fd = os.open(filename, os.O_RDONLY, 0644) + n = 0 + debug_start("jit-backend-arch") + try: + buf = os.read(fd, 2048) + if not buf: + debug_print("Could not detect ARM architecture " + "version, assuming", "ARMv%d" % n) + n = 6 # we asume ARMv6 as base case + finally: + os.close(fd) + # "Processor : ARMv%d-compatible processor rev 7 (v6l)" + i = buf.find('ARMv') + if i == -1: + raise ValueError("Unknown Processor entry") + + n = int(buf[i + 4]) + + if n < 6: + raise ValueError("Unsupported ARM architecture version") + + debug_print("Detected", "ARMv%d" % n) + + if n > 7: + n = 7 + debug_print("Architecture version not explicitly supported, " + "falling back to", "ARMv%d" % n) + debug_stop("jit-backend-arch") + return n diff --git a/rpython/jit/backend/arm/test/test_detect.py b/rpython/jit/backend/arm/test/test_detect.py new file mode 100644 --- /dev/null +++ b/rpython/jit/backend/arm/test/test_detect.py @@ -0,0 +1,24 @@ +import py +from rpython.tool.udir import udir +from rpython.jit.backend.arm.detect import detect_arch_version + +cpuinfo = "Processor : ARMv%d-compatible processor rev 7 (v6l)""" + + +def write_cpuinfo(info): + filepath = udir.join('get_arch_version') + filepath.write(info) + return str(filepath) + + +def test_detect_arch_version(): + # currently supported cases + for i in (6, 7, ): + filepath = write_cpuinfo(cpuinfo % i) + assert detect_arch_version(filepath) == i + # unsupported cases + assert detect_arch_version(write_cpuinfo(cpuinfo % 8)) == 7 + py.test.raises(ValueError, + 'detect_arch_version(write_cpuinfo(cpuinfo % 5))') + py.test.raises(ValueError, + 'detect_arch_version(write_cpuinfo("Lorem ipsum dolor sit amet, consectetur"))') From noreply at buildbot.pypy.org Thu Apr 18 18:05:07 2013 From: noreply at buildbot.pypy.org (bivab) Date: Thu, 18 Apr 2013 18:05:07 +0200 (CEST) Subject: [pypy-commit] pypy default: detect the architecture and ABI during JIT-backend setup at runtime Message-ID: <20130418160507.BE6541C31C9@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63480:56f159906969 Date: 2013-04-18 18:04 +0200 http://bitbucket.org/pypy/pypy/changeset/56f159906969/ Log: detect the architecture and ABI during JIT-backend setup at runtime diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -25,7 +25,6 @@ from rpython.rlib.rarithmetic import r_uint from rpython.rtyper.annlowlevel import llhelper, cast_instance_to_gcref from rpython.rtyper.lltypesystem import lltype, rffi -from rpython.jit.backend.arm.detect import detect_hardfloat class AssemblerARM(ResOpAssembler): @@ -51,7 +50,6 @@ def setup_once(self): BaseAssembler.setup_once(self) - self.hf_abi = detect_hardfloat() def setup(self, looptoken): assert self.memcpy_addr != 0, 'setup_once() not called?' diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -354,7 +354,7 @@ # whether to worry about a CALL that can collect; this # is always true except in call_release_gil can_collect=True): - if self.hf_abi: + if self.cpu.hf_abi: stack_args, adr = self._setup_call_hf(adr, arglocs, fcond, resloc, result_info) else: @@ -382,7 +382,7 @@ # ensure the result is wellformed and stored in the correct location if resloc is not None: - if resloc.is_vfp_reg() and not self.hf_abi: + if resloc.is_vfp_reg() and not self.cpu.hf_abi: # move result to the allocated register self.mov_to_vfp_loc(r.r0, r.r1, resloc) elif resloc.is_reg() and result_info != (-1, -1): diff --git a/rpython/jit/backend/arm/runner.py b/rpython/jit/backend/arm/runner.py --- a/rpython/jit/backend/arm/runner.py +++ b/rpython/jit/backend/arm/runner.py @@ -7,6 +7,7 @@ from rpython.rlib.jit_hooks import LOOP_RUN_CONTAINER from rpython.rtyper.lltypesystem import lltype, llmemory from rpython.jit.backend.arm.detect import detect_hardfloat +from rpython.jit.backend.arm.detect import detect_arch_version jitframe.STATICSIZE = JITFRAME_FIXED_SIZE @@ -26,7 +27,7 @@ frame_reg = fp hf_abi = False # use hard float abi flag - arch_version = 7 + arch_version = 6 # assume ARMv6 as base case def __init__(self, rtyper, stats, opts=None, translate_support_code=False, gcdescr=None): @@ -46,6 +47,8 @@ self.assembler = AssemblerARM(self, self.translate_support_code) def setup_once(self): + self.arch_version = detect_arch_version() + self.hf_abi = detect_hardfloat() self.assembler.setup_once() def finish_once(self): @@ -115,8 +118,3 @@ class CPU_ARM(AbstractARMCPU): """ARM v7""" backend_name = "armv7" - -class CPU_ARMv6(AbstractARMCPU): - """ ARM v6, uses hardfp ABI, requires vfp""" - arch_version = 6 - backend_name = "armv6" diff --git a/rpython/jit/backend/detect_cpu.py b/rpython/jit/backend/detect_cpu.py --- a/rpython/jit/backend/detect_cpu.py +++ b/rpython/jit/backend/detect_cpu.py @@ -33,8 +33,8 @@ 'x86_64': 'x86', 'amd64': 'x86', # freebsd 'AMD64': 'x86', # win64 - 'armv7l': 'armv7', - 'armv6l': 'armv6', + 'armv7l': 'arm', + 'armv6l': 'arm', }[mach] except KeyError: return mach @@ -75,9 +75,7 @@ return "rpython.jit.backend.x86.runner", "CPU_X86_64" elif backend_name == 'cli': return "rpython.jit.backend.cli.runner", "CliCPU" - elif backend_name.startswith('armv6'): - return "rpython.jit.backend.arm.runner", "CPU_ARMv6" - elif backend_name.startswith('armv7'): + elif backend_name.startswith('arm'): return "rpython.jit.backend.arm.runner", "CPU_ARM" else: raise ProcessorAutodetectError, ( From noreply at buildbot.pypy.org Thu Apr 18 18:10:09 2013 From: noreply at buildbot.pypy.org (bivab) Date: Thu, 18 Apr 2013 18:10:09 +0200 (CEST) Subject: [pypy-commit] pypy default: update translation options and a other places that refer to the different ARM versions Message-ID: <20130418161009.842EB1C31A5@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63481:3a005983e686 Date: 2013-04-18 18:09 +0200 http://bitbucket.org/pypy/pypy/changeset/3a005983e686/ Log: update translation options and a other places that refer to the different ARM versions diff --git a/pypy/doc/arm.rst b/pypy/doc/arm.rst --- a/pypy/doc/arm.rst +++ b/pypy/doc/arm.rst @@ -153,7 +153,7 @@ :: - pypy /rpython/bin/rpython -Ojit --platform=arm --gcrootfinder=shadowstack --jit-backend=armv7 targetpypystandalone.py + pypy /rpython/bin/rpython -Ojit --platform=arm --gcrootfinder=shadowstack --jit-backend=arm targetpypystandalone.py The gcrootfinder option is needed to work around `issue 1377`_ and the jit-backend works around `issue 1376`_ diff --git a/rpython/config/translationoption.py b/rpython/config/translationoption.py --- a/rpython/config/translationoption.py +++ b/rpython/config/translationoption.py @@ -115,7 +115,7 @@ ("translation.gcrootfinder", DEFL_ROOTFINDER_WITHJIT), ("translation.list_comprehension_operations", True)]), ChoiceOption("jit_backend", "choose the backend for the JIT", - ["auto", "x86", "x86-without-sse2", 'armv7', 'armv7hf', 'armv6hf'], + ["auto", "x86", "x86-without-sse2", 'arm'], default="auto", cmdline="--jit-backend"), ChoiceOption("jit_profiler", "integrate profiler support into the JIT", ["off", "oprofile"], diff --git a/rpython/jit/backend/arm/runner.py b/rpython/jit/backend/arm/runner.py --- a/rpython/jit/backend/arm/runner.py +++ b/rpython/jit/backend/arm/runner.py @@ -116,5 +116,5 @@ class CPU_ARM(AbstractARMCPU): - """ARM v7""" - backend_name = "armv7" + """ARM""" + backend_name = "arm" diff --git a/rpython/jit/backend/arm/test/test_runner.py b/rpython/jit/backend/arm/test/test_runner.py --- a/rpython/jit/backend/arm/test/test_runner.py +++ b/rpython/jit/backend/arm/test/test_runner.py @@ -27,7 +27,7 @@ bridge_loop_instructions = ['ldr', 'mov', 'nop', 'cmp', 'bge', 'push', 'mov', 'mov', 'push', 'mov', 'mov', 'blx', 'mov', 'mov', 'bx'] - if CPU.backend_name.startswith('armv7'): + if CPU.arch_version == 7: bridge_loop_instructions = ['ldr', 'mov', 'nop', 'cmp', 'bge', 'push', 'mov', 'mov', 'push', 'mov', 'mov', 'blx', 'mov', 'mov', 'bx'] From noreply at buildbot.pypy.org Thu Apr 18 18:13:06 2013 From: noreply at buildbot.pypy.org (bivab) Date: Thu, 18 Apr 2013 18:13:06 +0200 (CEST) Subject: [pypy-commit] buildbot default: update jittranslation args for ARM Message-ID: <20130418161306.AAF721C31A5@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r789:159b2bc9a32c Date: 2013-04-18 18:12 +0200 http://bitbucket.org/pypy/buildbot/changeset/159b2bc9a32c/ Log: update jittranslation args for ARM diff --git a/bot2/pypybuildbot/arm_master.py b/bot2/pypybuildbot/arm_master.py --- a/bot2/pypybuildbot/arm_master.py +++ b/bot2/pypybuildbot/arm_master.py @@ -8,8 +8,7 @@ # ARM own test factories jit_translation_args = ['-Ojit'] crosstranslationargs = ['--platform=arm', '--gcrootfinder=shadowstack'] -crosstranslationjitargs = ['--jit-backend=armv7'] -crosstranslationjitargs_raspbian = ['--jit-backend=armv6hf'] +crosstranslationjitargs = ['--jit-backend=arm'] # this one needs a larger timeout due to how it is run pypyJitBackendOnlyOwnTestFactoryARM = pypybuilds.Own( cherrypick=':'.join(["jit/backend/arm", @@ -46,7 +45,7 @@ pypyJITCrossTranslationFactoryRaspbianHF = pypybuilds.NightlyBuild( translationArgs=(crosstranslationargs + jit_translation_args - + crosstranslationjitargs_raspbian), + + crosstranslationjitargs), platform='linux-armhf-raspbian', interpreter='pypy', prefix=['schroot', '-c', 'raspbian'], From noreply at buildbot.pypy.org Thu Apr 18 18:32:32 2013 From: noreply at buildbot.pypy.org (mattip) Date: Thu, 18 Apr 2013 18:32:32 +0200 (CEST) Subject: [pypy-commit] pypy win32-fixes3: skip asmgcroot for msvc (arigato) Message-ID: <20130418163232.902F41C31A5@cobra.cs.uni-duesseldorf.de> Author: mattip Branch: win32-fixes3 Changeset: r63482:a7ee176918f6 Date: 2013-04-18 19:29 +0300 http://bitbucket.org/pypy/pypy/changeset/a7ee176918f6/ Log: skip asmgcroot for msvc (arigato) diff --git a/rpython/rtyper/tool/test/test_rffi_platform.py b/rpython/rtyper/tool/test/test_rffi_platform.py --- a/rpython/rtyper/tool/test/test_rffi_platform.py +++ b/rpython/rtyper/tool/test/test_rffi_platform.py @@ -288,7 +288,7 @@ return (a + b); } """ - if platform.cc == 'cl.exe': + if platform.name == 'mscv': c_source = '__declspec(dllexport) ' + c_source libname = 'libc_lib' else: diff --git a/rpython/translator/c/gcc/test/test_asmgcroot.py b/rpython/translator/c/gcc/test/test_asmgcroot.py --- a/rpython/translator/c/gcc/test/test_asmgcroot.py +++ b/rpython/translator/c/gcc/test/test_asmgcroot.py @@ -25,8 +25,8 @@ @classmethod def make_config(cls): - if _MSVC and _WIN64: - py.test.skip("all asmgcroot tests disabled for MSVC X64") + if _MSVC: + py.test.skip("all asmgcroot tests disabled for MSVC") from rpython.config.translationoption import get_combined_translation_config config = get_combined_translation_config(translating=True) config.translation.gc = cls.gcpolicy From noreply at buildbot.pypy.org Thu Apr 18 21:08:07 2013 From: noreply at buildbot.pypy.org (bivab) Date: Thu, 18 Apr 2013 21:08:07 +0200 (CEST) Subject: [pypy-commit] pypy default: translation fix Message-ID: <20130418190807.CCDE51C31C9@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63483:7d779d5ec7f2 Date: 2013-04-18 21:06 +0200 http://bitbucket.org/pypy/pypy/changeset/7d779d5ec7f2/ Log: translation fix diff --git a/rpython/memory/gc/env.py b/rpython/memory/gc/env.py --- a/rpython/memory/gc/env.py +++ b/rpython/memory/gc/env.py @@ -207,15 +207,8 @@ def _detect_arm_cpu(data): # check for the presence of a 'Processor' entry - start = _findend(data, 'Processor', 0) - if start >= 0: - # *** data[start:linepos] == " : ARMv6-compatible processor rev 7\n" - start = _skipspace(data, start) - if data[start] == ':': - # *** data[start:linepos] == ": ARMv6-compatible processor rev 7\n" - start = _skipspace(data, start + 1) - return data[start], data[start + 1], data[start + 2] == 'A','R','M' - return False + p = _findend(data, 'Processor', 0) + return p >= 0 and _findend(data, 'ARMv', p) > 0 # ---------- Darwin ---------- diff --git a/rpython/memory/gc/test/test_env.py b/rpython/memory/gc/test/test_env.py --- a/rpython/memory/gc/test/test_env.py +++ b/rpython/memory/gc/test/test_env.py @@ -172,3 +172,12 @@ """) result = env.get_L2cache_linux2(str(filepath)) assert result == -1 + +def test__detect_arm(): + assert env._detect_arm_cpu("Processor : ARMv6-compatible processor rev 7 (v6l)") + assert not env._detect_arm_cpu("""\ +processor : 0 +vendor_id : GenuineIntel +cpu family : 6 +model : 37 +""") From noreply at buildbot.pypy.org Thu Apr 18 21:46:47 2013 From: noreply at buildbot.pypy.org (fijal) Date: Thu, 18 Apr 2013 21:46:47 +0200 (CEST) Subject: [pypy-commit] pypy default: fix translation on ARM, I believe Message-ID: <20130418194647.15E4E1C101D@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r63484:e64058419d45 Date: 2013-04-18 21:46 +0200 http://bitbucket.org/pypy/pypy/changeset/e64058419d45/ Log: fix translation on ARM, I believe diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -249,7 +249,9 @@ else: self.wb_slowpath[withcards + 2 * withfloats] = rawstart - def _build_malloc_slowpath(self): + def _build_malloc_slowpath(self, kind): + if kind != 'fixed': + return 0 mc = InstrBuilder(self.cpu.arch_version) self._push_all_regs_to_jitframe(mc, [r.r0, r.r1], self.cpu.supports_floats) ofs = self.cpu.get_ofs_of_frame_field('jf_gcmap') From noreply at buildbot.pypy.org Thu Apr 18 22:37:37 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Thu, 18 Apr 2013 22:37:37 +0200 (CEST) Subject: [pypy-commit] pypy py3k: fix window's urandom to return bytes Message-ID: <20130418203737.C44B21C31C8@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63485:a1924f27cfd4 Date: 2013-04-18 13:33 -0700 http://bitbucket.org/pypy/pypy/changeset/a1924f27cfd4/ Log: fix window's urandom to return bytes diff --git a/pypy/module/posix/interp_posix.py b/pypy/module/posix/interp_posix.py --- a/pypy/module/posix/interp_posix.py +++ b/pypy/module/posix/interp_posix.py @@ -1172,6 +1172,6 @@ """ context = get(space).random_context try: - return space.wrap(rurandom.urandom(context, n)) + return space.wrapbytes(rurandom.urandom(context, n)) except OSError, e: raise wrap_oserror(space, e) From noreply at buildbot.pypy.org Thu Apr 18 22:37:39 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Thu, 18 Apr 2013 22:37:39 +0200 (CEST) Subject: [pypy-commit] pypy py3k: _winreg -> winreg, and some fixes Message-ID: <20130418203739.0866E1C31C8@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63486:5cfe1e61a672 Date: 2013-04-18 13:36 -0700 http://bitbucket.org/pypy/pypy/changeset/5cfe1e61a672/ Log: _winreg -> winreg, and some fixes diff --git a/pypy/module/_winreg/__init__.py b/pypy/module/_winreg/__init__.py --- a/pypy/module/_winreg/__init__.py +++ b/pypy/module/_winreg/__init__.py @@ -38,6 +38,8 @@ Many constants are defined - see the documentation for each function to see what constants are used, and where.""" + applevel_name = 'winreg' + appleveldefs = { } interpleveldefs = { diff --git a/pypy/module/_winreg/interp_winreg.py b/pypy/module/_winreg/interp_winreg.py --- a/pypy/module/_winreg/interp_winreg.py +++ b/pypy/module/_winreg/interp_winreg.py @@ -109,14 +109,9 @@ elif isinstance(w_hkey, W_HKEY): return w_hkey.hkey elif space.isinstance_w(w_hkey, space.w_int): - try: - value = space.int_w(w_hkey) - except OperationError, e: - if not e.match(space, space.w_TypeError): - raise - return rffi.cast(rwinreg.HKEY, space.uint_w(w_hkey)) - else: + if space.is_true(space.lt(w_hkey, space.wrap(0))): return rffi.cast(rwinreg.HKEY, space.int_w(w_hkey)) + return rffi.cast(rwinreg.HKEY, space.uint_w(w_hkey)) else: errstring = space.wrap("The object is not a PyHKEY object") raise OperationError(space.w_TypeError, errstring) @@ -373,7 +368,7 @@ return space.newlist(l) else: # REG_BINARY and all other types - return space.wrap(rffi.charpsize2str(buf, buflen)) + return space.wrapbytes(rffi.charpsize2str(buf, buflen)) @unwrap_spec(value_name=str, typ=int) def SetValueEx(space, w_hkey, value_name, w_reserved, typ, w_value): diff --git a/pypy/module/_winreg/test/test_winreg.py b/pypy/module/_winreg/test/test_winreg.py --- a/pypy/module/_winreg/test/test_winreg.py +++ b/pypy/module/_winreg/test/test_winreg.py @@ -45,9 +45,12 @@ ("Unicode Value", u"A unicode Value", _winreg.REG_SZ), ("Str Expand", "The path is %path%", _winreg.REG_EXPAND_SZ), ("Multi Str", ["Several", "string", u"values"], _winreg.REG_MULTI_SZ), - ("Raw data", "binary"+chr(0)+"data", _winreg.REG_BINARY), ] - cls.w_test_data = space.wrap(test_data) + cls.w_test_data = w_test_data = space.wrap(test_data) + w_btest = space.newtuple([space.wrap("Raw data"), + space.wrapbytes("binary\x00data"), + space.wrap(_winreg.REG_BINARY)]) + w_test_data.append(w_btest) def teardown_class(cls): import _winreg From noreply at buildbot.pypy.org Thu Apr 18 22:37:40 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Thu, 18 Apr 2013 22:37:40 +0200 (CEST) Subject: [pypy-commit] pypy py3k: 2to3 Message-ID: <20130418203740.2C0301C31C8@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63487:dcc0b43bd43a Date: 2013-04-18 13:36 -0700 http://bitbucket.org/pypy/pypy/changeset/dcc0b43bd43a/ Log: 2to3 diff --git a/pypy/module/_winreg/test/test_winreg.py b/pypy/module/_winreg/test/test_winreg.py --- a/pypy/module/_winreg/test/test_winreg.py +++ b/pypy/module/_winreg/test/test_winreg.py @@ -22,8 +22,8 @@ spaceconfig = dict(usemodules=('_winreg',)) def test_repr(self): - import _winreg - k = _winreg.HKEYType(0x123) + import winreg + k = winreg.HKEYType(0x123) assert str(k) == "" class AppTestFfi: @@ -60,19 +60,19 @@ pass def test_constants(self): - from _winreg import ( + from winreg import ( HKEY_LOCAL_MACHINE, HKEY_CLASSES_ROOT, HKEY_CURRENT_CONFIG, HKEY_CURRENT_USER, HKEY_DYN_DATA, HKEY_LOCAL_MACHINE, HKEY_PERFORMANCE_DATA, HKEY_USERS) def test_simple_write(self): - from _winreg import SetValue, QueryValue, REG_SZ + from winreg import SetValue, QueryValue, REG_SZ value = "Some Default value" SetValue(self.root_key, self.test_key_name, REG_SZ, value) assert QueryValue(self.root_key, self.test_key_name) == value def test_CreateKey(self): - from _winreg import CreateKey, QueryInfoKey + from winreg import CreateKey, QueryInfoKey key = CreateKey(self.root_key, self.test_key_name) sub_key = CreateKey(key, "sub_key") @@ -83,8 +83,8 @@ assert nkeys == 0 def test_CreateKeyEx(self): - from _winreg import CreateKeyEx, QueryInfoKey - from _winreg import KEY_ALL_ACCESS, KEY_READ + from winreg import CreateKeyEx, QueryInfoKey + from winreg import KEY_ALL_ACCESS, KEY_READ key = CreateKeyEx(self.root_key, self.test_key_name, 0, KEY_ALL_ACCESS) sub_key = CreateKeyEx(key, "sub_key", 0, KEY_READ) @@ -95,7 +95,7 @@ assert nkeys == 0 def test_close(self): - from _winreg import OpenKey, CloseKey, FlushKey, QueryInfoKey + from winreg import OpenKey, CloseKey, FlushKey, QueryInfoKey key = OpenKey(self.root_key, self.test_key_name) sub_key = OpenKey(key, "sub_key") @@ -117,7 +117,7 @@ raises(EnvironmentError, QueryInfoKey, int_key) # now closed def test_with(self): - from _winreg import OpenKey + from winreg import OpenKey with OpenKey(self.root_key, self.test_key_name) as key: with OpenKey(key, "sub_key") as sub_key: assert key.handle != 0 @@ -126,11 +126,11 @@ assert sub_key.handle == 0 def test_exception(self): - from _winreg import QueryInfoKey + from winreg import QueryInfoKey import errno try: QueryInfoKey(0) - except EnvironmentError, e: + except EnvironmentError as e: assert e.winerror == 6 assert e.errno == errno.EBADF # XXX translations... @@ -140,21 +140,21 @@ assert 0, "Did not raise" def test_SetValueEx(self): - from _winreg import CreateKey, SetValueEx + from winreg import CreateKey, SetValueEx key = CreateKey(self.root_key, self.test_key_name) sub_key = CreateKey(key, "sub_key") for name, value, type in self.test_data: SetValueEx(sub_key, name, 0, type, value) def test_readValues(self): - from _winreg import OpenKey, EnumValue, QueryValueEx, EnumKey + from winreg import OpenKey, EnumValue, QueryValueEx, EnumKey key = OpenKey(self.root_key, self.test_key_name) sub_key = OpenKey(key, "sub_key") index = 0 while 1: try: data = EnumValue(sub_key, index) - except EnvironmentError, e: + except EnvironmentError as e: break assert data in self.test_data index = index + 1 @@ -167,7 +167,7 @@ raises(EnvironmentError, EnumKey, key, 1) def test_delete(self): - from _winreg import OpenKey, KEY_ALL_ACCESS, DeleteValue, DeleteKey + from winreg import OpenKey, KEY_ALL_ACCESS, DeleteValue, DeleteKey key = OpenKey(self.root_key, self.test_key_name, 0, KEY_ALL_ACCESS) sub_key = OpenKey(key, "sub_key", 0, KEY_ALL_ACCESS) @@ -177,14 +177,14 @@ DeleteKey(key, "sub_key") def test_connect(self): - from _winreg import ConnectRegistry, HKEY_LOCAL_MACHINE + from winreg import ConnectRegistry, HKEY_LOCAL_MACHINE h = ConnectRegistry(None, HKEY_LOCAL_MACHINE) h.Close() def test_savekey(self): if not self.canSaveKey: skip("CPython needs win32api to set the SeBackupPrivilege security privilege") - from _winreg import OpenKey, KEY_ALL_ACCESS, SaveKey + from winreg import OpenKey, KEY_ALL_ACCESS, SaveKey import os try: os.unlink(self.tmpfilename) @@ -195,17 +195,17 @@ SaveKey(key, self.tmpfilename) def test_expand_environment_string(self): - from _winreg import ExpandEnvironmentStrings + from winreg import ExpandEnvironmentStrings import nt - r = ExpandEnvironmentStrings(u"%windir%\\test") - assert isinstance(r, unicode) - if 'WINDIR' in nt.environ.keys(): + r = ExpandEnvironmentStrings("%windir%\\test") + assert isinstance(r, str) + if 'WINDIR' in list(nt.environ.keys()): assert r == nt.environ["WINDIR"] + "\\test" else: assert r == nt.environ["windir"] + "\\test" def test_long_key(self): - from _winreg import ( + from winreg import ( HKEY_CURRENT_USER, KEY_ALL_ACCESS, CreateKey, SetValue, EnumKey, REG_SZ, QueryInfoKey, OpenKey, DeleteKey) name = 'x'*256 @@ -221,10 +221,10 @@ DeleteKey(HKEY_CURRENT_USER, self.test_key_name) def test_dynamic_key(self): - from _winreg import EnumValue, QueryValueEx, HKEY_PERFORMANCE_DATA + from winreg import EnumValue, QueryValueEx, HKEY_PERFORMANCE_DATA try: EnumValue(HKEY_PERFORMANCE_DATA, 0) - except WindowsError, e: + except WindowsError as e: import errno if e.errno in (errno.EPERM, errno.EACCES): skip("access denied to registry key " @@ -236,7 +236,7 @@ import sys if sys.getwindowsversion() >= (5, 2): skip("Requires Windows XP") - from _winreg import ( + from winreg import ( CreateKey, DisableReflectionKey, EnableReflectionKey, QueryReflectionKey, DeleteKeyEx) with CreateKey(self.root_key, self.test_key_name) as key: From noreply at buildbot.pypy.org Thu Apr 18 22:41:28 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Thu, 18 Apr 2013 22:41:28 +0200 (CEST) Subject: [pypy-commit] pypy py3k: restrict default usemodules on windows Message-ID: <20130418204128.2D4A51C101D@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63488:650f2f62b4ce Date: 2013-04-18 13:40 -0700 http://bitbucket.org/pypy/pypy/changeset/650f2f62b4ce/ Log: restrict default usemodules on windows diff --git a/lib-python/conftest.py b/lib-python/conftest.py --- a/lib-python/conftest.py +++ b/lib-python/conftest.py @@ -59,8 +59,10 @@ def __init__(self, basename, core=False, compiler=None, usemodules='', skip=None): self.basename = basename - self._usemodules = usemodules.split() + ['signal', 'rctime', 'binascii', '_socket', - 'select', 'fcntl', '_posixsubprocess'] + self._usemodules = usemodules.split() + [ + '_socket', 'binascii', 'rctime', 'select', 'signal'] + if not sys.platform == 'win32': + self._usemodules.extend(['_posixsubprocess', 'fcntl']) self._compiler = compiler self.core = core self.skip = skip From noreply at buildbot.pypy.org Thu Apr 18 23:37:32 2013 From: noreply at buildbot.pypy.org (wlav) Date: Thu, 18 Apr 2013 23:37:32 +0200 (CEST) Subject: [pypy-commit] pypy reflex-support: add rule to create .s from .cxx Message-ID: <20130418213732.39F671C31A5@cobra.cs.uni-duesseldorf.de> Author: Wim Lavrijsen Branch: reflex-support Changeset: r63489:56e32cdbf135 Date: 2013-04-12 12:54 -0700 http://bitbucket.org/pypy/pypy/changeset/56e32cdbf135/ Log: add rule to create .s from .cxx diff --git a/rpython/translator/c/genc.py b/rpython/translator/c/genc.py --- a/rpython/translator/c/genc.py +++ b/rpython/translator/c/genc.py @@ -462,6 +462,7 @@ else: mk.definition('OBJECTS', '$(ASMLBLFILES) gcmaptable.s') mk.rule('%.s', '%.c', '$(CC) $(CFLAGS) $(CFLAGSEXTRA) -frandom-seed=$< -o $@ -S $< $(INCLUDEDIRS)') + mk.rule('%.s', '%.cxx', '$(CXX) $(CFLAGS) $(CFLAGSEXTRA) -frandom-seed=$< -o $@ -S $< $(INCLUDEDIRS)') mk.rule('%.lbl.s %.gcmap', '%.s', [ '$(PYTHON) $(RPYDIR)/translator/c/gcc/trackgcroot.py ' From noreply at buildbot.pypy.org Thu Apr 18 23:37:36 2013 From: noreply at buildbot.pypy.org (wlav) Date: Thu, 18 Apr 2013 23:37:36 +0200 (CEST) Subject: [pypy-commit] pypy reflex-support: o) merge default into branch Message-ID: <20130418213736.5FF451C31A5@cobra.cs.uni-duesseldorf.de> Author: Wim Lavrijsen Branch: reflex-support Changeset: r63490:b1795b144bc1 Date: 2013-04-18 11:36 -0700 http://bitbucket.org/pypy/pypy/changeset/b1795b144bc1/ Log: o) merge default into branch o) fixups to bring code up to date with merged code o) allow [] syntax for templates diff too long, truncating to 2000 out of 15484 lines diff --git a/.hgignore b/.hgignore --- a/.hgignore +++ b/.hgignore @@ -70,6 +70,7 @@ ^rpython/translator/cli/src/pypylib\.dll$ ^rpython/translator/cli/src/query\.exe$ ^rpython/translator/cli/src/main\.exe$ +^lib_pypy/__pycache__$ ^lib_pypy/ctypes_config_cache/_.+_cache\.py$ ^lib_pypy/ctypes_config_cache/_.+_.+_\.py$ ^rpython/translator/cli/query-descriptions$ diff --git a/README.rst b/README.rst --- a/README.rst +++ b/README.rst @@ -13,9 +13,9 @@ http://pypy.org/ -The getting-started document will help guide you: +If you want to help developing PyPy, this document might help you: - http://doc.pypy.org/en/latest/getting-started.html + http://doc.pypy.org/ It will also point you to the rest of the documentation which is generated from files in the pypy/doc directory within the source repositories. Enjoy diff --git a/lib-python/conftest.py b/lib-python/conftest.py --- a/lib-python/conftest.py +++ b/lib-python/conftest.py @@ -1,91 +1,89 @@ """ test configuration(s) for running CPython's regression -test suite on top of PyPy +test suite on top of PyPy """ import py import sys import pypy import re -from pypy.interpreter.gateway import ApplevelClass +from pypy.interpreter.gateway import ApplevelClass from pypy.interpreter.error import OperationError -from pypy.interpreter.module import Module as PyPyModule +from pypy.interpreter.module import Module as PyPyModule from pypy.interpreter.main import run_string, run_file -# the following adds command line options as a side effect! -from pypy.conftest import option as pypy_option +# the following adds command line options as a side effect! +from pypy.conftest import option as pypy_option -from pypy.tool.pytest import appsupport +from pypy.tool.pytest import appsupport from pypy.tool.pytest.confpath import pypydir, rpythondir, testdir, testresultdir from rpython.config.parse import parse_info pytest_plugins = "resultlog", rsyncdirs = ['.', '../pypy/'] -# -# Interfacing/Integrating with py.test's collection process +# +# Interfacing/Integrating with py.test's collection process # def pytest_addoption(parser): - group = parser.getgroup("complicance testing options") - group.addoption('-T', '--timeout', action="store", type="string", - default="1000", dest="timeout", - help="fail a test module after the given timeout. " - "specify in seconds or 'NUMmp' aka Mega-Pystones") - group.addoption('--pypy', action="store", type="string", - dest="pypy", help="use given pypy executable to run lib-python tests. " - "This will run the tests directly (i.e. not through py.py)") + group = parser.getgroup("complicance testing options") + group.addoption('-T', '--timeout', action="store", type="string", + default="1000", dest="timeout", + help="fail a test module after the given timeout. " + "specify in seconds or 'NUMmp' aka Mega-Pystones") + group.addoption('--pypy', action="store", type="string", dest="pypy", + help="use given pypy executable to run lib-python tests. " + "This will run the tests directly (i.e. not through py.py)") group.addoption('--filter', action="store", type="string", default=None, - dest="unittest_filter", help="Similar to -k, XXX") + dest="unittest_filter", help="Similar to -k, XXX") -def gettimeout(timeout): +def gettimeout(timeout): from rpython.translator.test import rpystone - if timeout.endswith('mp'): + if timeout.endswith('mp'): megapystone = float(timeout[:-2]) t, stone = pystone.Proc0(10000) - pystonetime = t/stone - seconds = megapystone * 1000000 * pystonetime - return seconds - return float(timeout) + pystonetime = t/stone + seconds = megapystone * 1000000 * pystonetime + return seconds + return float(timeout) # ________________________________________________________________________ # -# classification of all tests files (this is ongoing work) +# classification of all tests files (this is ongoing work) # -class RegrTest: - """ Regression Test Declaration.""" - def __init__(self, basename, core=False, - compiler=None, - usemodules = '', - skip=None): - self.basename = basename +class RegrTest: + """ Regression Test Declaration.""" + def __init__(self, basename, core=False, compiler=None, usemodules='', + skip=None): + self.basename = basename self._usemodules = usemodules.split() + ['signal', 'rctime', 'itertools', '_socket'] - self._compiler = compiler + self._compiler = compiler self.core = core self.skip = skip assert self.getfspath().check(), "%r not found!" % (basename,) def usemodules(self): - return self._usemodules #+ pypy_option.usemodules + return self._usemodules # + pypy_option.usemodules usemodules = property(usemodules) - def compiler(self): - return self._compiler #or pypy_option.compiler + def compiler(self): + return self._compiler # or pypy_option.compiler compiler = property(compiler) - def ismodified(self): + def ismodified(self): #XXX: ask hg return None - def getfspath(self): + def getfspath(self): return testdir.join(self.basename) - def run_file(self, space): + def run_file(self, space): fspath = self.getfspath() assert fspath.check() - modname = fspath.purebasename + modname = fspath.purebasename space.appexec([], '''(): from test import %(modname)s m = %(modname)s @@ -424,7 +422,7 @@ RegrTest('test_textwrap.py'), RegrTest('test_thread.py', usemodules="thread", core=True), RegrTest('test_threaded_import.py', usemodules="thread", core=True), - RegrTest('test_threadedtempfile.py', + RegrTest('test_threadedtempfile.py', usemodules="thread", core=False), RegrTest('test_threading.py', usemodules="thread", core=True), RegrTest('test_threading_local.py', usemodules="thread", core=True), @@ -504,7 +502,7 @@ def pytest_configure(config): config._basename2spec = cache = {} - for x in testmap: + for x in testmap: cache[x.basename] = x def pytest_collect_file(path, parent, __multicall__): @@ -520,33 +518,33 @@ return RunFileExternal(path.basename, parent=parent, regrtest=regrtest) class RunFileExternal(py.test.collect.File): - def __init__(self, name, parent, regrtest): - super(RunFileExternal, self).__init__(name, parent) - self.regrtest = regrtest + def __init__(self, name, parent, regrtest): + super(RunFileExternal, self).__init__(name, parent) + self.regrtest = regrtest self.fspath = regrtest.getfspath() - def collect(self): - if self.regrtest.ismodified(): + def collect(self): + if self.regrtest.ismodified(): name = 'modified' else: name = 'unmodified' - return [ReallyRunFileExternal(name, parent=self)] + return [ReallyRunFileExternal(name, parent=self)] # -# testmethod: +# testmethod: # invoking in a separate process: py.py TESTFILE # import os import time import getpass -class ReallyRunFileExternal(py.test.collect.Item): +class ReallyRunFileExternal(py.test.collect.Item): class ExternalFailure(Exception): """Failure in running subprocess""" - def getinvocation(self, regrtest): - fspath = regrtest.getfspath() - python = sys.executable + def getinvocation(self, regrtest): + fspath = regrtest.getfspath() + python = sys.executable pypy_script = pypydir.join('bin', 'pyinteractive.py') alarm_script = pypydir.join('tool', 'alarm.py') if sys.platform == 'win32': @@ -555,9 +553,9 @@ watchdog_name = 'watchdog.py' watchdog_script = rpythondir.join('tool', watchdog_name) - regr_script = pypydir.join('tool', 'pytest', + regr_script = pypydir.join('tool', 'pytest', 'run-script', 'regrverbose.py') - + regrrun = str(regr_script) option = self.config.option TIMEOUT = gettimeout(option.timeout.lower()) @@ -566,8 +564,7 @@ if not execpath.check(): execpath = py.path.local.sysfind(option.pypy) if not execpath: - raise LookupError("could not find executable %r" % - (option.pypy,)) + raise LookupError("could not find executable %r" % option.pypy) # check modules info = py.process.cmdexec("%s --info" % execpath) @@ -576,34 +573,29 @@ if info.get('objspace.usemodules.%s' % mod) is not True: py.test.skip("%s module not included in %s" % (mod, execpath)) - - cmd = "%s %s %s" %( - execpath, - regrrun, fspath.purebasename) + cmd = "%s %s %s" % (execpath, regrrun, fspath.purebasename) # add watchdog for timing out - cmd = "%s %s %s %s" %( - python, watchdog_script, TIMEOUT, - cmd) + cmd = "%s %s %s %s" % (python, watchdog_script, TIMEOUT, cmd) else: pypy_options = [] pypy_options.extend( ['--withmod-%s' % mod for mod in regrtest.usemodules]) - sopt = " ".join(pypy_options) - cmd = "%s %s %d %s -S %s %s %s -v" %( - python, alarm_script, TIMEOUT, - pypy_script, sopt, + sopt = " ".join(pypy_options) + cmd = "%s %s %d %s -S %s %s %s -v" % ( + python, alarm_script, TIMEOUT, + pypy_script, sopt, regrrun, fspath.purebasename) - return cmd + return cmd - def runtest(self): - """ invoke a subprocess running the test file via PyPy. - record its output into the 'result/user at host' subdirectory. - (we might want to create subdirectories for - each user, because we will probably all produce + def runtest(self): + """ invoke a subprocess running the test file via PyPy. + record its output into the 'result/user at host' subdirectory. + (we might want to create subdirectories for + each user, because we will probably all produce such result runs and they will not be the same - i am afraid. - """ + i am afraid. + """ regrtest = self.parent.regrtest if regrtest.skip: if regrtest.skip is True: @@ -611,8 +603,8 @@ else: msg = regrtest.skip py.test.skip(msg) - (skipped, exit_status, test_stdout, - test_stderr) = self.getresult(regrtest) + (skipped, exit_status, test_stdout, test_stderr) = \ + self.getresult(regrtest) if skipped: py.test.skip(test_stderr.splitlines()[-1]) if exit_status: @@ -624,13 +616,13 @@ out, err = excinfo.value.args return out + err - def getstatusouterr(self, cmd): + def getstatusouterr(self, cmd): tempdir = py.test.ensuretemp(self.fspath.basename) stdout = tempdir.join(self.fspath.basename) + '.out' stderr = tempdir.join(self.fspath.basename) + '.err' if sys.platform == 'win32': - status = os.system("%s >%s 2>%s" %(cmd, stdout, stderr)) - if status>=0: + status = os.system("%s >%s 2>%s" % (cmd, stdout, stderr)) + if status >= 0: status = status else: status = 'abnormal termination 0x%x' % status @@ -644,22 +636,22 @@ stdout.write('') stderr.write('') else: - status = os.system("%s >>%s 2>>%s" %(cmd, stdout, stderr)) + status = os.system("%s >>%s 2>>%s" % (cmd, stdout, stderr)) if os.WIFEXITED(status): status = os.WEXITSTATUS(status) else: status = 'abnormal termination 0x%x' % status return status, stdout.read(mode='rU'), stderr.read(mode='rU') - def getresult(self, regrtest): + def getresult(self, regrtest): cmd = self.getinvocation(regrtest) tempdir = py.test.ensuretemp(self.fspath.basename) oldcwd = tempdir.chdir() exit_status, test_stdout, test_stderr = self.getstatusouterr(cmd) oldcwd.chdir() skipped = False - timedout = test_stderr.rfind(26*"=" + "timedout" + 26*"=") != -1 - if not timedout: + timedout = test_stderr.rfind(26*"=" + "timedout" + 26*"=") != -1 + if not timedout: timedout = test_stderr.rfind("KeyboardInterrupt") != -1 if test_stderr.rfind(26*"=" + "skipped" + 26*"=") != -1: skipped = True @@ -669,12 +661,12 @@ # test in test_zipimport_support.py if re.search(r'\bFAIL\b', test_stdout) or re.search('[^:]ERROR', test_stderr): outcome = 'FAIL' - exit_status = 2 - elif timedout: - outcome = "T/O" - else: + exit_status = 2 + elif timedout: + outcome = "T/O" + else: outcome = "ERR" - + return skipped, exit_status, test_stdout, test_stderr def _keywords(self): @@ -683,4 +675,3 @@ if regrtest.core: lst.append('core') return lst - diff --git a/lib_pypy/_collections.py b/lib_pypy/_collections.py --- a/lib_pypy/_collections.py +++ b/lib_pypy/_collections.py @@ -8,7 +8,6 @@ # Note that PyPy also contains a built-in module '_collections' which will hide # this one if compiled in. -import operator try: from threading import _get_ident as _thread_ident except ImportError: diff --git a/lib_pypy/_ctypes/function.py b/lib_pypy/_ctypes/function.py --- a/lib_pypy/_ctypes/function.py +++ b/lib_pypy/_ctypes/function.py @@ -8,7 +8,6 @@ import _ffi import sys import traceback -import warnings try: from __pypy__ import builtinify except ImportError: builtinify = lambda f: f @@ -315,8 +314,12 @@ return if argtypes is None: - warnings.warn('C function without declared arguments called', - RuntimeWarning, stacklevel=2) + # XXX this warning was originally meaning "it's going to be + # really slow". Now we don't worry that much about slowness + # of ctypes, and it's strange to get warnings for perfectly- + # legal code. + #warnings.warn('C function without declared arguments called', + # RuntimeWarning, stacklevel=2) argtypes = [] if self._com_index: @@ -342,6 +345,7 @@ if not outargs: return result + from ctypes import c_void_p simple_cdata = type(c_void_p()).__bases__[0] outargs = [x.value if type(x).__bases__[0] is simple_cdata else x for x in outargs] diff --git a/lib_pypy/_curses.py b/lib_pypy/_curses.py --- a/lib_pypy/_curses.py +++ b/lib_pypy/_curses.py @@ -359,9 +359,14 @@ if not lib._m_NetBSD: for key in range(lib.KEY_MIN, lib.KEY_MAX): key_n = lib.keyname(key) - if key_n == ffi.NULL or ffi.string(key_n) == "UNKNOWN KEY": + if key_n == ffi.NULL: continue - key_n = ffi.string(key_n).replace('(', '').replace(')', '') + key_n = ffi.string(key_n) + if key_n == b"UNKNOWN KEY": + continue + if not isinstance(key_n, str): # python 3 + key_n = key_n.decode() + key_n = key_n.replace('(', '').replace(')', '') globals()[key_n] = key _setup() diff --git a/lib_pypy/_functools.py b/lib_pypy/_functools.py --- a/lib_pypy/_functools.py +++ b/lib_pypy/_functools.py @@ -20,3 +20,16 @@ if self.keywords is not None: fkeywords = dict(self.keywords, **fkeywords) return self.func(*(self.args + fargs), **fkeywords) + + def __reduce__(self): + d = dict((k, v) for k, v in self.__dict__.iteritems() if k not in + ('func', 'args', 'keywords')) + if len(d) == 0: + d = None + return (type(self), (self.func,), + (self.func, self.args, self.keywords, d)) + + def __setstate__(self, state): + self.func, self.args, self.keywords, d = state + if d is not None: + self.__dict__.update(d) diff --git a/lib_pypy/_pypy_interact.py b/lib_pypy/_pypy_interact.py --- a/lib_pypy/_pypy_interact.py +++ b/lib_pypy/_pypy_interact.py @@ -44,7 +44,7 @@ import code if mainmodule is None: import __main__ as mainmodule - console = code.InteractiveConsole(mainmodule.__dict__) + console = code.InteractiveConsole(mainmodule.__dict__, filename='') # some parts of code.py are copied here because it seems to be impossible # to start an interactive console without printing at least one line # of banner @@ -74,7 +74,6 @@ # ____________________________________________________________ if __name__ == '__main__': # for testing - import os if os.getenv('PYTHONSTARTUP'): execfile(os.getenv('PYTHONSTARTUP')) interactive_console() diff --git a/lib_pypy/_sha512.py b/lib_pypy/_sha512.py --- a/lib_pypy/_sha512.py +++ b/lib_pypy/_sha512.py @@ -30,23 +30,23 @@ def sha_transform(sha_info): W = [] - + d = sha_info['data'] for i in xrange(0,16): W.append( (d[8*i]<<56) + (d[8*i+1]<<48) + (d[8*i+2]<<40) + (d[8*i+3]<<32) + (d[8*i+4]<<24) + (d[8*i+5]<<16) + (d[8*i+6]<<8) + d[8*i+7]) - + for i in xrange(16,80): W.append( (Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]) & 0xffffffffffffffff ) - + ss = sha_info['digest'][:] - + def RND(a,b,c,d,e,f,g,h,i,ki): t0 = (h + Sigma1(e) + Ch(e, f, g) + ki + W[i]) & 0xffffffffffffffff t1 = (Sigma0(a) + Maj(a, b, c)) & 0xffffffffffffffff d = (d + t0) & 0xffffffffffffffff h = (t0 + t1) & 0xffffffffffffffff return d & 0xffffffffffffffff, h & 0xffffffffffffffff - + ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],0,0x428a2f98d728ae22) ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],1,0x7137449123ef65cd) ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],2,0xb5c0fbcfec4d3b2f) @@ -127,8 +127,7 @@ ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],77,0x597f299cfc657e2a) ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],78,0x5fcb6fab3ad6faec) ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],79,0x6c44198c4a475817) - - + dig = [] for i, x in enumerate(sha_info['digest']): dig.append( (x + ss[i]) & 0xffffffffffffffff ) @@ -167,36 +166,35 @@ if clo < sha_info['count_lo']: sha_info['count_hi'] += 1 sha_info['count_lo'] = clo - + sha_info['count_hi'] += (count >> 29) - + if sha_info['local']: i = SHA_BLOCKSIZE - sha_info['local'] if i > count: i = count - + # copy buffer for x in enumerate(buffer[buffer_idx:buffer_idx+i]): sha_info['data'][sha_info['local']+x[0]] = struct.unpack('B', x[1])[0] - + count -= i buffer_idx += i - + sha_info['local'] += i if sha_info['local'] == SHA_BLOCKSIZE: sha_transform(sha_info) sha_info['local'] = 0 else: return - + while count >= SHA_BLOCKSIZE: # copy buffer sha_info['data'] = [struct.unpack('B',c)[0] for c in buffer[buffer_idx:buffer_idx + SHA_BLOCKSIZE]] count -= SHA_BLOCKSIZE buffer_idx += SHA_BLOCKSIZE sha_transform(sha_info) - - + # copy buffer pos = sha_info['local'] sha_info['data'][pos:pos+count] = [struct.unpack('B',c)[0] for c in buffer[buffer_idx:buffer_idx + count]] @@ -216,7 +214,7 @@ sha_info['data'] = [0] * SHA_BLOCKSIZE else: sha_info['data'] = sha_info['data'][:count] + ([0] * (SHA_BLOCKSIZE - count)) - + sha_info['data'][112] = 0; sha_info['data'][113] = 0; sha_info['data'][114] = 0; @@ -225,7 +223,7 @@ sha_info['data'][117] = 0; sha_info['data'][118] = 0; sha_info['data'][119] = 0; - + sha_info['data'][120] = (hi_bit_count >> 24) & 0xff sha_info['data'][121] = (hi_bit_count >> 16) & 0xff sha_info['data'][122] = (hi_bit_count >> 8) & 0xff @@ -234,9 +232,9 @@ sha_info['data'][125] = (lo_bit_count >> 16) & 0xff sha_info['data'][126] = (lo_bit_count >> 8) & 0xff sha_info['data'][127] = (lo_bit_count >> 0) & 0xff - + sha_transform(sha_info) - + dig = [] for i in sha_info['digest']: dig.extend([ ((i>>56) & 0xff), ((i>>48) & 0xff), ((i>>40) & 0xff), ((i>>32) & 0xff), ((i>>24) & 0xff), ((i>>16) & 0xff), ((i>>8) & 0xff), (i & 0xff) ]) @@ -250,13 +248,13 @@ self._sha = sha_init() if s: sha_update(self._sha, getbuf(s)) - + def update(self, s): sha_update(self._sha, getbuf(s)) - + def digest(self): return sha_final(self._sha.copy())[:self._sha['digestsize']] - + def hexdigest(self): return ''.join(['%.2x' % ord(i) for i in self.digest()]) @@ -279,12 +277,14 @@ return new def test(): + import _sha512 + a_str = "just a test string" - + assert _sha512.sha512().hexdigest() == sha512().hexdigest() assert _sha512.sha512(a_str).hexdigest() == sha512(a_str).hexdigest() assert _sha512.sha512(a_str*7).hexdigest() == sha512(a_str*7).hexdigest() - + s = sha512(a_str) s.update(a_str) assert _sha512.sha512(a_str+a_str).hexdigest() == s.hexdigest() diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -218,7 +218,7 @@ const char **pzTail /* OUT: Pointer to unused portion of zSql */ ); -void sqlite3_result_blob(sqlite3_context*, const char*, int, void(*)(void*)); +void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); void sqlite3_result_double(sqlite3_context*, double); void sqlite3_result_error(sqlite3_context*, const char*, int); void sqlite3_result_error16(sqlite3_context*, const void*, int); @@ -256,7 +256,13 @@ typedef ... sqlite3; int sqlite3_enable_load_extension(sqlite3 *db, int onoff); """) - unverified_lib = unverified_ffi.dlopen('sqlite3') + libname = 'sqlite3' + if sys.platform == 'win32': + import os + _libname = os.path.join(os.path.dirname(sys.executable), libname) + if os.path.exists(_libname + '.dll'): + libname = _libname + unverified_lib = unverified_ffi.dlopen(libname) return hasattr(unverified_lib, 'sqlite3_enable_load_extension') if _has_load_extension(): @@ -759,9 +765,9 @@ if isinstance(name, unicode): name = name.encode('utf-8') ret = _lib.sqlite3_create_collation(self._db, name, - _lib.SQLITE_UTF8, - _ffi.NULL, - collation_callback) + _lib.SQLITE_UTF8, + _ffi.NULL, + collation_callback) if ret != _lib.SQLITE_OK: raise self._get_exception(ret) @@ -780,9 +786,7 @@ return _lib.SQLITE_DENY self.__func_cache[callback] = authorizer - ret = _lib.sqlite3_set_authorizer(self._db, - authorizer, - _ffi.NULL) + ret = _lib.sqlite3_set_authorizer(self._db, authorizer, _ffi.NULL) if ret != _lib.SQLITE_OK: raise self._get_exception(ret) @@ -798,15 +802,13 @@ @_ffi.callback("int(void*)") def progress_handler(userdata): try: - ret = callable() - return bool(ret) + return bool(callable()) except Exception: # abort query if error occurred return 1 self.__func_cache[callable] = progress_handler - _lib.sqlite3_progress_handler(self._db, nsteps, - progress_handler, - _ffi.NULL) + _lib.sqlite3_progress_handler(self._db, nsteps, progress_handler, + _ffi.NULL) if sys.version_info[0] >= 3: def __get_in_transaction(self): @@ -888,8 +890,8 @@ def __check_reset(self): if self._reset: raise InterfaceError( - "Cursor needed to be reset because of commit/rollback " - "and can no longer be fetched from.") + "Cursor needed to be reset because of commit/rollback " + "and can no longer be fetched from.") def __build_row_cast_map(self): if not self.__connection._detect_types: @@ -996,17 +998,18 @@ # Actually execute the SQL statement ret = _lib.sqlite3_step(self.__statement._statement) - if ret not in (_lib.SQLITE_DONE, _lib.SQLITE_ROW): - self.__statement._reset() - raise self.__connection._get_exception(ret) if ret == _lib.SQLITE_ROW: if multiple: raise ProgrammingError("executemany() can only execute DML statements.") self.__build_row_cast_map() self.__next_row = self.__fetch_one_row() - elif ret == _lib.SQLITE_DONE and not multiple: + elif ret == _lib.SQLITE_DONE: + if not multiple: + self.__statement._reset() + else: self.__statement._reset() + raise self.__connection._get_exception(ret) if self.__statement._type in ("UPDATE", "DELETE", "INSERT", "REPLACE"): if self.__rowcount == -1: @@ -1087,7 +1090,6 @@ try: next_row = self.__next_row except AttributeError: - self.__statement._reset() raise StopIteration del self.__next_row @@ -1095,11 +1097,12 @@ next_row = self.row_factory(self, next_row) ret = _lib.sqlite3_step(self.__statement._statement) - if ret not in (_lib.SQLITE_DONE, _lib.SQLITE_ROW): + if ret == _lib.SQLITE_ROW: + self.__next_row = self.__fetch_one_row() + else: self.__statement._reset() - raise self.__connection._get_exception(ret) - elif ret == _lib.SQLITE_ROW: - self.__next_row = self.__fetch_one_row() + if ret != _lib.SQLITE_DONE: + raise self.__connection._get_exception(ret) return next_row if sys.version_info[0] < 3: diff --git a/lib_pypy/dbm.py b/lib_pypy/dbm.py --- a/lib_pypy/dbm.py +++ b/lib_pypy/dbm.py @@ -168,7 +168,7 @@ 'c': os.O_RDWR | os.O_CREAT, 'n': os.O_RDWR | os.O_CREAT | os.O_TRUNC, }[flag] - except KeyError, e: + except KeyError: raise error("arg 2 to open should be 'r', 'w', 'c', or 'n'") a_db = getattr(lib, funcs['open'])(filename, openflag, mode) diff --git a/lib_pypy/greenlet.py b/lib_pypy/greenlet.py --- a/lib_pypy/greenlet.py +++ b/lib_pypy/greenlet.py @@ -1,4 +1,4 @@ -import _continuation, sys +import _continuation __version__ = "0.4.0" diff --git a/lib_pypy/pyrepl/python_reader.py b/lib_pypy/pyrepl/python_reader.py --- a/lib_pypy/pyrepl/python_reader.py +++ b/lib_pypy/pyrepl/python_reader.py @@ -171,11 +171,11 @@ def execute(self, text): try: - # ooh, look at the hack: + # ooh, look at the hack: code = self.compile("# coding:utf8\n"+text.encode('utf-8'), - '', 'single') + '', 'single') except (OverflowError, SyntaxError, ValueError): - self.showsyntaxerror("") + self.showsyntaxerror('') else: self.runcode(code) if sys.stdout and not sys.stdout.closed: diff --git a/lib_pypy/pyrepl/simple_interact.py b/lib_pypy/pyrepl/simple_interact.py --- a/lib_pypy/pyrepl/simple_interact.py +++ b/lib_pypy/pyrepl/simple_interact.py @@ -37,13 +37,13 @@ import code if mainmodule is None: import __main__ as mainmodule - console = code.InteractiveConsole(mainmodule.__dict__) + console = code.InteractiveConsole(mainmodule.__dict__, filename='') def more_lines(unicodetext): # ooh, look at the hack: src = "#coding:utf-8\n"+unicodetext.encode('utf-8') try: - code = console.compile(src, '', 'single') + code = console.compile(src, '', 'single') except (OverflowError, SyntaxError, ValueError): return False else: diff --git a/pypy/doc/arm.rst b/pypy/doc/arm.rst --- a/pypy/doc/arm.rst +++ b/pypy/doc/arm.rst @@ -153,7 +153,7 @@ :: - pypy /rpython/bin/rpython -Ojit --platform=arm --gcrootfinder=shadowstack --jit-backend=armv7 targetpypystandalone.py + pypy /rpython/bin/rpython -Ojit --platform=arm --gcrootfinder=shadowstack --jit-backend=arm targetpypystandalone.py The gcrootfinder option is needed to work around `issue 1377`_ and the jit-backend works around `issue 1376`_ diff --git a/pypy/doc/dir-reference.rst b/pypy/doc/dir-reference.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/dir-reference.rst @@ -0,0 +1,140 @@ +PyPy directory cross-reference +------------------------------ + +Here is a fully referenced alphabetical two-level deep +directory overview of PyPy: + +================================= ============================================ +Directory explanation/links +================================= ============================================ +`pypy/bin/`_ command-line scripts, mainly + `pypy/bin/pyinteractive.py`_ + +`pypy/config/`_ handles the numerous options for building + and running PyPy + +`pypy/doc/`_ text versions of PyPy developer + documentation + +`pypy/doc/config/`_ documentation for the numerous translation + options + +`pypy/doc/discussion/`_ drafts of ideas and documentation + +``doc/*/`` other specific documentation topics or tools + +`pypy/interpreter/`_ `bytecode interpreter`_ and related objects + (frames, functions, modules,...) + +`pypy/interpreter/pyparser/`_ interpreter-level Python source parser + +`pypy/interpreter/astcompiler/`_ interpreter-level bytecode compiler, + via an AST representation + +`pypy/module/`_ contains `mixed modules`_ + implementing core modules with + both application and interpreter level code. + Not all are finished and working. Use + the ``--withmod-xxx`` + or ``--allworkingmodules`` translation + options. + +`pypy/objspace/`_ `object space`_ implementations + +`pypy/objspace/std/`_ the StdObjSpace_ implementing CPython's + objects and types + +`pypy/tool/`_ various utilities and hacks used + from various places + +`pypy/tool/algo/`_ general-purpose algorithmic and mathematic + tools + +`pypy/tool/pytest/`_ support code for our `testing methods`_ + + +`rpython/annotator/`_ `type inferencing code`_ for + `RPython`_ programs + +`rpython/config/`_ handles the numerous options for RPython + + +`rpython/flowspace/`_ the FlowObjSpace_ implementing + `abstract interpretation`_ + +`rpython/rlib/`_ a `"standard library"`_ for RPython_ + programs + +`rpython/rtyper/`_ the `RPython Typer`_ + +`rpython/rtyper/lltypesystem/`_ the `low-level type system`_ for + C-like backends + +`rpython/rtyper/ootypesystem/`_ the `object-oriented type system`_ + for OO backends + +`rpython/memory/`_ the `garbage collector`_ construction + framework + +`rpython/translator/`_ translation_ backends and support code + +`rpython/translator/backendopt/`_ general optimizations that run before a + backend generates code + +`rpython/translator/c/`_ the `GenC backend`_, producing C code + from an + RPython program (generally via the rtyper_) + +`rpython/translator/cli/`_ the `CLI backend`_ for `.NET`_ + (Microsoft CLR or Mono_) + +`pypy/goal/`_ our `main PyPy-translation scripts`_ + live here + +`rpython/translator/jvm/`_ the Java backend + +`rpython/translator/tool/`_ helper tools for translation + +`dotviewer/`_ `graph viewer`_ + +``*/test/`` many directories have a test subdirectory + containing test + modules (see `Testing in PyPy`_) + +``_cache/`` holds cache files from various purposes +================================= ============================================ + +.. _`bytecode interpreter`: interpreter.html +.. _`Testing in PyPy`: coding-guide.html#testing-in-pypy +.. _`mixed modules`: coding-guide.html#mixed-modules +.. _`modules`: coding-guide.html#modules +.. _`basil`: http://people.cs.uchicago.edu/~jriehl/BasilTalk.pdf +.. _`object space`: objspace.html +.. _FlowObjSpace: objspace.html#the-flow-object-space +.. _`transparent proxies`: objspace-proxies.html#tproxy +.. _`Differences between PyPy and CPython`: cpython_differences.html +.. _`What PyPy can do for your objects`: objspace-proxies.html +.. _`Continulets and greenlets`: stackless.html +.. _StdObjSpace: objspace.html#the-standard-object-space +.. _`abstract interpretation`: http://en.wikipedia.org/wiki/Abstract_interpretation +.. _`rpython`: coding-guide.html#rpython +.. _`type inferencing code`: translation.html#the-annotation-pass +.. _`RPython Typer`: translation.html#rpython-typer +.. _`testing methods`: coding-guide.html#testing-in-pypy +.. _`translation`: translation.html +.. _`GenC backend`: translation.html#genc +.. _`CLI backend`: cli-backend.html +.. _`py.py`: getting-started-python.html#the-py.py-interpreter +.. _`translatorshell.py`: getting-started-dev.html#try-out-the-translator +.. _JIT: jit/index.html +.. _`JIT Generation in PyPy`: jit/index.html +.. _`just-in-time compiler generator`: jit/index.html +.. _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 +.. _`main PyPy-translation scripts`: getting-started-python.html#translating-the-pypy-python-interpreter +.. _`.NET`: http://www.microsoft.com/net/ +.. _Mono: http://www.mono-project.com/ +.. _`"standard library"`: rlib.html +.. _`graph viewer`: getting-started-dev.html#try-out-the-translator diff --git a/pypy/doc/getting-started-dev.rst b/pypy/doc/getting-started-dev.rst --- a/pypy/doc/getting-started-dev.rst +++ b/pypy/doc/getting-started-dev.rst @@ -1,13 +1,58 @@ -=============================================================================== -Getting Started with the Translation Toolchain and Development Process -=============================================================================== +============================ +Getting Started with RPython +============================ .. contents:: +RPython is a subset of Python that can be statically compiled. The PyPy +interpreter is written mostly in RPython (with pieces in Python), while +the RPython compiler is written in Python. The hard to understand part +is that Python is a meta-programming language for RPython, that is, +RPython is considered from live objects **after** the imports are done. +This might require more explanation. You start writing RPython from +``entry_point``, a good starting point is +``rpython/translator/goal/targetnopstandalone.py``. This does not do all that +much, but is a start. Now if code analyzed (in this case ``entry_point``) +calls some functions, those calls will be followed. Those followed calls +have to be RPython themselves (and everything they call etc.), however not +entire module files. To show how you can use metaprogramming, we can do +a silly example (note that closures are not RPython):: + + def generator(operation): + if operation == 'add': + def f(a, b): + return a + b + else: + def f(a, b): + return a - b + return f + + add = generator('add') + sub = generator('sub') + + def entry_point(argv): + print add(sub(int(argv[1]), 3) 4) + return 0 + +In this example ``entry_point`` is RPython, ``add`` and ``sub`` are RPython, +however, ``generator`` is not. + +A good introductory level articles are available: + +* Laurence Tratt -- `Fast Enough VMs in Fast Enough Time`_. + +* `How to write interpreters in RPython`_ and `part 2`_ by Andrew Brown. + +.. _`Fast Enough VMs in Fast Enough Time`: http://tratt.net/laurie/tech_articles/articles/fast_enough_vms_in_fast_enough_time + +.. _`How to write interpreters in RPython`: http://morepypy.blogspot.com/2011/04/tutorial-writing-interpreter-with-pypy.html + +.. _`part 2`: http://morepypy.blogspot.com/2011/04/tutorial-part-2-adding-jit.html + .. _`try out the translator`: Trying out the translator -------------------------- +------------------------- The translator is a tool based on the PyPy interpreter which can translate sufficiently static RPython programs into low-level code (in particular it can @@ -28,7 +73,7 @@ >>> t = Translation(snippet.is_perfect_number, [int]) >>> t.view() - + After that, the graph viewer pops up, that lets you interactively inspect the flow graph. To move around, click on something that you want to inspect. To get help about how to use it, press 'H'. To close it again, press 'Q'. @@ -83,10 +128,10 @@ The object returned by ``compile_cli`` or ``compile_jvm`` is a wrapper around the real executable: the parameters are passed as command line arguments, and -the returned value is read from the standard output. +the returned value is read from the standard output. Once you have compiled the snippet, you can also try to launch the -executable directly from the shell. You will find the +executable directly from the shell. You will find the executable in one of the ``/tmp/usession-*`` directories:: # For CLI: diff --git a/pypy/doc/getting-started-python.rst b/pypy/doc/getting-started-python.rst --- a/pypy/doc/getting-started-python.rst +++ b/pypy/doc/getting-started-python.rst @@ -6,7 +6,7 @@ PyPy's Python interpreter is a very compliant Python -interpreter implemented in Python. When translated to C, it passes most of +interpreter implemented in RPython. When compiled, it passes most of `CPythons core language regression tests`_ and comes with many of the extension modules included in the standard library including ``ctypes``. It can run large libraries such as Django_ and Twisted_. There are some small behavioral @@ -147,6 +147,8 @@ Translating using the CLI backend +++++++++++++++++++++++++++++++++ +**Note: the CLI backend is no longer maintained** + To create a standalone .NET executable using the `CLI backend`_:: ./translate.py --backend=cli targetpypystandalone.py diff --git a/pypy/doc/how-to-contribute.rst b/pypy/doc/how-to-contribute.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/how-to-contribute.rst @@ -0,0 +1,78 @@ +How to contribute to PyPy +------------------------- + +This page describes how to contribute to the PyPy project. The first thing +to remember is that PyPy project is very different than most projects out there. +It's also different from a classic compiler project, so academic courses +about compilers often don't apply or lead in the wrong direction. + +Don't just hack +--------------- + +The first and most important rule how not to contribute to PyPy is +"just hacking". This won't work. There are two major reasons why not +-- build times are large and PyPy has very thick layer separation which +make it harder to "just hack a feature". + +Test driven development +----------------------- + +Instead, we practice a lot of test driven development. This is partly because +of very high quality requirements for compilers and partly because there is +simply no other way to get around such complex project, that will keep you sane. +There are probably people out there who are smart enough not to need it, we're +not one of those. You may consider familiarizing yourself with `pytest`_, +since this is a tool we use for tests. +This leads to the next issue: + +Layers +------ + +PyPy has layers. Those layers help us keep the respective parts separated enough +to be worked on independently and make the complexity manageable. This is, +again, just a sanity requirement for such a complex project. For example writing +a new optimization for the JIT usually does **not** involve touching a Python +interpreter at all or the JIT assembler backend or the garbage collector. +Instead it requires writing small tests in +``rpython/jit/metainterp/optimizeopt/test/test_*`` and fixing files there. +After that, you can just compile PyPy and things should just work. + +The short list of layers for further reading. For each of those layers, a good +entry point is a test subdirectory in respective directories. It usually +describes (better or worse) the interfaces between the submodules. For the +``pypy`` subdirectory, most tests are small snippets of python programs that +check for correctness (calls ``AppTestXxx``) that will call the appropriate +part of the interpreter. For the ``rpython`` directory, most tests are small +RPython interpreters that perform certain tasks. To see how they translate +to low-level graphs, run them with ``--view``. To see small interpreters +with a JIT compiler, use ``--viewloops`` option. + +* **python interpreter** - it's the part implemented in the ``pypy/`` directory. + It's implemented in RPython, which is a high level static language with + classes, garbage collection, just-in-time compiler generation and the ability + to call C. A cool part about it is that it can be run untranslated, so all + the tests are runnable without translating PyPy. + + **interpreter** contains the interpreter core + + **objspace** contains implementations of various objects exported to + the Python layer + + **module** directory contains extension modules written in RPython + +* **rpython compiler** that resides in ``rpython/annotator`` and + ``rpython/rtyper`` directories. Consult `introduction to RPython`_ for + further reading + +* **JIT generator** lives in ``rpython/jit`` directory. optimizations live + in ``rpython/jit/metainterp/optimizeopt``, the main JIT in + ``rpython/jit/metainterp`` (runtime part) and + ``rpython/jit/codewriter`` (translation-time part). Backends live in + ``rpython/jit/backend``. + +* **garbage collection** lives in ``rpython/memory`` + +The rest of directories serve specific niche goal and are unlikely a good +entry point. + +.. _`introduction to RPython`: getting-started-dev.rst diff --git a/pypy/doc/index.rst b/pypy/doc/index.rst --- a/pypy/doc/index.rst +++ b/pypy/doc/index.rst @@ -1,15 +1,40 @@ -Welcome to PyPy Development -============================================= +Welcome to PyPy +=============== -The PyPy project aims at producing a flexible and fast Python_ -implementation. The guiding idea is to translate a Python-level -description of the Python language itself to lower level languages. -Rumors have it that the secret goal is being faster-than-C which is -nonsense, isn't it? `more...`_ +The PyPy project aims to produce a flexible and fast Python_ +implementation. This page documents the development of the PyPy +project itself. If you don't know what PyPy is, consult the `PyPy +website`_. If you just want to use PyPy, consult the `download`_ page +and the `getting started with pypy`_ documents. If you want to help +develop PyPy -- keep reading! -Getting into PyPy ... -============================================= +PyPy is written in a language called `RPython`_, which is suitable for +writing dynamic language interpreters (and not much else). RPython is +a subset of Python and is itself written in Python. If you'd like to +learn more about RPython, `Starting with RPython`_ should provide a +reasonable overview. + +**If you would like to contribute to PyPy**, please read `how to +contribute`_ first. PyPy's development style is somewhat different to +that of many other software projects and it often surprises +newcomers. What is **not** necessary is an academic background from +university in writing compilers -- much of it does not apply to PyPy +any way. + +All of the documentation and source code is available under the MIT license, +unless otherwise specified. Consult `LICENSE`_ + +.. _`download`: http://pypy.org/download.html +.. _`getting started with pypy`: getting-started-python.html +.. _`RPython`: coding-guide.html#RPython +.. _`Starting with RPython`: getting-started-dev.html +.. _`how to contribute`: how-to-contribute.html +.. _`PyPy website`: http://pypy.org +.. _`LICENSE`: https://bitbucket.org/pypy/pypy/src/default/LICENSE + +Index of various topics: +======================== * `Getting started`_: how to install and run the PyPy Python interpreter @@ -25,20 +50,30 @@ * `potential project ideas`_: In case you want to get your feet wet... +* `more stuff`_: this is a collection of documentation that's there, but not + particularly organized + Documentation for the PyPy Python Interpreter -=============================================== +============================================= New features of PyPy's Python Interpreter and Translation Framework: * `Differences between PyPy and CPython`_ - * `What PyPy can do for your objects`_ - * `Continulets and greenlets`_ + * `What PyPy can do for your objects`_ - transparent proxy documentation + * `Continulets and greenlets`_ - documentation about stackless features * `JIT Generation in PyPy`_ + * `JIT hooks`_ * `Sandboxing Python code`_ + * `Garbage collection environment variables`_ -Status_ of the project. - +.. _`Differences between PyPy and CPython`: cpython_differences.html +.. _`What PyPy can do for your objects`: objspace-proxies.html +.. _`Continulets and greenlets`: stackless.html +.. _`JIT Generation in PyPy`: jit/index.html +.. _`JIT hooks`: jit-hooks.html +.. _`Sandboxing Python code`: sandbox.html +.. _`Garbage collection environment variables`: gc_info.html Mailing lists, bug tracker, IRC channel ============================================= @@ -79,354 +114,6 @@ .. _`speed.pypy.org`: http://speed.pypy.org .. _`RPython toolchain`: translation.html .. _`potential project ideas`: project-ideas.html - -Project Documentation -===================================== - -PyPy was funded by the EU for several years. See the `web site of the EU -project`_ for more details. - -.. _`web site of the EU project`: http://pypy.org - -architecture_ gives a complete view of PyPy's basic design. - -`coding guide`_ helps you to write code for PyPy (especially also describes -coding in RPython a bit). - -`sprint reports`_ lists reports written at most of our sprints, from -2003 to the present. - -`papers, talks and related projects`_ lists presentations -and related projects as well as our published papers. - -`PyPy video documentation`_ is a page linking to the videos (e.g. of talks and -introductions) that are available. - -`Technical reports`_ is a page that contains links to the -reports that we submitted to the European Union. - -`development methodology`_ describes our sprint-driven approach. - -`LICENSE`_ contains licensing details (basically a straight MIT-license). - -`Glossary`_ of PyPy words to help you align your inner self with -the PyPy universe. - - -Status -=================================== - -PyPy can be used to run Python programs on Linux, OS/X, -Windows, on top of .NET, and on top of Java. -To dig into PyPy it is recommended to try out the current -Mercurial default branch, which is always working or mostly working, -instead of the latest release, which is `2.0 beta1`__. - -.. __: release-2.0.0-beta1.html - -PyPy is mainly developed on Linux and Mac OS X. Windows is supported, -but platform-specific bugs tend to take longer before we notice and fix -them. Linux 64-bit machines are supported (though it may also take some -time before we notice and fix bugs). - -PyPy's own tests `summary`_, daily updated, run through BuildBot infrastructure. -You can also find CPython's compliance tests run with compiled ``pypy-c`` -executables there. - - -Source Code Documentation -=============================================== - -`object spaces`_ discusses the object space interface -and several implementations. - -`bytecode interpreter`_ explains the basic mechanisms -of the bytecode interpreter and virtual machine. - -`interpreter optimizations`_ describes our various strategies for -improving the performance of our interpreter, including alternative -object implementations (for strings, dictionaries and lists) in the -standard object space. - -`translation`_ is a detailed overview of our translation process. The -rtyper_ is the largest component of our translation process. - -`dynamic-language translation`_ is a paper that describes -the translation process, especially the flow object space -and the annotator in detail. (This document is one -of the `EU reports`_.) - -`low-level encapsulation`_ describes how our approach hides -away a lot of low level details. This document is also part -of the `EU reports`_. - -`translation aspects`_ describes how we weave different -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. - -`rlib`_ describes some modules that can be used when implementing programs in -RPython. - -`configuration documentation`_ describes the various configuration options that -allow you to customize PyPy. - -`CLI backend`_ describes the details of the .NET backend. - -`JIT Generation in PyPy`_ describes how we produce the Python Just-in-time Compiler -from our Python interpreter. - - - -.. _`FAQ`: faq.html -.. _Glossary: glossary.html -.. _`PyPy video documentation`: video-index.html -.. _parser: parser.html -.. _`development methodology`: dev_method.html -.. _`sprint reports`: sprint-reports.html -.. _`papers, talks and related projects`: extradoc.html -.. _`object spaces`: objspace.html -.. _`interpreter optimizations`: interpreter-optimizations.html -.. _`translation`: translation.html -.. _`dynamic-language translation`: https://bitbucket.org/pypy/extradoc/raw/tip/eu-report/D05.1_Publish_on_translating_a_very-high-level_description.pdf -.. _`low-level encapsulation`: low-level-encapsulation.html -.. _`translation aspects`: translation-aspects.html -.. _`configuration documentation`: config/ -.. _`coding guide`: coding-guide.html -.. _`architecture`: architecture.html -.. _`getting started`: getting-started.html -.. _`bytecode interpreter`: interpreter.html -.. _`EU reports`: index-report.html -.. _`Technical reports`: index-report.html -.. _`summary`: http://buildbot.pypy.org/summary -.. _`ideas for PyPy related projects`: project-ideas.html -.. _`Nightly builds and benchmarks`: http://tuatara.cs.uni-duesseldorf.de/benchmark.html -.. _`directory reference`: -.. _`rlib`: rlib.html -.. _`Sandboxing Python code`: sandbox.html -.. _`LICENSE`: https://bitbucket.org/pypy/pypy/src/default/LICENSE - -PyPy directory cross-reference ------------------------------- - -Here is a fully referenced alphabetical two-level deep -directory overview of PyPy: - -================================= ============================================ -Directory explanation/links -================================= ============================================ -`pypy/bin/`_ command-line scripts, mainly - `pypy/bin/pyinteractive.py`_ - -`pypy/config/`_ handles the numerous options for building - and running PyPy - -`pypy/doc/`_ text versions of PyPy developer - documentation - -`pypy/doc/config/`_ documentation for the numerous translation - options - -`pypy/doc/discussion/`_ drafts of ideas and documentation - -``doc/*/`` other specific documentation topics or tools - -`pypy/interpreter/`_ `bytecode interpreter`_ and related objects - (frames, functions, modules,...) - -`pypy/interpreter/pyparser/`_ interpreter-level Python source parser - -`pypy/interpreter/astcompiler/`_ interpreter-level bytecode compiler, - via an AST representation - -`pypy/module/`_ contains `mixed modules`_ - implementing core modules with - both application and interpreter level code. - Not all are finished and working. Use - the ``--withmod-xxx`` - or ``--allworkingmodules`` translation - options. - -`pypy/objspace/`_ `object space`_ implementations - -`pypy/objspace/std/`_ the StdObjSpace_ implementing CPython's - objects and types - -`pypy/tool/`_ various utilities and hacks used - from various places - -`pypy/tool/algo/`_ general-purpose algorithmic and mathematic - tools - -`pypy/tool/pytest/`_ support code for our `testing methods`_ - - -`rpython/annotator/`_ `type inferencing code`_ for - `RPython`_ programs - -`rpython/config/`_ handles the numerous options for RPython - - -`rpython/flowspace/`_ the FlowObjSpace_ implementing - `abstract interpretation`_ - -`rpython/rlib/`_ a `"standard library"`_ for RPython_ - programs - -`rpython/rtyper/`_ the `RPython Typer`_ - -`rpython/rtyper/lltypesystem/`_ the `low-level type system`_ for - C-like backends - -`rpython/rtyper/ootypesystem/`_ the `object-oriented type system`_ - for OO backends - -`rpython/memory/`_ the `garbage collector`_ construction - framework - -`rpython/translator/`_ translation_ backends and support code - -`rpython/translator/backendopt/`_ general optimizations that run before a - backend generates code - -`rpython/translator/c/`_ the `GenC backend`_, producing C code - from an - RPython program (generally via the rtyper_) - -`rpython/translator/cli/`_ the `CLI backend`_ for `.NET`_ - (Microsoft CLR or Mono_) - -`pypy/goal/`_ our `main PyPy-translation scripts`_ - live here - -`rpython/translator/jvm/`_ the Java backend - -`rpython/translator/tool/`_ helper tools for translation - -`dotviewer/`_ `graph viewer`_ - -``*/test/`` many directories have a test subdirectory - containing test - modules (see `Testing in PyPy`_) - -``_cache/`` holds cache files from various purposes -================================= ============================================ - -.. _`bytecode interpreter`: interpreter.html -.. _`Testing in PyPy`: coding-guide.html#testing-in-pypy -.. _`mixed modules`: coding-guide.html#mixed-modules -.. _`modules`: coding-guide.html#modules -.. _`basil`: http://people.cs.uchicago.edu/~jriehl/BasilTalk.pdf -.. _`object space`: objspace.html -.. _FlowObjSpace: objspace.html#the-flow-object-space -.. _`transparent proxies`: objspace-proxies.html#tproxy -.. _`Differences between PyPy and CPython`: cpython_differences.html -.. _`What PyPy can do for your objects`: objspace-proxies.html -.. _`Continulets and greenlets`: stackless.html -.. _StdObjSpace: objspace.html#the-standard-object-space -.. _`abstract interpretation`: http://en.wikipedia.org/wiki/Abstract_interpretation -.. _`rpython`: coding-guide.html#rpython -.. _`type inferencing code`: translation.html#the-annotation-pass -.. _`RPython Typer`: translation.html#rpython-typer -.. _`testing methods`: coding-guide.html#testing-in-pypy -.. _`translation`: translation.html -.. _`GenC backend`: translation.html#genc -.. _`CLI backend`: cli-backend.html -.. _`py.py`: getting-started-python.html#the-py.py-interpreter -.. _`translatorshell.py`: getting-started-dev.html#try-out-the-translator -.. _JIT: jit/index.html -.. _`JIT Generation in PyPy`: jit/index.html -.. _`just-in-time compiler generator`: jit/index.html -.. _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 -.. _`main PyPy-translation scripts`: getting-started-python.html#translating-the-pypy-python-interpreter -.. _`.NET`: http://www.microsoft.com/net/ -.. _Mono: http://www.mono-project.com/ -.. _`"standard library"`: rlib.html -.. _`graph viewer`: getting-started-dev.html#try-out-the-translator - - -.. The following documentation is important and reasonably up-to-date: - -.. extradoc: should this be integrated one level up: dcolish? - - -.. toctree:: - :maxdepth: 1 - :hidden: - - getting-started.rst - getting-started-python.rst - getting-started-dev.rst - windows.rst - faq.rst - commandline_ref.rst - architecture.rst - coding-guide.rst - cpython_differences.rst - garbage_collection.rst - gc_info.rst - interpreter.rst - objspace.rst - __pypy__-module.rst - objspace-proxies.rst - config/index.rst - - dev_method.rst - extending.rst - - extradoc.rst - video-index.rst - - glossary.rst - - contributor.rst - - interpreter-optimizations.rst - configuration.rst - parser.rst - rlib.rst - rtyper.rst - rffi.rst - - translation.rst - jit/index.rst - jit/overview.rst - jit/pyjitpl5.rst - - index-of-release-notes.rst - - ctypes-implementation.rst - - how-to-release.rst - - index-report.rst - - stackless.rst - sandbox.rst - - discussions.rst - - cleanup.rst - - sprint-reports.rst - - eventhistory.rst - statistic/index.rst - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`search` -* :ref:`glossary` - +.. _`more stuff`: project-documentation.html .. include:: _ref.txt diff --git a/pypy/doc/needswork.txt b/pypy/doc/needswork.txt deleted file mode 100644 --- a/pypy/doc/needswork.txt +++ /dev/null @@ -1,3 +0,0 @@ -.. warning:: - - This documentation needs work (as discussed during the Gothenburg sprint in 2011) diff --git a/pypy/doc/objspace-proxies.rst b/pypy/doc/objspace-proxies.rst --- a/pypy/doc/objspace-proxies.rst +++ b/pypy/doc/objspace-proxies.rst @@ -5,7 +5,6 @@ .. contents:: - Thanks to the `Object Space`_ architecture, any feature that is based on proxying, extending, changing or otherwise controlling the behavior of all objects in a running program is easy to implement on diff --git a/pypy/doc/project-documentation.rst b/pypy/doc/project-documentation.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/project-documentation.rst @@ -0,0 +1,177 @@ + +Project Documentation +===================================== + +`architecture`_ gives a complete view of PyPy's basic design. + +`coding guide`_ helps you to write code for PyPy (especially also describes +coding in RPython a bit). + +`sprint reports`_ lists reports written at most of our sprints, from +2003 to the present. + +`papers, talks and related projects`_ lists presentations +and related projects as well as our published papers. + +`PyPy video documentation`_ is a page linking to the videos (e.g. of talks and +introductions) that are available. + +`Technical reports`_ is a page that contains links to the +reports that we submitted to the European Union. + +`development methodology`_ describes our sprint-driven approach. + +`LICENSE`_ contains licensing details (basically a straight MIT-license). + +`Glossary`_ of PyPy words to help you align your inner self with +the PyPy universe. + +Source Code Documentation +=============================================== + +`object spaces`_ discusses the object space interface +and several implementations. + +`bytecode interpreter`_ explains the basic mechanisms +of the bytecode interpreter and virtual machine. + +`interpreter optimizations`_ describes our various strategies for +improving the performance of our interpreter, including alternative +object implementations (for strings, dictionaries and lists) in the +standard object space. + +`translation`_ is a detailed overview of our translation process. The +rtyper_ is the largest component of our translation process. + +`dynamic-language translation`_ is a paper that describes +the translation process, especially the flow object space +and the annotator in detail. (This document is one +of the `EU reports`_.) + +`low-level encapsulation`_ describes how our approach hides +away a lot of low level details. This document is also part +of the `EU reports`_. + +`translation aspects`_ describes how we weave different +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. + +`rlib`_ describes some modules that can be used when implementing programs in +RPython. + +`configuration documentation`_ describes the various configuration options that +allow you to customize PyPy. + +`pypy on windows`_ + +`command line reference`_ + +`CLI backend`_ describes the details of the .NET backend. + +`JIT Generation in PyPy`_ describes how we produce the Python Just-in-time Compiler +from our Python interpreter. + +`directory cross-reference`_ + +.. _`garbage collector`: garbage_collection.html +.. _`directory cross-reference`: dir-reference.html +.. _`pypy on windows`: windows.html +.. _`command line reference`: commandline_ref.html +.. _`FAQ`: faq.html +.. _Glossary: glossary.html +.. _`PyPy video documentation`: video-index.html +.. _parser: parser.html +.. _`development methodology`: dev_method.html +.. _`sprint reports`: sprint-reports.html +.. _`papers, talks and related projects`: extradoc.html +.. _`object spaces`: objspace.html +.. _`interpreter optimizations`: interpreter-optimizations.html +.. _`translation`: translation.html +.. _`dynamic-language translation`: https://bitbucket.org/pypy/extradoc/raw/tip/eu-report/D05.1_Publish_on_translating_a_very-high-level_description.pdf +.. _`low-level encapsulation`: low-level-encapsulation.html +.. _`translation aspects`: translation-aspects.html +.. _`configuration documentation`: config/ +.. _`coding guide`: coding-guide.html +.. _`Architecture`: architecture.html +.. _`getting started`: getting-started.html +.. _`bytecode interpreter`: interpreter.html +.. _`EU reports`: index-report.html +.. _`Technical reports`: index-report.html +.. _`summary`: http://buildbot.pypy.org/summary +.. _`ideas for PyPy related projects`: project-ideas.html +.. _`Nightly builds and benchmarks`: http://tuatara.cs.uni-duesseldorf.de/benchmark.html +.. _`directory reference`: +.. _`rlib`: rlib.html +.. _`Sandboxing Python code`: sandbox.html +.. _`LICENSE`: https://bitbucket.org/pypy/pypy/src/default/LICENSE + +.. The following documentation is important and reasonably up-to-date: + +.. extradoc: should this be integrated one level up: dcolish? + +.. toctree:: + :maxdepth: 1 + :hidden: + + interpreter.rst + objspace.rst + __pypy__-module.rst + objspace-proxies.rst + config/index.rst + + dev_method.rst + extending.rst + + extradoc.rst + video-index.rst + + glossary.rst + + contributor.rst + + interpreter-optimizations.rst + configuration.rst + parser.rst + rlib.rst + rtyper.rst + rffi.rst + + translation.rst + jit/index.rst + jit/overview.rst + jit/pyjitpl5.rst + + index-of-release-notes.rst + + ctypes-implementation.rst + + how-to-release.rst + + index-report.rst + + stackless.rst + sandbox.rst + + discussions.rst + + cleanup.rst + + sprint-reports.rst + + eventhistory.rst + statistic/index.rst + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`search` +* :ref:`glossary` + +.. include:: _ref.txt diff --git a/pypy/doc/release-2.0.0-beta2.rst b/pypy/doc/release-2.0.0-beta2.rst --- a/pypy/doc/release-2.0.0-beta2.rst +++ b/pypy/doc/release-2.0.0-beta2.rst @@ -82,3 +82,13 @@ * we now have special strategies for ``dict``/``set``/``list`` which contain unicode strings, which means that now such collections will be both faster and more compact. + +.. _`eventlet`: http://eventlet.net/ +.. _`gevent`: http://www.gevent.org/ +.. _`cffi`: http://cffi.readthedocs.org/en/release-0.6/ +.. _`JIT hooks`: http://doc.pypy.org/en/latest/jit-hooks.html +.. _`pypycore`: https://github.com/gevent-on-pypy/pypycore +.. _`pypy-hacks`: https://github.com/schmir/gevent/tree/pypy-hacks +.. _`_curses.py`: https://bitbucket.org/pypy/pypy/src/aefddd47f224e3c12e2ea74f5c796d76f4355bdb/lib_pypy/_curses.py?at=default +.. _`_sqlite3.py`: https://bitbucket.org/pypy/pypy/src/aefddd47f224e3c12e2ea74f5c796d76f4355bdb/lib_pypy/_sqlite3.py?at=default + diff --git a/pypy/doc/stackless.rst b/pypy/doc/stackless.rst --- a/pypy/doc/stackless.rst +++ b/pypy/doc/stackless.rst @@ -17,8 +17,8 @@ Continulets can be directly used by application code, or it is possible to write (entirely at app-level) more user-friendly interfaces. -Currently PyPy implements greenlets_ on top of continulets. It would be -easy to implement tasklets and channels as well, emulating the model +Currently PyPy implements greenlets_ on top of continulets. It also +implements (an approximation of) tasklets and channels, emulating the model of `Stackless Python`_. Continulets are extremely light-weight, which means that PyPy should be diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -43,9 +43,21 @@ Rudimentary support for bytearray in RPython .. branch: refactor-call_release_gil -Fix a bug which casused cffi to return the wrong result when calling a C +Fix a bug which caused cffi to return the wrong result when calling a C function which calls a Python callback which forces the frames +.. branch: virtual-raw-mallocs +JIT optimizations which make cffi calls even faster, by removing the need to +allocate a temporary buffer where to store the arguments. + +.. branch: improve-docs-2 +Improve documents and straighten out links + +.. branch: fast-newarray +Inline the fast path of newarray in the assembler. +Disabled on ARM until we fix issues. + + .. branches we don't care about .. branch: autoreds .. branch: reflex-support @@ -115,9 +127,12 @@ .. branch: remove-list-smm .. branch: bridge-logging .. branch: curses_cffi - cffi implementation of _curses .. branch: sqlite-cffi +cffi implementation of sqlite3 -cffi implementation of sqlite3 +.. branch: release-2.0-beta2 +.. branch: unbreak-freebsd + +.. branch: virtualref-virtualizable diff --git a/pypy/goal/getnightly.py b/pypy/goal/getnightly.py --- a/pypy/goal/getnightly.py +++ b/pypy/goal/getnightly.py @@ -13,8 +13,13 @@ if sys.maxint == 2**63 - 1: arch += '64' +hg = py.path.local.sysfind('hg') +branch = hg.sysexec('branch').strip() +if branch == 'default': + branch = 'trunk' + filename = 'pypy-c-jit-latest-%s.tar.bz2' % arch -url = 'http://buildbot.pypy.org/nightly/trunk/%s' % filename +url = 'http://buildbot.pypy.org/nightly/%s/%s' % (branch, filename) tmp = py.path.local.mkdtemp() mydir = tmp.chdir() print 'Downloading pypy to', tmp diff --git a/pypy/interpreter/astcompiler/misc.py b/pypy/interpreter/astcompiler/misc.py --- a/pypy/interpreter/astcompiler/misc.py +++ b/pypy/interpreter/astcompiler/misc.py @@ -1,5 +1,4 @@ from pypy.interpreter import gateway -from pypy.interpreter.astcompiler import ast from rpython.rlib.objectmodel import we_are_translated from rpython.rlib.unroll import unrolling_iterable @@ -28,6 +27,7 @@ def parse_future(tree, feature_flags): + from pypy.interpreter.astcompiler import ast future_lineno = 0 future_column = 0 flags = 0 @@ -91,13 +91,9 @@ return lookup -MANGLE_LEN = 256 # magic constant from compile.c - def mangle(name, klass): if not name.startswith('__'): return name - if len(name) + 2 >= MANGLE_LEN: - return name # Don't mangle __id__ or names with dots. The only time a name with a dot # can occur is when we are compiling an import statement that has a package # name. @@ -109,14 +105,4 @@ i = i + 1 except IndexError: return name - klass = klass[i:] - - tlen = len(klass) + len(name) - if tlen > MANGLE_LEN: - end = len(klass) + MANGLE_LEN-tlen - if end < 0: - klass = '' # slices of negative length are invalid in RPython - else: - klass = klass[:end] - - return "_%s%s" % (klass, name) + return "_%s%s" % (klass[i:], name) diff --git a/pypy/interpreter/astcompiler/test/test_misc.py b/pypy/interpreter/astcompiler/test/test_misc.py new file mode 100644 --- /dev/null +++ b/pypy/interpreter/astcompiler/test/test_misc.py @@ -0,0 +1,14 @@ +from pypy.interpreter.astcompiler.misc import mangle + +def test_mangle(): + assert mangle("foo", "Bar") == "foo" + assert mangle("__foo__", "Bar") == "__foo__" + assert mangle("foo.baz", "Bar") == "foo.baz" + assert mangle("__", "Bar") == "__" + assert mangle("___", "Bar") == "___" + assert mangle("____", "Bar") == "____" + assert mangle("__foo", "Bar") == "_Bar__foo" + assert mangle("__foo", "_Bar") == "_Bar__foo" + assert mangle("__foo", "__Bar") == "_Bar__foo" + assert mangle("__foo", "___") == "__foo" + assert mangle("___foo", "__Bar") == "_Bar___foo" diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py --- a/pypy/interpreter/baseobjspace.py +++ b/pypy/interpreter/baseobjspace.py @@ -709,6 +709,8 @@ def new_interned_w_str(self, w_s): s = self.str_w(w_s) + if not we_are_translated(): + assert type(s) is str try: return self.interned_strings[s] except KeyError: @@ -717,6 +719,8 @@ return w_s def new_interned_str(self, s): + if not we_are_translated(): + assert type(s) is str try: return self.interned_strings[s] except KeyError: diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py --- a/pypy/interpreter/pyopcode.py +++ b/pypy/interpreter/pyopcode.py @@ -255,19 +255,7 @@ "code=%d, name=%s" % (self.last_instr, opcode, methodname)) - try: - res = meth(oparg, next_instr) - except Exception: - if 0: - import dis, sys - print "*** %s at offset %d (%s)" % (sys.exc_info()[0], - self.last_instr, - methodname) - try: From noreply at buildbot.pypy.org Thu Apr 18 23:37:37 2013 From: noreply at buildbot.pypy.org (wlav) Date: Thu, 18 Apr 2013 23:37:37 +0200 (CEST) Subject: [pypy-commit] pypy reflex-support: allow operator== to be defined virtual Message-ID: <20130418213737.935171C31A5@cobra.cs.uni-duesseldorf.de> Author: Wim Lavrijsen Branch: reflex-support Changeset: r63491:6025b73044af Date: 2013-04-18 12:20 -0700 http://bitbucket.org/pypy/pypy/changeset/6025b73044af/ Log: allow operator== to be defined virtual diff --git a/pypy/module/cppyy/pythonify.py b/pypy/module/cppyy/pythonify.py --- a/pypy/module/cppyy/pythonify.py +++ b/pypy/module/cppyy/pythonify.py @@ -313,9 +313,11 @@ if '__eq__' in pyclass.__dict__: def __eq__(self, other): if other is None: return not self - if type(self) is not type(other): return False if not self and not other: return True - return self._cxx_eq(other) + try: + return self._cxx_eq(other) + except TypeError: + return NotImplemented pyclass._cxx_eq = pyclass.__dict__['__eq__'] pyclass.__eq__ = __eq__ diff --git a/pypy/module/cppyy/test/operators.cxx b/pypy/module/cppyy/test/operators.cxx --- a/pypy/module/cppyy/test/operators.cxx +++ b/pypy/module/cppyy/test/operators.cxx @@ -1,1 +1,16 @@ #include "operators.h" + +// for testing the case of virtual operator== +v_opeq_base::v_opeq_base(int val) : m_val(val) {} +v_opeq_base::~v_opeq_base() {} + +bool v_opeq_base::operator==(const v_opeq_base& other) { + return m_val == other.m_val; +} + +v_opeq_derived::v_opeq_derived(int val) : v_opeq_base(val) {} +v_opeq_derived::~v_opeq_derived() {} + +bool v_opeq_derived::operator==(const v_opeq_derived& other) { + return m_val != other.m_val; +} diff --git a/pypy/module/cppyy/test/operators.h b/pypy/module/cppyy/test/operators.h --- a/pypy/module/cppyy/test/operators.h +++ b/pypy/module/cppyy/test/operators.h @@ -93,3 +93,23 @@ operator float() { return m_float; } float m_float; }; + +//---------------------------------------------------------------------------- +class v_opeq_base { +public: + v_opeq_base(int val); + virtual ~v_opeq_base(); + + virtual bool operator==(const v_opeq_base& other); + +protected: + int m_val; +}; + +class v_opeq_derived : public v_opeq_base { +public: + v_opeq_derived(int val); + virtual ~v_opeq_derived(); + + virtual bool operator==(const v_opeq_derived& other); +}; diff --git a/pypy/module/cppyy/test/operators.xml b/pypy/module/cppyy/test/operators.xml --- a/pypy/module/cppyy/test/operators.xml +++ b/pypy/module/cppyy/test/operators.xml @@ -2,5 +2,6 @@ + diff --git a/pypy/module/cppyy/test/test_operators.py b/pypy/module/cppyy/test/test_operators.py --- a/pypy/module/cppyy/test/test_operators.py +++ b/pypy/module/cppyy/test/test_operators.py @@ -136,3 +136,43 @@ o = gbl.operator_float(); o.m_float = 3.14 assert round(o.m_float - 3.14, 5) == 0. assert round(float(o) - 3.14, 5) == 0. + + def test07_virtual_operator_eq(self): + """Test use of virtual bool operator==""" + + import cppyy + + b1 = cppyy.gbl.v_opeq_base(1) + b1a = cppyy.gbl.v_opeq_base(1) + b2 = cppyy.gbl.v_opeq_base(2) + b2a = cppyy.gbl.v_opeq_base(2) + + assert b1 == b1 + assert b1 == b1a + assert not b1 == b2 + assert not b1 == b2a + assert b2 == b2 + assert b2 == b2a + + d1 = cppyy.gbl.v_opeq_derived(1) + d1a = cppyy.gbl.v_opeq_derived(1) + d2 = cppyy.gbl.v_opeq_derived(2) + d2a = cppyy.gbl.v_opeq_derived(2) + + # derived operator== returns opposite + assert not d1 == d1 + assert not d1 == d1a + assert d1 == d2 + assert d1 == d2a + assert not d2 == d2 + assert not d2 == d2a + + # the following is a wee bit interesting due to python resolution + # rules on the one hand, and C++ inheritance on the other: python + # will never select the derived comparison b/c the call will fail + # to pass a base through a const derived& + assert b1 == d1 + assert d1 == b1 + assert not b1 == d2 + assert not d2 == b1 + From noreply at buildbot.pypy.org Thu Apr 18 23:37:38 2013 From: noreply at buildbot.pypy.org (wlav) Date: Thu, 18 Apr 2013 23:37:38 +0200 (CEST) Subject: [pypy-commit] pypy reflex-support: virtual operator== testing with CINT backend Message-ID: <20130418213738.BEBC61C31A5@cobra.cs.uni-duesseldorf.de> Author: Wim Lavrijsen Branch: reflex-support Changeset: r63492:341d88da422c Date: 2013-04-18 12:22 -0700 http://bitbucket.org/pypy/pypy/changeset/341d88da422c/ Log: virtual operator== testing with CINT backend diff --git a/pypy/module/cppyy/test/operators_LinkDef.h b/pypy/module/cppyy/test/operators_LinkDef.h --- a/pypy/module/cppyy/test/operators_LinkDef.h +++ b/pypy/module/cppyy/test/operators_LinkDef.h @@ -16,4 +16,7 @@ #pragma link C++ struct operator_unsigned_long; #pragma link C++ struct operator_float; +#pragma link C++ class v_opeq_base; +#pragma link C++ class v_opeq_derived; + #endif From noreply at buildbot.pypy.org Thu Apr 18 23:37:39 2013 From: noreply at buildbot.pypy.org (wlav) Date: Thu, 18 Apr 2013 23:37:39 +0200 (CEST) Subject: [pypy-commit] pypy reflex-support: merge default into branch; now translates again ... Message-ID: <20130418213739.E3DA81C31A5@cobra.cs.uni-duesseldorf.de> Author: Wim Lavrijsen Branch: reflex-support Changeset: r63493:c38f9fe83a3a Date: 2013-04-18 14:13 -0700 http://bitbucket.org/pypy/pypy/changeset/c38f9fe83a3a/ Log: merge default into branch; now translates again ... diff --git a/rpython/memory/gc/env.py b/rpython/memory/gc/env.py --- a/rpython/memory/gc/env.py +++ b/rpython/memory/gc/env.py @@ -207,15 +207,8 @@ def _detect_arm_cpu(data): # check for the presence of a 'Processor' entry - start = _findend(data, 'Processor', 0) - if start >= 0: - # *** data[start:linepos] == " : ARMv6-compatible processor rev 7\n" - start = _skipspace(data, start) - if data[start] == ':': - # *** data[start:linepos] == ": ARMv6-compatible processor rev 7\n" - start = _skipspace(data, start + 1) - return data[start], data[start + 1], data[start + 2] == 'A','R','M' - return False + p = _findend(data, 'Processor', 0) + return p >= 0 and _findend(data, 'ARMv', p) > 0 # ---------- Darwin ---------- diff --git a/rpython/memory/gc/test/test_env.py b/rpython/memory/gc/test/test_env.py --- a/rpython/memory/gc/test/test_env.py +++ b/rpython/memory/gc/test/test_env.py @@ -172,3 +172,12 @@ """) result = env.get_L2cache_linux2(str(filepath)) assert result == -1 + +def test__detect_arm(): + assert env._detect_arm_cpu("Processor : ARMv6-compatible processor rev 7 (v6l)") + assert not env._detect_arm_cpu("""\ +processor : 0 +vendor_id : GenuineIntel +cpu family : 6 +model : 37 +""") From noreply at buildbot.pypy.org Fri Apr 19 00:16:25 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 19 Apr 2013 00:16:25 +0200 (CEST) Subject: [pypy-commit] pypy stm-gc-2: Add fetch_and_add to the C sources and expose it via rlib.atomic_ops. Message-ID: <20130418221625.E63781C034F@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: stm-gc-2 Changeset: r63494:c58a07fafc8b Date: 2013-04-18 16:52 +0200 http://bitbucket.org/pypy/pypy/changeset/c58a07fafc8b/ Log: Add fetch_and_add to the C sources and expose it via rlib.atomic_ops. diff --git a/rpython/rlib/atomic_ops.py b/rpython/rlib/atomic_ops.py --- a/rpython/rlib/atomic_ops.py +++ b/rpython/rlib/atomic_ops.py @@ -1,11 +1,10 @@ import py -from pypy.tool.autopath import pypydir from rpython.rtyper.lltypesystem import lltype, llmemory, rffi from rpython.translator.tool.cbuild import ExternalCompilationInfo -cdir = py.path.local(pypydir) / 'translator' / 'stm' -cdir2 = py.path.local(pypydir) / 'translator' / 'c' +cdir = py.path.local(__file__).join('..', '..', 'translator', 'stm') +cdir2 = py.path.local(__file__).join('..', '..', 'translator', 'c') eci = ExternalCompilationInfo( include_dirs = [cdir, cdir2], @@ -15,9 +14,16 @@ bool_cas((volatile unsigned long*)(ptr), \\ (unsigned long)(old), \\ (unsigned long)(_new)) +#define pypy_fetch_and_add(ptr, value) \\ + fetch_and_add((volatile unsigned long*)(ptr), \\ + (unsigned long)(value)) '''], ) bool_cas = rffi.llexternal('pypy_bool_cas', [llmemory.Address]*3, lltype.Bool, compilation_info=eci, macro=True) +fetch_and_add = rffi.llexternal('pypy_fetch_and_add', [llmemory.Address, + lltype.Signed], + lltype.Signed, + compilation_info=eci, macro=True) diff --git a/rpython/rlib/test/test_atomic_ops.py b/rpython/rlib/test/test_atomic_ops.py --- a/rpython/rlib/test/test_atomic_ops.py +++ b/rpython/rlib/test/test_atomic_ops.py @@ -1,4 +1,4 @@ -from rpython.rlib.atomic_ops import bool_cas +from rpython.rlib.atomic_ops import bool_cas, fetch_and_add from rpython.rtyper.lltypesystem import lltype, llmemory, rffi @@ -21,11 +21,28 @@ assert rffi.cast(lltype.Signed, a[0]) == 43 # lltype.free(a, flavor='raw') - return 0 -def test_translate_bool_cas(): +def test_fetch_and_add(): + a = lltype.malloc(ARRAY, 1, flavor='raw') + a[0] = rffi.cast(llmemory.Address, 42) + # + res = fetch_and_add(rffi.cast(llmemory.Address, a), -2) + assert res == 42 + assert rffi.cast(lltype.Signed, a[0]) == 40 + res = fetch_and_add(rffi.cast(llmemory.Address, a), 3) + assert res == 40 + assert rffi.cast(lltype.Signed, a[0]) == 43 + # + lltype.free(a, flavor='raw') + +def test_translate(): from rpython.translator.c.test.test_genc import compile - f = compile(test_bool_cas, []) + def llf(): + test_bool_cas() + test_fetch_and_add() + return 0 + + f = compile(llf, []) res = f() assert res == 0 diff --git a/rpython/translator/stm/src_stm/atomic_ops.h b/rpython/translator/stm/src_stm/atomic_ops.h --- a/rpython/translator/stm/src_stm/atomic_ops.h +++ b/rpython/translator/stm/src_stm/atomic_ops.h @@ -21,11 +21,13 @@ #ifdef __llvm__ # define HAS_SYNC_BOOL_COMPARE_AND_SWAP +# define HAS_SYNC_FETCH_AND_ADD #endif #ifdef __GNUC__ # if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) # define HAS_SYNC_BOOL_COMPARE_AND_SWAP +# define HAS_SYNC_FETCH_AND_ADD # endif #endif @@ -59,6 +61,35 @@ /* end */ #endif +#ifdef HAS_SYNC_FETCH_AND_ADD +# define fetch_and_add __sync_fetch_and_add +#else +/* x86 (32 bits and 64 bits) */ +static inline Unsigned +fetch_and_add(volatile Unsigned *ptr, Unsigned value) +{ + Unsigned prev; +#if defined(__amd64__) + assert(sizeof(Unsigned) == 8); +#elif defined(__i386__) + assert(sizeof(Unsigned) == 4); +#else +# error "the custom version of fetch_and_add() is only for x86 or x86-64" +#endif + asm volatile("lock;" +#if defined(__amd64__) + "xaddq %1, %2;" +#else + "xaddl %1, %2;" +#endif + : "=r"(prev) + : "0"(value), "m"(*ptr) + : "memory"); + return prev; +} +/* end */ +#endif + static inline void spinloop(void) { diff --git a/rpython/translator/stm/test/test_stmgcintf.c b/rpython/translator/stm/test/test_stmgcintf.c --- a/rpython/translator/stm/test/test_stmgcintf.c +++ b/rpython/translator/stm/test/test_stmgcintf.c @@ -73,6 +73,33 @@ /************************************************************/ +void test_bool_cas(void) +{ + volatile Unsigned bv = 10; + + assert(bool_cas(&bv, 10, 15)); + assert(bv == 15); + assert(!bool_cas(&bv, 10, 15)); + assert(bv == 15); + assert(!bool_cas(&bv, 10, 25)); + assert(bv == 15); + assert(bool_cas(&bv, 15, 14)); + assert(bv == 14); +} + +void test_fetch_and_add(void) +{ + volatile Unsigned bv = 14; + + assert(fetch_and_add(&bv, 2) == 14); + assert(bv == 16); + assert(fetch_and_add(&bv, 7) == 16); + assert(fetch_and_add(&bv, (Unsigned)-1) == 23); + assert(bv == 22); +} + +/************************************************************/ + void test_set_get_del(void) { stm_set_tls((void *)42); @@ -365,6 +392,9 @@ int main(int argc, char **argv) { + XTEST(bool_cas); + XTEST(fetch_and_add); + DescriptorInit(); XTEST(set_get_del); XTEST(run_all_transactions); From noreply at buildbot.pypy.org Fri Apr 19 00:16:27 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 19 Apr 2013 00:16:27 +0200 (CEST) Subject: [pypy-commit] pypy default: Test and fix for cffi issue #78. Consolidate in rx86.py the 'abs_' and Message-ID: <20130418221627.375B91C034F@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63495:0ea3b7331c89 Date: 2013-04-19 00:16 +0200 http://bitbucket.org/pypy/pypy/changeset/0ea3b7331c89/ Log: Test and fix for cffi issue #78. Consolidate in rx86.py the 'abs_' and the following 'immediate()' in a single 'abs_()', which avoids getting suddenly a truncated 16-bit address because the same instruction also takes a 16-bit immediate afterwards. diff --git a/rpython/jit/backend/test/runner_test.py b/rpython/jit/backend/test/runner_test.py --- a/rpython/jit/backend/test/runner_test.py +++ b/rpython/jit/backend/test/runner_test.py @@ -3935,3 +3935,19 @@ descr = self.cpu.get_latest_descr(frame) assert descr.identifier == 42 assert not self.cpu.grab_exc_value(frame) + + def test_setarrayitem_raw_short(self): + # setarrayitem_raw(140737353744432, 0, 30583, descr=) + A = rffi.CArray(rffi.SHORT) + arraydescr = self.cpu.arraydescrof(A) + a = lltype.malloc(A, 2, flavor='raw') + a[0] = rffi.cast(rffi.SHORT, 666) + a[1] = rffi.cast(rffi.SHORT, 777) + a_int = rffi.cast(lltype.Signed, a) + print 'a_int:', a_int + self.execute_operation(rop.SETARRAYITEM_RAW, + [ConstInt(a_int), ConstInt(0), ConstInt(-7654)], + 'void', descr=arraydescr) + assert rffi.cast(lltype.Signed, a[0]) == -7654 + assert rffi.cast(lltype.Signed, a[1]) == 777 + lltype.free(a, flavor='raw') diff --git a/rpython/jit/backend/x86/rx86.py b/rpython/jit/backend/x86/rx86.py --- a/rpython/jit/backend/x86/rx86.py +++ b/rpython/jit/backend/x86/rx86.py @@ -126,6 +126,8 @@ mc.writeimm64(immediate) else: if mc._use_16_bit_immediate: + # special case for the default width='i' for immediate(), + # to support 16-bit if the flag is set by regloc.py mc.writeimm16(immediate) else: mc.writeimm32(immediate) @@ -282,16 +284,20 @@ # (the immediate address itself must be explicitely encoded as well, # with immediate(argnum)). -def encode_abs(mc, _1, _2, orbyte): + at specialize.arg(2) +def encode_abs(mc, immediate, _, orbyte): # expands to either '\x05' on 32-bit, or '\x04\x25' on 64-bit if mc.WORD == 8: mc.writechar(chr(0x04 | orbyte)) mc.writechar(chr(0x25)) else: mc.writechar(chr(0x05 | orbyte)) + # followed by an immediate, always 32 bits + mc.writeimm32(immediate) return 0 -abs_ = encode_abs, 0, None, None +def abs_(argnum): + return encode_abs, argnum, None, None # ____________________________________________________________ # For 64-bits mode: the REX.W, REX.R, REX.X, REG.B prefixes @@ -374,9 +380,8 @@ INSN_br = insn(rex_w, chr(base+1), register(2,8), stack_bp(1)) INSN_rb = insn(rex_w, chr(base+3), register(1,8), stack_bp(2)) INSN_rm = insn(rex_w, chr(base+3), register(1,8), mem_reg_plus_const(2)) - INSN_rj = insn(rex_w, chr(base+3), register(1,8), abs_, immediate(2)) - INSN_ji8 = insn(rex_w, '\x83', orbyte(base), abs_, immediate(1), - immediate(2,'b')) + INSN_rj = insn(rex_w, chr(base+3), register(1,8), abs_(2)) + INSN_ji8 = insn(rex_w, '\x83', orbyte(base), abs_(1), immediate(2,'b')) INSN_mi8 = insn(rex_w, '\x83', orbyte(base), mem_reg_plus_const(1), immediate(2,'b')) INSN_bi8 = insn(rex_w, '\x83', orbyte(base), stack_bp(1), immediate(2,'b')) @@ -489,12 +494,10 @@ CMP_mi = select_8_or_32_bit_immed(CMP_mi8, CMP_mi32) CMP_mr = insn(rex_w, '\x39', register(2, 8), mem_reg_plus_const(1)) - CMP_ji8 = insn(rex_w, '\x83', orbyte(7<<3), abs_, - immediate(1), immediate(2, 'b')) - CMP_ji32 = insn(rex_w, '\x81', orbyte(7<<3), abs_, - immediate(1), immediate(2)) + CMP_ji8 = insn(rex_w, '\x83', orbyte(7<<3), abs_(1), immediate(2, 'b')) + CMP_ji32 = insn(rex_w, '\x81', orbyte(7<<3), abs_(1), immediate(2)) CMP_ji = select_8_or_32_bit_immed(CMP_ji8, CMP_ji32) - CMP_jr = insn(rex_w, '\x39', register(2, 8), abs_, immediate(1)) + CMP_jr = insn(rex_w, '\x39', register(2, 8), abs_(1)) CMP32_mi = insn(rex_nw, '\x81', orbyte(7<<3), mem_reg_plus_const(1), immediate(2)) @@ -505,7 +508,7 @@ OR8_rr = insn(rex_fw, '\x08', byte_register(1), byte_register(2,8), '\xC0') OR8_mi = insn(rex_nw, '\x80', orbyte(1<<3), mem_reg_plus_const(1), immediate(2, 'b')) - OR8_ji = insn(rex_nw, '\x80', orbyte(1<<3), abs_, immediate(1), + OR8_ji = insn(rex_nw, '\x80', orbyte(1<<3), abs_(1), immediate(2, 'b')) NEG_r = insn(rex_w, '\xF7', register(1), '\xD8') @@ -556,7 +559,7 @@ LEA32_rb = insn(rex_w, '\x8D', register(1,8),stack_bp(2,force_32bits=True)) LEA_ra = insn(rex_w, '\x8D', register(1, 8), mem_reg_plus_scaled_reg_plus_const(2)) LEA_rm = insn(rex_w, '\x8D', register(1, 8), mem_reg_plus_const(2)) - LEA_rj = insn(rex_w, '\x8D', register(1, 8), abs_, immediate(2)) + LEA_rj = insn(rex_w, '\x8D', register(1, 8), abs_(2)) CALL_l = insn('\xE8', relative(1)) CALL_r = insn(rex_nw, '\xFF', register(1), chr(0xC0 | (2<<3))) @@ -583,11 +586,11 @@ TEST8_mi = insn(rex_nw, '\xF6', orbyte(0<<3), mem_reg_plus_const(1), immediate(2, 'b')) TEST8_bi = insn(rex_nw, '\xF6', orbyte(0<<3), stack_bp(1), immediate(2, 'b')) - TEST8_ji = insn(rex_nw, '\xF6', orbyte(0<<3), abs_, immediate(1), immediate(2, 'b')) + TEST8_ji = insn(rex_nw, '\xF6', orbyte(0<<3), abs_(1), immediate(2, 'b')) TEST_rr = insn(rex_w, '\x85', register(2,8), register(1), '\xC0') BTS_mr = insn(rex_w, '\x0F\xAB', register(2,8), mem_reg_plus_const(1)) - BTS_jr = insn(rex_w, '\x0F\xAB', register(2,8), abs_, immediate(1)) + BTS_jr = insn(rex_w, '\x0F\xAB', register(2,8), abs_(1)) # x87 instructions FSTPL_b = insn('\xDD', orbyte(3<<3), stack_bp(1)) # rffi.DOUBLE ('as' wants L??) @@ -718,7 +721,7 @@ add_insn('s', stack_sp(modrm_argnum)) add_insn('m', mem_reg_plus_const(modrm_argnum)) add_insn('a', mem_reg_plus_scaled_reg_plus_const(modrm_argnum)) - add_insn('j', abs_, immediate(modrm_argnum)) + add_insn('j', abs_(modrm_argnum)) # Define a regular MOV, and a variant MOV32 that only uses the low 4 bytes of a # register @@ -766,7 +769,7 @@ # assert insnname_template.count('*') == 1 add_insn('x', register(2), '\xC0') - add_insn('j', abs_, immediate(2)) + add_insn('j', abs_(2)) add_insn('m', mem_reg_plus_const(2)) define_pxmm_insn('PADDQ_x*', '\xD4') From noreply at buildbot.pypy.org Fri Apr 19 00:35:54 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 19 Apr 2013 00:35:54 +0200 (CEST) Subject: [pypy-commit] pypy default: Bah, fix it properly for 64-bit too. Actually done by killing an Message-ID: <20130418223554.DDDC51C30AF@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63496:3e87dbfef460 Date: 2013-04-19 00:34 +0200 http://bitbucket.org/pypy/pypy/changeset/3e87dbfef460/ Log: Bah, fix it properly for 64-bit too. Actually done by killing an obscure hack and just writing the official 3 lines of description for MOV16 and CMP16. diff --git a/rpython/jit/backend/x86/regloc.py b/rpython/jit/backend/x86/regloc.py --- a/rpython/jit/backend/x86/regloc.py +++ b/rpython/jit/backend/x86/regloc.py @@ -521,17 +521,6 @@ return func_with_new_name(INSN, "INSN_" + name) - def _16_bit_binaryop(name): - def INSN(self, loc1, loc2): - # Select 16-bit operand mode - self.writechar('\x66') - # XXX: Hack to let immediate() in rx86 know to do a 16-bit encoding - self._use_16_bit_immediate = True - getattr(self, name)(loc1, loc2) - self._use_16_bit_immediate = False - - return INSN - def _addr_as_reg_offset(self, addr): # Encodes a (64-bit) address as an offset from the scratch register. # If we are within a "reuse_scratch_register" block, we remember the @@ -616,10 +605,10 @@ NEG = _unaryop('NEG') CMP = _binaryop('CMP') - CMP16 = _16_bit_binaryop('CMP') + CMP16 = _binaryop('CMP16') MOV = _binaryop('MOV') MOV8 = _binaryop('MOV8') - MOV16 = _16_bit_binaryop('MOV') + MOV16 = _binaryop('MOV16') MOVZX8 = _binaryop('MOVZX8') MOVSX8 = _binaryop('MOVSX8') MOVZX16 = _binaryop('MOVZX16') diff --git a/rpython/jit/backend/x86/rx86.py b/rpython/jit/backend/x86/rx86.py --- a/rpython/jit/backend/x86/rx86.py +++ b/rpython/jit/backend/x86/rx86.py @@ -125,12 +125,7 @@ elif width == 'q' and mc.WORD == 8: mc.writeimm64(immediate) else: - if mc._use_16_bit_immediate: - # special case for the default width='i' for immediate(), - # to support 16-bit if the flag is set by regloc.py - mc.writeimm16(immediate) - else: - mc.writeimm32(immediate) + mc.writeimm32(immediate) return 0 def immediate(argnum, width='i'): @@ -311,9 +306,6 @@ def encode_rex(mc, rexbyte, basevalue, orbyte): if mc.WORD == 8: assert 0 <= rexbyte < 8 - # XXX: Hack. Ignore REX.W if we are using 16-bit operands - if mc._use_16_bit_immediate: - basevalue &= ~REX_W if basevalue != 0 or rexbyte != 0: if basevalue == 0: basevalue = 0x40 @@ -454,9 +446,6 @@ class AbstractX86CodeBuilder(object): """Abstract base class.""" - # Used by the 16-bit version of instructions - _use_16_bit_immediate = False - def writechar(self, char): raise NotImplementedError @@ -500,7 +489,7 @@ CMP_jr = insn(rex_w, '\x39', register(2, 8), abs_(1)) CMP32_mi = insn(rex_nw, '\x81', orbyte(7<<3), mem_reg_plus_const(1), immediate(2)) - + CMP16_mi = insn('\x66', rex_nw, '\x81', orbyte(7<<3), mem_reg_plus_const(1), immediate(2, 'h')) CMP8_ri = insn(rex_fw, '\x80', byte_register(1), '\xF8', immediate(2, 'b')) AND8_rr = insn(rex_fw, '\x20', byte_register(1), byte_register(2,8), '\xC0') @@ -732,6 +721,8 @@ define_modrm_modes('MOV8_*r', [rex_fw, '\x88', byte_register(2, 8)], regtype='BYTE') define_modrm_modes('MOV8_*i', [rex_fw, '\xC6', orbyte(0<<3)], [immediate(2, 'b')], regtype='BYTE') +define_modrm_modes('MOV16_*r', ['\x66', rex_nw, '\x89', register(2, 8)]) +define_modrm_modes('MOV16_*i', ['\x66', rex_nw, '\xC7', orbyte(0<<3)], [immediate(2, 'h')]) define_modrm_modes('MOVZX8_r*', [rex_w, '\x0F\xB6', register(1, 8)], regtype='BYTE') define_modrm_modes('MOVSX8_r*', [rex_w, '\x0F\xBE', register(1, 8)], regtype='BYTE') From noreply at buildbot.pypy.org Fri Apr 19 03:13:19 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Fri, 19 Apr 2013 03:13:19 +0200 (CEST) Subject: [pypy-commit] pypy py3k: accept py3 strs via CreateProcessW Message-ID: <20130419011319.725C31C101D@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63497:995f8366f830 Date: 2013-04-18 18:11 -0700 http://bitbucket.org/pypy/pypy/changeset/995f8366f830/ Log: accept py3 strs via CreateProcessW diff --git a/lib_pypy/_subprocess.py b/lib_pypy/_subprocess.py --- a/lib_pypy/_subprocess.py +++ b/lib_pypy/_subprocess.py @@ -77,9 +77,9 @@ ("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, +_CreateProcess = _kernel32.CreateProcessW +_CreateProcess.argtypes = [ctypes.c_wchar_p, ctypes.c_wchar_p, ctypes.c_void_p, ctypes.c_void_p, + ctypes.c_int, ctypes.c_int, ctypes.c_wchar_p, ctypes.c_wchar_p, ctypes.POINTER(_STARTUPINFO), ctypes.POINTER(_PROCESS_INFORMATION)] _CreateProcess.restype = ctypes.c_int From noreply at buildbot.pypy.org Fri Apr 19 03:13:20 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Fri, 19 Apr 2013 03:13:20 +0200 (CEST) Subject: [pypy-commit] pypy py3k: apply workaround from default: Don't rely on reference counting to close the Message-ID: <20130419011320.AD3A81C101D@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63498:7737ba1bb77c Date: 2013-04-18 18:11 -0700 http://bitbucket.org/pypy/pypy/changeset/7737ba1bb77c/ Log: apply workaround from default: Don't rely on reference counting to close the non-heritable handle. This avoids a deadlock on Windows, when stdout=PIPE. diff --git a/lib-python/3/subprocess.py b/lib-python/3/subprocess.py --- a/lib-python/3/subprocess.py +++ b/lib-python/3/subprocess.py @@ -886,10 +886,14 @@ def _make_inheritable(self, handle): """Return a duplicate of handle, which is inheritable""" - return _subprocess.DuplicateHandle(_subprocess.GetCurrentProcess(), + dupl = _subprocess.DuplicateHandle(_subprocess.GetCurrentProcess(), handle, _subprocess.GetCurrentProcess(), 0, 1, _subprocess.DUPLICATE_SAME_ACCESS) - + # If the initial handle was obtained with CreatePipe, close + # it + if not isinstance(handle, int): + handle.Close() + return dupl def _find_w9xpopen(self): """Find and return absolut path to w9xpopen.exe""" From noreply at buildbot.pypy.org Fri Apr 19 11:29:41 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 19 Apr 2013 11:29:41 +0200 (CEST) Subject: [pypy-commit] pypy stm-gc-2: In-progress: trying to get the safe points correctly is hard Message-ID: <20130419092941.47AAB1C31C7@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: stm-gc-2 Changeset: r63499:9a7f6d86069c Date: 2013-04-19 11:29 +0200 http://bitbucket.org/pypy/pypy/changeset/9a7f6d86069c/ Log: In-progress: trying to get the safe points correctly is hard diff --git a/rpython/memory/gc/stmgc.py b/rpython/memory/gc/stmgc.py --- a/rpython/memory/gc/stmgc.py +++ b/rpython/memory/gc/stmgc.py @@ -182,6 +182,10 @@ # self.stm_operations = stm_operations self.nursery_size = nursery_size + self.major_collection_threshold = 1.82 # xxx + self.min_heap_size = r_uint(8 * self.nursery_size) + self.real_limit_for_major_gc = self.min_heap_pages + self.dyn_limit_for_major_gc = self.real_limit_for_major_gc #self.maximum_extra_threshold = 0 self.sharedarea = stmshared.StmGCSharedArea(self, page_size, small_request_threshold) @@ -238,6 +242,7 @@ self.remove_from_linked_list(stmtls) self.stm_operations.begin_inevitable_transaction() stmtls.delete() + teardown_thread._dont_inline_ = True def acquire_global_lock(self): if self.ll_global_lock: @@ -330,9 +335,10 @@ def collect(self, gen=1): - self.get_tls().local_collection() - if gen > 0: - debug_print("XXX not implemented: global collect()") + if gen <= 0: + self.get_tls().local_collection() + else: + self.major_collection(force=True) def start_transaction(self): self.get_tls().start_transaction() @@ -401,6 +407,41 @@ ## stmtls.set_extra_threshold(reserved_size) # ---------- + # major collections + + def maybe_major_collection(self): + """Check the memory usage, and maybe do a major GC collection.""" + if (self.sharedarea.fetch_count_total_bytes() >= + self.dyn_limit_for_major_gc): + self.major_collection() + return True + else: + return False + + def major_collection(self, force=False): + """Do a major collection. This uses a stop-the-world system.""" + # + # When the present function is called we know we'll do at least + # one major GC. Setting this limit to 0 now will invite other + # threads to enter major_collection() soon too. + self.dyn_limit_for_major_gc = r_uint(0) + # + # While still running multithreaded, do a local collection. + # This is not strictly needed. + self.get_tls().local_collection(run_finalizers=False) + # + # Now wait until we can acquire the RW lock in exclusive mode. + self.stm_operations.start_single_thread() + # + # At this point all other threads should be blocked or running + # external C code + if (self.sharedarea.fetch_count_total_bytes() >= + self.limit_for_major_collection): + xxxxxxx + self.stm_operations.stop_single_thread() + major_collection._dont_inline_ = True + + # ---------- # id() and identityhash() support def id_or_identityhash(self, gcobj, is_hash): diff --git a/rpython/memory/gc/stmshared.py b/rpython/memory/gc/stmshared.py --- a/rpython/memory/gc/stmshared.py +++ b/rpython/memory/gc/stmshared.py @@ -1,8 +1,8 @@ from rpython.rtyper.lltypesystem import lltype, llmemory, llarena, rffi -from rpython.rlib.rarithmetic import LONG_BIT +from rpython.rlib.rarithmetic import LONG_BIT, r_uint from rpython.rlib.objectmodel import free_non_gc_object, we_are_translated from rpython.rlib.debug import ll_assert, fatalerror -from rpython.rlib import rthread +from rpython.rlib import rthread, atomic_ops WORD = LONG_BIT // 8 NULL = llmemory.NULL @@ -78,10 +78,20 @@ # # Counters for statistics self.count_global_pages = 0 + self.v_count_total_bytes = lltype.malloc(rffi.CArray(lltype.Unsigned), + 1, flavor='raw', + immortal=True, zero=True) def setup(self): pass + def fetch_count_total_bytes(self): + return self.v_count_total_bytes[0] + + def fetch_count_total_bytes_and_add(self, increment): + adr = rffi.cast(llmemory.Address, self.v_count_total_bytes) + return r_uint(atomic_ops.fetch_and_add(adr, increment)) + # ------------------------------------------------------------ @@ -145,16 +155,18 @@ def _allocate_new_page(self, size_class): """Allocate and return a new page for the given size_class.""" # - result = llarena.arena_malloc(self.sharedarea.page_size, 0) + sharedarea = self.sharedarea + result = llarena.arena_malloc(sharedarea.page_size, 0) if not result: fatalerror("FIXME: Out of memory! (should raise MemoryError)") return NULL if not we_are_translated(): self._seen_pages.add(result) self.count_pages += 1 - llarena.arena_reserve(result, llmemory.sizeof(PAGE_HEADER)) + sharedarea.fetch_count_total_bytes_and_add(sharedarea.page_size) # # Initialize the fields of the resulting page + llarena.arena_reserve(result, llmemory.sizeof(PAGE_HEADER)) page = llmemory.cast_adr_to_ptr(result, PAGE_PTR) page.nextpage = self.pages_for_size[size_class] self.pages_for_size[size_class] = page @@ -165,7 +177,7 @@ "free_loc_for_size is supposed to contain NULL here") self.free_loc_for_size[size_class] = head # - i = self.sharedarea.nblocks_for_size[size_class] + i = sharedarea.nblocks_for_size[size_class] nsize = size_class << WORD_POWER_2 current = head while True: @@ -189,8 +201,13 @@ size_class = (nsize + WORD_POWER_2 - 1) >> WORD_POWER_2 return self._malloc_size_class(size_class) else: - return llarena.arena_malloc( - llmemory.raw_malloc_usage(totalsize), 0) + count = llmemory.raw_malloc_usage(totalsize) + result = llarena.arena_malloc(count, 0) + # increment the counter *after* arena_malloc() returned + # successfully, otherwise we might increment it of a huge + # bogus number + self.sharedarea.fetch_count_total_bytes_and_add(count) + return result def malloc_object(self, objsize): totalsize = self.gc.gcheaderbuilder.size_gc_header + objsize @@ -212,6 +229,10 @@ size_class = (totalsize + WORD_POWER_2 - 1) >> WORD_POWER_2 self._free_size_class(adr1, size_class) else: + # decrement the counter *before* we free the memory, + # otherwise there could in theory be a race condition that + # ends up overflowing the counter + self.sharedarea.fetch_count_total_bytes_and_add(-totalsize) llarena.arena_free(llarena.getfakearenaaddress(adr1)) def free_and_clear(self): diff --git a/rpython/memory/gc/stmtls.py b/rpython/memory/gc/stmtls.py --- a/rpython/memory/gc/stmtls.py +++ b/rpython/memory/gc/stmtls.py @@ -166,6 +166,7 @@ nursery and track which objects are still alive now, and then mark all these objects as global.""" self.local_collection(end_of_transaction=True) + self.gc.maybe_major_collection() if not self.local_nursery_is_empty(): self.local_collection(end_of_transaction=True, run_finalizers=False) @@ -273,10 +274,8 @@ if llmemory.raw_malloc_usage(size) > self.nursery_size // 8 * 7: fatalerror("XXX object too large to ever fit in the nursery") # - self.local_collection(run_finalizers=True) - # - # call this here in case another thread is waiting for a global GC - self.stm_operations.should_break_transaction() + if not self.gc.maybe_major_collection(): + self.local_collection(run_finalizers=True) # # if we have now enough space, return it free = self.nursery_free diff --git a/rpython/memory/gctransform/stmframework.py b/rpython/memory/gctransform/stmframework.py --- a/rpython/memory/gctransform/stmframework.py +++ b/rpython/memory/gctransform/stmframework.py @@ -163,14 +163,13 @@ base = self.stackgcdata.root_stack_base llmemory.raw_free(base) - def walk_stack_roots(self, collect_stack_root): + def walk_roots(self, *args): + "NOT_RPYTHON" raise NotImplementedError - # XXX only to walk the main thread's shadow stack, so far - stackgcdata = self.stackgcdata - if self.gcdata.main_thread_stack_base != stackgcdata.root_stack_base: - fatalerror_notb("XXX not implemented: walk_stack_roots in thread") - self.rootstackhook(collect_stack_root, self.gcdata.gc, - stackgcdata.root_stack_top) + + def walk_stack_roots(self, *args): + "NOT_RPYTHON" + raise NotImplementedError @specialize.argtype(2) def walk_current_stack_roots(self, collect_stack_root, arg): diff --git a/rpython/translator/stm/jitdriver.py b/rpython/translator/stm/jitdriver.py --- a/rpython/translator/stm/jitdriver.py +++ b/rpython/translator/stm/jitdriver.py @@ -159,7 +159,7 @@ raise cast_base_ptr_to_instance(Exception, p.got_exception) return p.result_value """ % (', '.join(['a%d' % i for i in irange]), - '\n '.join(['p.a%d = a%d' % (i, i) for i in irange])) + '; '.join(['p.a%d = a%d' % (i, i) for i in irange])) d = {'CONTAINER': CONTAINER, 'lltype': lltype, 'perform_transaction': perform_transaction, diff --git a/rpython/translator/stm/src_stm/et.h b/rpython/translator/stm/src_stm/et.h --- a/rpython/translator/stm/src_stm/et.h +++ b/rpython/translator/stm/src_stm/et.h @@ -87,7 +87,6 @@ //int _FakeReach(gcptr); void CommitTransaction(void); void BecomeInevitable(const char *why); -//void BeginInevitableTransaction(void); int DescriptorInit(void); void DescriptorDone(void); diff --git a/rpython/translator/stm/src_stm/rpyintf.c b/rpython/translator/stm/src_stm/rpyintf.c --- a/rpython/translator/stm/src_stm/rpyintf.c +++ b/rpython/translator/stm/src_stm/rpyintf.c @@ -63,8 +63,9 @@ } static unsigned long stm_regular_length_limit = ULONG_MAX; -static volatile int break_please = 0; +/* sync_required is either 0 or 0xffffffff */ +static volatile unsigned long sync_required = 0; static void reached_safe_point(void); void stm_add_atomic(long delta) @@ -86,9 +87,10 @@ /* a single comparison to handle all cases: + - first, if sync_required == 0xffffffff, this should return True. + - if d->atomic, then we should return False. This is done by - forcing reads_size_limit to ULONG_MAX as soon as atomic > 0, - and no possible value of 'count_reads' is greater than ULONG_MAX. + forcing reads_size_limit to ULONG_MAX as soon as atomic > 0. - otherwise, if is_inevitable(), then we should return True. This is done by forcing both reads_size_limit and @@ -109,10 +111,7 @@ assert(d->reads_size_limit_nonatomic == 0); #endif - if (break_please) - reached_safe_point(); - - return d->count_reads > d->reads_size_limit; + return (sync_required | d->count_reads) >= d->reads_size_limit; } void stm_set_transaction_length(long length_max) @@ -178,9 +177,14 @@ } if (!d->atomic) BeginTransaction(&_jmpbuf); - - if (break_please) - reached_safe_point(); + else + { + /* atomic transaction: a common case is that callback() returned + even though we are atomic because we need a major GC. For + that case, release and require the rw lock here. */ + if (sync_required) + reached_safe_point(); + } /* invoke the callback in the new transaction */ result = callback(arg, counter); @@ -207,14 +211,16 @@ { /* Called by the GC, just after a minor collection, when we need to do a major collection. When it returns, it acquired the "write lock" - which prevents any other thread from running a transaction. */ + which prevents any other thread from running in a transaction. + Warning, may block waiting for rwlock_in_transaction while another + thread runs a major GC itself! */ int err; - break_please = 1; + sync_required = (unsigned long)-1; err = pthread_rwlock_unlock(&rwlock_in_transaction); assert(err == 0); err = pthread_rwlock_wrlock(&rwlock_in_transaction); assert(err == 0); - break_please = 0; + sync_required = 0; assert(in_single_thread == NULL); in_single_thread = thread_descriptor; @@ -223,6 +229,8 @@ void stm_stop_single_thread(void) { + /* Warning, may block waiting for rwlock_in_transaction while another + thread runs a major GC */ int err; assert(in_single_thread == thread_descriptor); @@ -236,6 +244,10 @@ static void reached_safe_point(void) { + /* Warning: all places that call this function from RPython code + must do so with a llop with canmallocgc=True! The release of + the rwlock_in_transaction below means a major GC could run in + another thread! */ int err; struct tx_descriptor *d = thread_descriptor; assert(in_single_thread != d); From noreply at buildbot.pypy.org Fri Apr 19 13:36:28 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 19 Apr 2013 13:36:28 +0200 (CEST) Subject: [pypy-commit] pypy stm-gc-2: In-progress. Message-ID: <20130419113628.8CD571C31C0@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: stm-gc-2 Changeset: r63500:6fe3b9967ab2 Date: 2013-04-19 13:35 +0200 http://bitbucket.org/pypy/pypy/changeset/6fe3b9967ab2/ Log: In-progress. diff --git a/rpython/memory/gc/stmgc.py b/rpython/memory/gc/stmgc.py --- a/rpython/memory/gc/stmgc.py +++ b/rpython/memory/gc/stmgc.py @@ -2,11 +2,11 @@ from rpython.rtyper.lltypesystem.lloperation import llop from rpython.rtyper.lltypesystem.llmemory import raw_malloc_usage, raw_memcopy from rpython.memory.gc.base import GCBase, MovingGCBase +from rpython.memory.gc.env import addressable_size from rpython.memory.support import mangle_hash from rpython.rtyper.annlowlevel import llhelper from rpython.rlib.rarithmetic import LONG_BIT, r_uint -from rpython.rlib.debug import ll_assert, debug_start, debug_stop, fatalerror -from rpython.rlib.debug import debug_print +from rpython.rlib.debug import ll_assert, fatalerror from rpython.rlib import rthread from rpython.memory.gc import stmshared @@ -183,9 +183,8 @@ self.stm_operations = stm_operations self.nursery_size = nursery_size self.major_collection_threshold = 1.82 # xxx - self.min_heap_size = r_uint(8 * self.nursery_size) - self.real_limit_for_major_gc = self.min_heap_pages - self.dyn_limit_for_major_gc = self.real_limit_for_major_gc + self.min_heap_size = 8.0 * self.nursery_size + self.limit_for_major_gc = r_uint(self.min_heap_size) #self.maximum_extra_threshold = 0 self.sharedarea = stmshared.StmGCSharedArea(self, page_size, small_request_threshold) @@ -335,10 +334,9 @@ def collect(self, gen=1): - if gen <= 0: - self.get_tls().local_collection() - else: - self.major_collection(force=True) + self.get_tls().local_collection() + if gen > 0: + self.major_collection() def start_transaction(self): self.get_tls().start_transaction() @@ -412,32 +410,41 @@ def maybe_major_collection(self): """Check the memory usage, and maybe do a major GC collection.""" if (self.sharedarea.fetch_count_total_bytes() >= - self.dyn_limit_for_major_gc): + self.limit_for_major_gc): self.major_collection() - return True - else: - return False - def major_collection(self, force=False): + def major_collection(self): """Do a major collection. This uses a stop-the-world system.""" # - # When the present function is called we know we'll do at least - # one major GC. Setting this limit to 0 now will invite other - # threads to enter major_collection() soon too. - self.dyn_limit_for_major_gc = r_uint(0) - # - # While still running multithreaded, do a local collection. - # This is not strictly needed. - self.get_tls().local_collection(run_finalizers=False) + # Setting this limit to 0 now will invite other threads to enter + # major_collection() soon too. Note that this doesn't create a + # race, because all threads are first going to run until they are + # all at the start_single_thread() below, or in C code at a + # reached_safe_point() or outside a transaction. + self.limit_for_major_gc = r_uint(0) # # Now wait until we can acquire the RW lock in exclusive mode. self.stm_operations.start_single_thread() # - # At this point all other threads should be blocked or running - # external C code - if (self.sharedarea.fetch_count_total_bytes() >= - self.limit_for_major_collection): - xxxxxxx + # If several threads were blocked on the previous line, the first + # one to proceed sees 0 in this variable. It's the thread that + # will do the major collection. Afterwards the other threads will + # also acquire the RW lock in exclusive mode, but won't do anything. + if self.limit_for_major_gc == r_uint(0): + # + # do the major collection + self.sharedarea.do_major_collection() + # + # reset 'limit_for_major_gc' to the correct value at which the + # following major collection should take place. + in_use = self.sharedarea.fetch_count_total_bytes() + threshold = in_use * self.major_collection_threshold + if threshold < self.min_heap_size: + threshold = self.min_heap_size + if threshold > addressable_size * 0.99: + threshold = addressable_size * 0.99 + self.limit_for_major_gc = r_uint(threshold) + # self.stm_operations.stop_single_thread() major_collection._dont_inline_ = True diff --git a/rpython/memory/gc/stmshared.py b/rpython/memory/gc/stmshared.py --- a/rpython/memory/gc/stmshared.py +++ b/rpython/memory/gc/stmshared.py @@ -2,6 +2,7 @@ from rpython.rlib.rarithmetic import LONG_BIT, r_uint from rpython.rlib.objectmodel import free_non_gc_object, we_are_translated from rpython.rlib.debug import ll_assert, fatalerror +from rpython.rlib.debug import debug_start, debug_stop, debug_print from rpython.rlib import rthread, atomic_ops WORD = LONG_BIT // 8 @@ -78,6 +79,7 @@ # # Counters for statistics self.count_global_pages = 0 + self.num_major_collects = 0 self.v_count_total_bytes = lltype.malloc(rffi.CArray(lltype.Unsigned), 1, flavor='raw', immortal=True, zero=True) @@ -92,6 +94,31 @@ adr = rffi.cast(llmemory.Address, self.v_count_total_bytes) return r_uint(atomic_ops.fetch_and_add(adr, increment)) + def do_major_collection(self): + """Perform a major collection.""" + # At this point all other threads should be blocked or running + # external C code or careful non-GC-using code, with all GC roots + # in their shadow stack. Even if some nurseries are not empty + # we can still trace through them: a major collection does not + # move any object. The point is only that after the "sweep" phase, + # we have identified all locations that are now free, and added + # them to the chained lists of StmGCSharedArea for reuse. + debug_start("gc-collect") + debug_print() + debug_print(".----------- Full collection ------------------") + debug_print("| used before collection:", + self.fetch_count_total_bytes(), "bytes") + # + fatalerror("do_major_collection: in-progress") + # + self.num_major_collects += 1 + debug_print("| used after collection:", + self.fetch_count_total_bytes(), "bytes") + debug_print("| number of major collects: ", + self.num_major_collects) + debug_print("`----------------------------------------------") + debug_stop("gc-collect") + # ------------------------------------------------------------ diff --git a/rpython/memory/gc/stmtls.py b/rpython/memory/gc/stmtls.py --- a/rpython/memory/gc/stmtls.py +++ b/rpython/memory/gc/stmtls.py @@ -274,8 +274,8 @@ if llmemory.raw_malloc_usage(size) > self.nursery_size // 8 * 7: fatalerror("XXX object too large to ever fit in the nursery") # - if not self.gc.maybe_major_collection(): - self.local_collection(run_finalizers=True) + self.local_collection(run_finalizers=True) + self.gc.maybe_major_collection() # # if we have now enough space, return it free = self.nursery_free diff --git a/rpython/memory/gc/test/test_stmtls.py b/rpython/memory/gc/test/test_stmtls.py --- a/rpython/memory/gc/test/test_stmtls.py +++ b/rpython/memory/gc/test/test_stmtls.py @@ -140,6 +140,9 @@ if addr.address[0]: callback(addr, arg) + def maybe_major_collection(self): + pass + class TestStmGCTLS(object): diff --git a/rpython/memory/gctransform/stmframework.py b/rpython/memory/gctransform/stmframework.py --- a/rpython/memory/gctransform/stmframework.py +++ b/rpython/memory/gctransform/stmframework.py @@ -163,8 +163,7 @@ base = self.stackgcdata.root_stack_base llmemory.raw_free(base) - def walk_roots(self, *args): - "NOT_RPYTHON" + def walk_roots(self, c1, c2, c3): raise NotImplementedError def walk_stack_roots(self, *args): diff --git a/rpython/rlib/atomic_ops.py b/rpython/rlib/atomic_ops.py --- a/rpython/rlib/atomic_ops.py +++ b/rpython/rlib/atomic_ops.py @@ -22,8 +22,8 @@ bool_cas = rffi.llexternal('pypy_bool_cas', [llmemory.Address]*3, lltype.Bool, - compilation_info=eci, macro=True) + compilation_info=eci, macro=True, _nowrapper=True) fetch_and_add = rffi.llexternal('pypy_fetch_and_add', [llmemory.Address, lltype.Signed], - lltype.Signed, - compilation_info=eci, macro=True) + lltype.Signed, compilation_info=eci, + macro=True, _nowrapper=True) diff --git a/rpython/translator/stm/src_stm/rpyintf.c b/rpython/translator/stm/src_stm/rpyintf.c --- a/rpython/translator/stm/src_stm/rpyintf.c +++ b/rpython/translator/stm/src_stm/rpyintf.c @@ -65,6 +65,7 @@ static unsigned long stm_regular_length_limit = ULONG_MAX; /* sync_required is either 0 or 0xffffffff */ +#define SYNC_REQUIRED ((unsigned long)-1) static volatile unsigned long sync_required = 0; static void reached_safe_point(void); @@ -215,7 +216,7 @@ Warning, may block waiting for rwlock_in_transaction while another thread runs a major GC itself! */ int err; - sync_required = (unsigned long)-1; + sync_required = SYNC_REQUIRED; err = pthread_rwlock_unlock(&rwlock_in_transaction); assert(err == 0); err = pthread_rwlock_wrlock(&rwlock_in_transaction); @@ -244,22 +245,19 @@ static void reached_safe_point(void) { - /* Warning: all places that call this function from RPython code - must do so with a llop with canmallocgc=True! The release of - the rwlock_in_transaction below means a major GC could run in - another thread! */ + /* Warning, may block waiting for rwlock_in_transaction while another + thread runs a major GC */ int err; struct tx_descriptor *d = thread_descriptor; + assert(d->active); assert(in_single_thread != d); - if (d->active) - { - err = pthread_rwlock_unlock(&rwlock_in_transaction); - assert(err == 0); - /* another thread should be waiting in pthread_rwlock_wrlock(), - which takes priority here */ - err = pthread_rwlock_rdlock(&rwlock_in_transaction); - assert(err == 0); - } + + err = pthread_rwlock_unlock(&rwlock_in_transaction); + assert(err == 0); + /* another thread should be waiting in pthread_rwlock_wrlock(), + which takes priority here */ + err = pthread_rwlock_rdlock(&rwlock_in_transaction); + assert(err == 0); } void stm_abort_and_retry(void) From noreply at buildbot.pypy.org Fri Apr 19 14:12:43 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 19 Apr 2013 14:12:43 +0200 (CEST) Subject: [pypy-commit] pypy default: Improve the error reporting of a failing "no_collect". Message-ID: <20130419121243.4A2491C31C0@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63502:37498701240c Date: 2013-04-19 13:48 +0200 http://bitbucket.org/pypy/pypy/changeset/37498701240c/ Log: Improve the error reporting of a failing "no_collect". diff --git a/rpython/memory/gctransform/framework.py b/rpython/memory/gctransform/framework.py --- a/rpython/memory/gctransform/framework.py +++ b/rpython/memory/gctransform/framework.py @@ -619,6 +619,12 @@ func = getattr(graph, 'func', None) if func and getattr(func, '_gc_no_collect_', False): if self.collect_analyzer.analyze_direct_call(graph): + print '!'*79 + ca = CollectAnalyzer(self.translator) + ca.verbose = True + ca.analyze_direct_call(graph) + # ^^^ for the dump of which operation in which graph actually + # causes it to return True raise Exception("'no_collect' function can trigger collection:" " %s" % func) From noreply at buildbot.pypy.org Fri Apr 19 14:12:42 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 19 Apr 2013 14:12:42 +0200 (CEST) Subject: [pypy-commit] pypy default: Improve the debug dump in case we have several analyzers around. Message-ID: <20130419121242.02F521C101D@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63501:7ca4087519cc Date: 2013-04-19 13:45 +0200 http://bitbucket.org/pypy/pypy/changeset/7ca4087519cc/ Log: Improve the debug dump in case we have several analyzers around. diff --git a/rpython/translator/backendopt/graphanalyze.py b/rpython/translator/backendopt/graphanalyze.py --- a/rpython/translator/backendopt/graphanalyze.py +++ b/rpython/translator/backendopt/graphanalyze.py @@ -80,21 +80,21 @@ if graph is None: x = self.analyze_external_call(op, seen) if self.verbose and x: - print '\tanalyze_external_call %s: %r' % (op, x) + self.dump_info('analyze_external_call %s: %r' % (op, x)) return x x = self.analyze_direct_call(graph, seen) if self.verbose and x: - print '\tanalyze_direct_call(%s): %r' % (graph, x) + self.dump_info('analyze_direct_call(%s): %r' % (graph, x)) return x elif op.opname == "indirect_call": graphs = op.args[-1].value if graphs is None: if self.verbose: - print '\t%s to unknown' % (op,) + self.dump_info('%s to unknown' % (op,)) return self.top_result() x = self.analyze_indirect_call(graphs, seen) if self.verbose and x: - print '\tanalyze_indirect_call(%s): %r' % (graphs, x) + self.dump_info('analyze_indirect_call(%s): %r' % (graphs, x)) return x elif op.opname == "oosend": name = op.args[0].value @@ -106,9 +106,12 @@ return self.analyze_oosend(TYPE, name, seen) x = self.analyze_simple_operation(op, graphinfo) if self.verbose and x: - print '\t%s: %r' % (op, x) + self.dump_info('%s: %r' % (op, x)) return x + def dump_info(self, info): + print '[%s] %s' % (self.__class__.__name__, info) + def analyze_direct_call(self, graph, seen=None): if seen is None: seen = DependencyTracker(self) From noreply at buildbot.pypy.org Fri Apr 19 14:12:44 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 19 Apr 2013 14:12:44 +0200 (CEST) Subject: [pypy-commit] pypy default: Avoid allocating here too. Message-ID: <20130419121244.6BCA91C101D@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63503:a100f62c995d Date: 2013-04-19 14:10 +0200 http://bitbucket.org/pypy/pypy/changeset/a100f62c995d/ Log: Avoid allocating here too. diff --git a/rpython/memory/gc/minimark.py b/rpython/memory/gc/minimark.py --- a/rpython/memory/gc/minimark.py +++ b/rpython/memory/gc/minimark.py @@ -130,6 +130,7 @@ FORWARDSTUB = lltype.GcStruct('forwarding_stub', ('forw', llmemory.Address)) FORWARDSTUBPTR = lltype.Ptr(FORWARDSTUB) +NURSARRAY = lltype.Array(llmemory.Address) # ____________________________________________________________ @@ -263,7 +264,7 @@ self.nursery_top = NULL self.nursery_real_top = NULL self.debug_tiny_nursery = -1 - self.debug_rotating_nurseries = None + self.debug_rotating_nurseries = lltype.nullptr(NURSARRAY) self.extra_threshold = 0 # # The ArenaCollection() handles the nonmovable objects allocation. @@ -471,23 +472,32 @@ # and use them alternatively, while mprotect()ing the unused # ones to detect invalid access. debug_start("gc-debug") - self.debug_rotating_nurseries = [] - for i in range(22): + self.debug_rotating_nurseries = lltype.malloc( + NURSARRAY, 22, flavor='raw', track_allocation=False) + i = 0 + while i < 22: nurs = self._alloc_nursery() llarena.arena_protect(nurs, self._nursery_memory_size(), True) - self.debug_rotating_nurseries.append(nurs) + self.debug_rotating_nurseries[i] = nurs + i += 1 debug_print("allocated", len(self.debug_rotating_nurseries), "extra nurseries") debug_stop("gc-debug") def debug_rotate_nursery(self): - if self.debug_rotating_nurseries is not None: + if self.debug_rotating_nurseries: debug_start("gc-debug") oldnurs = self.nursery llarena.arena_protect(oldnurs, self._nursery_memory_size(), True) - self.debug_rotating_nurseries.append(oldnurs) # - newnurs = self.debug_rotating_nurseries.pop(0) + newnurs = self.debug_rotating_nurseries[0] + i = 0 + while i < len(self.debug_rotating_nurseries) - 1: + self.debug_rotating_nurseries[i] = ( + self.debug_rotating_nurseries[i + 1]) + i += 1 + self.debug_rotating_nurseries[i] = oldnurs + # llarena.arena_protect(newnurs, self._nursery_memory_size(), False) self.nursery = newnurs self.nursery_top = self.nursery + self.initial_cleanup From noreply at buildbot.pypy.org Fri Apr 19 14:18:37 2013 From: noreply at buildbot.pypy.org (timfel) Date: Fri, 19 Apr 2013 14:18:37 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: fix tests that segfaultet Message-ID: <20130419121837.EBC561C31C7@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: Changeset: r300:15149caf13f0 Date: 2013-04-19 14:17 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/15149caf13f0/ Log: fix tests that segfaultet diff --git a/spyvm/test/test_model.py b/spyvm/test/test_model.py --- a/spyvm/test/test_model.py +++ b/spyvm/test/test_model.py @@ -2,7 +2,7 @@ import math from spyvm import model, shadow from spyvm.shadow import MethodNotFound -from spyvm import objspace, error +from spyvm import objspace, error, display from rpython.rlib.rarithmetic import intmask, r_uint mockclass = objspace.bootstrap_class @@ -288,7 +288,16 @@ assert hex(r_uint(target.value)) == hex(r_uint(source.value)) def test_display_bitmap(): - target = model.W_DisplayBitmap.create(space, space.w_Array, 100, 1, None) + # XXX: Patch SDLDisplay -> get_pixelbuffer() to circumvent + # double-free bug + def get_pixelbuffer(self): + from rpython.rtyper.lltypesystem import lltype, rffi + return lltype.malloc(rffi.ULONGP.TO, self.width * self.height * 32, flavor='raw') + display.SDLDisplay.get_pixelbuffer = get_pixelbuffer + d = display.SDLDisplay("test") + d.set_video_mode(10, 10, 1) + + target = model.W_DisplayBitmap.create(space, space.w_Array, 100, 1, d) target.setword(0, 0xFF00) assert bin(target.getword(0)) == bin(0xFF00) target.setword(0, 0x00FF00FF) diff --git a/spyvm/test/test_primitives.py b/spyvm/test/test_primitives.py --- a/spyvm/test/test_primitives.py +++ b/spyvm/test/test_primitives.py @@ -637,7 +637,13 @@ assert w_1 is not w_2 def test_primitive_be_display(): - py.test.fail("This test leads to a Segfault.") + # XXX: Patch SDLDisplay -> get_pixelbuffer() to circumvent + # double-free bug + def get_pixelbuffer(self): + from rpython.rtyper.lltypesystem import lltype, rffi + return lltype.malloc(rffi.ULONGP.TO, self.width * self.height * 32, flavor='raw') + display.SDLDisplay.get_pixelbuffer = get_pixelbuffer + assert space.objtable["w_display"] is None mock_display = model.W_PointersObject(space, space.w_Point, 4) w_wordbmp = model.W_WordsObject(space, space.w_Array, 100) @@ -671,7 +677,13 @@ assert mock_display.fetch(space, 0) is w_bitmap def test_primitive_force_display_update(monkeypatch): - py.test.fail("This test leads to a Segfault.") + # XXX: Patch SDLDisplay -> get_pixelbuffer() to circumvent + # double-free bug + def get_pixelbuffer(self): + from rpython.rtyper.lltypesystem import lltype, rffi + return lltype.malloc(rffi.ULONGP.TO, self.width * self.height * 32, flavor='raw') + display.SDLDisplay.get_pixelbuffer = get_pixelbuffer + mock_display = model.W_PointersObject(space, space.w_Point, 4) w_wordbmp = model.W_WordsObject(space, space.w_Array, 100) mock_display.store(space, 0, w_wordbmp) # bitmap @@ -701,6 +713,7 @@ self.w_simulateCopyBits = "simulateCopyBits" mock_bitblt = model.W_PointersObject(space, space.w_Point, 15) + mock_bitblt.store(space, 3, space.wrap_int(15)) # combination rule def perform_mock(w_selector, argcount, interp): if w_selector == "simulateCopyBits" or w_selector.as_string() == "simulateCopyBits": From noreply at buildbot.pypy.org Fri Apr 19 16:53:47 2013 From: noreply at buildbot.pypy.org (timfel) Date: Fri, 19 Apr 2013 16:53:47 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: (krono, timfel) fix closure detection when creating a MethodContext shadow Message-ID: <20130419145347.B55BE1C31C0@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: Changeset: r301:aa6a44388258 Date: 2013-04-19 16:51 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/aa6a44388258/ Log: (krono, timfel) fix closure detection when creating a MethodContext shadow diff --git a/spyvm/shadow.py b/spyvm/shadow.py --- a/spyvm/shadow.py +++ b/spyvm/shadow.py @@ -873,8 +873,10 @@ @jit.dont_look_inside def attach_shadow(self): - # Make sure the method is updated first + # Make sure the method and closure_or_nil are updated first, + # otherwise tempsize may be wrong self.copy_from_w_self(constants.MTHDCTX_METHOD) + self.copy_from_w_self(constants.MTHDCTX_CLOSURE_OR_NIL) self.init_stack_and_temps() ContextPartShadow.attach_shadow(self) From noreply at buildbot.pypy.org Fri Apr 19 17:03:54 2013 From: noreply at buildbot.pypy.org (fijal) Date: Fri, 19 Apr 2013 17:03:54 +0200 (CEST) Subject: [pypy-commit] pypy default: don't store attributes on a PBC Message-ID: <20130419150354.5C2B01C31C0@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r63504:85c38bff6115 Date: 2013-04-19 17:02 +0200 http://bitbucket.org/pypy/pypy/changeset/85c38bff6115/ Log: don't store attributes on a PBC diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -56,7 +56,7 @@ if we_are_translated(): self.debug = False self.current_clt = looptoken.compiled_loop_token - self.mc = InstrBuilder(self.cpu.arch_version) + self.mc = InstrBuilder(self.cpu.cpuinfo.arch_version) self.pending_guards = [] assert self.datablockwrapper is None allblocks = self.get_asmmemmgr_blocks(looptoken) @@ -80,7 +80,7 @@ if not self.cpu.propagate_exception_descr: return # not supported (for tests, or non-translated) # - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) self._store_and_reset_exception(mc, r.r0) ofs = self.cpu.get_ofs_of_frame_field('jf_guard_exc') # make sure ofs fits into a register @@ -165,7 +165,7 @@ # | my own retaddr | <-- sp # +-----------------------+ # - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) # save argument registers and return address mc.PUSH([reg.value for reg in r.argument_regs] + [r.ip.value, r.lr.value]) # stack is aligned here @@ -206,7 +206,7 @@ # write barriers. It must save all registers, and optionally # all vfp registers. It takes a single argument which is in r0. # It must keep stack alignment accordingly. - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) # exc0 = exc1 = None mc.PUSH([r.ip.value, r.lr.value]) # push two words to keep alignment @@ -252,7 +252,7 @@ def _build_malloc_slowpath(self, kind): if kind != 'fixed': return 0 - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) self._push_all_regs_to_jitframe(mc, [r.r0, r.r1], self.cpu.supports_floats) ofs = self.cpu.get_ofs_of_frame_field('jf_gcmap') # store the gc pattern @@ -364,7 +364,7 @@ self.load_reg(mc, vfpr, r.fp, ofs) def _build_failure_recovery(self, exc, withfloats=False): - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) self._push_all_regs_to_jitframe(mc, [], withfloats) if exc: @@ -647,7 +647,7 @@ expected_size=expected_size) def _patch_frame_depth(self, adr, allocated_depth): - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) mc.gen_load_int(r.lr.value, allocated_depth) mc.copy_to_raw_memory(adr) @@ -723,7 +723,7 @@ # f) store the address of the new jitframe in the shadowstack # c) set the gcmap field to 0 in the new jitframe # g) restore registers and return - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) self._push_all_regs_to_jitframe(mc, [], self.cpu.supports_floats) # this is the gcmap stored by push_gcmap(mov=True) in _check_stack_frame # and the expected_size pushed in _check_stack_frame @@ -783,7 +783,7 @@ self.target_tokens_currently_compiling = None def _patch_stackadjust(self, adr, allocated_depth): - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) mc.gen_load_int(r.lr.value, allocated_depth) mc.copy_to_raw_memory(adr) @@ -823,7 +823,7 @@ # patch the guard jumpt to the stub # overwrite the generate NOP with a B_offs to the pos of the # stub - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) mc.B_offs(relative_offset, c.get_opposite_of(tok.fcond)) mc.copy_to_raw_memory(guard_pos) else: @@ -902,7 +902,7 @@ self.mc.ASR_ri(resloc.value, resloc.value, 16) def patch_trace(self, faildescr, looptoken, bridge_addr, regalloc): - b = InstrBuilder(self.cpu.arch_version) + b = InstrBuilder(self.cpu.cpuinfo.arch_version) patch_addr = faildescr._arm_failure_recovery_block assert patch_addr != 0 b.B(bridge_addr) diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -354,7 +354,7 @@ # whether to worry about a CALL that can collect; this # is always true except in call_release_gil can_collect=True): - if self.cpu.hf_abi: + if self.cpu.cpuinfo.hf_abi: stack_args, adr = self._setup_call_hf(adr, arglocs, fcond, resloc, result_info) else: @@ -382,7 +382,7 @@ # ensure the result is wellformed and stored in the correct location if resloc is not None: - if resloc.is_vfp_reg() and not self.cpu.hf_abi: + if resloc.is_vfp_reg() and not self.cpu.cpuinfo.hf_abi: # move result to the allocated register self.mov_to_vfp_loc(r.r0, r.r1, resloc) elif resloc.is_reg() and result_info != (-1, -1): @@ -1230,7 +1230,7 @@ baseofs = self.cpu.get_baseofs_of_frame_field() newlooptoken.compiled_loop_token.update_frame_info( oldlooptoken.compiled_loop_token, baseofs) - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) mc.B(target) mc.copy_to_raw_memory(oldadr) diff --git a/rpython/jit/backend/arm/runner.py b/rpython/jit/backend/arm/runner.py --- a/rpython/jit/backend/arm/runner.py +++ b/rpython/jit/backend/arm/runner.py @@ -11,6 +11,10 @@ jitframe.STATICSIZE = JITFRAME_FIXED_SIZE +class CPUInfo(object): + hf_abi = False + arch_version = 6 + class AbstractARMCPU(AbstractLLCPU): IS_64_BIT = False @@ -26,13 +30,11 @@ float_regs = VFPRegisterManager.all_regs frame_reg = fp - hf_abi = False # use hard float abi flag - arch_version = 6 # assume ARMv6 as base case - def __init__(self, rtyper, stats, opts=None, translate_support_code=False, gcdescr=None): AbstractLLCPU.__init__(self, rtyper, stats, opts, translate_support_code, gcdescr) + self.cpuinfo = CPUInfo() def set_debug(self, flag): return self.assembler.set_debug(flag) @@ -47,8 +49,8 @@ self.assembler = AssemblerARM(self, self.translate_support_code) def setup_once(self): - self.arch_version = detect_arch_version() - self.hf_abi = detect_hardfloat() + self.cpuinfo.arch_version = detect_arch_version() + self.cpuinfo.hf_abi = detect_hardfloat() self.assembler.setup_once() def finish_once(self): @@ -92,7 +94,7 @@ from rpython.jit.backend.arm.codebuilder import InstrBuilder for jmp, tgt in looptoken.compiled_loop_token.invalidate_positions: - mc = InstrBuilder(self.arch_version) + mc = InstrBuilder(self.cpuinfo.arch_version) mc.B_offs(tgt) mc.copy_to_raw_memory(jmp) # positions invalidated diff --git a/rpython/jit/backend/arm/test/test_runner.py b/rpython/jit/backend/arm/test/test_runner.py --- a/rpython/jit/backend/arm/test/test_runner.py +++ b/rpython/jit/backend/arm/test/test_runner.py @@ -27,7 +27,7 @@ bridge_loop_instructions = ['ldr', 'mov', 'nop', 'cmp', 'bge', 'push', 'mov', 'mov', 'push', 'mov', 'mov', 'blx', 'mov', 'mov', 'bx'] - if CPU.arch_version == 7: + if CPU.cpuinfo.arch_version == 7: bridge_loop_instructions = ['ldr', 'mov', 'nop', 'cmp', 'bge', 'push', 'mov', 'mov', 'push', 'mov', 'mov', 'blx', 'mov', 'mov', 'bx'] From noreply at buildbot.pypy.org Fri Apr 19 17:03:55 2013 From: noreply at buildbot.pypy.org (fijal) Date: Fri, 19 Apr 2013 17:03:55 +0200 (CEST) Subject: [pypy-commit] pypy default: merge Message-ID: <20130419150355.BE8141C31C0@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r63505:93e73352baa9 Date: 2013-04-19 17:03 +0200 http://bitbucket.org/pypy/pypy/changeset/93e73352baa9/ Log: merge diff --git a/rpython/jit/backend/test/runner_test.py b/rpython/jit/backend/test/runner_test.py --- a/rpython/jit/backend/test/runner_test.py +++ b/rpython/jit/backend/test/runner_test.py @@ -3935,3 +3935,19 @@ descr = self.cpu.get_latest_descr(frame) assert descr.identifier == 42 assert not self.cpu.grab_exc_value(frame) + + def test_setarrayitem_raw_short(self): + # setarrayitem_raw(140737353744432, 0, 30583, descr=) + A = rffi.CArray(rffi.SHORT) + arraydescr = self.cpu.arraydescrof(A) + a = lltype.malloc(A, 2, flavor='raw') + a[0] = rffi.cast(rffi.SHORT, 666) + a[1] = rffi.cast(rffi.SHORT, 777) + a_int = rffi.cast(lltype.Signed, a) + print 'a_int:', a_int + self.execute_operation(rop.SETARRAYITEM_RAW, + [ConstInt(a_int), ConstInt(0), ConstInt(-7654)], + 'void', descr=arraydescr) + assert rffi.cast(lltype.Signed, a[0]) == -7654 + assert rffi.cast(lltype.Signed, a[1]) == 777 + lltype.free(a, flavor='raw') diff --git a/rpython/jit/backend/x86/regloc.py b/rpython/jit/backend/x86/regloc.py --- a/rpython/jit/backend/x86/regloc.py +++ b/rpython/jit/backend/x86/regloc.py @@ -521,17 +521,6 @@ return func_with_new_name(INSN, "INSN_" + name) - def _16_bit_binaryop(name): - def INSN(self, loc1, loc2): - # Select 16-bit operand mode - self.writechar('\x66') - # XXX: Hack to let immediate() in rx86 know to do a 16-bit encoding - self._use_16_bit_immediate = True - getattr(self, name)(loc1, loc2) - self._use_16_bit_immediate = False - - return INSN - def _addr_as_reg_offset(self, addr): # Encodes a (64-bit) address as an offset from the scratch register. # If we are within a "reuse_scratch_register" block, we remember the @@ -616,10 +605,10 @@ NEG = _unaryop('NEG') CMP = _binaryop('CMP') - CMP16 = _16_bit_binaryop('CMP') + CMP16 = _binaryop('CMP16') MOV = _binaryop('MOV') MOV8 = _binaryop('MOV8') - MOV16 = _16_bit_binaryop('MOV') + MOV16 = _binaryop('MOV16') MOVZX8 = _binaryop('MOVZX8') MOVSX8 = _binaryop('MOVSX8') MOVZX16 = _binaryop('MOVZX16') diff --git a/rpython/jit/backend/x86/rx86.py b/rpython/jit/backend/x86/rx86.py --- a/rpython/jit/backend/x86/rx86.py +++ b/rpython/jit/backend/x86/rx86.py @@ -125,10 +125,7 @@ elif width == 'q' and mc.WORD == 8: mc.writeimm64(immediate) else: - if mc._use_16_bit_immediate: - mc.writeimm16(immediate) - else: - mc.writeimm32(immediate) + mc.writeimm32(immediate) return 0 def immediate(argnum, width='i'): @@ -282,16 +279,20 @@ # (the immediate address itself must be explicitely encoded as well, # with immediate(argnum)). -def encode_abs(mc, _1, _2, orbyte): + at specialize.arg(2) +def encode_abs(mc, immediate, _, orbyte): # expands to either '\x05' on 32-bit, or '\x04\x25' on 64-bit if mc.WORD == 8: mc.writechar(chr(0x04 | orbyte)) mc.writechar(chr(0x25)) else: mc.writechar(chr(0x05 | orbyte)) + # followed by an immediate, always 32 bits + mc.writeimm32(immediate) return 0 -abs_ = encode_abs, 0, None, None +def abs_(argnum): + return encode_abs, argnum, None, None # ____________________________________________________________ # For 64-bits mode: the REX.W, REX.R, REX.X, REG.B prefixes @@ -305,9 +306,6 @@ def encode_rex(mc, rexbyte, basevalue, orbyte): if mc.WORD == 8: assert 0 <= rexbyte < 8 - # XXX: Hack. Ignore REX.W if we are using 16-bit operands - if mc._use_16_bit_immediate: - basevalue &= ~REX_W if basevalue != 0 or rexbyte != 0: if basevalue == 0: basevalue = 0x40 @@ -374,9 +372,8 @@ INSN_br = insn(rex_w, chr(base+1), register(2,8), stack_bp(1)) INSN_rb = insn(rex_w, chr(base+3), register(1,8), stack_bp(2)) INSN_rm = insn(rex_w, chr(base+3), register(1,8), mem_reg_plus_const(2)) - INSN_rj = insn(rex_w, chr(base+3), register(1,8), abs_, immediate(2)) - INSN_ji8 = insn(rex_w, '\x83', orbyte(base), abs_, immediate(1), - immediate(2,'b')) + INSN_rj = insn(rex_w, chr(base+3), register(1,8), abs_(2)) + INSN_ji8 = insn(rex_w, '\x83', orbyte(base), abs_(1), immediate(2,'b')) INSN_mi8 = insn(rex_w, '\x83', orbyte(base), mem_reg_plus_const(1), immediate(2,'b')) INSN_bi8 = insn(rex_w, '\x83', orbyte(base), stack_bp(1), immediate(2,'b')) @@ -449,9 +446,6 @@ class AbstractX86CodeBuilder(object): """Abstract base class.""" - # Used by the 16-bit version of instructions - _use_16_bit_immediate = False - def writechar(self, char): raise NotImplementedError @@ -489,15 +483,13 @@ CMP_mi = select_8_or_32_bit_immed(CMP_mi8, CMP_mi32) CMP_mr = insn(rex_w, '\x39', register(2, 8), mem_reg_plus_const(1)) - CMP_ji8 = insn(rex_w, '\x83', orbyte(7<<3), abs_, - immediate(1), immediate(2, 'b')) - CMP_ji32 = insn(rex_w, '\x81', orbyte(7<<3), abs_, - immediate(1), immediate(2)) + CMP_ji8 = insn(rex_w, '\x83', orbyte(7<<3), abs_(1), immediate(2, 'b')) + CMP_ji32 = insn(rex_w, '\x81', orbyte(7<<3), abs_(1), immediate(2)) CMP_ji = select_8_or_32_bit_immed(CMP_ji8, CMP_ji32) - CMP_jr = insn(rex_w, '\x39', register(2, 8), abs_, immediate(1)) + CMP_jr = insn(rex_w, '\x39', register(2, 8), abs_(1)) CMP32_mi = insn(rex_nw, '\x81', orbyte(7<<3), mem_reg_plus_const(1), immediate(2)) - + CMP16_mi = insn('\x66', rex_nw, '\x81', orbyte(7<<3), mem_reg_plus_const(1), immediate(2, 'h')) CMP8_ri = insn(rex_fw, '\x80', byte_register(1), '\xF8', immediate(2, 'b')) AND8_rr = insn(rex_fw, '\x20', byte_register(1), byte_register(2,8), '\xC0') @@ -505,7 +497,7 @@ OR8_rr = insn(rex_fw, '\x08', byte_register(1), byte_register(2,8), '\xC0') OR8_mi = insn(rex_nw, '\x80', orbyte(1<<3), mem_reg_plus_const(1), immediate(2, 'b')) - OR8_ji = insn(rex_nw, '\x80', orbyte(1<<3), abs_, immediate(1), + OR8_ji = insn(rex_nw, '\x80', orbyte(1<<3), abs_(1), immediate(2, 'b')) NEG_r = insn(rex_w, '\xF7', register(1), '\xD8') @@ -556,7 +548,7 @@ LEA32_rb = insn(rex_w, '\x8D', register(1,8),stack_bp(2,force_32bits=True)) LEA_ra = insn(rex_w, '\x8D', register(1, 8), mem_reg_plus_scaled_reg_plus_const(2)) LEA_rm = insn(rex_w, '\x8D', register(1, 8), mem_reg_plus_const(2)) - LEA_rj = insn(rex_w, '\x8D', register(1, 8), abs_, immediate(2)) + LEA_rj = insn(rex_w, '\x8D', register(1, 8), abs_(2)) CALL_l = insn('\xE8', relative(1)) CALL_r = insn(rex_nw, '\xFF', register(1), chr(0xC0 | (2<<3))) @@ -583,11 +575,11 @@ TEST8_mi = insn(rex_nw, '\xF6', orbyte(0<<3), mem_reg_plus_const(1), immediate(2, 'b')) TEST8_bi = insn(rex_nw, '\xF6', orbyte(0<<3), stack_bp(1), immediate(2, 'b')) - TEST8_ji = insn(rex_nw, '\xF6', orbyte(0<<3), abs_, immediate(1), immediate(2, 'b')) + TEST8_ji = insn(rex_nw, '\xF6', orbyte(0<<3), abs_(1), immediate(2, 'b')) TEST_rr = insn(rex_w, '\x85', register(2,8), register(1), '\xC0') BTS_mr = insn(rex_w, '\x0F\xAB', register(2,8), mem_reg_plus_const(1)) - BTS_jr = insn(rex_w, '\x0F\xAB', register(2,8), abs_, immediate(1)) + BTS_jr = insn(rex_w, '\x0F\xAB', register(2,8), abs_(1)) # x87 instructions FSTPL_b = insn('\xDD', orbyte(3<<3), stack_bp(1)) # rffi.DOUBLE ('as' wants L??) @@ -718,7 +710,7 @@ add_insn('s', stack_sp(modrm_argnum)) add_insn('m', mem_reg_plus_const(modrm_argnum)) add_insn('a', mem_reg_plus_scaled_reg_plus_const(modrm_argnum)) - add_insn('j', abs_, immediate(modrm_argnum)) + add_insn('j', abs_(modrm_argnum)) # Define a regular MOV, and a variant MOV32 that only uses the low 4 bytes of a # register @@ -729,6 +721,8 @@ define_modrm_modes('MOV8_*r', [rex_fw, '\x88', byte_register(2, 8)], regtype='BYTE') define_modrm_modes('MOV8_*i', [rex_fw, '\xC6', orbyte(0<<3)], [immediate(2, 'b')], regtype='BYTE') +define_modrm_modes('MOV16_*r', ['\x66', rex_nw, '\x89', register(2, 8)]) +define_modrm_modes('MOV16_*i', ['\x66', rex_nw, '\xC7', orbyte(0<<3)], [immediate(2, 'h')]) define_modrm_modes('MOVZX8_r*', [rex_w, '\x0F\xB6', register(1, 8)], regtype='BYTE') define_modrm_modes('MOVSX8_r*', [rex_w, '\x0F\xBE', register(1, 8)], regtype='BYTE') @@ -766,7 +760,7 @@ # assert insnname_template.count('*') == 1 add_insn('x', register(2), '\xC0') - add_insn('j', abs_, immediate(2)) + add_insn('j', abs_(2)) add_insn('m', mem_reg_plus_const(2)) define_pxmm_insn('PADDQ_x*', '\xD4') diff --git a/rpython/memory/gc/minimark.py b/rpython/memory/gc/minimark.py --- a/rpython/memory/gc/minimark.py +++ b/rpython/memory/gc/minimark.py @@ -130,6 +130,7 @@ FORWARDSTUB = lltype.GcStruct('forwarding_stub', ('forw', llmemory.Address)) FORWARDSTUBPTR = lltype.Ptr(FORWARDSTUB) +NURSARRAY = lltype.Array(llmemory.Address) # ____________________________________________________________ @@ -263,7 +264,7 @@ self.nursery_top = NULL self.nursery_real_top = NULL self.debug_tiny_nursery = -1 - self.debug_rotating_nurseries = None + self.debug_rotating_nurseries = lltype.nullptr(NURSARRAY) self.extra_threshold = 0 # # The ArenaCollection() handles the nonmovable objects allocation. @@ -471,23 +472,32 @@ # and use them alternatively, while mprotect()ing the unused # ones to detect invalid access. debug_start("gc-debug") - self.debug_rotating_nurseries = [] - for i in range(22): + self.debug_rotating_nurseries = lltype.malloc( + NURSARRAY, 22, flavor='raw', track_allocation=False) + i = 0 + while i < 22: nurs = self._alloc_nursery() llarena.arena_protect(nurs, self._nursery_memory_size(), True) - self.debug_rotating_nurseries.append(nurs) + self.debug_rotating_nurseries[i] = nurs + i += 1 debug_print("allocated", len(self.debug_rotating_nurseries), "extra nurseries") debug_stop("gc-debug") def debug_rotate_nursery(self): - if self.debug_rotating_nurseries is not None: + if self.debug_rotating_nurseries: debug_start("gc-debug") oldnurs = self.nursery llarena.arena_protect(oldnurs, self._nursery_memory_size(), True) - self.debug_rotating_nurseries.append(oldnurs) # - newnurs = self.debug_rotating_nurseries.pop(0) + newnurs = self.debug_rotating_nurseries[0] + i = 0 + while i < len(self.debug_rotating_nurseries) - 1: + self.debug_rotating_nurseries[i] = ( + self.debug_rotating_nurseries[i + 1]) + i += 1 + self.debug_rotating_nurseries[i] = oldnurs + # llarena.arena_protect(newnurs, self._nursery_memory_size(), False) self.nursery = newnurs self.nursery_top = self.nursery + self.initial_cleanup diff --git a/rpython/memory/gctransform/framework.py b/rpython/memory/gctransform/framework.py --- a/rpython/memory/gctransform/framework.py +++ b/rpython/memory/gctransform/framework.py @@ -619,6 +619,12 @@ func = getattr(graph, 'func', None) if func and getattr(func, '_gc_no_collect_', False): if self.collect_analyzer.analyze_direct_call(graph): + print '!'*79 + ca = CollectAnalyzer(self.translator) + ca.verbose = True + ca.analyze_direct_call(graph) + # ^^^ for the dump of which operation in which graph actually + # causes it to return True raise Exception("'no_collect' function can trigger collection:" " %s" % func) diff --git a/rpython/translator/backendopt/graphanalyze.py b/rpython/translator/backendopt/graphanalyze.py --- a/rpython/translator/backendopt/graphanalyze.py +++ b/rpython/translator/backendopt/graphanalyze.py @@ -80,21 +80,21 @@ if graph is None: x = self.analyze_external_call(op, seen) if self.verbose and x: - print '\tanalyze_external_call %s: %r' % (op, x) + self.dump_info('analyze_external_call %s: %r' % (op, x)) return x x = self.analyze_direct_call(graph, seen) if self.verbose and x: - print '\tanalyze_direct_call(%s): %r' % (graph, x) + self.dump_info('analyze_direct_call(%s): %r' % (graph, x)) return x elif op.opname == "indirect_call": graphs = op.args[-1].value if graphs is None: if self.verbose: - print '\t%s to unknown' % (op,) + self.dump_info('%s to unknown' % (op,)) return self.top_result() x = self.analyze_indirect_call(graphs, seen) if self.verbose and x: - print '\tanalyze_indirect_call(%s): %r' % (graphs, x) + self.dump_info('analyze_indirect_call(%s): %r' % (graphs, x)) return x elif op.opname == "oosend": name = op.args[0].value @@ -106,9 +106,12 @@ return self.analyze_oosend(TYPE, name, seen) x = self.analyze_simple_operation(op, graphinfo) if self.verbose and x: - print '\t%s: %r' % (op, x) + self.dump_info('%s: %r' % (op, x)) return x + def dump_info(self, info): + print '[%s] %s' % (self.__class__.__name__, info) + def analyze_direct_call(self, graph, seen=None): if seen is None: seen = DependencyTracker(self) From noreply at buildbot.pypy.org Fri Apr 19 17:09:55 2013 From: noreply at buildbot.pypy.org (fijal) Date: Fri, 19 Apr 2013 17:09:55 +0200 (CEST) Subject: [pypy-commit] pypy default: Fix for the test (static attribute is not enough) Message-ID: <20130419150955.80E101C31C0@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r63506:05f197a8723c Date: 2013-04-19 17:09 +0200 http://bitbucket.org/pypy/pypy/changeset/05f197a8723c/ Log: Fix for the test (static attribute is not enough) diff --git a/rpython/jit/backend/arm/test/test_runner.py b/rpython/jit/backend/arm/test/test_runner.py --- a/rpython/jit/backend/arm/test/test_runner.py +++ b/rpython/jit/backend/arm/test/test_runner.py @@ -10,6 +10,7 @@ from rpython.rtyper.annlowlevel import llhelper from rpython.jit.codewriter.effectinfo import EffectInfo from rpython.jit.metainterp.history import JitCellToken, TargetToken +from rpython.jit.backend.arm.detect import detect_arch_version CPU = getcpuclass() @@ -27,7 +28,8 @@ bridge_loop_instructions = ['ldr', 'mov', 'nop', 'cmp', 'bge', 'push', 'mov', 'mov', 'push', 'mov', 'mov', 'blx', 'mov', 'mov', 'bx'] - if CPU.cpuinfo.arch_version == 7: + arch_version = detect_arch_version() + if arch_version == 7: bridge_loop_instructions = ['ldr', 'mov', 'nop', 'cmp', 'bge', 'push', 'mov', 'mov', 'push', 'mov', 'mov', 'blx', 'mov', 'mov', 'bx'] From noreply at buildbot.pypy.org Fri Apr 19 17:14:09 2013 From: noreply at buildbot.pypy.org (fijal) Date: Fri, 19 Apr 2013 17:14:09 +0200 (CEST) Subject: [pypy-commit] pypy default: fix Message-ID: <20130419151409.6C0781C31C0@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r63507:d3d1784b566b Date: 2013-04-19 17:13 +0200 http://bitbucket.org/pypy/pypy/changeset/d3d1784b566b/ Log: fix diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -289,9 +289,7 @@ self.store_reg(mc, r.ip, r.fp, ofs) # return mc.POP([r.ip.value, r.pc.value]) - - rawstart = mc.materialize(self.cpu.asmmemmgr, []) - self.malloc_slowpath = rawstart + return mc.materialize(self.cpu.asmmemmgr, []) def _reload_frame_if_necessary(self, mc): gcrootmap = self.cpu.gc_ll_descr.gcrootmap From noreply at buildbot.pypy.org Fri Apr 19 17:16:01 2013 From: noreply at buildbot.pypy.org (timfel) Date: Fri, 19 Apr 2013 17:16:01 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: skip test on CI that fails there Message-ID: <20130419151601.4A4C91C31C7@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: Changeset: r302:e6f2d9402270 Date: 2013-04-19 17:15 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/e6f2d9402270/ Log: skip test on CI that fails there diff --git a/spyvm/test/test_model.py b/spyvm/test/test_model.py --- a/spyvm/test/test_model.py +++ b/spyvm/test/test_model.py @@ -1,5 +1,6 @@ import py import math +import socket from spyvm import model, shadow from spyvm.shadow import MethodNotFound from spyvm import objspace, error, display @@ -287,6 +288,7 @@ assert target.at0(space, i) == source.at0(space, i) assert hex(r_uint(target.value)) == hex(r_uint(source.value)) + at pytest.mark.skipif("socket.gethostname() == 'precise32'") def test_display_bitmap(): # XXX: Patch SDLDisplay -> get_pixelbuffer() to circumvent # double-free bug From noreply at buildbot.pypy.org Fri Apr 19 17:49:56 2013 From: noreply at buildbot.pypy.org (fijal) Date: Fri, 19 Apr 2013 17:49:56 +0200 (CEST) Subject: [pypy-commit] pypy default: Fix comment and a situation where the cache size is odd (although I think Message-ID: <20130419154956.043E91C31C0@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r63508:40490851e8b7 Date: 2013-04-19 17:49 +0200 http://bitbucket.org/pypy/pypy/changeset/40490851e8b7/ Log: Fix comment and a situation where the cache size is odd (although I think it does change a thing since it should be a power of 2) diff --git a/rpython/memory/gc/env.py b/rpython/memory/gc/env.py --- a/rpython/memory/gc/env.py +++ b/rpython/memory/gc/env.py @@ -279,7 +279,7 @@ def best_nursery_size_for_L2cache(L2cache): # Heuristically, the best nursery size to choose is about half # of the L2 cache. - if L2cache > 1024 * 1024: # we don't want to have nursery estimated + if L2cache > 2 * 1024 * 1024: # we don't want to have nursery estimated # on L2 when L3 is present return L2cache // 2 else: diff --git a/rpython/memory/gc/minimark.py b/rpython/memory/gc/minimark.py --- a/rpython/memory/gc/minimark.py +++ b/rpython/memory/gc/minimark.py @@ -351,8 +351,6 @@ # hacking at the current nursery position in collect_and_reserve(). if newsize <= 0: newsize = env.estimate_best_nursery_size() - # 4*1024*1024 # fixed to 4MB by default - # (it was env.estimate_best_nursery_size()) if newsize <= 0: newsize = defaultsize if newsize < minsize: From noreply at buildbot.pypy.org Fri Apr 19 19:38:29 2013 From: noreply at buildbot.pypy.org (bivab) Date: Fri, 19 Apr 2013 19:38:29 +0200 (CEST) Subject: [pypy-commit] pypy default: fallback to ARMv6 instead of crashing if we cannot detect the architecture at all (i.e running in a qemu-chroot) Message-ID: <20130419173829.C405E1C101D@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63509:5ce89761d04a Date: 2013-04-19 19:37 +0200 http://bitbucket.org/pypy/pypy/changeset/5ce89761d04a/ Log: fallback to ARMv6 instead of crashing if we cannot detect the architecture at all (i.e running in a qemu-chroot) diff --git a/rpython/jit/backend/arm/detect.py b/rpython/jit/backend/arm/detect.py --- a/rpython/jit/backend/arm/detect.py +++ b/rpython/jit/backend/arm/detect.py @@ -1,7 +1,6 @@ import os from rpython.translator.tool.cbuild import ExternalCompilationInfo -from rpython.rlib.clibffi import FFI_DEFAULT_ABI, FFI_SYSV, FFI_VFP from rpython.rtyper.tool import rffi_platform from rpython.translator.platform import CompilationError from rpython.rlib.debug import debug_print, debug_start, debug_stop @@ -46,9 +45,11 @@ # "Processor : ARMv%d-compatible processor rev 7 (v6l)" i = buf.find('ARMv') if i == -1: - raise ValueError("Unknown Processor entry") - - n = int(buf[i + 4]) + n = 6 + debug_print("Could not detect architecture version, " + "falling back to", "ARMv%d" % n) + else: + n = int(buf[i + 4]) if n < 6: raise ValueError("Unsupported ARM architecture version") diff --git a/rpython/jit/backend/arm/test/test_detect.py b/rpython/jit/backend/arm/test/test_detect.py --- a/rpython/jit/backend/arm/test/test_detect.py +++ b/rpython/jit/backend/arm/test/test_detect.py @@ -3,7 +3,32 @@ from rpython.jit.backend.arm.detect import detect_arch_version cpuinfo = "Processor : ARMv%d-compatible processor rev 7 (v6l)""" - +cpuinfo2 = """processor : 0 +vendor_id : GenuineIntel +cpu family : 6 +model : 23 +model name : Intel(R) Core(TM)2 Duo CPU E8400 @ 3.00GHz +stepping : 10 +microcode : 0xa07 +cpu MHz : 2997.000 +cache size : 6144 KB +physical id : 0 +siblings : 2 +core id : 0 +cpu cores : 2 +apicid : 0 +initial apicid : 0 +fpu : yes +fpu_exception : yes +cpuid level : 13 +wp : yes +flags : fpu vme ... +bogomips : 5993.08 +clflush size : 64 +cache_alignment : 64 +address sizes : 36 bits physical, 48 bits virtual +power management: +""" def write_cpuinfo(info): filepath = udir.join('get_arch_version') @@ -20,5 +45,4 @@ assert detect_arch_version(write_cpuinfo(cpuinfo % 8)) == 7 py.test.raises(ValueError, 'detect_arch_version(write_cpuinfo(cpuinfo % 5))') - py.test.raises(ValueError, - 'detect_arch_version(write_cpuinfo("Lorem ipsum dolor sit amet, consectetur"))') + assert detect_arch_version(write_cpuinfo(cpuinfo2)) == 6 From noreply at buildbot.pypy.org Fri Apr 19 19:49:09 2013 From: noreply at buildbot.pypy.org (bivab) Date: Fri, 19 Apr 2013 19:49:09 +0200 (CEST) Subject: [pypy-commit] pypy default: this line should stay Message-ID: <20130419174909.EF9CB1C101D@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63510:4a4a9df37aa1 Date: 2013-04-19 19:48 +0200 http://bitbucket.org/pypy/pypy/changeset/4a4a9df37aa1/ Log: this line should stay diff --git a/rpython/jit/backend/arm/detect.py b/rpython/jit/backend/arm/detect.py --- a/rpython/jit/backend/arm/detect.py +++ b/rpython/jit/backend/arm/detect.py @@ -2,6 +2,7 @@ from rpython.translator.tool.cbuild import ExternalCompilationInfo from rpython.rtyper.tool import rffi_platform +from rpython.rlib.clibffi import FFI_DEFAULT_ABI, FFI_SYSV, FFI_VFP from rpython.translator.platform import CompilationError from rpython.rlib.debug import debug_print, debug_start, debug_stop From noreply at buildbot.pypy.org Sat Apr 20 00:15:46 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Sat, 20 Apr 2013 00:15:46 +0200 (CEST) Subject: [pypy-commit] pypy default: o untangle the Trait classes out of ll_os, avoids circular imports when Message-ID: <20130419221546.7F9FF1C31C7@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: Changeset: r63511:bc867140e4f2 Date: 2013-04-19 15:11 -0700 http://bitbucket.org/pypy/pypy/changeset/bc867140e4f2/ Log: o untangle the Trait classes out of ll_os, avoids circular imports when ll_os_environ begins using them directly o add scoped_str2charp to the Traits diff --git a/rpython/annotator/model.py b/rpython/annotator/model.py --- a/rpython/annotator/model.py +++ b/rpython/annotator/model.py @@ -527,6 +527,7 @@ s_Int = SomeInteger() s_ImpossibleValue = SomeImpossibleValue() s_Str0 = SomeString(no_nul=True) +s_Unicode0 = SomeUnicodeString(no_nul=True) # ____________________________________________________________ diff --git a/rpython/rtyper/module/ll_os.py b/rpython/rtyper/module/ll_os.py --- a/rpython/rtyper/module/ll_os.py +++ b/rpython/rtyper/module/ll_os.py @@ -7,14 +7,15 @@ import os, sys, errno import py -from rpython.rtyper.module.support import OOSupport +from rpython.rtyper.module.support import ( + _WIN32, OOSupport, StringTraits, UnicodeTraits, underscore_on_windows) from rpython.tool.sourcetools import func_renamer from rpython.rlib.rarithmetic import r_longlong from rpython.rtyper.extfunc import ( BaseLazyRegistering, register_external) from rpython.rtyper.extfunc import registering, registering_if, extdef from rpython.annotator.model import ( - SomeInteger, SomeString, SomeTuple, SomeFloat, SomeUnicodeString) + SomeInteger, SomeString, SomeTuple, SomeFloat, s_Str0, s_Unicode0) from rpython.annotator.model import s_ImpossibleValue, s_None, s_Bool from rpython.rtyper.lltypesystem import rffi from rpython.rtyper.lltypesystem import lltype @@ -25,8 +26,8 @@ from rpython.rtyper.lltypesystem.rstr import STR from rpython.rlib.objectmodel import specialize -str0 = SomeString(no_nul=True) -unicode0 = SomeUnicodeString(no_nul=True) +str0 = s_Str0 +unicode0 = s_Unicode0 def monkeypatch_rposix(posixfunc, unicodefunc, signature): func_name = posixfunc.__name__ @@ -66,42 +67,6 @@ # Monkeypatch the function in rpython.rlib.rposix setattr(rposix, func_name, new_func) -class StringTraits: - str = str - str0 = str0 - CHAR = rffi.CHAR - CCHARP = rffi.CCHARP - charp2str = staticmethod(rffi.charp2str) - str2charp = staticmethod(rffi.str2charp) - free_charp = staticmethod(rffi.free_charp) - scoped_alloc_buffer = staticmethod(rffi.scoped_alloc_buffer) - - @staticmethod - def posix_function_name(name): - return underscore_on_windows + name - - @staticmethod - def ll_os_name(name): - return 'll_os.ll_os_' + name - -class UnicodeTraits: - str = unicode - str0 = unicode0 - CHAR = rffi.WCHAR_T - CCHARP = rffi.CWCHARP - charp2str = staticmethod(rffi.wcharp2unicode) - str2charp = staticmethod(rffi.unicode2wcharp) - free_charp = staticmethod(rffi.free_wcharp) - scoped_alloc_buffer = staticmethod(rffi.scoped_alloc_unicodebuffer) - - @staticmethod - def posix_function_name(name): - return underscore_on_windows + 'w' + name - - @staticmethod - def ll_os_name(name): - return 'll_os.ll_os_w' + name - def registering_str_unicode(posixfunc, condition=True): if not condition or posixfunc is None: return registering(None, condition=False) @@ -129,16 +94,6 @@ posix = __import__(os.name) -if sys.platform.startswith('win'): - _WIN32 = True -else: - _WIN32 = False - -if _WIN32: - underscore_on_windows = '_' -else: - underscore_on_windows = '' - includes = [] if not _WIN32: # XXX many of these includes are not portable at all diff --git a/rpython/rtyper/module/support.py b/rpython/rtyper/module/support.py --- a/rpython/rtyper/module/support.py +++ b/rpython/rtyper/module/support.py @@ -1,6 +1,12 @@ -from rpython.rtyper.lltypesystem import lltype +import os +import sys + +from rpython.annotator import model as annmodel +from rpython.rtyper.lltypesystem import lltype, rffi from rpython.rtyper.ootypesystem import ootype -import os + +_WIN32 = sys.platform.startswith('win') +underscore_on_windows = '_' if _WIN32 else '' # utility conversion functions class LLSupport: @@ -64,6 +70,45 @@ from_rstr_nonnull = staticmethod(from_rstr_nonnull) +class StringTraits: + str = str + str0 = annmodel.s_Str0 + CHAR = rffi.CHAR + CCHARP = rffi.CCHARP + charp2str = staticmethod(rffi.charp2str) + scoped_str2charp = staticmethod(rffi.scoped_str2charp) + str2charp = staticmethod(rffi.str2charp) + free_charp = staticmethod(rffi.free_charp) + scoped_alloc_buffer = staticmethod(rffi.scoped_alloc_buffer) + + @staticmethod + def posix_function_name(name): + return underscore_on_windows + name + + @staticmethod + def ll_os_name(name): + return 'll_os.ll_os_' + name + +class UnicodeTraits: + str = unicode + str0 = annmodel.s_Unicode0 + CHAR = rffi.WCHAR_T + CCHARP = rffi.CWCHARP + charp2str = staticmethod(rffi.wcharp2unicode) + str2charp = staticmethod(rffi.unicode2wcharp) + scoped_str2charp = staticmethod(rffi.scoped_unicode2wcharp) + free_charp = staticmethod(rffi.free_wcharp) + scoped_alloc_buffer = staticmethod(rffi.scoped_alloc_unicodebuffer) + + @staticmethod + def posix_function_name(name): + return underscore_on_windows + 'w' + name + + @staticmethod + def ll_os_name(name): + return 'll_os.ll_os_w' + name + + def ll_strcpy(dst_s, src_s, n): dstchars = dst_s.chars srcchars = src_s.chars @@ -78,5 +123,3 @@ while i < n: dstchars[i] = srcchars[i] i += 1 - - From noreply at buildbot.pypy.org Sat Apr 20 00:15:47 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Sat, 20 Apr 2013 00:15:47 +0200 (CEST) Subject: [pypy-commit] pypy default: rearrange and support building wide versions of some environ impls, for windows Message-ID: <20130419221547.B4B301C31E5@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: Changeset: r63512:b57c65395e02 Date: 2013-04-19 15:12 -0700 http://bitbucket.org/pypy/pypy/changeset/b57c65395e02/ Log: rearrange and support building wide versions of some environ impls, for windows diff --git a/rpython/rtyper/module/ll_os_environ.py b/rpython/rtyper/module/ll_os_environ.py --- a/rpython/rtyper/module/ll_os_environ.py +++ b/rpython/rtyper/module/ll_os_environ.py @@ -4,10 +4,10 @@ from rpython.rtyper.controllerentry import Controller from rpython.rtyper.extfunc import register_external from rpython.rtyper.lltypesystem import rffi, lltype -from rpython.rtyper.module import ll_os -from rpython.rlib import rposix +from rpython.rtyper.module.support import _WIN32, StringTraits, UnicodeTraits +from rpython.translator.tool.cbuild import ExternalCompilationInfo -str0 = ll_os.str0 +str0 = annmodel.s_Str0 # ____________________________________________________________ # @@ -59,85 +59,8 @@ return r_getenv # ____________________________________________________________ -# -# Lower-level interface: dummy placeholders and external registations - -def r_getenv(name): - just_a_placeholder # should return None if name not found - -os_getenv = rffi.llexternal('getenv', [rffi.CCHARP], rffi.CCHARP, - threadsafe=False) - -def getenv_llimpl(name): - with rffi.scoped_str2charp(name) as l_name: - l_result = os_getenv(l_name) - return rffi.charp2str(l_result) if l_result else None - -register_external(r_getenv, [str0], - annmodel.SomeString(can_be_None=True, no_nul=True), - export_name='ll_os.ll_os_getenv', - llimpl=getenv_llimpl) - -# ____________________________________________________________ - -def r_putenv(name, value): - just_a_placeholder - -class EnvKeepalive: - pass -envkeepalive = EnvKeepalive() -envkeepalive.byname = {} - -os_putenv = rffi.llexternal('putenv', [rffi.CCHARP], rffi.INT) - -def putenv_llimpl(name, value): - l_string = rffi.str2charp('%s=%s' % (name, value)) - error = rffi.cast(lltype.Signed, os_putenv(l_string)) - if error: - rffi.free_charp(l_string) - raise OSError(rposix.get_errno(), "os_putenv failed") - # keep 'l_string' alive - we know that the C library needs it - # until the next call to putenv() with the same 'name'. - l_oldstring = envkeepalive.byname.get(name, lltype.nullptr(rffi.CCHARP.TO)) - envkeepalive.byname[name] = l_string - if l_oldstring: - rffi.free_charp(l_oldstring) - -register_external(r_putenv, [str0, str0], annmodel.s_None, - export_name='ll_os.ll_os_putenv', - llimpl=putenv_llimpl) - -# ____________________________________________________________ - -def r_unsetenv(name): - # default implementation for platforms without a real unsetenv() - r_putenv(name, '') - -if hasattr(__import__(os.name), 'unsetenv'): - os_unsetenv = rffi.llexternal('unsetenv', [rffi.CCHARP], rffi.INT) - - def unsetenv_llimpl(name): - with rffi.scoped_str2charp(name) as l_name: - error = rffi.cast(lltype.Signed, os_unsetenv(l_name)) - if error: - raise OSError(rposix.get_errno(), "os_unsetenv failed") - try: - l_oldstring = envkeepalive.byname[name] - except KeyError: - pass - else: - del envkeepalive.byname[name] - rffi.free_charp(l_oldstring) - - register_external(r_unsetenv, [str0], annmodel.s_None, - export_name='ll_os.ll_os_unsetenv', - llimpl=unsetenv_llimpl) - -# ____________________________________________________________ # Access to the 'environ' external variable -from rpython.translator.tool.cbuild import ExternalCompilationInfo - if sys.platform.startswith('darwin'): CCHARPPP = rffi.CArrayPtr(rffi.CCHARPP) _os_NSGetEnviron = rffi.llexternal( @@ -146,16 +69,21 @@ ) def os_get_environ(): return _os_NSGetEnviron()[0] -elif sys.platform.startswith('win'): +elif _WIN32: + eci = ExternalCompilationInfo(includes=['stdlib.h']) + CWCHARPP = lltype.Ptr(lltype.Array(rffi.CWCHARP, hints={'nolength': True})) + os_get_environ, _os_set_environ = rffi.CExternVariable( - rffi.CCHARPP, - '_environ', - ExternalCompilationInfo(includes=['stdlib.h'])) + rffi.CCHARPP, '_environ', eci) + get__wenviron, _set__wenviron = rffi.CExternVariable( + CWCHARPP, '_wenviron', eci, c_type='wchar_t **') else: os_get_environ, _os_set_environ = rffi.CExternVariable( rffi.CCHARPP, 'environ', ExternalCompilationInfo()) # ____________________________________________________________ +# +# Lower-level interface: dummy placeholders and external registations def r_envkeys(): just_a_placeholder @@ -181,18 +109,109 @@ def r_envitems(): just_a_placeholder -def envitems_llimpl(): - environ = os_get_environ() - result = [] - i = 0 - while environ[i]: - name_value = rffi.charp2str(environ[i]) - p = name_value.find('=') - if p >= 0: - result.append((name_value[:p], name_value[p+1:])) - i += 1 - return result +def r_getenv(name): + just_a_placeholder # should return None if name not found + +def r_putenv(name, value): + just_a_placeholder + +os_getenv = rffi.llexternal('getenv', [rffi.CCHARP], rffi.CCHARP, + threadsafe=False) +os_putenv = rffi.llexternal('putenv', [rffi.CCHARP], rffi.INT) +if _WIN32: + _wgetenv = rffi.llexternal('_wgetenv', [rffi.CWCHARP], rffi.CWCHARP, + compilation_info=eci, threadsafe=False) + _wputenv = rffi.llexternal('_wputenv', [rffi.CWCHARP], rffi.INT, + compilation_info=eci) + +class EnvKeepalive: + pass +envkeepalive = EnvKeepalive() +envkeepalive.byname = {} +envkeepalive.bywname = {} + +def make_env_impls(win32=False): + if not win32: + traits = StringTraits() + get_environ, getenv, putenv = os_get_environ, os_getenv, os_putenv + byname, eq = envkeepalive.byname, '=' + def last_error(msg): + from rpython.rlib import rposix + raise OSError(rposix.get_errno(), msg) + else: + traits = UnicodeTraits() + get_environ, getenv, putenv = get__wenviron, _wgetenv, _wputenv + byname, eq = envkeepalive.bywname, u'=' + from rpython.rlib.rwin32 import lastWindowsError as last_error + + def envitems_llimpl(): + environ = get_environ() + result = [] + i = 0 + while environ[i]: + name_value = traits.charp2str(environ[i]) + p = name_value.find(eq) + if p >= 0: + result.append((name_value[:p], name_value[p+1:])) + i += 1 + return result + + def getenv_llimpl(name): + with traits.scoped_str2charp(name) as l_name: + l_result = getenv(l_name) + return traits.charp2str(l_result) if l_result else None + + def putenv_llimpl(name, value): + l_string = traits.str2charp(name + eq + value) + error = rffi.cast(lltype.Signed, putenv(l_string)) + if error: + traits.free_charp(l_string) + last_error("putenv failed") + # keep 'l_string' alive - we know that the C library needs it + # until the next call to putenv() with the same 'name'. + l_oldstring = byname.get(name, lltype.nullptr(traits.CCHARP.TO)) + byname[name] = l_string + if l_oldstring: + traits.free_charp(l_oldstring) + + return envitems_llimpl, getenv_llimpl, putenv_llimpl + +envitems_llimpl, getenv_llimpl, putenv_llimpl = make_env_impls() register_external(r_envitems, [], [(str0, str0)], export_name='ll_os.ll_os_envitems', llimpl=envitems_llimpl) +register_external(r_getenv, [str0], + annmodel.SomeString(can_be_None=True, no_nul=True), + export_name='ll_os.ll_os_getenv', + llimpl=getenv_llimpl) +register_external(r_putenv, [str0, str0], annmodel.s_None, + export_name='ll_os.ll_os_putenv', + llimpl=putenv_llimpl) + +# ____________________________________________________________ + +def r_unsetenv(name): + # default implementation for platforms without a real unsetenv() + r_putenv(name, '') + +if hasattr(__import__(os.name), 'unsetenv'): + os_unsetenv = rffi.llexternal('unsetenv', [rffi.CCHARP], rffi.INT) + + def unsetenv_llimpl(name): + with rffi.scoped_str2charp(name) as l_name: + error = rffi.cast(lltype.Signed, os_unsetenv(l_name)) + if error: + from rpython.rlib import rposix + raise OSError(rposix.get_errno(), "os_unsetenv failed") + try: + l_oldstring = envkeepalive.byname[name] + except KeyError: + pass + else: + del envkeepalive.byname[name] + rffi.free_charp(l_oldstring) + + register_external(r_unsetenv, [str0], annmodel.s_None, + export_name='ll_os.ll_os_unsetenv', + llimpl=unsetenv_llimpl) From noreply at buildbot.pypy.org Sat Apr 20 00:15:48 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Sat, 20 Apr 2013 00:15:48 +0200 (CEST) Subject: [pypy-commit] pypy default: add wenviron functions to rwin32 Message-ID: <20130419221548.EB23D1C31E6@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: Changeset: r63513:1407219a3903 Date: 2013-04-19 15:13 -0700 http://bitbucket.org/pypy/pypy/changeset/1407219a3903/ Log: add wenviron functions to rwin32 diff --git a/rpython/rlib/rwin32.py b/rpython/rlib/rwin32.py --- a/rpython/rlib/rwin32.py +++ b/rpython/rlib/rwin32.py @@ -5,6 +5,7 @@ import os import errno +from rpython.rtyper.module.ll_os_environ import make_env_impls from rpython.rtyper.tool import rffi_platform from rpython.tool.udir import udir from rpython.translator.tool.cbuild import ExternalCompilationInfo @@ -390,3 +391,5 @@ raise lastWindowsError('os_kill failed to terminate process') finally: CloseHandle(handle) + + _wenviron_items, _wgetenv, _wputenv = make_env_impls(win32=True) diff --git a/rpython/rlib/test/test_rwin32.py b/rpython/rlib/test/test_rwin32.py --- a/rpython/rlib/test/test_rwin32.py +++ b/rpython/rlib/test/test_rwin32.py @@ -1,3 +1,4 @@ +# encoding: utf-8 import os, py if os.name != 'nt': py.test.skip('tests for win32 only') @@ -47,3 +48,13 @@ rwin32.CloseHandle(handle) assert proc.wait() == signal.SIGTERM + at py.test.mark.dont_track_allocations('putenv intentionally keeps strings alive') +def test_wenviron(): + name, value = u'PYPY_TEST_日本', u'foobar日本' + rwin32._wputenv(name, value) + assert rwin32._wgetenv(name) == value + env = dict(rwin32._wenviron_items()) + assert env[name] == value + for key, value in env.iteritems(): + assert type(key) is unicode + assert type(value) is unicode From noreply at buildbot.pypy.org Sat Apr 20 00:15:50 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Sat, 20 Apr 2013 00:15:50 +0200 (CEST) Subject: [pypy-commit] pypy py3k: merge default Message-ID: <20130419221550.92F3B1C31E8@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63514:af2904581ca4 Date: 2013-04-19 15:14 -0700 http://bitbucket.org/pypy/pypy/changeset/af2904581ca4/ Log: merge default diff --git a/pypy/doc/arm.rst b/pypy/doc/arm.rst --- a/pypy/doc/arm.rst +++ b/pypy/doc/arm.rst @@ -153,7 +153,7 @@ :: - pypy /rpython/bin/rpython -Ojit --platform=arm --gcrootfinder=shadowstack --jit-backend=armv7 targetpypystandalone.py + pypy /rpython/bin/rpython -Ojit --platform=arm --gcrootfinder=shadowstack --jit-backend=arm targetpypystandalone.py The gcrootfinder option is needed to work around `issue 1377`_ and the jit-backend works around `issue 1376`_ diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -43,11 +43,11 @@ Rudimentary support for bytearray in RPython .. branch: refactor-call_release_gil -Fix a bug which casused cffi to return the wrong result when calling a C +Fix a bug which caused cffi to return the wrong result when calling a C function which calls a Python callback which forces the frames .. branch: virtual-raw-mallocs -JIT optimizations which makes cffi calls even faster, by removing the need to +JIT optimizations which make cffi calls even faster, by removing the need to allocate a temporary buffer where to store the arguments. .. branch: improve-docs-2 diff --git a/rpython/annotator/model.py b/rpython/annotator/model.py --- a/rpython/annotator/model.py +++ b/rpython/annotator/model.py @@ -527,6 +527,7 @@ s_Int = SomeInteger() s_ImpossibleValue = SomeImpossibleValue() s_Str0 = SomeString(no_nul=True) +s_Unicode0 = SomeUnicodeString(no_nul=True) # ____________________________________________________________ diff --git a/rpython/config/translationoption.py b/rpython/config/translationoption.py --- a/rpython/config/translationoption.py +++ b/rpython/config/translationoption.py @@ -115,7 +115,7 @@ ("translation.gcrootfinder", DEFL_ROOTFINDER_WITHJIT), ("translation.list_comprehension_operations", True)]), ChoiceOption("jit_backend", "choose the backend for the JIT", - ["auto", "x86", "x86-without-sse2", 'armv7', 'armv7hf', 'armv6hf'], + ["auto", "x86", "x86-without-sse2", 'arm'], default="auto", cmdline="--jit-backend"), ChoiceOption("jit_profiler", "integrate profiler support into the JIT", ["off", "oprofile"], diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -25,7 +25,6 @@ from rpython.rlib.rarithmetic import r_uint from rpython.rtyper.annlowlevel import llhelper, cast_instance_to_gcref from rpython.rtyper.lltypesystem import lltype, rffi -from rpython.jit.backend.arm.detect import detect_hardfloat class AssemblerARM(ResOpAssembler): @@ -51,14 +50,13 @@ def setup_once(self): BaseAssembler.setup_once(self) - self.hf_abi = detect_hardfloat() def setup(self, looptoken): assert self.memcpy_addr != 0, 'setup_once() not called?' if we_are_translated(): self.debug = False self.current_clt = looptoken.compiled_loop_token - self.mc = InstrBuilder(self.cpu.arch_version) + self.mc = InstrBuilder(self.cpu.cpuinfo.arch_version) self.pending_guards = [] assert self.datablockwrapper is None allblocks = self.get_asmmemmgr_blocks(looptoken) @@ -82,7 +80,7 @@ if not self.cpu.propagate_exception_descr: return # not supported (for tests, or non-translated) # - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) self._store_and_reset_exception(mc, r.r0) ofs = self.cpu.get_ofs_of_frame_field('jf_guard_exc') # make sure ofs fits into a register @@ -167,7 +165,7 @@ # | my own retaddr | <-- sp # +-----------------------+ # - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) # save argument registers and return address mc.PUSH([reg.value for reg in r.argument_regs] + [r.ip.value, r.lr.value]) # stack is aligned here @@ -208,7 +206,7 @@ # write barriers. It must save all registers, and optionally # all vfp registers. It takes a single argument which is in r0. # It must keep stack alignment accordingly. - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) # exc0 = exc1 = None mc.PUSH([r.ip.value, r.lr.value]) # push two words to keep alignment @@ -251,8 +249,10 @@ else: self.wb_slowpath[withcards + 2 * withfloats] = rawstart - def _build_malloc_slowpath(self): - mc = InstrBuilder(self.cpu.arch_version) + def _build_malloc_slowpath(self, kind): + if kind != 'fixed': + return 0 + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) self._push_all_regs_to_jitframe(mc, [r.r0, r.r1], self.cpu.supports_floats) ofs = self.cpu.get_ofs_of_frame_field('jf_gcmap') # store the gc pattern @@ -289,9 +289,7 @@ self.store_reg(mc, r.ip, r.fp, ofs) # return mc.POP([r.ip.value, r.pc.value]) - - rawstart = mc.materialize(self.cpu.asmmemmgr, []) - self.malloc_slowpath = rawstart + return mc.materialize(self.cpu.asmmemmgr, []) def _reload_frame_if_necessary(self, mc): gcrootmap = self.cpu.gc_ll_descr.gcrootmap @@ -364,7 +362,7 @@ self.load_reg(mc, vfpr, r.fp, ofs) def _build_failure_recovery(self, exc, withfloats=False): - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) self._push_all_regs_to_jitframe(mc, [], withfloats) if exc: @@ -647,7 +645,7 @@ expected_size=expected_size) def _patch_frame_depth(self, adr, allocated_depth): - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) mc.gen_load_int(r.lr.value, allocated_depth) mc.copy_to_raw_memory(adr) @@ -723,7 +721,7 @@ # f) store the address of the new jitframe in the shadowstack # c) set the gcmap field to 0 in the new jitframe # g) restore registers and return - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) self._push_all_regs_to_jitframe(mc, [], self.cpu.supports_floats) # this is the gcmap stored by push_gcmap(mov=True) in _check_stack_frame # and the expected_size pushed in _check_stack_frame @@ -783,7 +781,7 @@ self.target_tokens_currently_compiling = None def _patch_stackadjust(self, adr, allocated_depth): - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) mc.gen_load_int(r.lr.value, allocated_depth) mc.copy_to_raw_memory(adr) @@ -823,7 +821,7 @@ # patch the guard jumpt to the stub # overwrite the generate NOP with a B_offs to the pos of the # stub - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) mc.B_offs(relative_offset, c.get_opposite_of(tok.fcond)) mc.copy_to_raw_memory(guard_pos) else: @@ -902,7 +900,7 @@ self.mc.ASR_ri(resloc.value, resloc.value, 16) def patch_trace(self, faildescr, looptoken, bridge_addr, regalloc): - b = InstrBuilder(self.cpu.arch_version) + b = InstrBuilder(self.cpu.cpuinfo.arch_version) patch_addr = faildescr._arm_failure_recovery_block assert patch_addr != 0 b.B(bridge_addr) diff --git a/rpython/jit/backend/arm/detect.py b/rpython/jit/backend/arm/detect.py --- a/rpython/jit/backend/arm/detect.py +++ b/rpython/jit/backend/arm/detect.py @@ -1,7 +1,10 @@ +import os + from rpython.translator.tool.cbuild import ExternalCompilationInfo +from rpython.rtyper.tool import rffi_platform from rpython.rlib.clibffi import FFI_DEFAULT_ABI, FFI_SYSV, FFI_VFP -from rpython.rtyper.tool import rffi_platform from rpython.translator.platform import CompilationError +from rpython.rlib.debug import debug_print, debug_start, debug_stop eci = ExternalCompilationInfo( post_include_bits=[""" @@ -26,3 +29,37 @@ return True except CompilationError: return False + + +def detect_arch_version(filename="/proc/cpuinfo"): + fd = os.open(filename, os.O_RDONLY, 0644) + n = 0 + debug_start("jit-backend-arch") + try: + buf = os.read(fd, 2048) + if not buf: + debug_print("Could not detect ARM architecture " + "version, assuming", "ARMv%d" % n) + n = 6 # we asume ARMv6 as base case + finally: + os.close(fd) + # "Processor : ARMv%d-compatible processor rev 7 (v6l)" + i = buf.find('ARMv') + if i == -1: + n = 6 + debug_print("Could not detect architecture version, " + "falling back to", "ARMv%d" % n) + else: + n = int(buf[i + 4]) + + if n < 6: + raise ValueError("Unsupported ARM architecture version") + + debug_print("Detected", "ARMv%d" % n) + + if n > 7: + n = 7 + debug_print("Architecture version not explicitly supported, " + "falling back to", "ARMv%d" % n) + debug_stop("jit-backend-arch") + return n diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -354,7 +354,7 @@ # whether to worry about a CALL that can collect; this # is always true except in call_release_gil can_collect=True): - if self.hf_abi: + if self.cpu.cpuinfo.hf_abi: stack_args, adr = self._setup_call_hf(adr, arglocs, fcond, resloc, result_info) else: @@ -382,7 +382,7 @@ # ensure the result is wellformed and stored in the correct location if resloc is not None: - if resloc.is_vfp_reg() and not self.hf_abi: + if resloc.is_vfp_reg() and not self.cpu.cpuinfo.hf_abi: # move result to the allocated register self.mov_to_vfp_loc(r.r0, r.r1, resloc) elif resloc.is_reg() and result_info != (-1, -1): @@ -1230,7 +1230,7 @@ baseofs = self.cpu.get_baseofs_of_frame_field() newlooptoken.compiled_loop_token.update_frame_info( oldlooptoken.compiled_loop_token, baseofs) - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) mc.B(target) mc.copy_to_raw_memory(oldadr) diff --git a/rpython/jit/backend/arm/runner.py b/rpython/jit/backend/arm/runner.py --- a/rpython/jit/backend/arm/runner.py +++ b/rpython/jit/backend/arm/runner.py @@ -7,9 +7,14 @@ from rpython.rlib.jit_hooks import LOOP_RUN_CONTAINER from rpython.rtyper.lltypesystem import lltype, llmemory from rpython.jit.backend.arm.detect import detect_hardfloat +from rpython.jit.backend.arm.detect import detect_arch_version jitframe.STATICSIZE = JITFRAME_FIXED_SIZE +class CPUInfo(object): + hf_abi = False + arch_version = 6 + class AbstractARMCPU(AbstractLLCPU): IS_64_BIT = False @@ -25,13 +30,11 @@ float_regs = VFPRegisterManager.all_regs frame_reg = fp - hf_abi = False # use hard float abi flag - arch_version = 7 - def __init__(self, rtyper, stats, opts=None, translate_support_code=False, gcdescr=None): AbstractLLCPU.__init__(self, rtyper, stats, opts, translate_support_code, gcdescr) + self.cpuinfo = CPUInfo() def set_debug(self, flag): return self.assembler.set_debug(flag) @@ -46,6 +49,8 @@ self.assembler = AssemblerARM(self, self.translate_support_code) def setup_once(self): + self.cpuinfo.arch_version = detect_arch_version() + self.cpuinfo.hf_abi = detect_hardfloat() self.assembler.setup_once() def finish_once(self): @@ -89,7 +94,7 @@ from rpython.jit.backend.arm.codebuilder import InstrBuilder for jmp, tgt in looptoken.compiled_loop_token.invalidate_positions: - mc = InstrBuilder(self.arch_version) + mc = InstrBuilder(self.cpuinfo.arch_version) mc.B_offs(tgt) mc.copy_to_raw_memory(jmp) # positions invalidated @@ -113,10 +118,5 @@ class CPU_ARM(AbstractARMCPU): - """ARM v7""" - backend_name = "armv7" - -class CPU_ARMv6(AbstractARMCPU): - """ ARM v6, uses hardfp ABI, requires vfp""" - arch_version = 6 - backend_name = "armv6" + """ARM""" + backend_name = "arm" diff --git a/rpython/jit/backend/arm/test/test_detect.py b/rpython/jit/backend/arm/test/test_detect.py new file mode 100644 --- /dev/null +++ b/rpython/jit/backend/arm/test/test_detect.py @@ -0,0 +1,48 @@ +import py +from rpython.tool.udir import udir +from rpython.jit.backend.arm.detect import detect_arch_version + +cpuinfo = "Processor : ARMv%d-compatible processor rev 7 (v6l)""" +cpuinfo2 = """processor : 0 +vendor_id : GenuineIntel +cpu family : 6 +model : 23 +model name : Intel(R) Core(TM)2 Duo CPU E8400 @ 3.00GHz +stepping : 10 +microcode : 0xa07 +cpu MHz : 2997.000 +cache size : 6144 KB +physical id : 0 +siblings : 2 +core id : 0 +cpu cores : 2 +apicid : 0 +initial apicid : 0 +fpu : yes +fpu_exception : yes +cpuid level : 13 +wp : yes +flags : fpu vme ... +bogomips : 5993.08 +clflush size : 64 +cache_alignment : 64 +address sizes : 36 bits physical, 48 bits virtual +power management: +""" + +def write_cpuinfo(info): + filepath = udir.join('get_arch_version') + filepath.write(info) + return str(filepath) + + +def test_detect_arch_version(): + # currently supported cases + for i in (6, 7, ): + filepath = write_cpuinfo(cpuinfo % i) + assert detect_arch_version(filepath) == i + # unsupported cases + assert detect_arch_version(write_cpuinfo(cpuinfo % 8)) == 7 + py.test.raises(ValueError, + 'detect_arch_version(write_cpuinfo(cpuinfo % 5))') + assert detect_arch_version(write_cpuinfo(cpuinfo2)) == 6 diff --git a/rpython/jit/backend/arm/test/test_runner.py b/rpython/jit/backend/arm/test/test_runner.py --- a/rpython/jit/backend/arm/test/test_runner.py +++ b/rpython/jit/backend/arm/test/test_runner.py @@ -10,6 +10,7 @@ from rpython.rtyper.annlowlevel import llhelper from rpython.jit.codewriter.effectinfo import EffectInfo from rpython.jit.metainterp.history import JitCellToken, TargetToken +from rpython.jit.backend.arm.detect import detect_arch_version CPU = getcpuclass() @@ -27,7 +28,8 @@ bridge_loop_instructions = ['ldr', 'mov', 'nop', 'cmp', 'bge', 'push', 'mov', 'mov', 'push', 'mov', 'mov', 'blx', 'mov', 'mov', 'bx'] - if CPU.backend_name.startswith('armv7'): + arch_version = detect_arch_version() + if arch_version == 7: bridge_loop_instructions = ['ldr', 'mov', 'nop', 'cmp', 'bge', 'push', 'mov', 'mov', 'push', 'mov', 'mov', 'blx', 'mov', 'mov', 'bx'] diff --git a/rpython/jit/backend/detect_cpu.py b/rpython/jit/backend/detect_cpu.py --- a/rpython/jit/backend/detect_cpu.py +++ b/rpython/jit/backend/detect_cpu.py @@ -33,8 +33,8 @@ 'x86_64': 'x86', 'amd64': 'x86', # freebsd 'AMD64': 'x86', # win64 - 'armv7l': 'armv7', - 'armv6l': 'armv6', + 'armv7l': 'arm', + 'armv6l': 'arm', }[mach] except KeyError: return mach @@ -75,9 +75,7 @@ return "rpython.jit.backend.x86.runner", "CPU_X86_64" elif backend_name == 'cli': return "rpython.jit.backend.cli.runner", "CliCPU" - elif backend_name.startswith('armv6'): - return "rpython.jit.backend.arm.runner", "CPU_ARMv6" - elif backend_name.startswith('armv7'): + elif backend_name.startswith('arm'): return "rpython.jit.backend.arm.runner", "CPU_ARM" else: raise ProcessorAutodetectError, ( diff --git a/rpython/jit/backend/test/runner_test.py b/rpython/jit/backend/test/runner_test.py --- a/rpython/jit/backend/test/runner_test.py +++ b/rpython/jit/backend/test/runner_test.py @@ -1057,6 +1057,28 @@ r = self.cpu.bh_getinteriorfield_gc_i(a_box.getref_base(), 4, vsdescr) assert r == 4 + def test_array_of_structs_all_sizes(self): + # x86 has special support that can be used for sizes + # 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 16, 18, 20, 24, 32, 36, 40, 64, 72 + for length in range(1, 75): + ITEM = lltype.FixedSizeArray(lltype.Char, length) + a_box, A = self.alloc_array_of(ITEM, 5) + a = a_box.getref(lltype.Ptr(A)) + middle = length // 2 + a[3][middle] = chr(65 + length) + fdescr = self.cpu.interiorfielddescrof(A, 'item%d' % middle) + r = self.execute_operation(rop.GETINTERIORFIELD_GC, + [a_box, BoxInt(3)], + 'int', descr=fdescr) + r = r.getint() + assert r == 65 + length + self.execute_operation(rop.SETINTERIORFIELD_GC, + [a_box, BoxInt(2), BoxInt(r + 1)], + 'void', descr=fdescr) + r1 = self.cpu.bh_getinteriorfield_gc_i(a_box.getref_base(), 2, + fdescr) + assert r1 == r + 1 + def test_string_basic(self): s_box = self.alloc_string("hello\xfe") r = self.execute_operation(rop.STRLEN, [s_box], 'int') @@ -3913,3 +3935,19 @@ descr = self.cpu.get_latest_descr(frame) assert descr.identifier == 42 assert not self.cpu.grab_exc_value(frame) + + def test_setarrayitem_raw_short(self): + # setarrayitem_raw(140737353744432, 0, 30583, descr=) + A = rffi.CArray(rffi.SHORT) + arraydescr = self.cpu.arraydescrof(A) + a = lltype.malloc(A, 2, flavor='raw') + a[0] = rffi.cast(rffi.SHORT, 666) + a[1] = rffi.cast(rffi.SHORT, 777) + a_int = rffi.cast(lltype.Signed, a) + print 'a_int:', a_int + self.execute_operation(rop.SETARRAYITEM_RAW, + [ConstInt(a_int), ConstInt(0), ConstInt(-7654)], + 'void', descr=arraydescr) + assert rffi.cast(lltype.Signed, a[0]) == -7654 + assert rffi.cast(lltype.Signed, a[1]) == 777 + lltype.free(a, flavor='raw') diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -1537,22 +1537,50 @@ src_addr = addr_add(base_loc, ofs_loc, ofs.value, 0) self.load_from_mem(resloc, src_addr, size_loc, sign_loc) + def _imul_const_scaled(self, mc, targetreg, sourcereg, itemsize): + """Produce one operation to do roughly + targetreg = sourcereg * itemsize + except that the targetreg may still need shifting by 0,1,2,3. + """ + if (itemsize & 7) == 0: + shift = 3 + elif (itemsize & 3) == 0: + shift = 2 + elif (itemsize & 1) == 0: + shift = 1 + else: + shift = 0 + itemsize >>= shift + # + if _valid_addressing_size(itemsize - 1): + mc.LEA_ra(targetreg, (sourcereg, sourcereg, + _get_scale(itemsize - 1), 0)) + elif _valid_addressing_size(itemsize): + mc.LEA_ra(targetreg, (rx86.NO_BASE_REGISTER, sourcereg, + _get_scale(itemsize), 0)) + else: + mc.IMUL_rri(targetreg, sourcereg, itemsize) + # + return shift + def _get_interiorfield_addr(self, temp_loc, index_loc, itemsize_loc, base_loc, ofs_loc): assert isinstance(itemsize_loc, ImmedLoc) + itemsize = itemsize_loc.value if isinstance(index_loc, ImmedLoc): - temp_loc = imm(index_loc.value * itemsize_loc.value) - elif _valid_addressing_size(itemsize_loc.value): - return AddressLoc(base_loc, index_loc, _get_scale(itemsize_loc.value), ofs_loc.value) + temp_loc = imm(index_loc.value * itemsize) + shift = 0 + elif _valid_addressing_size(itemsize): + temp_loc = index_loc + shift = _get_scale(itemsize) else: - # XXX should not use IMUL in more cases, it can use a clever LEA + assert isinstance(index_loc, RegLoc) assert isinstance(temp_loc, RegLoc) - assert isinstance(index_loc, RegLoc) assert not temp_loc.is_xmm - self.mc.IMUL_rri(temp_loc.value, index_loc.value, - itemsize_loc.value) + shift = self._imul_const_scaled(self.mc, temp_loc.value, + index_loc.value, itemsize) assert isinstance(ofs_loc, ImmedLoc) - return AddressLoc(base_loc, temp_loc, 0, ofs_loc.value) + return AddressLoc(base_loc, temp_loc, shift, ofs_loc.value) def genop_getinteriorfield_gc(self, op, arglocs, resloc): (base_loc, ofs_loc, itemsize_loc, fieldsize_loc, @@ -2415,11 +2443,12 @@ jmp_adr0 = self.mc.get_relative_pos() self.mc.MOV(eax, heap(nursery_free_adr)) - shift = size2shift(itemsize) - if shift < 0: - self.mc.IMUL_rri(edi.value, varsizeloc.value, itemsize) + if _valid_addressing_size(itemsize): + shift = _get_scale(itemsize) + else: + shift = self._imul_const_scaled(self.mc, edi.value, + varsizeloc.value, itemsize) varsizeloc = edi - shift = 0 # now varsizeloc is a register != eax. The size of # the variable part of the array is (varsizeloc << shift) assert arraydescr.basesize >= self.gc_minimal_size_in_nursery @@ -2523,13 +2552,5 @@ os.write(2, '[x86/asm] %s\n' % msg) raise NotImplementedError(msg) -def size2shift(size): - "Return a result 0..3 such that (1<= 0 and _findend(data, 'ARMv', p) > 0 + # ---------- Darwin ---------- sysctlbyname = rffi.llexternal('sysctlbyname', @@ -270,7 +279,7 @@ def best_nursery_size_for_L2cache(L2cache): # Heuristically, the best nursery size to choose is about half # of the L2 cache. - if L2cache > 1024 * 1024: # we don't want to have nursery estimated + if L2cache > 2 * 1024 * 1024: # we don't want to have nursery estimated # on L2 when L3 is present return L2cache // 2 else: diff --git a/rpython/memory/gc/minimark.py b/rpython/memory/gc/minimark.py --- a/rpython/memory/gc/minimark.py +++ b/rpython/memory/gc/minimark.py @@ -130,6 +130,7 @@ FORWARDSTUB = lltype.GcStruct('forwarding_stub', ('forw', llmemory.Address)) FORWARDSTUBPTR = lltype.Ptr(FORWARDSTUB) +NURSARRAY = lltype.Array(llmemory.Address) # ____________________________________________________________ @@ -263,7 +264,7 @@ self.nursery_top = NULL self.nursery_real_top = NULL self.debug_tiny_nursery = -1 - self.debug_rotating_nurseries = None + self.debug_rotating_nurseries = lltype.nullptr(NURSARRAY) self.extra_threshold = 0 # # The ArenaCollection() handles the nonmovable objects allocation. @@ -350,8 +351,6 @@ # hacking at the current nursery position in collect_and_reserve(). if newsize <= 0: newsize = env.estimate_best_nursery_size() - # 4*1024*1024 # fixed to 4MB by default - # (it was env.estimate_best_nursery_size()) if newsize <= 0: newsize = defaultsize if newsize < minsize: @@ -471,23 +470,32 @@ # and use them alternatively, while mprotect()ing the unused # ones to detect invalid access. debug_start("gc-debug") - self.debug_rotating_nurseries = [] - for i in range(22): + self.debug_rotating_nurseries = lltype.malloc( + NURSARRAY, 22, flavor='raw', track_allocation=False) + i = 0 + while i < 22: nurs = self._alloc_nursery() llarena.arena_protect(nurs, self._nursery_memory_size(), True) - self.debug_rotating_nurseries.append(nurs) + self.debug_rotating_nurseries[i] = nurs + i += 1 debug_print("allocated", len(self.debug_rotating_nurseries), "extra nurseries") debug_stop("gc-debug") def debug_rotate_nursery(self): - if self.debug_rotating_nurseries is not None: + if self.debug_rotating_nurseries: debug_start("gc-debug") oldnurs = self.nursery llarena.arena_protect(oldnurs, self._nursery_memory_size(), True) - self.debug_rotating_nurseries.append(oldnurs) # - newnurs = self.debug_rotating_nurseries.pop(0) + newnurs = self.debug_rotating_nurseries[0] + i = 0 + while i < len(self.debug_rotating_nurseries) - 1: + self.debug_rotating_nurseries[i] = ( + self.debug_rotating_nurseries[i + 1]) + i += 1 + self.debug_rotating_nurseries[i] = oldnurs + # llarena.arena_protect(newnurs, self._nursery_memory_size(), False) self.nursery = newnurs self.nursery_top = self.nursery + self.initial_cleanup diff --git a/rpython/memory/gc/test/test_env.py b/rpython/memory/gc/test/test_env.py --- a/rpython/memory/gc/test/test_env.py +++ b/rpython/memory/gc/test/test_env.py @@ -161,3 +161,23 @@ """) result = env.get_L2cache_linux2(str(filepath)) assert result == 3072 * 1024 + +def test_estimate_best_nursery_size_linux2_arm(): + filepath = udir.join('estimate_best_nursery_size_linux2') + filepath.write("""\ +Processor : ARMv6-compatible processor rev 7 (v6l) +# this is not actually from cpuinfo, but here for the test +cache size : 3072 KB +... +""") + result = env.get_L2cache_linux2(str(filepath)) + assert result == -1 + +def test__detect_arm(): + assert env._detect_arm_cpu("Processor : ARMv6-compatible processor rev 7 (v6l)") + assert not env._detect_arm_cpu("""\ +processor : 0 +vendor_id : GenuineIntel +cpu family : 6 +model : 37 +""") diff --git a/rpython/memory/gctransform/framework.py b/rpython/memory/gctransform/framework.py --- a/rpython/memory/gctransform/framework.py +++ b/rpython/memory/gctransform/framework.py @@ -619,6 +619,12 @@ func = getattr(graph, 'func', None) if func and getattr(func, '_gc_no_collect_', False): if self.collect_analyzer.analyze_direct_call(graph): + print '!'*79 + ca = CollectAnalyzer(self.translator) + ca.verbose = True + ca.analyze_direct_call(graph) + # ^^^ for the dump of which operation in which graph actually + # causes it to return True raise Exception("'no_collect' function can trigger collection:" " %s" % func) diff --git a/rpython/rlib/rwin32.py b/rpython/rlib/rwin32.py --- a/rpython/rlib/rwin32.py +++ b/rpython/rlib/rwin32.py @@ -5,6 +5,7 @@ import os import errno +from rpython.rtyper.module.ll_os_environ import make_env_impls from rpython.rtyper.tool import rffi_platform from rpython.tool.udir import udir from rpython.translator.tool.cbuild import ExternalCompilationInfo @@ -390,3 +391,5 @@ raise lastWindowsError('os_kill failed to terminate process') finally: CloseHandle(handle) + + _wenviron_items, _wgetenv, _wputenv = make_env_impls(win32=True) diff --git a/rpython/rlib/test/test_rwin32.py b/rpython/rlib/test/test_rwin32.py --- a/rpython/rlib/test/test_rwin32.py +++ b/rpython/rlib/test/test_rwin32.py @@ -1,3 +1,4 @@ +# encoding: utf-8 import os, py if os.name != 'nt': py.test.skip('tests for win32 only') @@ -47,3 +48,13 @@ rwin32.CloseHandle(handle) assert proc.wait() == signal.SIGTERM + at py.test.mark.dont_track_allocations('putenv intentionally keeps strings alive') +def test_wenviron(): + name, value = u'PYPY_TEST_日本', u'foobar日本' + rwin32._wputenv(name, value) + assert rwin32._wgetenv(name) == value + env = dict(rwin32._wenviron_items()) + assert env[name] == value + for key, value in env.iteritems(): + assert type(key) is unicode + assert type(value) is unicode diff --git a/rpython/rtyper/module/ll_os.py b/rpython/rtyper/module/ll_os.py --- a/rpython/rtyper/module/ll_os.py +++ b/rpython/rtyper/module/ll_os.py @@ -7,14 +7,15 @@ import os, sys, errno import py -from rpython.rtyper.module.support import OOSupport +from rpython.rtyper.module.support import ( + _WIN32, OOSupport, StringTraits, UnicodeTraits, underscore_on_windows) from rpython.tool.sourcetools import func_renamer from rpython.rlib.rarithmetic import r_longlong from rpython.rtyper.extfunc import ( BaseLazyRegistering, register_external) from rpython.rtyper.extfunc import registering, registering_if, extdef from rpython.annotator.model import ( - SomeInteger, SomeString, SomeTuple, SomeFloat, SomeUnicodeString) + SomeInteger, SomeString, SomeTuple, SomeFloat, s_Str0, s_Unicode0) from rpython.annotator.model import s_ImpossibleValue, s_None, s_Bool from rpython.rtyper.lltypesystem import rffi from rpython.rtyper.lltypesystem import lltype @@ -25,8 +26,8 @@ from rpython.rtyper.lltypesystem.rstr import STR from rpython.rlib.objectmodel import specialize -str0 = SomeString(no_nul=True) -unicode0 = SomeUnicodeString(no_nul=True) +str0 = s_Str0 +unicode0 = s_Unicode0 def monkeypatch_rposix(posixfunc, unicodefunc, signature): func_name = posixfunc.__name__ @@ -66,42 +67,6 @@ # Monkeypatch the function in rpython.rlib.rposix setattr(rposix, func_name, new_func) -class StringTraits: - str = str - str0 = str0 - CHAR = rffi.CHAR - CCHARP = rffi.CCHARP - charp2str = staticmethod(rffi.charp2str) - str2charp = staticmethod(rffi.str2charp) - free_charp = staticmethod(rffi.free_charp) - scoped_alloc_buffer = staticmethod(rffi.scoped_alloc_buffer) - - @staticmethod - def posix_function_name(name): - return underscore_on_windows + name - - @staticmethod - def ll_os_name(name): - return 'll_os.ll_os_' + name - -class UnicodeTraits: - str = unicode - str0 = unicode0 - CHAR = rffi.WCHAR_T - CCHARP = rffi.CWCHARP - charp2str = staticmethod(rffi.wcharp2unicode) - str2charp = staticmethod(rffi.unicode2wcharp) - free_charp = staticmethod(rffi.free_wcharp) - scoped_alloc_buffer = staticmethod(rffi.scoped_alloc_unicodebuffer) - - @staticmethod - def posix_function_name(name): - return underscore_on_windows + 'w' + name - - @staticmethod - def ll_os_name(name): - return 'll_os.ll_os_w' + name - def registering_str_unicode(posixfunc, condition=True): if not condition or posixfunc is None: return registering(None, condition=False) @@ -129,16 +94,6 @@ posix = __import__(os.name) -if sys.platform.startswith('win'): - _WIN32 = True -else: - _WIN32 = False - -if _WIN32: - underscore_on_windows = '_' -else: - underscore_on_windows = '' - includes = [] if not _WIN32: # XXX many of these includes are not portable at all diff --git a/rpython/rtyper/module/ll_os_environ.py b/rpython/rtyper/module/ll_os_environ.py --- a/rpython/rtyper/module/ll_os_environ.py +++ b/rpython/rtyper/module/ll_os_environ.py @@ -4,10 +4,10 @@ from rpython.rtyper.controllerentry import Controller from rpython.rtyper.extfunc import register_external from rpython.rtyper.lltypesystem import rffi, lltype -from rpython.rtyper.module import ll_os -from rpython.rlib import rposix +from rpython.rtyper.module.support import _WIN32, StringTraits, UnicodeTraits +from rpython.translator.tool.cbuild import ExternalCompilationInfo -str0 = ll_os.str0 +str0 = annmodel.s_Str0 # ____________________________________________________________ # @@ -59,85 +59,8 @@ return r_getenv # ____________________________________________________________ -# -# Lower-level interface: dummy placeholders and external registations - -def r_getenv(name): - just_a_placeholder # should return None if name not found - -os_getenv = rffi.llexternal('getenv', [rffi.CCHARP], rffi.CCHARP, - threadsafe=False) - -def getenv_llimpl(name): - with rffi.scoped_str2charp(name) as l_name: - l_result = os_getenv(l_name) - return rffi.charp2str(l_result) if l_result else None - -register_external(r_getenv, [str0], - annmodel.SomeString(can_be_None=True, no_nul=True), - export_name='ll_os.ll_os_getenv', - llimpl=getenv_llimpl) - -# ____________________________________________________________ - -def r_putenv(name, value): - just_a_placeholder - -class EnvKeepalive: - pass -envkeepalive = EnvKeepalive() -envkeepalive.byname = {} - -os_putenv = rffi.llexternal('putenv', [rffi.CCHARP], rffi.INT) - -def putenv_llimpl(name, value): - l_string = rffi.str2charp('%s=%s' % (name, value)) - error = rffi.cast(lltype.Signed, os_putenv(l_string)) - if error: - rffi.free_charp(l_string) - raise OSError(rposix.get_errno(), "os_putenv failed") - # keep 'l_string' alive - we know that the C library needs it - # until the next call to putenv() with the same 'name'. - l_oldstring = envkeepalive.byname.get(name, lltype.nullptr(rffi.CCHARP.TO)) - envkeepalive.byname[name] = l_string - if l_oldstring: - rffi.free_charp(l_oldstring) - -register_external(r_putenv, [str0, str0], annmodel.s_None, - export_name='ll_os.ll_os_putenv', - llimpl=putenv_llimpl) - -# ____________________________________________________________ - -def r_unsetenv(name): - # default implementation for platforms without a real unsetenv() - r_putenv(name, '') - -if hasattr(__import__(os.name), 'unsetenv'): - os_unsetenv = rffi.llexternal('unsetenv', [rffi.CCHARP], rffi.INT) - - def unsetenv_llimpl(name): - with rffi.scoped_str2charp(name) as l_name: - error = rffi.cast(lltype.Signed, os_unsetenv(l_name)) - if error: - raise OSError(rposix.get_errno(), "os_unsetenv failed") - try: - l_oldstring = envkeepalive.byname[name] - except KeyError: - pass - else: - del envkeepalive.byname[name] - rffi.free_charp(l_oldstring) - - register_external(r_unsetenv, [str0], annmodel.s_None, - export_name='ll_os.ll_os_unsetenv', - llimpl=unsetenv_llimpl) - -# ____________________________________________________________ # Access to the 'environ' external variable -from rpython.translator.tool.cbuild import ExternalCompilationInfo - if sys.platform.startswith('darwin'): CCHARPPP = rffi.CArrayPtr(rffi.CCHARPP) _os_NSGetEnviron = rffi.llexternal( @@ -146,16 +69,21 @@ ) def os_get_environ(): return _os_NSGetEnviron()[0] -elif sys.platform.startswith('win'): +elif _WIN32: + eci = ExternalCompilationInfo(includes=['stdlib.h']) + CWCHARPP = lltype.Ptr(lltype.Array(rffi.CWCHARP, hints={'nolength': True})) + os_get_environ, _os_set_environ = rffi.CExternVariable( - rffi.CCHARPP, - '_environ', - ExternalCompilationInfo(includes=['stdlib.h'])) + rffi.CCHARPP, '_environ', eci) + get__wenviron, _set__wenviron = rffi.CExternVariable( + CWCHARPP, '_wenviron', eci, c_type='wchar_t **') else: os_get_environ, _os_set_environ = rffi.CExternVariable( rffi.CCHARPP, 'environ', ExternalCompilationInfo()) # ____________________________________________________________ +# +# Lower-level interface: dummy placeholders and external registations def r_envkeys(): just_a_placeholder @@ -181,18 +109,109 @@ def r_envitems(): just_a_placeholder -def envitems_llimpl(): - environ = os_get_environ() - result = [] - i = 0 - while environ[i]: - name_value = rffi.charp2str(environ[i]) - p = name_value.find('=') - if p >= 0: - result.append((name_value[:p], name_value[p+1:])) - i += 1 - return result +def r_getenv(name): + just_a_placeholder # should return None if name not found + +def r_putenv(name, value): + just_a_placeholder + +os_getenv = rffi.llexternal('getenv', [rffi.CCHARP], rffi.CCHARP, + threadsafe=False) +os_putenv = rffi.llexternal('putenv', [rffi.CCHARP], rffi.INT) +if _WIN32: + _wgetenv = rffi.llexternal('_wgetenv', [rffi.CWCHARP], rffi.CWCHARP, + compilation_info=eci, threadsafe=False) + _wputenv = rffi.llexternal('_wputenv', [rffi.CWCHARP], rffi.INT, + compilation_info=eci) + +class EnvKeepalive: + pass +envkeepalive = EnvKeepalive() +envkeepalive.byname = {} +envkeepalive.bywname = {} + +def make_env_impls(win32=False): + if not win32: + traits = StringTraits() + get_environ, getenv, putenv = os_get_environ, os_getenv, os_putenv + byname, eq = envkeepalive.byname, '=' + def last_error(msg): + from rpython.rlib import rposix + raise OSError(rposix.get_errno(), msg) + else: + traits = UnicodeTraits() + get_environ, getenv, putenv = get__wenviron, _wgetenv, _wputenv + byname, eq = envkeepalive.bywname, u'=' + from rpython.rlib.rwin32 import lastWindowsError as last_error + + def envitems_llimpl(): + environ = get_environ() + result = [] + i = 0 + while environ[i]: + name_value = traits.charp2str(environ[i]) + p = name_value.find(eq) + if p >= 0: + result.append((name_value[:p], name_value[p+1:])) + i += 1 + return result + + def getenv_llimpl(name): + with traits.scoped_str2charp(name) as l_name: + l_result = getenv(l_name) + return traits.charp2str(l_result) if l_result else None + + def putenv_llimpl(name, value): + l_string = traits.str2charp(name + eq + value) + error = rffi.cast(lltype.Signed, putenv(l_string)) + if error: + traits.free_charp(l_string) + last_error("putenv failed") + # keep 'l_string' alive - we know that the C library needs it + # until the next call to putenv() with the same 'name'. + l_oldstring = byname.get(name, lltype.nullptr(traits.CCHARP.TO)) + byname[name] = l_string + if l_oldstring: + traits.free_charp(l_oldstring) + + return envitems_llimpl, getenv_llimpl, putenv_llimpl + +envitems_llimpl, getenv_llimpl, putenv_llimpl = make_env_impls() register_external(r_envitems, [], [(str0, str0)], export_name='ll_os.ll_os_envitems', llimpl=envitems_llimpl) +register_external(r_getenv, [str0], + annmodel.SomeString(can_be_None=True, no_nul=True), + export_name='ll_os.ll_os_getenv', + llimpl=getenv_llimpl) +register_external(r_putenv, [str0, str0], annmodel.s_None, + export_name='ll_os.ll_os_putenv', + llimpl=putenv_llimpl) + +# ____________________________________________________________ + +def r_unsetenv(name): + # default implementation for platforms without a real unsetenv() + r_putenv(name, '') + +if hasattr(__import__(os.name), 'unsetenv'): + os_unsetenv = rffi.llexternal('unsetenv', [rffi.CCHARP], rffi.INT) + + def unsetenv_llimpl(name): + with rffi.scoped_str2charp(name) as l_name: + error = rffi.cast(lltype.Signed, os_unsetenv(l_name)) + if error: + from rpython.rlib import rposix + raise OSError(rposix.get_errno(), "os_unsetenv failed") + try: + l_oldstring = envkeepalive.byname[name] + except KeyError: + pass + else: + del envkeepalive.byname[name] + rffi.free_charp(l_oldstring) + + register_external(r_unsetenv, [str0], annmodel.s_None, + export_name='ll_os.ll_os_unsetenv', + llimpl=unsetenv_llimpl) diff --git a/rpython/rtyper/module/support.py b/rpython/rtyper/module/support.py --- a/rpython/rtyper/module/support.py +++ b/rpython/rtyper/module/support.py @@ -1,6 +1,12 @@ -from rpython.rtyper.lltypesystem import lltype +import os +import sys + +from rpython.annotator import model as annmodel +from rpython.rtyper.lltypesystem import lltype, rffi from rpython.rtyper.ootypesystem import ootype -import os + +_WIN32 = sys.platform.startswith('win') +underscore_on_windows = '_' if _WIN32 else '' # utility conversion functions class LLSupport: @@ -64,6 +70,45 @@ from_rstr_nonnull = staticmethod(from_rstr_nonnull) +class StringTraits: + str = str + str0 = annmodel.s_Str0 + CHAR = rffi.CHAR + CCHARP = rffi.CCHARP + charp2str = staticmethod(rffi.charp2str) + scoped_str2charp = staticmethod(rffi.scoped_str2charp) + str2charp = staticmethod(rffi.str2charp) + free_charp = staticmethod(rffi.free_charp) + scoped_alloc_buffer = staticmethod(rffi.scoped_alloc_buffer) + + @staticmethod + def posix_function_name(name): + return underscore_on_windows + name + + @staticmethod + def ll_os_name(name): + return 'll_os.ll_os_' + name + +class UnicodeTraits: + str = unicode + str0 = annmodel.s_Unicode0 + CHAR = rffi.WCHAR_T + CCHARP = rffi.CWCHARP + charp2str = staticmethod(rffi.wcharp2unicode) + str2charp = staticmethod(rffi.unicode2wcharp) + scoped_str2charp = staticmethod(rffi.scoped_unicode2wcharp) + free_charp = staticmethod(rffi.free_wcharp) + scoped_alloc_buffer = staticmethod(rffi.scoped_alloc_unicodebuffer) + + @staticmethod + def posix_function_name(name): + return underscore_on_windows + 'w' + name + + @staticmethod + def ll_os_name(name): + return 'll_os.ll_os_w' + name + + def ll_strcpy(dst_s, src_s, n): dstchars = dst_s.chars srcchars = src_s.chars @@ -78,5 +123,3 @@ while i < n: dstchars[i] = srcchars[i] i += 1 - - diff --git a/rpython/translator/backendopt/graphanalyze.py b/rpython/translator/backendopt/graphanalyze.py --- a/rpython/translator/backendopt/graphanalyze.py +++ b/rpython/translator/backendopt/graphanalyze.py @@ -80,21 +80,21 @@ if graph is None: x = self.analyze_external_call(op, seen) if self.verbose and x: - print '\tanalyze_external_call %s: %r' % (op, x) + self.dump_info('analyze_external_call %s: %r' % (op, x)) return x x = self.analyze_direct_call(graph, seen) if self.verbose and x: - print '\tanalyze_direct_call(%s): %r' % (graph, x) + self.dump_info('analyze_direct_call(%s): %r' % (graph, x)) return x elif op.opname == "indirect_call": graphs = op.args[-1].value if graphs is None: if self.verbose: - print '\t%s to unknown' % (op,) + self.dump_info('%s to unknown' % (op,)) return self.top_result() x = self.analyze_indirect_call(graphs, seen) if self.verbose and x: - print '\tanalyze_indirect_call(%s): %r' % (graphs, x) + self.dump_info('analyze_indirect_call(%s): %r' % (graphs, x)) return x elif op.opname == "oosend": name = op.args[0].value @@ -106,9 +106,12 @@ return self.analyze_oosend(TYPE, name, seen) x = self.analyze_simple_operation(op, graphinfo) if self.verbose and x: - print '\t%s: %r' % (op, x) + self.dump_info('%s: %r' % (op, x)) return x + def dump_info(self, info): + print '[%s] %s' % (self.__class__.__name__, info) + def analyze_direct_call(self, graph, seen=None): if seen is None: seen = DependencyTracker(self) From noreply at buildbot.pypy.org Sat Apr 20 00:17:53 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Sat, 20 Apr 2013 00:17:53 +0200 (CEST) Subject: [pypy-commit] pypy py3k: use wide environ APIs on windows Message-ID: <20130419221753.3A5391C31E5@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63515:60f1685169d9 Date: 2013-04-19 15:15 -0700 http://bitbucket.org/pypy/pypy/changeset/60f1685169d9/ Log: use wide environ APIs on windows diff --git a/pypy/module/posix/interp_posix.py b/pypy/module/posix/interp_posix.py --- a/pypy/module/posix/interp_posix.py +++ b/pypy/module/posix/interp_posix.py @@ -12,7 +12,7 @@ _WIN32 = sys.platform == 'win32' if _WIN32: - from rpython.rlib.rwin32 import _MAX_ENV + from rpython.rlib import rwin32 c_int = "c_int" @@ -481,6 +481,7 @@ self.w_environ = space.newdict() self.random_context = rurandom.init_urandom() def startup(self, space): + space.call_method(self.w_environ, 'clear') _convertenviron(space, self.w_environ) def _freeze_(self): # don't capture the environment in the translated pypy @@ -493,29 +494,46 @@ def get(space): return space.fromcache(State) -def _convertenviron(space, w_env): - space.call_method(w_env, 'clear') - for key, value in os.environ.items(): - space.setitem(w_env, space.wrapbytes(key), space.wrapbytes(value)) +if _WIN32: + def _convertenviron(space, w_env): + # _wenviron must be initialized in this way if the program is + # started through main() instead of wmain() + rwin32._wgetenv(u"") + for key, value in rwin32._wenviron_items(): + space.setitem(w_env, space.wrap(key), space.wrap(value)) -def putenv(space, w_name, w_value): - """Change or add an environment variable.""" - if _WIN32 and len(name) > _MAX_ENV: - raise OperationError(space.w_ValueError, space.wrap( - "the environment variable is longer than %d bytes" % _MAX_ENV)) - try: - dispatch_filename_2(rposix.putenv)(space, w_name, w_value) - except OSError, e: - raise wrap_oserror(space, e) + @unwrap_spec(name=unicode, value=unicode) + def putenv(space, name, value): + """Change or add an environment variable.""" + # len includes space for '=' and a trailing NUL + if len(name) + len(value) + 2 > rwin32._MAX_ENV: + msg = ("the environment variable is longer than %d characters" % + rwin32._MAX_ENV) + raise OperationError(space.w_ValueError, space.wrap(msg)) + try: + rwin32._wputenv(name, value) + except OSError, e: + raise wrap_oserror(space, e) +else: + def _convertenviron(space, w_env): + for key, value in os.environ.items(): + space.setitem(w_env, space.wrapbytes(key), space.wrapbytes(value)) -def unsetenv(space, w_name): - """Delete an environment variable.""" - try: - dispatch_filename(rposix.unsetenv)(space, w_name) - except KeyError: - pass - except OSError, e: - raise wrap_oserror(space, e) + def putenv(space, w_name, w_value): + """Change or add an environment variable.""" + try: + dispatch_filename_2(rposix.putenv)(space, w_name, w_value) + except OSError, e: + raise wrap_oserror(space, e) + + def unsetenv(space, w_name): + """Delete an environment variable.""" + try: + dispatch_filename(rposix.unsetenv)(space, w_name) + except KeyError: + pass + except OSError, e: + raise wrap_oserror(space, e) @unwrap_spec(w_dirname=WrappedDefault(u".")) diff --git a/pypy/module/posix/test/test_posix2.py b/pypy/module/posix/test/test_posix2.py --- a/pypy/module/posix/test/test_posix2.py +++ b/pypy/module/posix/test/test_posix2.py @@ -938,12 +938,27 @@ cls.w_path = space.wrap(str(path)) def test_environ(self): - posix = self.posix + import sys + environ = self.posix.environ + item_type = str if sys.platform.startswith('win') else bytes + for k, v in environ.items(): + assert type(k) is item_type + assert type(v) is item_type + name = next(iter(environ)) + assert environ[name] is not None + del environ[name] + raises(KeyError, lambda: environ[name]) + + @py.test.mark.dont_track_allocations('putenv intentionally keeps strings alive') + def test_environ_nonascii(self): os = self.os - assert posix.environ[b'PATH'] - del posix.environ[b'PATH'] - def fn(): posix.environ[b'PATH'] - raises(KeyError, fn) + name, value = 'PYPY_TEST_日本', 'foobar日本' + os.environ[name] = value + assert os.environ[name] == value + assert os.getenv(name) == value + del os.environ[name] + assert os.environ.get(name) is None + assert os.getenv(name) is None if hasattr(__import__(os.name), "unsetenv"): def test_unsetenv_nonexisting(self): From noreply at buildbot.pypy.org Sat Apr 20 08:42:07 2013 From: noreply at buildbot.pypy.org (bivab) Date: Sat, 20 Apr 2013 08:42:07 +0200 (CEST) Subject: [pypy-commit] pypy default: move _valid_addressing_size and _get_scale to a shared location Message-ID: <20130420064207.216951C01E1@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63516:da11abc1cba6 Date: 2013-04-20 00:35 +0200 http://bitbucket.org/pypy/pypy/changeset/da11abc1cba6/ Log: move _valid_addressing_size and _get_scale to a shared location diff --git a/rpython/jit/backend/llsupport/regalloc.py b/rpython/jit/backend/llsupport/regalloc.py --- a/rpython/jit/backend/llsupport/regalloc.py +++ b/rpython/jit/backend/llsupport/regalloc.py @@ -740,6 +740,16 @@ op = Fake(None) return op.is_comparison() or op.is_ovf() +def valid_addressing_size(size): + return size == 1 or size == 2 or size == 4 or size == 8 + +def get_scale(size): + assert valid_addressing_size(size) + if size < 4: + return size - 1 # 1, 2 => 0, 1 + else: + return (size >> 2) + 1 # 4, 8 => 2, 3 + def not_implemented(msg): os.write(2, '[llsupport/regalloc] %s\n' % msg) diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -13,8 +13,9 @@ from rpython.rtyper.annlowlevel import llhelper, cast_instance_to_gcref from rpython.rlib.jit import AsmInfo from rpython.jit.backend.model import CompiledLoopToken -from rpython.jit.backend.x86.regalloc import (RegAlloc, get_ebp_ofs, _get_scale, - gpr_reg_mgr_cls, xmm_reg_mgr_cls, _valid_addressing_size) +from rpython.jit.backend.x86.regalloc import (RegAlloc, get_ebp_ofs, + gpr_reg_mgr_cls, xmm_reg_mgr_cls) +from rpython.jit.backend.llsupport.regalloc import (get_scale, valid_addressing_size) from rpython.jit.backend.x86.arch import (FRAME_FIXED_SIZE, WORD, IS_X86_64, JITFRAME_FIXED_SIZE, IS_X86_32, PASS_ON_MY_FRAME) @@ -1523,7 +1524,7 @@ base_loc, ofs_loc, size_loc, ofs, sign_loc = arglocs assert isinstance(ofs, ImmedLoc) assert isinstance(size_loc, ImmedLoc) - scale = _get_scale(size_loc.value) + scale = get_scale(size_loc.value) src_addr = addr_add(base_loc, ofs_loc, ofs.value, scale) self.load_from_mem(resloc, src_addr, size_loc, sign_loc) @@ -1552,12 +1553,12 @@ shift = 0 itemsize >>= shift # - if _valid_addressing_size(itemsize - 1): + if valid_addressing_size(itemsize - 1): mc.LEA_ra(targetreg, (sourcereg, sourcereg, - _get_scale(itemsize - 1), 0)) - elif _valid_addressing_size(itemsize): + get_scale(itemsize - 1), 0)) + elif valid_addressing_size(itemsize): mc.LEA_ra(targetreg, (rx86.NO_BASE_REGISTER, sourcereg, - _get_scale(itemsize), 0)) + get_scale(itemsize), 0)) else: mc.IMUL_rri(targetreg, sourcereg, itemsize) # @@ -1570,9 +1571,9 @@ if isinstance(index_loc, ImmedLoc): temp_loc = imm(index_loc.value * itemsize) shift = 0 - elif _valid_addressing_size(itemsize): + elif valid_addressing_size(itemsize): temp_loc = index_loc - shift = _get_scale(itemsize) + shift = get_scale(itemsize) else: assert isinstance(index_loc, RegLoc) assert isinstance(temp_loc, RegLoc) @@ -1610,7 +1611,7 @@ base_loc, ofs_loc, value_loc, size_loc, baseofs = arglocs assert isinstance(baseofs, ImmedLoc) assert isinstance(size_loc, ImmedLoc) - scale = _get_scale(size_loc.value) + scale = get_scale(size_loc.value) dest_addr = AddressLoc(base_loc, ofs_loc, scale, baseofs.value) self.save_into_mem(dest_addr, value_loc, size_loc) @@ -2443,8 +2444,8 @@ jmp_adr0 = self.mc.get_relative_pos() self.mc.MOV(eax, heap(nursery_free_adr)) - if _valid_addressing_size(itemsize): - shift = _get_scale(itemsize) + if valid_addressing_size(itemsize): + shift = get_scale(itemsize) else: shift = self._imul_const_scaled(self.mc, edi.value, varsizeloc.value, itemsize) diff --git a/rpython/jit/backend/x86/regalloc.py b/rpython/jit/backend/x86/regalloc.py --- a/rpython/jit/backend/x86/regalloc.py +++ b/rpython/jit/backend/x86/regalloc.py @@ -1380,16 +1380,6 @@ # i.e. the n'th word beyond the fixed frame size. return base_ofs + WORD * (position + JITFRAME_FIXED_SIZE) -def _valid_addressing_size(size): - return size == 1 or size == 2 or size == 4 or size == 8 - -def _get_scale(size): - assert _valid_addressing_size(size) - if size < 4: - return size - 1 # 1, 2 => 0, 1 - else: - return (size >> 2) + 1 # 4, 8 => 2, 3 - def not_implemented(msg): os.write(2, '[x86/regalloc] %s\n' % msg) raise NotImplementedError(msg) From noreply at buildbot.pypy.org Sat Apr 20 08:42:08 2013 From: noreply at buildbot.pypy.org (bivab) Date: Sat, 20 Apr 2013 08:42:08 +0200 (CEST) Subject: [pypy-commit] pypy default: implement malloc_cond_varsize, malloc_slowpath_varsize for the different types and enable can_inline_varsize_malloc on ARM Message-ID: <20130420064208.5ECAB1C1463@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63517:d6520ed985b4 Date: 2013-04-20 00:49 +0200 http://bitbucket.org/pypy/pypy/changeset/d6520ed985b4/ Log: implement malloc_cond_varsize, malloc_slowpath_varsize for the different types and enable can_inline_varsize_malloc on ARM diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -3,6 +3,7 @@ import os from rpython.jit.backend.arm import conditions as c, registers as r +from rpython.jit.backend.arm import shift from rpython.jit.backend.arm.arch import (WORD, DOUBLE_WORD, FUNC_ALIGN, JITFRAME_FIXED_SIZE) from rpython.jit.backend.arm.codebuilder import InstrBuilder, OverwritingBuilder @@ -12,8 +13,9 @@ CoreRegisterManager, check_imm_arg, VFPRegisterManager, operations as regalloc_operations, operations_with_guard as regalloc_operations_with_guard) -from rpython.jit.backend.llsupport import jitframe +from rpython.jit.backend.llsupport import jitframe, rewrite from rpython.jit.backend.llsupport.assembler import DEBUG_COUNTER, debug_bridge, BaseAssembler +from rpython.jit.backend.llsupport.regalloc import get_scale, valid_addressing_size from rpython.jit.backend.llsupport.asmmemmgr import MachineDataBlockWrapper from rpython.jit.backend.model import CompiledLoopToken from rpython.jit.codewriter.effectinfo import EffectInfo @@ -250,27 +252,59 @@ self.wb_slowpath[withcards + 2 * withfloats] = rawstart def _build_malloc_slowpath(self, kind): - if kind != 'fixed': - return 0 + """ While arriving on slowpath, we have a gcpattern on stack 0. + The arguments are passed in r0 and r10, as follows: + + kind == 'fixed': nursery_head in r0 and the size in r1 - r0. + + kind == 'str/unicode': length of the string to allocate in r0. + + kind == 'var': length to allocate in r1, tid in r0, + and itemsize on the stack. + + This function must preserve all registers apart from r0 and r1. + """ + assert kind in ['fixed', 'str', 'unicode', 'var'] mc = InstrBuilder(self.cpu.arch_version) + # self._push_all_regs_to_jitframe(mc, [r.r0, r.r1], self.cpu.supports_floats) + # + if kind == 'fixed': + addr = self.cpu.gc_ll_descr.get_malloc_slowpath_addr() + elif kind == 'str': + addr = self.cpu.gc_ll_descr.get_malloc_fn_addr('malloc_str') + elif kind == 'unicode': + addr = self.cpu.gc_ll_descr.get_malloc_fn_addr('malloc_unicode') + else: + addr = self.cpu.gc_ll_descr.get_malloc_slowpath_array_addr() + if kind == 'fixed': + # stack layout: [gcmap] + # At this point we know that the values we need to compute the size + # are stored in r0 and r1. + mc.SUB_rr(r.r0.value, r.r1.value, r.r0.value) # compute the size we want + + if hasattr(self.cpu.gc_ll_descr, 'passes_frame'): + mc.MOV_rr(r.r1.value, r.fp.value) + elif kind == 'str' or kind == 'unicode': + # stack layout: [gcmap] + mc.MOV_rr(r.r0.value, r.r1.value) + else: # var + # stack layout: [gcmap][itemsize]... + # tid is in r0 + # length is in r1 + mc.MOV_rr(r.r2.value, r.r1.value) + mc.MOV_rr(r.r1.value, r.r0.value) + mc.POP([r.r0.value]) # load itemsize + # store the gc pattern + mc.POP([r.r4.value]) ofs = self.cpu.get_ofs_of_frame_field('jf_gcmap') - # store the gc pattern - mc.POP([r.r2.value]) - self.store_reg(mc, r.r2, r.fp, ofs) + self.store_reg(mc, r.r4, r.fp, ofs) + # # We need to push two registers here because we are going to make a # call an therefore the stack needs to be 8-byte aligned mc.PUSH([r.ip.value, r.lr.value]) - # At this point we know that the values we need to compute the size - # are stored in r0 and r1. - mc.SUB_rr(r.r0.value, r.r1.value, r.r0.value) # compute the size we want - - if hasattr(self.cpu.gc_ll_descr, 'passes_frame'): - mc.MOV_rr(r.r1.value, r.fp.value) - - addr = self.cpu.gc_ll_descr.get_malloc_slowpath_addr() + # mc.BL(addr) - # # If the slowpath malloc failed, we raise a MemoryError that # always interrupts the current loop, as a "good enough" @@ -290,8 +324,9 @@ # return mc.POP([r.ip.value, r.pc.value]) + # rawstart = mc.materialize(self.cpu.asmmemmgr, []) - self.malloc_slowpath = rawstart + return rawstart def _reload_frame_if_necessary(self, mc): gcrootmap = self.cpu.gc_ll_descr.gcrootmap @@ -1170,21 +1205,17 @@ else: raise AssertionError('Trying to pop to an invalid location') - def malloc_cond(self, nursery_free_adr, nursery_top_adr, sizeloc, gcmap): - if sizeloc.is_imm(): # must be correctly aligned - assert sizeloc.value & (WORD-1) == 0 + def malloc_cond(self, nursery_free_adr, nursery_top_adr, size, gcmap): + assert size & (WORD-1) == 0 self.mc.gen_load_int(r.r0.value, nursery_free_adr) self.mc.LDR_ri(r.r0.value, r.r0.value) - if sizeloc.is_imm(): - if check_imm_arg(sizeloc.value): - self.mc.ADD_ri(r.r1.value, r.r0.value, sizeloc.value) - else: - self.mc.gen_load_int(r.r1.value, sizeloc.value) - self.mc.ADD_rr(r.r1.value, r.r0.value, r.r1.value) + if check_imm_arg(size): + self.mc.ADD_ri(r.r1.value, r.r0.value, size) else: - self.mc.ADD_rr(r.r1.value, r.r0.value, sizeloc.value) + self.mc.gen_load_int(r.r1.value, size) + self.mc.ADD_rr(r.r1.value, r.r0.value, r.r1.value) self.mc.gen_load_int(r.ip.value, nursery_top_adr) self.mc.LDR_ri(r.ip.value, r.ip.value) @@ -1205,6 +1236,128 @@ self.mc.gen_load_int(r.ip.value, nursery_free_adr) self.mc.STR_ri(r.r1.value, r.ip.value) + def malloc_cond_varsize_frame(self, nursery_free_adr, nursery_top_adr, + sizeloc, gcmap): + if sizeloc is r.r0: + self.mc.MOV_rr(r.r1.value, r.r0.value) + sizeloc = r.r1 + self.mc.gen_load_int(r.r0.value, nursery_free_adr) + self.mc.LDR_ri(r.r0.value, r.r0.value) + # + self.mc.ADD_rr(r.r1.value, r.r0.value, sizeloc.value) + # + self.mc.gen_load_int(r.ip.value, nursery_top_adr) + self.mc.LDR_ri(r.ip.value, r.ip.value) + + self.mc.CMP_rr(r.r1.value, r.ip.value) + # + self.push_gcmap(self.mc, gcmap, push=True, cond=c.HI) + + self.mc.BL(self.malloc_slowpath, c=c.HI) + + self.mc.gen_load_int(r.ip.value, nursery_free_adr) + self.mc.STR_ri(r.r1.value, r.ip.value) + + def malloc_cond_varsize(self, kind, nursery_free_adr, nursery_top_adr, + lengthloc, itemsize, maxlength, gcmap, + arraydescr): + from rpython.jit.backend.llsupport.descr import ArrayDescr + assert isinstance(arraydescr, ArrayDescr) + + # lengthloc is the length of the array, which we must not modify! + assert lengthloc is not r.r0 and lengthloc is not r.r1 + if lengthloc.is_reg(): + varsizeloc = lengthloc + else: + assert lengthloc.is_stack() + self.regalloc_mov(lengthloc, r.r1) + varsizeloc = r.r1 + # + if check_imm_arg(maxlength): + self.mc.CMP_ri(varsizeloc.value, maxlength) + else: + self.mc.gen_load_int(r.ip.value, maxlength) + self.mc.CMP_rr(varsizeloc.value, r.ip.value) + jmp_adr0 = self.mc.currpos() # jump to (large) + self.mc.BKPT() + # + self.mc.gen_load_int(r.r0.value, nursery_free_adr) + self.mc.LDR_ri(r.r0.value, r.r0.value) + + + if valid_addressing_size(itemsize): + shiftsize = get_scale(itemsize) + else: + shiftsize = self._mul_const_scaled(self.mc, r.lr, varsizeloc, + itemsize) + varsizeloc = r.lr + # now varsizeloc is a register != r0. The size of + # the variable part of the array is (varsizeloc << shiftsize) + assert arraydescr.basesize >= self.gc_minimal_size_in_nursery + constsize = arraydescr.basesize + self.gc_size_of_header + force_realignment = (itemsize % WORD) != 0 + if force_realignment: + constsize += WORD - 1 + self.mc.gen_load_int(r.ip.value, constsize) + # constsize + (varsizeloc << shiftsize) + self.mc.ADD_rr(r.r1.value, r.ip.value, varsizeloc.value, + imm=shiftsize, shifttype=shift.LSL) + self.mc.ADD_rr(r.r1.value, r.r1.value, r.r0.value) + if force_realignment: + self.mc.MVN_ri(r.ip.value, imm=(WORD - 1)) + self.mc.AND_rr(r.r1.value, r.r1.value, r.ip.value) + # now r1 contains the total size in bytes, rounded up to a multiple + # of WORD, plus nursery_free_adr + # + self.mc.gen_load_int(r.ip.value, nursery_top_adr) + self.mc.LDR_ri(r.ip.value, r.ip.value) + + self.mc.CMP_rr(r.r1.value, r.ip.value) + jmp_adr1 = self.mc.currpos() # jump to (after-call) + self.mc.BKPT() + # + # (large) + currpos = self.mc.currpos() + pmc = OverwritingBuilder(self.mc, jmp_adr0, WORD) + pmc.B_offs(currpos, c.GT) + # + # save the gcmap + self.push_gcmap(self.mc, gcmap, push=True) + # + if kind == rewrite.FLAG_ARRAY: + self.mc.gen_load_int(r.r0.value, arraydescr.tid) + self.regalloc_mov(lengthloc, r.r1) + self.regalloc_push(imm(itemsize)) + addr = self.malloc_slowpath_varsize + else: + if kind == rewrite.FLAG_STR: + addr = self.malloc_slowpath_str + else: + assert kind == rewrite.FLAG_UNICODE + addr = self.malloc_slowpath_unicode + self.regalloc_mov(lengthloc, r.r1) + self.mc.BL(addr) + # + jmp_location = self.mc.currpos() # jump to (done) + self.mc.BKPT() + # (after-call) + currpos = self.mc.currpos() + pmc = OverwritingBuilder(self.mc, jmp_adr1, WORD) + pmc.B_offs(currpos, c.LS) + # + # write down the tid, but not if it's the result of the CALL + self.mc.gen_load_int(r.ip.value, arraydescr.tid) + self.mc.STR_ri(r.ip.value, r.r0.value) + + # while we're at it, this line is not needed if we've done the CALL + self.mc.gen_load_int(r.ip.value, nursery_free_adr) + self.mc.STR_ri(r.r1.value, r.ip.value) + # (done) + # skip instructions after call + currpos = self.mc.currpos() + pmc = OverwritingBuilder(self.mc, jmp_location, WORD) + pmc.B_offs(currpos) + def push_gcmap(self, mc, gcmap, push=False, store=False, cond=c.AL): ptr = rffi.cast(lltype.Signed, gcmap) if push: @@ -1222,6 +1375,32 @@ mc.gen_load_int(r.ip.value, 0) self.store_reg(mc, r.ip, r.fp, ofs) + def _mul_const_scaled(self, mc, targetreg, sourcereg, itemsize): + """Produce one operation to do roughly + targetreg = sourcereg * itemsize + except that the targetreg may still need shifting by 0,1,2,3. + """ + if (itemsize & 7) == 0: + shiftsize = 3 + elif (itemsize & 3) == 0: + shiftsize = 2 + elif (itemsize & 1) == 0: + shiftsize = 1 + else: + shiftsize = 0 + itemsize >>= shiftsize + # + if valid_addressing_size(itemsize - 1): + self.mc.ADD_rr(targetreg.value, sourcereg.value, sourcereg.value, + imm=get_scale(itemsize - 1), shifttype=shift.LSL) + elif valid_addressing_size(itemsize): + self.mc.LSL_ri(targetreg.value, sourcereg.value, + get_scale(itemsize)) + else: + mc.gen_load_int(targetreg.value, itemsize.value) + mc.MUL(targetreg.value, sourcereg.value, targetreg.value) + # + return shiftsize def not_implemented(msg): os.write(2, '[ARM/asm] %s\n' % msg) diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -191,7 +191,7 @@ return fcond def _emit_guard(self, op, arglocs, fcond, save_exc, - is_guard_not_invalidated=False, + is_guard_not_invalidated=False, is_guard_not_forced=False): assert isinstance(save_exc, bool) assert isinstance(fcond, int) @@ -297,7 +297,7 @@ return self._emit_guard(op, locs, fcond, save_exc=False, is_guard_not_invalidated=True) - def emit_op_label(self, op, arglocs, regalloc, fcond): + def emit_op_label(self, op, arglocs, regalloc, fcond): self._check_frame_depth_debug(self.mc) return fcond @@ -1334,23 +1334,6 @@ self._alignment_check() return fcond - def emit_op_call_malloc_nursery(self, op, arglocs, regalloc, fcond): - # registers r0 and r1 are allocated for this call - assert len(arglocs) == 1 - sizeloc = arglocs[0] - gc_ll_descr = self.cpu.gc_ll_descr - gcmap = regalloc.get_gcmap([r.r0, r.r1]) - self.malloc_cond( - gc_ll_descr.get_nursery_free_addr(), - gc_ll_descr.get_nursery_top_addr(), - sizeloc, - gcmap - ) - self._alignment_check() - return fcond - emit_op_call_malloc_nursery_varsize_frame = emit_op_call_malloc_nursery - - def _alignment_check(self): if not self.debug: return @@ -1436,7 +1419,7 @@ self.mc.VCVT_f64_f32(r.vfp_ip.value, arg.value) self.mc.VMOV_rc(res.value, r.ip.value, r.vfp_ip.value) return fcond - + def emit_op_cast_singlefloat_to_float(self, op, arglocs, regalloc, fcond): arg, res = arglocs assert res.is_vfp_reg() diff --git a/rpython/jit/backend/arm/regalloc.py b/rpython/jit/backend/arm/regalloc.py --- a/rpython/jit/backend/arm/regalloc.py +++ b/rpython/jit/backend/arm/regalloc.py @@ -2,7 +2,8 @@ from rpython.rlib import rgc from rpython.rlib.debug import debug_print, debug_start, debug_stop from rpython.jit.backend.llsupport.regalloc import FrameManager, \ - RegisterManager, TempBox, compute_vars_longevity, BaseRegalloc + RegisterManager, TempBox, compute_vars_longevity, BaseRegalloc, \ + get_scale from rpython.jit.backend.arm import registers as r from rpython.jit.backend.arm import locations from rpython.jit.backend.arm.locations import imm, get_fp_offset @@ -1011,20 +1012,72 @@ self.rm.force_allocate_reg(op.result, selected_reg=r.r0) t = TempInt() self.rm.force_allocate_reg(t, selected_reg=r.r1) + + sizeloc = size_box.getint() + gc_ll_descr = self.cpu.gc_ll_descr + gcmap = self.get_gcmap([r.r0, r.r1]) self.possibly_free_var(t) - return [imm(size)] + self.assembler.malloc_cond( + gc_ll_descr.get_nursery_free_addr(), + gc_ll_descr.get_nursery_top_addr(), + sizeloc, + gcmap + ) + self.assembler._alignment_check() def prepare_op_call_malloc_nursery_varsize_frame(self, op, fcond): size_box = op.getarg(0) - assert isinstance(size_box, BoxInt) - + assert isinstance(size_box, BoxInt) # we cannot have a const here! + # sizeloc must be in a register, but we can free it now + # (we take care explicitly of conflicts with r0 or r1) + sizeloc = self.rm.make_sure_var_in_reg(size_box) + self.rm.possibly_free_var(size_box) + # self.rm.force_allocate_reg(op.result, selected_reg=r.r0) + # t = TempInt() self.rm.force_allocate_reg(t, selected_reg=r.r1) - argloc = self.make_sure_var_in_reg(size_box, - forbidden_vars=[op.result, t]) + # + gcmap = self.get_gcmap([r.r0, r.r1]) self.possibly_free_var(t) - return [argloc] + # + gc_ll_descr = self.assembler.cpu.gc_ll_descr + self.assembler.malloc_cond_varsize_frame( + gc_ll_descr.get_nursery_free_addr(), + gc_ll_descr.get_nursery_top_addr(), + sizeloc, + gcmap + ) + self.assembler._alignment_check() + + def prepare_op_call_malloc_nursery_varsize(self, op, fcond): + gc_ll_descr = self.assembler.cpu.gc_ll_descr + if not hasattr(gc_ll_descr, 'max_size_of_young_obj'): + raise Exception("unreachable code") + # for boehm, this function should never be called + arraydescr = op.getdescr() + length_box = op.getarg(2) + assert isinstance(length_box, BoxInt) # we cannot have a const here! + # the result will be in r0 + self.rm.force_allocate_reg(op.result, selected_reg=r.r0) + # we need r1 as a temporary + tmp_box = TempBox() + self.rm.force_allocate_reg(tmp_box, selected_reg=r.r1) + gcmap = self.get_gcmap([r.r0, r.r1]) # allocate the gcmap *before* + self.rm.possibly_free_var(tmp_box) + # length_box always survives: it's typically also present in the + # next operation that will copy it inside the new array. It's + # fine to load it from the stack too, as long as it's != r0, r1. + lengthloc = self.rm.loc(length_box) + self.rm.possibly_free_var(length_box) + # + itemsize = op.getarg(1).getint() + maxlength = (gc_ll_descr.max_size_of_young_obj - WORD * 2) / itemsize + self.assembler.malloc_cond_varsize( + op.getarg(0).getint(), + gc_ll_descr.get_nursery_free_addr(), + gc_ll_descr.get_nursery_top_addr(), + lengthloc, itemsize, maxlength, gcmap, arraydescr) prepare_op_debug_merge_point = void prepare_op_jit_debug = void @@ -1211,13 +1264,6 @@ operations_with_guard = [notimplemented_with_guard] * (rop._LAST + 1) -def get_scale(size): - scale = 0 - while (1 << scale) < size: - scale += 1 - assert (1 << scale) == size - return scale - for key, value in rop.__dict__.items(): key = key.lower() if key.startswith('_'): diff --git a/rpython/jit/backend/arm/runner.py b/rpython/jit/backend/arm/runner.py --- a/rpython/jit/backend/arm/runner.py +++ b/rpython/jit/backend/arm/runner.py @@ -19,6 +19,7 @@ supports_longlong = False # XXX requires an implementation of # read_timestamp that works in user mode supports_singlefloats = not detect_hardfloat() + can_inline_varsize_malloc = True from rpython.jit.backend.arm.arch import JITFRAME_FIXED_SIZE all_reg_indexes = range(len(all_regs)) From noreply at buildbot.pypy.org Sat Apr 20 08:42:09 2013 From: noreply at buildbot.pypy.org (bivab) Date: Sat, 20 Apr 2013 08:42:09 +0200 (CEST) Subject: [pypy-commit] pypy default: merge heads Message-ID: <20130420064209.E5AA91C1464@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63518:6885a43961e2 Date: 2013-04-20 01:34 +0200 http://bitbucket.org/pypy/pypy/changeset/6885a43961e2/ Log: merge heads diff --git a/rpython/annotator/model.py b/rpython/annotator/model.py --- a/rpython/annotator/model.py +++ b/rpython/annotator/model.py @@ -527,6 +527,7 @@ s_Int = SomeInteger() s_ImpossibleValue = SomeImpossibleValue() s_Str0 = SomeString(no_nul=True) +s_Unicode0 = SomeUnicodeString(no_nul=True) # ____________________________________________________________ diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -58,7 +58,7 @@ if we_are_translated(): self.debug = False self.current_clt = looptoken.compiled_loop_token - self.mc = InstrBuilder(self.cpu.arch_version) + self.mc = InstrBuilder(self.cpu.cpuinfo.arch_version) self.pending_guards = [] assert self.datablockwrapper is None allblocks = self.get_asmmemmgr_blocks(looptoken) @@ -82,7 +82,7 @@ if not self.cpu.propagate_exception_descr: return # not supported (for tests, or non-translated) # - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) self._store_and_reset_exception(mc, r.r0) ofs = self.cpu.get_ofs_of_frame_field('jf_guard_exc') # make sure ofs fits into a register @@ -167,7 +167,7 @@ # | my own retaddr | <-- sp # +-----------------------+ # - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) # save argument registers and return address mc.PUSH([reg.value for reg in r.argument_regs] + [r.ip.value, r.lr.value]) # stack is aligned here @@ -208,7 +208,7 @@ # write barriers. It must save all registers, and optionally # all vfp registers. It takes a single argument which is in r0. # It must keep stack alignment accordingly. - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) # exc0 = exc1 = None mc.PUSH([r.ip.value, r.lr.value]) # push two words to keep alignment @@ -265,7 +265,7 @@ This function must preserve all registers apart from r0 and r1. """ assert kind in ['fixed', 'str', 'unicode', 'var'] - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) # self._push_all_regs_to_jitframe(mc, [r.r0, r.r1], self.cpu.supports_floats) # @@ -399,7 +399,7 @@ self.load_reg(mc, vfpr, r.fp, ofs) def _build_failure_recovery(self, exc, withfloats=False): - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) self._push_all_regs_to_jitframe(mc, [], withfloats) if exc: @@ -682,7 +682,7 @@ expected_size=expected_size) def _patch_frame_depth(self, adr, allocated_depth): - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) mc.gen_load_int(r.lr.value, allocated_depth) mc.copy_to_raw_memory(adr) @@ -758,7 +758,7 @@ # f) store the address of the new jitframe in the shadowstack # c) set the gcmap field to 0 in the new jitframe # g) restore registers and return - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) self._push_all_regs_to_jitframe(mc, [], self.cpu.supports_floats) # this is the gcmap stored by push_gcmap(mov=True) in _check_stack_frame # and the expected_size pushed in _check_stack_frame @@ -818,7 +818,7 @@ self.target_tokens_currently_compiling = None def _patch_stackadjust(self, adr, allocated_depth): - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) mc.gen_load_int(r.lr.value, allocated_depth) mc.copy_to_raw_memory(adr) @@ -858,7 +858,7 @@ # patch the guard jumpt to the stub # overwrite the generate NOP with a B_offs to the pos of the # stub - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) mc.B_offs(relative_offset, c.get_opposite_of(tok.fcond)) mc.copy_to_raw_memory(guard_pos) else: @@ -937,7 +937,7 @@ self.mc.ASR_ri(resloc.value, resloc.value, 16) def patch_trace(self, faildescr, looptoken, bridge_addr, regalloc): - b = InstrBuilder(self.cpu.arch_version) + b = InstrBuilder(self.cpu.cpuinfo.arch_version) patch_addr = faildescr._arm_failure_recovery_block assert patch_addr != 0 b.B(bridge_addr) @@ -1397,7 +1397,7 @@ self.mc.LSL_ri(targetreg.value, sourcereg.value, get_scale(itemsize)) else: - mc.gen_load_int(targetreg.value, itemsize.value) + mc.gen_load_int(targetreg.value, itemsize) mc.MUL(targetreg.value, sourcereg.value, targetreg.value) # return shiftsize diff --git a/rpython/jit/backend/arm/detect.py b/rpython/jit/backend/arm/detect.py --- a/rpython/jit/backend/arm/detect.py +++ b/rpython/jit/backend/arm/detect.py @@ -1,8 +1,8 @@ import os from rpython.translator.tool.cbuild import ExternalCompilationInfo +from rpython.rtyper.tool import rffi_platform from rpython.rlib.clibffi import FFI_DEFAULT_ABI, FFI_SYSV, FFI_VFP -from rpython.rtyper.tool import rffi_platform from rpython.translator.platform import CompilationError from rpython.rlib.debug import debug_print, debug_start, debug_stop @@ -46,9 +46,11 @@ # "Processor : ARMv%d-compatible processor rev 7 (v6l)" i = buf.find('ARMv') if i == -1: - raise ValueError("Unknown Processor entry") - - n = int(buf[i + 4]) + n = 6 + debug_print("Could not detect architecture version, " + "falling back to", "ARMv%d" % n) + else: + n = int(buf[i + 4]) if n < 6: raise ValueError("Unsupported ARM architecture version") diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -354,7 +354,7 @@ # whether to worry about a CALL that can collect; this # is always true except in call_release_gil can_collect=True): - if self.cpu.hf_abi: + if self.cpu.cpuinfo.hf_abi: stack_args, adr = self._setup_call_hf(adr, arglocs, fcond, resloc, result_info) else: @@ -382,7 +382,7 @@ # ensure the result is wellformed and stored in the correct location if resloc is not None: - if resloc.is_vfp_reg() and not self.cpu.hf_abi: + if resloc.is_vfp_reg() and not self.cpu.cpuinfo.hf_abi: # move result to the allocated register self.mov_to_vfp_loc(r.r0, r.r1, resloc) elif resloc.is_reg() and result_info != (-1, -1): @@ -1230,7 +1230,7 @@ baseofs = self.cpu.get_baseofs_of_frame_field() newlooptoken.compiled_loop_token.update_frame_info( oldlooptoken.compiled_loop_token, baseofs) - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) mc.B(target) mc.copy_to_raw_memory(oldadr) diff --git a/rpython/jit/backend/arm/runner.py b/rpython/jit/backend/arm/runner.py --- a/rpython/jit/backend/arm/runner.py +++ b/rpython/jit/backend/arm/runner.py @@ -11,6 +11,10 @@ jitframe.STATICSIZE = JITFRAME_FIXED_SIZE +class CPUInfo(object): + hf_abi = False + arch_version = 6 + class AbstractARMCPU(AbstractLLCPU): IS_64_BIT = False @@ -27,13 +31,11 @@ float_regs = VFPRegisterManager.all_regs frame_reg = fp - hf_abi = False # use hard float abi flag - arch_version = 6 # assume ARMv6 as base case - def __init__(self, rtyper, stats, opts=None, translate_support_code=False, gcdescr=None): AbstractLLCPU.__init__(self, rtyper, stats, opts, translate_support_code, gcdescr) + self.cpuinfo = CPUInfo() def set_debug(self, flag): return self.assembler.set_debug(flag) @@ -48,8 +50,8 @@ self.assembler = AssemblerARM(self, self.translate_support_code) def setup_once(self): - self.arch_version = detect_arch_version() - self.hf_abi = detect_hardfloat() + self.cpuinfo.arch_version = detect_arch_version() + self.cpuinfo.hf_abi = detect_hardfloat() self.assembler.setup_once() def finish_once(self): @@ -93,7 +95,7 @@ from rpython.jit.backend.arm.codebuilder import InstrBuilder for jmp, tgt in looptoken.compiled_loop_token.invalidate_positions: - mc = InstrBuilder(self.arch_version) + mc = InstrBuilder(self.cpuinfo.arch_version) mc.B_offs(tgt) mc.copy_to_raw_memory(jmp) # positions invalidated diff --git a/rpython/jit/backend/arm/test/test_detect.py b/rpython/jit/backend/arm/test/test_detect.py --- a/rpython/jit/backend/arm/test/test_detect.py +++ b/rpython/jit/backend/arm/test/test_detect.py @@ -3,7 +3,32 @@ from rpython.jit.backend.arm.detect import detect_arch_version cpuinfo = "Processor : ARMv%d-compatible processor rev 7 (v6l)""" - +cpuinfo2 = """processor : 0 +vendor_id : GenuineIntel +cpu family : 6 +model : 23 +model name : Intel(R) Core(TM)2 Duo CPU E8400 @ 3.00GHz +stepping : 10 +microcode : 0xa07 +cpu MHz : 2997.000 +cache size : 6144 KB +physical id : 0 +siblings : 2 +core id : 0 +cpu cores : 2 +apicid : 0 +initial apicid : 0 +fpu : yes +fpu_exception : yes +cpuid level : 13 +wp : yes +flags : fpu vme ... +bogomips : 5993.08 +clflush size : 64 +cache_alignment : 64 +address sizes : 36 bits physical, 48 bits virtual +power management: +""" def write_cpuinfo(info): filepath = udir.join('get_arch_version') @@ -20,5 +45,4 @@ assert detect_arch_version(write_cpuinfo(cpuinfo % 8)) == 7 py.test.raises(ValueError, 'detect_arch_version(write_cpuinfo(cpuinfo % 5))') - py.test.raises(ValueError, - 'detect_arch_version(write_cpuinfo("Lorem ipsum dolor sit amet, consectetur"))') + assert detect_arch_version(write_cpuinfo(cpuinfo2)) == 6 diff --git a/rpython/jit/backend/arm/test/test_runner.py b/rpython/jit/backend/arm/test/test_runner.py --- a/rpython/jit/backend/arm/test/test_runner.py +++ b/rpython/jit/backend/arm/test/test_runner.py @@ -10,6 +10,7 @@ from rpython.rtyper.annlowlevel import llhelper from rpython.jit.codewriter.effectinfo import EffectInfo from rpython.jit.metainterp.history import JitCellToken, TargetToken +from rpython.jit.backend.arm.detect import detect_arch_version CPU = getcpuclass() @@ -27,7 +28,8 @@ bridge_loop_instructions = ['ldr', 'mov', 'nop', 'cmp', 'bge', 'push', 'mov', 'mov', 'push', 'mov', 'mov', 'blx', 'mov', 'mov', 'bx'] - if CPU.arch_version == 7: + arch_version = detect_arch_version() + if arch_version == 7: bridge_loop_instructions = ['ldr', 'mov', 'nop', 'cmp', 'bge', 'push', 'mov', 'mov', 'push', 'mov', 'mov', 'blx', 'mov', 'mov', 'bx'] diff --git a/rpython/memory/gc/env.py b/rpython/memory/gc/env.py --- a/rpython/memory/gc/env.py +++ b/rpython/memory/gc/env.py @@ -279,7 +279,7 @@ def best_nursery_size_for_L2cache(L2cache): # Heuristically, the best nursery size to choose is about half # of the L2 cache. - if L2cache > 1024 * 1024: # we don't want to have nursery estimated + if L2cache > 2 * 1024 * 1024: # we don't want to have nursery estimated # on L2 when L3 is present return L2cache // 2 else: diff --git a/rpython/memory/gc/minimark.py b/rpython/memory/gc/minimark.py --- a/rpython/memory/gc/minimark.py +++ b/rpython/memory/gc/minimark.py @@ -351,8 +351,6 @@ # hacking at the current nursery position in collect_and_reserve(). if newsize <= 0: newsize = env.estimate_best_nursery_size() - # 4*1024*1024 # fixed to 4MB by default - # (it was env.estimate_best_nursery_size()) if newsize <= 0: newsize = defaultsize if newsize < minsize: diff --git a/rpython/rlib/rwin32.py b/rpython/rlib/rwin32.py --- a/rpython/rlib/rwin32.py +++ b/rpython/rlib/rwin32.py @@ -5,6 +5,7 @@ import os import errno +from rpython.rtyper.module.ll_os_environ import make_env_impls from rpython.rtyper.tool import rffi_platform from rpython.tool.udir import udir from rpython.translator.tool.cbuild import ExternalCompilationInfo @@ -390,3 +391,5 @@ raise lastWindowsError('os_kill failed to terminate process') finally: CloseHandle(handle) + + _wenviron_items, _wgetenv, _wputenv = make_env_impls(win32=True) diff --git a/rpython/rlib/test/test_rwin32.py b/rpython/rlib/test/test_rwin32.py --- a/rpython/rlib/test/test_rwin32.py +++ b/rpython/rlib/test/test_rwin32.py @@ -1,3 +1,4 @@ +# encoding: utf-8 import os, py if os.name != 'nt': py.test.skip('tests for win32 only') @@ -47,3 +48,13 @@ rwin32.CloseHandle(handle) assert proc.wait() == signal.SIGTERM + at py.test.mark.dont_track_allocations('putenv intentionally keeps strings alive') +def test_wenviron(): + name, value = u'PYPY_TEST_日本', u'foobar日本' + rwin32._wputenv(name, value) + assert rwin32._wgetenv(name) == value + env = dict(rwin32._wenviron_items()) + assert env[name] == value + for key, value in env.iteritems(): + assert type(key) is unicode + assert type(value) is unicode diff --git a/rpython/rtyper/module/ll_os.py b/rpython/rtyper/module/ll_os.py --- a/rpython/rtyper/module/ll_os.py +++ b/rpython/rtyper/module/ll_os.py @@ -7,14 +7,15 @@ import os, sys, errno import py -from rpython.rtyper.module.support import OOSupport +from rpython.rtyper.module.support import ( + _WIN32, OOSupport, StringTraits, UnicodeTraits, underscore_on_windows) from rpython.tool.sourcetools import func_renamer from rpython.rlib.rarithmetic import r_longlong from rpython.rtyper.extfunc import ( BaseLazyRegistering, register_external) from rpython.rtyper.extfunc import registering, registering_if, extdef from rpython.annotator.model import ( - SomeInteger, SomeString, SomeTuple, SomeFloat, SomeUnicodeString) + SomeInteger, SomeString, SomeTuple, SomeFloat, s_Str0, s_Unicode0) from rpython.annotator.model import s_ImpossibleValue, s_None, s_Bool from rpython.rtyper.lltypesystem import rffi from rpython.rtyper.lltypesystem import lltype @@ -25,8 +26,8 @@ from rpython.rtyper.lltypesystem.rstr import STR from rpython.rlib.objectmodel import specialize -str0 = SomeString(no_nul=True) -unicode0 = SomeUnicodeString(no_nul=True) +str0 = s_Str0 +unicode0 = s_Unicode0 def monkeypatch_rposix(posixfunc, unicodefunc, signature): func_name = posixfunc.__name__ @@ -66,42 +67,6 @@ # Monkeypatch the function in rpython.rlib.rposix setattr(rposix, func_name, new_func) -class StringTraits: - str = str - str0 = str0 - CHAR = rffi.CHAR - CCHARP = rffi.CCHARP - charp2str = staticmethod(rffi.charp2str) - str2charp = staticmethod(rffi.str2charp) - free_charp = staticmethod(rffi.free_charp) - scoped_alloc_buffer = staticmethod(rffi.scoped_alloc_buffer) - - @staticmethod - def posix_function_name(name): - return underscore_on_windows + name - - @staticmethod - def ll_os_name(name): - return 'll_os.ll_os_' + name - -class UnicodeTraits: - str = unicode - str0 = unicode0 - CHAR = rffi.WCHAR_T - CCHARP = rffi.CWCHARP - charp2str = staticmethod(rffi.wcharp2unicode) - str2charp = staticmethod(rffi.unicode2wcharp) - free_charp = staticmethod(rffi.free_wcharp) - scoped_alloc_buffer = staticmethod(rffi.scoped_alloc_unicodebuffer) - - @staticmethod - def posix_function_name(name): - return underscore_on_windows + 'w' + name - - @staticmethod - def ll_os_name(name): - return 'll_os.ll_os_w' + name - def registering_str_unicode(posixfunc, condition=True): if not condition or posixfunc is None: return registering(None, condition=False) @@ -129,16 +94,6 @@ posix = __import__(os.name) -if sys.platform.startswith('win'): - _WIN32 = True -else: - _WIN32 = False - -if _WIN32: - underscore_on_windows = '_' -else: - underscore_on_windows = '' - includes = [] if not _WIN32: # XXX many of these includes are not portable at all diff --git a/rpython/rtyper/module/ll_os_environ.py b/rpython/rtyper/module/ll_os_environ.py --- a/rpython/rtyper/module/ll_os_environ.py +++ b/rpython/rtyper/module/ll_os_environ.py @@ -4,10 +4,10 @@ from rpython.rtyper.controllerentry import Controller from rpython.rtyper.extfunc import register_external from rpython.rtyper.lltypesystem import rffi, lltype -from rpython.rtyper.module import ll_os -from rpython.rlib import rposix +from rpython.rtyper.module.support import _WIN32, StringTraits, UnicodeTraits +from rpython.translator.tool.cbuild import ExternalCompilationInfo -str0 = ll_os.str0 +str0 = annmodel.s_Str0 # ____________________________________________________________ # @@ -59,85 +59,8 @@ return r_getenv # ____________________________________________________________ -# -# Lower-level interface: dummy placeholders and external registations - -def r_getenv(name): - just_a_placeholder # should return None if name not found - -os_getenv = rffi.llexternal('getenv', [rffi.CCHARP], rffi.CCHARP, - threadsafe=False) - -def getenv_llimpl(name): - with rffi.scoped_str2charp(name) as l_name: - l_result = os_getenv(l_name) - return rffi.charp2str(l_result) if l_result else None - -register_external(r_getenv, [str0], - annmodel.SomeString(can_be_None=True, no_nul=True), - export_name='ll_os.ll_os_getenv', - llimpl=getenv_llimpl) - -# ____________________________________________________________ - -def r_putenv(name, value): - just_a_placeholder - -class EnvKeepalive: - pass -envkeepalive = EnvKeepalive() -envkeepalive.byname = {} - -os_putenv = rffi.llexternal('putenv', [rffi.CCHARP], rffi.INT) - -def putenv_llimpl(name, value): - l_string = rffi.str2charp('%s=%s' % (name, value)) - error = rffi.cast(lltype.Signed, os_putenv(l_string)) - if error: - rffi.free_charp(l_string) - raise OSError(rposix.get_errno(), "os_putenv failed") - # keep 'l_string' alive - we know that the C library needs it - # until the next call to putenv() with the same 'name'. - l_oldstring = envkeepalive.byname.get(name, lltype.nullptr(rffi.CCHARP.TO)) - envkeepalive.byname[name] = l_string - if l_oldstring: - rffi.free_charp(l_oldstring) - -register_external(r_putenv, [str0, str0], annmodel.s_None, - export_name='ll_os.ll_os_putenv', - llimpl=putenv_llimpl) - -# ____________________________________________________________ - -def r_unsetenv(name): - # default implementation for platforms without a real unsetenv() - r_putenv(name, '') - -if hasattr(__import__(os.name), 'unsetenv'): - os_unsetenv = rffi.llexternal('unsetenv', [rffi.CCHARP], rffi.INT) - - def unsetenv_llimpl(name): - with rffi.scoped_str2charp(name) as l_name: - error = rffi.cast(lltype.Signed, os_unsetenv(l_name)) - if error: - raise OSError(rposix.get_errno(), "os_unsetenv failed") - try: - l_oldstring = envkeepalive.byname[name] - except KeyError: - pass - else: - del envkeepalive.byname[name] - rffi.free_charp(l_oldstring) - - register_external(r_unsetenv, [str0], annmodel.s_None, - export_name='ll_os.ll_os_unsetenv', - llimpl=unsetenv_llimpl) - -# ____________________________________________________________ # Access to the 'environ' external variable -from rpython.translator.tool.cbuild import ExternalCompilationInfo - if sys.platform.startswith('darwin'): CCHARPPP = rffi.CArrayPtr(rffi.CCHARPP) _os_NSGetEnviron = rffi.llexternal( @@ -146,16 +69,21 @@ ) def os_get_environ(): return _os_NSGetEnviron()[0] -elif sys.platform.startswith('win'): +elif _WIN32: + eci = ExternalCompilationInfo(includes=['stdlib.h']) + CWCHARPP = lltype.Ptr(lltype.Array(rffi.CWCHARP, hints={'nolength': True})) + os_get_environ, _os_set_environ = rffi.CExternVariable( - rffi.CCHARPP, - '_environ', - ExternalCompilationInfo(includes=['stdlib.h'])) + rffi.CCHARPP, '_environ', eci) + get__wenviron, _set__wenviron = rffi.CExternVariable( + CWCHARPP, '_wenviron', eci, c_type='wchar_t **') else: os_get_environ, _os_set_environ = rffi.CExternVariable( rffi.CCHARPP, 'environ', ExternalCompilationInfo()) # ____________________________________________________________ +# +# Lower-level interface: dummy placeholders and external registations def r_envkeys(): just_a_placeholder @@ -181,18 +109,109 @@ def r_envitems(): just_a_placeholder -def envitems_llimpl(): - environ = os_get_environ() - result = [] - i = 0 - while environ[i]: - name_value = rffi.charp2str(environ[i]) - p = name_value.find('=') - if p >= 0: - result.append((name_value[:p], name_value[p+1:])) - i += 1 - return result +def r_getenv(name): + just_a_placeholder # should return None if name not found + +def r_putenv(name, value): + just_a_placeholder + +os_getenv = rffi.llexternal('getenv', [rffi.CCHARP], rffi.CCHARP, + threadsafe=False) +os_putenv = rffi.llexternal('putenv', [rffi.CCHARP], rffi.INT) +if _WIN32: + _wgetenv = rffi.llexternal('_wgetenv', [rffi.CWCHARP], rffi.CWCHARP, + compilation_info=eci, threadsafe=False) + _wputenv = rffi.llexternal('_wputenv', [rffi.CWCHARP], rffi.INT, + compilation_info=eci) + +class EnvKeepalive: + pass +envkeepalive = EnvKeepalive() +envkeepalive.byname = {} +envkeepalive.bywname = {} + +def make_env_impls(win32=False): + if not win32: + traits = StringTraits() + get_environ, getenv, putenv = os_get_environ, os_getenv, os_putenv + byname, eq = envkeepalive.byname, '=' + def last_error(msg): + from rpython.rlib import rposix + raise OSError(rposix.get_errno(), msg) + else: + traits = UnicodeTraits() + get_environ, getenv, putenv = get__wenviron, _wgetenv, _wputenv + byname, eq = envkeepalive.bywname, u'=' + from rpython.rlib.rwin32 import lastWindowsError as last_error + + def envitems_llimpl(): + environ = get_environ() + result = [] + i = 0 + while environ[i]: + name_value = traits.charp2str(environ[i]) + p = name_value.find(eq) + if p >= 0: + result.append((name_value[:p], name_value[p+1:])) + i += 1 + return result + + def getenv_llimpl(name): + with traits.scoped_str2charp(name) as l_name: + l_result = getenv(l_name) + return traits.charp2str(l_result) if l_result else None + + def putenv_llimpl(name, value): + l_string = traits.str2charp(name + eq + value) + error = rffi.cast(lltype.Signed, putenv(l_string)) + if error: + traits.free_charp(l_string) + last_error("putenv failed") + # keep 'l_string' alive - we know that the C library needs it + # until the next call to putenv() with the same 'name'. + l_oldstring = byname.get(name, lltype.nullptr(traits.CCHARP.TO)) + byname[name] = l_string + if l_oldstring: + traits.free_charp(l_oldstring) + + return envitems_llimpl, getenv_llimpl, putenv_llimpl + +envitems_llimpl, getenv_llimpl, putenv_llimpl = make_env_impls() register_external(r_envitems, [], [(str0, str0)], export_name='ll_os.ll_os_envitems', llimpl=envitems_llimpl) +register_external(r_getenv, [str0], + annmodel.SomeString(can_be_None=True, no_nul=True), + export_name='ll_os.ll_os_getenv', + llimpl=getenv_llimpl) +register_external(r_putenv, [str0, str0], annmodel.s_None, + export_name='ll_os.ll_os_putenv', + llimpl=putenv_llimpl) + +# ____________________________________________________________ + +def r_unsetenv(name): + # default implementation for platforms without a real unsetenv() + r_putenv(name, '') + +if hasattr(__import__(os.name), 'unsetenv'): + os_unsetenv = rffi.llexternal('unsetenv', [rffi.CCHARP], rffi.INT) + + def unsetenv_llimpl(name): + with rffi.scoped_str2charp(name) as l_name: + error = rffi.cast(lltype.Signed, os_unsetenv(l_name)) + if error: + from rpython.rlib import rposix + raise OSError(rposix.get_errno(), "os_unsetenv failed") + try: + l_oldstring = envkeepalive.byname[name] + except KeyError: + pass + else: + del envkeepalive.byname[name] + rffi.free_charp(l_oldstring) + + register_external(r_unsetenv, [str0], annmodel.s_None, + export_name='ll_os.ll_os_unsetenv', + llimpl=unsetenv_llimpl) diff --git a/rpython/rtyper/module/support.py b/rpython/rtyper/module/support.py --- a/rpython/rtyper/module/support.py +++ b/rpython/rtyper/module/support.py @@ -1,6 +1,12 @@ -from rpython.rtyper.lltypesystem import lltype +import os +import sys + +from rpython.annotator import model as annmodel +from rpython.rtyper.lltypesystem import lltype, rffi from rpython.rtyper.ootypesystem import ootype -import os + +_WIN32 = sys.platform.startswith('win') +underscore_on_windows = '_' if _WIN32 else '' # utility conversion functions class LLSupport: @@ -64,6 +70,45 @@ from_rstr_nonnull = staticmethod(from_rstr_nonnull) +class StringTraits: + str = str + str0 = annmodel.s_Str0 + CHAR = rffi.CHAR + CCHARP = rffi.CCHARP + charp2str = staticmethod(rffi.charp2str) + scoped_str2charp = staticmethod(rffi.scoped_str2charp) + str2charp = staticmethod(rffi.str2charp) + free_charp = staticmethod(rffi.free_charp) + scoped_alloc_buffer = staticmethod(rffi.scoped_alloc_buffer) + + @staticmethod + def posix_function_name(name): + return underscore_on_windows + name + + @staticmethod + def ll_os_name(name): + return 'll_os.ll_os_' + name + +class UnicodeTraits: + str = unicode + str0 = annmodel.s_Unicode0 + CHAR = rffi.WCHAR_T + CCHARP = rffi.CWCHARP + charp2str = staticmethod(rffi.wcharp2unicode) + str2charp = staticmethod(rffi.unicode2wcharp) + scoped_str2charp = staticmethod(rffi.scoped_unicode2wcharp) + free_charp = staticmethod(rffi.free_wcharp) + scoped_alloc_buffer = staticmethod(rffi.scoped_alloc_unicodebuffer) + + @staticmethod + def posix_function_name(name): + return underscore_on_windows + 'w' + name + + @staticmethod + def ll_os_name(name): + return 'll_os.ll_os_w' + name + + def ll_strcpy(dst_s, src_s, n): dstchars = dst_s.chars srcchars = src_s.chars @@ -78,5 +123,3 @@ while i < n: dstchars[i] = srcchars[i] i += 1 - - From noreply at buildbot.pypy.org Sat Apr 20 12:14:23 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sat, 20 Apr 2013 12:14:23 +0200 (CEST) Subject: [pypy-commit] pypy default: issue1453 in-progress: fix one particular bug I hit when debugging Message-ID: <20130420101423.2DAB21C1463@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63519:40390dcf161a Date: 2013-04-20 12:11 +0200 http://bitbucket.org/pypy/pypy/changeset/40390dcf161a/ Log: issue1453 in-progress: fix one particular bug I hit when debugging it. As usual with threads, hard to test. diff --git a/pypy/module/thread/threadlocals.py b/pypy/module/thread/threadlocals.py --- a/pypy/module/thread/threadlocals.py +++ b/pypy/module/thread/threadlocals.py @@ -52,7 +52,7 @@ def signals_enabled(self): ec = self.getvalue() - return ec._signals_enabled + return ec is not None and ec._signals_enabled def enable_signals(self, space): ec = self.getvalue() @@ -72,10 +72,12 @@ def leave_thread(self, space): "Notification that the current thread is about to stop." from pypy.module.thread.os_local import thread_is_stopping - try: - thread_is_stopping(self.getvalue()) - finally: - self.setvalue(None) + ec = self.getvalue() + if ec is not None: + try: + thread_is_stopping(ec) + finally: + self.setvalue(None) def reinit_threads(self, space): "Called in the child process after a fork()" From noreply at buildbot.pypy.org Sat Apr 20 16:44:06 2013 From: noreply at buildbot.pypy.org (bivab) Date: Sat, 20 Apr 2013 16:44:06 +0200 (CEST) Subject: [pypy-commit] pypy default: reload the frame in call_reaquire_gil Message-ID: <20130420144406.B60B51C073E@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63520:b4958ab843da Date: 2013-04-20 16:41 +0200 http://bitbucket.org/pypy/pypy/changeset/b4958ab843da/ Log: reload the frame in call_reaquire_gil diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -1320,6 +1320,7 @@ with saved_registers(self.mc, regs_to_save, vfp_regs_to_save): self._emit_call(imm(self.reacqgil_addr), [], fcond, can_collect=False) + self._reload_frame_if_necessary(self.mc) def _store_force_index(self, guard_op): faildescr = guard_op.getdescr() From noreply at buildbot.pypy.org Sat Apr 20 16:44:08 2013 From: noreply at buildbot.pypy.org (bivab) Date: Sat, 20 Apr 2013 16:44:08 +0200 (CEST) Subject: [pypy-commit] pypy default: merge heads Message-ID: <20130420144408.074521C073E@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63521:754ac043d6f0 Date: 2013-04-20 16:42 +0200 http://bitbucket.org/pypy/pypy/changeset/754ac043d6f0/ Log: merge heads diff --git a/pypy/module/thread/threadlocals.py b/pypy/module/thread/threadlocals.py --- a/pypy/module/thread/threadlocals.py +++ b/pypy/module/thread/threadlocals.py @@ -52,7 +52,7 @@ def signals_enabled(self): ec = self.getvalue() - return ec._signals_enabled + return ec is not None and ec._signals_enabled def enable_signals(self, space): ec = self.getvalue() @@ -72,10 +72,12 @@ def leave_thread(self, space): "Notification that the current thread is about to stop." from pypy.module.thread.os_local import thread_is_stopping - try: - thread_is_stopping(self.getvalue()) - finally: - self.setvalue(None) + ec = self.getvalue() + if ec is not None: + try: + thread_is_stopping(ec) + finally: + self.setvalue(None) def reinit_threads(self, space): "Called in the child process after a fork()" From noreply at buildbot.pypy.org Sat Apr 20 16:52:51 2013 From: noreply at buildbot.pypy.org (alex_gaynor) Date: Sat, 20 Apr 2013 16:52:51 +0200 (CEST) Subject: [pypy-commit] pypy default: Fixed #1460 -- correct an issue with loading empty JSON objects when using object_pairs_hook Message-ID: <20130420145251.941D91C01E1@cobra.cs.uni-duesseldorf.de> Author: Alex Gaynor Branch: Changeset: r63522:6794e06515db Date: 2013-04-20 07:51 -0700 http://bitbucket.org/pypy/pypy/changeset/6794e06515db/ Log: Fixed #1460 -- correct an issue with loading empty JSON objects when using object_pairs_hook diff --git a/lib-python/2.7/json/decoder.py b/lib-python/2.7/json/decoder.py --- a/lib-python/2.7/json/decoder.py +++ b/lib-python/2.7/json/decoder.py @@ -162,7 +162,7 @@ if nextchar == '}': if object_pairs_hook is not None: result = object_pairs_hook(pairs) - return result, end + return result, end + 1 pairs = {} if object_hook is not None: pairs = object_hook(pairs) diff --git a/lib-python/2.7/json/tests/test_decode.py b/lib-python/2.7/json/tests/test_decode.py --- a/lib-python/2.7/json/tests/test_decode.py +++ b/lib-python/2.7/json/tests/test_decode.py @@ -44,6 +44,7 @@ object_pairs_hook=OrderedDict, object_hook=lambda x: None), OrderedDict(p)) + self.assertEqual(self.loads("{}", object_pairs_hook=list), []) class TestPyDecode(TestDecode, PyTest): pass From noreply at buildbot.pypy.org Sat Apr 20 16:52:52 2013 From: noreply at buildbot.pypy.org (alex_gaynor) Date: Sat, 20 Apr 2013 16:52:52 +0200 (CEST) Subject: [pypy-commit] pypy default: merged upstream Message-ID: <20130420145252.D95F81C01E1@cobra.cs.uni-duesseldorf.de> Author: Alex Gaynor Branch: Changeset: r63523:db09ff648d53 Date: 2013-04-20 07:52 -0700 http://bitbucket.org/pypy/pypy/changeset/db09ff648d53/ Log: merged upstream diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -1320,6 +1320,7 @@ with saved_registers(self.mc, regs_to_save, vfp_regs_to_save): self._emit_call(imm(self.reacqgil_addr), [], fcond, can_collect=False) + self._reload_frame_if_necessary(self.mc) def _store_force_index(self, guard_op): faildescr = guard_op.getdescr() From noreply at buildbot.pypy.org Sat Apr 20 16:57:15 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sat, 20 Apr 2013 16:57:15 +0200 (CEST) Subject: [pypy-commit] pypy default: Document the fact that MSVC probably doesn't support asmgcc any longer. Message-ID: <20130420145715.995091C073E@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63524:d6f74094aa95 Date: 2013-04-20 16:56 +0200 http://bitbucket.org/pypy/pypy/changeset/d6f74094aa95/ Log: Document the fact that MSVC probably doesn't support asmgcc any longer. diff --git a/pypy/doc/config/translation.gcrootfinder.txt b/pypy/doc/config/translation.gcrootfinder.txt --- a/pypy/doc/config/translation.gcrootfinder.txt +++ b/pypy/doc/config/translation.gcrootfinder.txt @@ -9,7 +9,9 @@ - ``--gcrootfinder=asmgcc``: use assembler hackery to find the roots directly from the normal stack. This is a bit faster, but platform specific. It works so far with GCC or MSVC, - on i386 and x86-64. + on i386 and x86-64. It is tested only on Linux (where it is + the default) so other platforms (as well as MSVC) may need + various fixes before they can be used. You may have to force the use of the shadowstack root finder if you are running into troubles or if you insist on translating From noreply at buildbot.pypy.org Sat Apr 20 17:03:31 2013 From: noreply at buildbot.pypy.org (fijal) Date: Sat, 20 Apr 2013 17:03:31 +0200 (CEST) Subject: [pypy-commit] buildbot default: cleanup and use --make-jobs=1 on OSX Message-ID: <20130420150331.2B0331C1463@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r790:4749f7818c95 Date: 2013-04-20 17:03 +0200 http://bitbucket.org/pypy/buildbot/changeset/4749f7818c95/ Log: cleanup and use --make-jobs=1 on OSX diff --git a/bot2/pypybuildbot/master.py b/bot2/pypybuildbot/master.py --- a/bot2/pypybuildbot/master.py +++ b/bot2/pypybuildbot/master.py @@ -112,7 +112,7 @@ pypyJITTranslatedTestFactoryOSX = pypybuilds.Translated( platform='osx', - translationArgs=jit_translation_args, + translationArgs=jit_translation_args + ['--make-jobs=1'], targetArgs=[], lib_python=True, pypyjit=True, @@ -147,13 +147,6 @@ app_tests=True, ) -pypy_OjitTranslatedTestFactory = pypybuilds.Translated( - translationArgs=['-Ojit', '--gc=hybrid', '--no-translation-jit', - '--gcrootfinder=asmgcc'], - lib_python=True, - app_tests=True - ) - pypyJITBenchmarkFactory_tannit = pypybuilds.JITBenchmark() pypyJITBenchmarkFactory64_tannit = pypybuilds.JITBenchmark(platform='linux64', postfix='-64') @@ -206,8 +199,6 @@ # All the other linux tests run on allegro Nightly("nightly-0-00", [ # benchmarks - #JITBENCH64_2, # on speed.python.org, uses 1 core (in part exclusively) - #CPYTHON_64, # on speed.python.org, uses 1 core (in part exclusively) # linux tests LINUX32, # on tannit32, uses all cores LINUX64, # on allegro64, uses all cores @@ -231,7 +222,6 @@ Nightly("nightly-2-00-py3k", [ LINUX64, # on allegro64, uses all cores - #APPLVLLINUX32, # on tannit32, uses 1 core APPLVLLINUX64, # on allegro64, uses 1 core ], branch="py3k", hour=2, minute=0), From noreply at buildbot.pypy.org Sat Apr 20 17:28:13 2013 From: noreply at buildbot.pypy.org (bivab) Date: Sat, 20 Apr 2013 17:28:13 +0200 (CEST) Subject: [pypy-commit] pypy default: (fijal, bivab) correctly store exception value in _build_propagate_exception_path Message-ID: <20130420152813.68F6F1C1468@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63525:9896165fed1a Date: 2013-04-20 10:24 -0500 http://bitbucket.org/pypy/pypy/changeset/9896165fed1a/ Log: (fijal, bivab) correctly store exception value in _build_propagate_exception_path diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -87,15 +87,15 @@ ofs = self.cpu.get_ofs_of_frame_field('jf_guard_exc') # make sure ofs fits into a register assert check_imm_arg(ofs) - mc.LDR_ri(r.r0.value, r.fp.value, imm=ofs) + self.store_reg(mc, r.r0, r.fp, ofs) propagate_exception_descr = rffi.cast(lltype.Signed, cast_instance_to_gcref(self.cpu.propagate_exception_descr)) # put propagate_exception_descr into frame ofs = self.cpu.get_ofs_of_frame_field('jf_descr') # make sure ofs fits into a register assert check_imm_arg(ofs) - mc.gen_load_int(r.r0.value, propagate_exception_descr) - mc.STR_ri(r.r0.value, r.fp.value, imm=ofs) + mc.gen_load_int(r.r1.value, propagate_exception_descr) + self.store_reg(mc, r.r0, r.fp, ofs) mc.MOV_rr(r.r0.value, r.fp.value) self.gen_func_epilog(mc) rawstart = mc.materialize(self.cpu.asmmemmgr, []) From noreply at buildbot.pypy.org Sat Apr 20 17:28:14 2013 From: noreply at buildbot.pypy.org (bivab) Date: Sat, 20 Apr 2013 17:28:14 +0200 (CEST) Subject: [pypy-commit] pypy default: merge heads Message-ID: <20130420152814.A63E11C146E@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63526:a3da7e0bff01 Date: 2013-04-20 10:25 -0500 http://bitbucket.org/pypy/pypy/changeset/a3da7e0bff01/ Log: merge heads diff --git a/lib-python/2.7/json/decoder.py b/lib-python/2.7/json/decoder.py --- a/lib-python/2.7/json/decoder.py +++ b/lib-python/2.7/json/decoder.py @@ -162,7 +162,7 @@ if nextchar == '}': if object_pairs_hook is not None: result = object_pairs_hook(pairs) - return result, end + return result, end + 1 pairs = {} if object_hook is not None: pairs = object_hook(pairs) diff --git a/lib-python/2.7/json/tests/test_decode.py b/lib-python/2.7/json/tests/test_decode.py --- a/lib-python/2.7/json/tests/test_decode.py +++ b/lib-python/2.7/json/tests/test_decode.py @@ -44,6 +44,7 @@ object_pairs_hook=OrderedDict, object_hook=lambda x: None), OrderedDict(p)) + self.assertEqual(self.loads("{}", object_pairs_hook=list), []) class TestPyDecode(TestDecode, PyTest): pass diff --git a/pypy/doc/config/translation.gcrootfinder.txt b/pypy/doc/config/translation.gcrootfinder.txt --- a/pypy/doc/config/translation.gcrootfinder.txt +++ b/pypy/doc/config/translation.gcrootfinder.txt @@ -9,7 +9,9 @@ - ``--gcrootfinder=asmgcc``: use assembler hackery to find the roots directly from the normal stack. This is a bit faster, but platform specific. It works so far with GCC or MSVC, - on i386 and x86-64. + on i386 and x86-64. It is tested only on Linux (where it is + the default) so other platforms (as well as MSVC) may need + various fixes before they can be used. You may have to force the use of the shadowstack root finder if you are running into troubles or if you insist on translating diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -1320,6 +1320,7 @@ with saved_registers(self.mc, regs_to_save, vfp_regs_to_save): self._emit_call(imm(self.reacqgil_addr), [], fcond, can_collect=False) + self._reload_frame_if_necessary(self.mc) def _store_force_index(self, guard_op): faildescr = guard_op.getdescr() From noreply at buildbot.pypy.org Sat Apr 20 18:35:20 2013 From: noreply at buildbot.pypy.org (fijal) Date: Sat, 20 Apr 2013 18:35:20 +0200 (CEST) Subject: [pypy-commit] pypy default: Clarify building (no make install so far) Message-ID: <20130420163520.145B91C073E@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r63527:e6a2b2c90122 Date: 2013-04-20 18:34 +0200 http://bitbucket.org/pypy/pypy/changeset/e6a2b2c90122/ Log: Clarify building (no make install so far) diff --git a/Makefile b/Makefile new file mode 100644 --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ + +all: pypy-c + +pypy-c: + @echo "Building PyPy with JIT, it'll take about 40 minutes and 4G of RAM" + @sleep 3 + rpython/bin/rpython -Ojit pypy/goal/targetpypystandalone.py diff --git a/README.rst b/README.rst --- a/README.rst +++ b/README.rst @@ -22,3 +22,16 @@ and send us feedback! the pypy-dev team + +Building +======== + +build with:: + + rpython/bin/rpython -Ojit pypy/goal/targetpypystandalone.py + +This ends up with ``pypy-c`` binary in the main pypy directory. We suggest +to use virtualenv with the resulting pypy-c as the interpreter, you can +find more details about various installation schemes here: + +http://doc.pypy.org/en/latest/getting-started.html#installing-pypy From noreply at buildbot.pypy.org Sat Apr 20 18:36:07 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sat, 20 Apr 2013 18:36:07 +0200 (CEST) Subject: [pypy-commit] pypy default: Fix this test on llgraph. Message-ID: <20130420163607.450471C073E@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63528:674d0625fe33 Date: 2013-04-20 18:35 +0200 http://bitbucket.org/pypy/pypy/changeset/674d0625fe33/ Log: Fix this test on llgraph. diff --git a/rpython/jit/backend/test/runner_test.py b/rpython/jit/backend/test/runner_test.py --- a/rpython/jit/backend/test/runner_test.py +++ b/rpython/jit/backend/test/runner_test.py @@ -3943,7 +3943,8 @@ a = lltype.malloc(A, 2, flavor='raw') a[0] = rffi.cast(rffi.SHORT, 666) a[1] = rffi.cast(rffi.SHORT, 777) - a_int = rffi.cast(lltype.Signed, a) + addr = llmemory.cast_ptr_to_adr(a) + a_int = heaptracker.adr2int(addr) print 'a_int:', a_int self.execute_operation(rop.SETARRAYITEM_RAW, [ConstInt(a_int), ConstInt(0), ConstInt(-7654)], From noreply at buildbot.pypy.org Sat Apr 20 19:12:59 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sat, 20 Apr 2013 19:12:59 +0200 (CEST) Subject: [pypy-commit] pypy default: Fix in the code for a case that never shows up so far, as far as I can Message-ID: <20130420171259.694D61C1463@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63529:60987a394be9 Date: 2013-04-20 19:12 +0200 http://bitbucket.org/pypy/pypy/changeset/60987a394be9/ Log: Fix in the code for a case that never shows up so far, as far as I can see. Fix in the test for non-consequential changes. diff --git a/rpython/jit/backend/x86/rx86.py b/rpython/jit/backend/x86/rx86.py --- a/rpython/jit/backend/x86/rx86.py +++ b/rpython/jit/backend/x86/rx86.py @@ -682,10 +682,12 @@ def define_modrm_modes(insnname_template, before_modrm, after_modrm=[], regtype='GPR'): def add_insn(code, *modrm): - args = before_modrm + list(modrm) + after_modrm + args = before_modrm + list(modrm) methname = insnname_template.replace('*', code) - if methname.endswith('_rr') or methname.endswith('_xx'): + if (methname.endswith('_rr') or methname.endswith('_xx') + or methname.endswith('_ri')): args.append('\xC0') + args += after_modrm if regtype == 'XMM': insn_func = xmminsn(*args) diff --git a/rpython/jit/backend/x86/test/test_regloc.py b/rpython/jit/backend/x86/test/test_regloc.py --- a/rpython/jit/backend/x86/test/test_regloc.py +++ b/rpython/jit/backend/x86/test/test_regloc.py @@ -1,4 +1,5 @@ import struct, sys +from rpython.jit.backend.x86.rx86 import R from rpython.jit.backend.x86.regloc import * from rpython.jit.backend.x86.test.test_rx86 import CodeBuilder32, CodeBuilder64, assert_encodes_as from rpython.jit.backend.x86.assembler import heap @@ -15,36 +16,49 @@ cb32 = LocationCodeBuilder32 cb64 = LocationCodeBuilder64 +def test_mov_8(): + assert_encodes_as(cb32, "MOV8_ri", (R.cl, 25), '\xB1\x19') + def test_mov_16(): + # only 'MOV16_*r' and 'MOV16_*i' are supported # 32-bit assert_encodes_as(cb32, "MOV16", (ecx, ebx), '\x66\x89\xD9') - assert_encodes_as(cb32, "MOV16", (ecx, ImmedLoc(12345)), '\x66\xB9\x39\x30') - + assert_encodes_as(cb32, "MOV16", + (AddressLoc(ecx, ImmedLoc(16), 0, 0), ebx), + '\x66\x89\x59\x10') # 64-bit assert_encodes_as(cb64, "MOV16", (r8, ebx), '\x66\x41\x89\xD8') # 11 011 000 assert_encodes_as(cb64, "MOV16", (ebx, r8), '\x66\x44\x89\xC3') # 11 000 011 - assert_encodes_as(cb64, "MOV16", (ecx, ebx), '\x66\x40\x89\xD9') - assert_encodes_as(cb64, "MOV16", (ecx, ImmedLoc(12345)), '\x66\xB9\x39\x30') + assert_encodes_as(cb64, "MOV16", (ecx, ebx), '\x66\x89\xD9') # for the next case we don't pick the most efficient encoding, but well - expected = '\x66\x40\xC7\xC1\xC7\xCF' # could be '\x66\xB9\xC7\xCF' + expected = '\x66\xC7\xC1\x39\x30' # could be '\x66\xB9\x39\x30' + assert_encodes_as(cb64, "MOV16", (ecx, ImmedLoc(12345)), expected) + # for the next case we don't pick the most efficient encoding, but well + expected = '\x66\xC7\xC1\xC7\xCF' # could be '\x66\xB9\xC7\xCF' assert_encodes_as(cb64, "MOV16", (ecx, ImmedLoc(-12345)), expected) - assert_encodes_as(cb64, "MOV16", (r9, ImmedLoc(12345)), '\x66\x41\xB9\x39\x30') + # for the next case we don't pick the most efficient encoding, but well + expected = '\x66\x41\xC7\xC1\x39\x30' # could be '\x66\x41\xB9\x39\x30' + assert_encodes_as(cb64, "MOV16", (r9, ImmedLoc(12345)), expected) # for the next case we don't pick the most efficient encoding, but well expected = '\x66\x41\xC7\xC1\xC7\xCF' # could be '\x66\x41\xB9\xC7\xCF' assert_encodes_as(cb64, "MOV16", (r9, ImmedLoc(-12345)), expected) - assert_encodes_as(cb64, "MOV16", (AddressLoc(r13, ImmedLoc(0), 0, 0), ImmedLoc(12345)), '\x66\x41\xC7\x45\x00\x39\x30') + assert_encodes_as(cb64, "MOV16", + (AddressLoc(r13, ImmedLoc(0), 0, 0), ImmedLoc(12345)), + '\x66\x41\xC7\x45\x00\x39\x30') def test_cmp_16(): + # only 'CMP16_mi' is supported # 32-bit - assert_encodes_as(cb32, "CMP16", (ecx, ebx), '\x66\x39\xD9') - assert_encodes_as(cb32, "CMP16", (ecx, ImmedLoc(12345)), '\x66\x81\xF9\x39\x30') - + assert_encodes_as(cb32, "CMP16", + (AddressLoc(ecx, ImmedLoc(0), 0, 0), ImmedLoc(21324)), + '\x66\x81\x39\x4c\x53') + assert_encodes_as(cb32, "CMP16", + (AddressLoc(esi, ImmedLoc(2), 0, 0), ImmedLoc(-12345)), + '\x66\x81\x7e\x02\xc7\xcf') # 64-bit - assert_encodes_as(cb64, "CMP16", (r8, ebx), '\x66\x41\x39\xD8') # 11 011 000 - assert_encodes_as(cb64, "CMP16", (ebx, r8), '\x66\x44\x39\xC3') # 11 000 011 - assert_encodes_as(cb64, "CMP16", (ecx, ebx), '\x66\x40\x39\xD9') - assert_encodes_as(cb64, "CMP16", (ecx, ImmedLoc(12345)), '\x66\x40\x81\xF9\x39\x30') - assert_encodes_as(cb64, "CMP16", (AddressLoc(r13, ImmedLoc(0), 0, 0), ImmedLoc(12345)), '\x66\x41\x81\x7D\x00\x39\x30') + assert_encodes_as(cb64, "CMP16", + (AddressLoc(r13, ImmedLoc(0), 0, 0), ImmedLoc(12345)), + '\x66\x41\x81\x7D\x00\x39\x30') def test_relocation(): from rpython.rtyper.lltypesystem import lltype, rffi From noreply at buildbot.pypy.org Sat Apr 20 20:16:29 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Sat, 20 Apr 2013 20:16:29 +0200 (CEST) Subject: [pypy-commit] pypy py3k: py3 str envs need CREATE_UNICODE_ENVIRONMENT Message-ID: <20130420181629.BCF591C1463@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63530:2d36a06d788f Date: 2013-04-20 11:15 -0700 http://bitbucket.org/pypy/pypy/changeset/2d36a06d788f/ Log: py3 str envs need CREATE_UNICODE_ENVIRONMENT diff --git a/lib_pypy/_subprocess.py b/lib_pypy/_subprocess.py --- a/lib_pypy/_subprocess.py +++ b/lib_pypy/_subprocess.py @@ -152,6 +152,7 @@ si.hStdError = int(startup_info.hStdError) pi = _PROCESS_INFORMATION() + flags |= CREATE_UNICODE_ENVIRONMENT if env is not None: envbuf = "" @@ -170,9 +171,10 @@ return _handle(pi.hProcess), _handle(pi.hThread), pi.dwProcessID, pi.dwThreadID STARTF_USESHOWWINDOW = 0x001 STARTF_USESTDHANDLES = 0x100 -SW_HIDE = 0 -CREATE_NEW_CONSOLE = 0x010 +SW_HIDE = 0 +CREATE_NEW_CONSOLE = 0x010 CREATE_NEW_PROCESS_GROUP = 0x200 +CREATE_UNICODE_ENVIRONMENT = 0x400 def WaitForSingleObject(handle, milliseconds): res = _WaitForSingleObject(int(handle), milliseconds) From noreply at buildbot.pypy.org Sat Apr 20 20:45:34 2013 From: noreply at buildbot.pypy.org (mattip) Date: Sat, 20 Apr 2013 20:45:34 +0200 (CEST) Subject: [pypy-commit] pypy win32-fixes3: merge default into branch Message-ID: <20130420184534.19C981C01E1@cobra.cs.uni-duesseldorf.de> Author: mattip Branch: win32-fixes3 Changeset: r63531:7e95e169bc14 Date: 2013-04-20 21:45 +0300 http://bitbucket.org/pypy/pypy/changeset/7e95e169bc14/ Log: merge default into branch diff too long, truncating to 2000 out of 2200 lines diff --git a/Makefile b/Makefile new file mode 100644 --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ + +all: pypy-c + +pypy-c: + @echo "Building PyPy with JIT, it'll take about 40 minutes and 4G of RAM" + @sleep 3 + rpython/bin/rpython -Ojit pypy/goal/targetpypystandalone.py diff --git a/README.rst b/README.rst --- a/README.rst +++ b/README.rst @@ -22,3 +22,16 @@ and send us feedback! the pypy-dev team + +Building +======== + +build with:: + + rpython/bin/rpython -Ojit pypy/goal/targetpypystandalone.py + +This ends up with ``pypy-c`` binary in the main pypy directory. We suggest +to use virtualenv with the resulting pypy-c as the interpreter, you can +find more details about various installation schemes here: + +http://doc.pypy.org/en/latest/getting-started.html#installing-pypy diff --git a/lib-python/2.7/json/decoder.py b/lib-python/2.7/json/decoder.py --- a/lib-python/2.7/json/decoder.py +++ b/lib-python/2.7/json/decoder.py @@ -162,7 +162,7 @@ if nextchar == '}': if object_pairs_hook is not None: result = object_pairs_hook(pairs) - return result, end + return result, end + 1 pairs = {} if object_hook is not None: pairs = object_hook(pairs) diff --git a/lib-python/2.7/json/tests/test_decode.py b/lib-python/2.7/json/tests/test_decode.py --- a/lib-python/2.7/json/tests/test_decode.py +++ b/lib-python/2.7/json/tests/test_decode.py @@ -44,6 +44,7 @@ object_pairs_hook=OrderedDict, object_hook=lambda x: None), OrderedDict(p)) + self.assertEqual(self.loads("{}", object_pairs_hook=list), []) class TestPyDecode(TestDecode, PyTest): pass diff --git a/pypy/doc/arm.rst b/pypy/doc/arm.rst --- a/pypy/doc/arm.rst +++ b/pypy/doc/arm.rst @@ -153,7 +153,7 @@ :: - pypy /rpython/bin/rpython -Ojit --platform=arm --gcrootfinder=shadowstack --jit-backend=armv7 targetpypystandalone.py + pypy /rpython/bin/rpython -Ojit --platform=arm --gcrootfinder=shadowstack --jit-backend=arm targetpypystandalone.py The gcrootfinder option is needed to work around `issue 1377`_ and the jit-backend works around `issue 1376`_ diff --git a/pypy/doc/config/translation.gcrootfinder.txt b/pypy/doc/config/translation.gcrootfinder.txt --- a/pypy/doc/config/translation.gcrootfinder.txt +++ b/pypy/doc/config/translation.gcrootfinder.txt @@ -9,7 +9,9 @@ - ``--gcrootfinder=asmgcc``: use assembler hackery to find the roots directly from the normal stack. This is a bit faster, but platform specific. It works so far with GCC or MSVC, - on i386 and x86-64. + on i386 and x86-64. It is tested only on Linux (where it is + the default) so other platforms (as well as MSVC) may need + various fixes before they can be used. You may have to force the use of the shadowstack root finder if you are running into troubles or if you insist on translating diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -43,11 +43,11 @@ Rudimentary support for bytearray in RPython .. branch: refactor-call_release_gil -Fix a bug which casused cffi to return the wrong result when calling a C +Fix a bug which caused cffi to return the wrong result when calling a C function which calls a Python callback which forces the frames .. branch: virtual-raw-mallocs -JIT optimizations which makes cffi calls even faster, by removing the need to +JIT optimizations which make cffi calls even faster, by removing the need to allocate a temporary buffer where to store the arguments. .. branch: improve-docs-2 diff --git a/pypy/module/thread/threadlocals.py b/pypy/module/thread/threadlocals.py --- a/pypy/module/thread/threadlocals.py +++ b/pypy/module/thread/threadlocals.py @@ -52,7 +52,7 @@ def signals_enabled(self): ec = self.getvalue() - return ec._signals_enabled + return ec is not None and ec._signals_enabled def enable_signals(self, space): ec = self.getvalue() @@ -72,10 +72,12 @@ def leave_thread(self, space): "Notification that the current thread is about to stop." from pypy.module.thread.os_local import thread_is_stopping - try: - thread_is_stopping(self.getvalue()) - finally: - self.setvalue(None) + ec = self.getvalue() + if ec is not None: + try: + thread_is_stopping(ec) + finally: + self.setvalue(None) def reinit_threads(self, space): "Called in the child process after a fork()" diff --git a/rpython/annotator/model.py b/rpython/annotator/model.py --- a/rpython/annotator/model.py +++ b/rpython/annotator/model.py @@ -527,6 +527,7 @@ s_Int = SomeInteger() s_ImpossibleValue = SomeImpossibleValue() s_Str0 = SomeString(no_nul=True) +s_Unicode0 = SomeUnicodeString(no_nul=True) # ____________________________________________________________ diff --git a/rpython/config/translationoption.py b/rpython/config/translationoption.py --- a/rpython/config/translationoption.py +++ b/rpython/config/translationoption.py @@ -115,7 +115,7 @@ ("translation.gcrootfinder", DEFL_ROOTFINDER_WITHJIT), ("translation.list_comprehension_operations", True)]), ChoiceOption("jit_backend", "choose the backend for the JIT", - ["auto", "x86", "x86-without-sse2", 'armv7', 'armv7hf', 'armv6hf'], + ["auto", "x86", "x86-without-sse2", 'arm'], default="auto", cmdline="--jit-backend"), ChoiceOption("jit_profiler", "integrate profiler support into the JIT", ["off", "oprofile"], diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -3,6 +3,7 @@ import os from rpython.jit.backend.arm import conditions as c, registers as r +from rpython.jit.backend.arm import shift from rpython.jit.backend.arm.arch import (WORD, DOUBLE_WORD, FUNC_ALIGN, JITFRAME_FIXED_SIZE) from rpython.jit.backend.arm.codebuilder import InstrBuilder, OverwritingBuilder @@ -12,8 +13,9 @@ CoreRegisterManager, check_imm_arg, VFPRegisterManager, operations as regalloc_operations, operations_with_guard as regalloc_operations_with_guard) -from rpython.jit.backend.llsupport import jitframe +from rpython.jit.backend.llsupport import jitframe, rewrite from rpython.jit.backend.llsupport.assembler import DEBUG_COUNTER, debug_bridge, BaseAssembler +from rpython.jit.backend.llsupport.regalloc import get_scale, valid_addressing_size from rpython.jit.backend.llsupport.asmmemmgr import MachineDataBlockWrapper from rpython.jit.backend.model import CompiledLoopToken from rpython.jit.codewriter.effectinfo import EffectInfo @@ -25,7 +27,6 @@ from rpython.rlib.rarithmetic import r_uint from rpython.rtyper.annlowlevel import llhelper, cast_instance_to_gcref from rpython.rtyper.lltypesystem import lltype, rffi -from rpython.jit.backend.arm.detect import detect_hardfloat class AssemblerARM(ResOpAssembler): @@ -51,14 +52,13 @@ def setup_once(self): BaseAssembler.setup_once(self) - self.hf_abi = detect_hardfloat() def setup(self, looptoken): assert self.memcpy_addr != 0, 'setup_once() not called?' if we_are_translated(): self.debug = False self.current_clt = looptoken.compiled_loop_token - self.mc = InstrBuilder(self.cpu.arch_version) + self.mc = InstrBuilder(self.cpu.cpuinfo.arch_version) self.pending_guards = [] assert self.datablockwrapper is None allblocks = self.get_asmmemmgr_blocks(looptoken) @@ -82,20 +82,20 @@ if not self.cpu.propagate_exception_descr: return # not supported (for tests, or non-translated) # - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) self._store_and_reset_exception(mc, r.r0) ofs = self.cpu.get_ofs_of_frame_field('jf_guard_exc') # make sure ofs fits into a register assert check_imm_arg(ofs) - mc.LDR_ri(r.r0.value, r.fp.value, imm=ofs) + self.store_reg(mc, r.r0, r.fp, ofs) propagate_exception_descr = rffi.cast(lltype.Signed, cast_instance_to_gcref(self.cpu.propagate_exception_descr)) # put propagate_exception_descr into frame ofs = self.cpu.get_ofs_of_frame_field('jf_descr') # make sure ofs fits into a register assert check_imm_arg(ofs) - mc.gen_load_int(r.r0.value, propagate_exception_descr) - mc.STR_ri(r.r0.value, r.fp.value, imm=ofs) + mc.gen_load_int(r.r1.value, propagate_exception_descr) + self.store_reg(mc, r.r0, r.fp, ofs) mc.MOV_rr(r.r0.value, r.fp.value) self.gen_func_epilog(mc) rawstart = mc.materialize(self.cpu.asmmemmgr, []) @@ -167,7 +167,7 @@ # | my own retaddr | <-- sp # +-----------------------+ # - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) # save argument registers and return address mc.PUSH([reg.value for reg in r.argument_regs] + [r.ip.value, r.lr.value]) # stack is aligned here @@ -208,7 +208,7 @@ # write barriers. It must save all registers, and optionally # all vfp registers. It takes a single argument which is in r0. # It must keep stack alignment accordingly. - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) # exc0 = exc1 = None mc.PUSH([r.ip.value, r.lr.value]) # push two words to keep alignment @@ -251,26 +251,60 @@ else: self.wb_slowpath[withcards + 2 * withfloats] = rawstart - def _build_malloc_slowpath(self): - mc = InstrBuilder(self.cpu.arch_version) + def _build_malloc_slowpath(self, kind): + """ While arriving on slowpath, we have a gcpattern on stack 0. + The arguments are passed in r0 and r10, as follows: + + kind == 'fixed': nursery_head in r0 and the size in r1 - r0. + + kind == 'str/unicode': length of the string to allocate in r0. + + kind == 'var': length to allocate in r1, tid in r0, + and itemsize on the stack. + + This function must preserve all registers apart from r0 and r1. + """ + assert kind in ['fixed', 'str', 'unicode', 'var'] + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) + # self._push_all_regs_to_jitframe(mc, [r.r0, r.r1], self.cpu.supports_floats) + # + if kind == 'fixed': + addr = self.cpu.gc_ll_descr.get_malloc_slowpath_addr() + elif kind == 'str': + addr = self.cpu.gc_ll_descr.get_malloc_fn_addr('malloc_str') + elif kind == 'unicode': + addr = self.cpu.gc_ll_descr.get_malloc_fn_addr('malloc_unicode') + else: + addr = self.cpu.gc_ll_descr.get_malloc_slowpath_array_addr() + if kind == 'fixed': + # stack layout: [gcmap] + # At this point we know that the values we need to compute the size + # are stored in r0 and r1. + mc.SUB_rr(r.r0.value, r.r1.value, r.r0.value) # compute the size we want + + if hasattr(self.cpu.gc_ll_descr, 'passes_frame'): + mc.MOV_rr(r.r1.value, r.fp.value) + elif kind == 'str' or kind == 'unicode': + # stack layout: [gcmap] + mc.MOV_rr(r.r0.value, r.r1.value) + else: # var + # stack layout: [gcmap][itemsize]... + # tid is in r0 + # length is in r1 + mc.MOV_rr(r.r2.value, r.r1.value) + mc.MOV_rr(r.r1.value, r.r0.value) + mc.POP([r.r0.value]) # load itemsize + # store the gc pattern + mc.POP([r.r4.value]) ofs = self.cpu.get_ofs_of_frame_field('jf_gcmap') - # store the gc pattern - mc.POP([r.r2.value]) - self.store_reg(mc, r.r2, r.fp, ofs) + self.store_reg(mc, r.r4, r.fp, ofs) + # # We need to push two registers here because we are going to make a # call an therefore the stack needs to be 8-byte aligned mc.PUSH([r.ip.value, r.lr.value]) - # At this point we know that the values we need to compute the size - # are stored in r0 and r1. - mc.SUB_rr(r.r0.value, r.r1.value, r.r0.value) # compute the size we want - - if hasattr(self.cpu.gc_ll_descr, 'passes_frame'): - mc.MOV_rr(r.r1.value, r.fp.value) - - addr = self.cpu.gc_ll_descr.get_malloc_slowpath_addr() + # mc.BL(addr) - # # If the slowpath malloc failed, we raise a MemoryError that # always interrupts the current loop, as a "good enough" @@ -290,8 +324,9 @@ # return mc.POP([r.ip.value, r.pc.value]) + # rawstart = mc.materialize(self.cpu.asmmemmgr, []) - self.malloc_slowpath = rawstart + return rawstart def _reload_frame_if_necessary(self, mc): gcrootmap = self.cpu.gc_ll_descr.gcrootmap @@ -364,7 +399,7 @@ self.load_reg(mc, vfpr, r.fp, ofs) def _build_failure_recovery(self, exc, withfloats=False): - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) self._push_all_regs_to_jitframe(mc, [], withfloats) if exc: @@ -647,7 +682,7 @@ expected_size=expected_size) def _patch_frame_depth(self, adr, allocated_depth): - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) mc.gen_load_int(r.lr.value, allocated_depth) mc.copy_to_raw_memory(adr) @@ -723,7 +758,7 @@ # f) store the address of the new jitframe in the shadowstack # c) set the gcmap field to 0 in the new jitframe # g) restore registers and return - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) self._push_all_regs_to_jitframe(mc, [], self.cpu.supports_floats) # this is the gcmap stored by push_gcmap(mov=True) in _check_stack_frame # and the expected_size pushed in _check_stack_frame @@ -783,7 +818,7 @@ self.target_tokens_currently_compiling = None def _patch_stackadjust(self, adr, allocated_depth): - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) mc.gen_load_int(r.lr.value, allocated_depth) mc.copy_to_raw_memory(adr) @@ -823,7 +858,7 @@ # patch the guard jumpt to the stub # overwrite the generate NOP with a B_offs to the pos of the # stub - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) mc.B_offs(relative_offset, c.get_opposite_of(tok.fcond)) mc.copy_to_raw_memory(guard_pos) else: @@ -902,7 +937,7 @@ self.mc.ASR_ri(resloc.value, resloc.value, 16) def patch_trace(self, faildescr, looptoken, bridge_addr, regalloc): - b = InstrBuilder(self.cpu.arch_version) + b = InstrBuilder(self.cpu.cpuinfo.arch_version) patch_addr = faildescr._arm_failure_recovery_block assert patch_addr != 0 b.B(bridge_addr) @@ -1170,21 +1205,17 @@ else: raise AssertionError('Trying to pop to an invalid location') - def malloc_cond(self, nursery_free_adr, nursery_top_adr, sizeloc, gcmap): - if sizeloc.is_imm(): # must be correctly aligned - assert sizeloc.value & (WORD-1) == 0 + def malloc_cond(self, nursery_free_adr, nursery_top_adr, size, gcmap): + assert size & (WORD-1) == 0 self.mc.gen_load_int(r.r0.value, nursery_free_adr) self.mc.LDR_ri(r.r0.value, r.r0.value) - if sizeloc.is_imm(): - if check_imm_arg(sizeloc.value): - self.mc.ADD_ri(r.r1.value, r.r0.value, sizeloc.value) - else: - self.mc.gen_load_int(r.r1.value, sizeloc.value) - self.mc.ADD_rr(r.r1.value, r.r0.value, r.r1.value) + if check_imm_arg(size): + self.mc.ADD_ri(r.r1.value, r.r0.value, size) else: - self.mc.ADD_rr(r.r1.value, r.r0.value, sizeloc.value) + self.mc.gen_load_int(r.r1.value, size) + self.mc.ADD_rr(r.r1.value, r.r0.value, r.r1.value) self.mc.gen_load_int(r.ip.value, nursery_top_adr) self.mc.LDR_ri(r.ip.value, r.ip.value) @@ -1205,6 +1236,128 @@ self.mc.gen_load_int(r.ip.value, nursery_free_adr) self.mc.STR_ri(r.r1.value, r.ip.value) + def malloc_cond_varsize_frame(self, nursery_free_adr, nursery_top_adr, + sizeloc, gcmap): + if sizeloc is r.r0: + self.mc.MOV_rr(r.r1.value, r.r0.value) + sizeloc = r.r1 + self.mc.gen_load_int(r.r0.value, nursery_free_adr) + self.mc.LDR_ri(r.r0.value, r.r0.value) + # + self.mc.ADD_rr(r.r1.value, r.r0.value, sizeloc.value) + # + self.mc.gen_load_int(r.ip.value, nursery_top_adr) + self.mc.LDR_ri(r.ip.value, r.ip.value) + + self.mc.CMP_rr(r.r1.value, r.ip.value) + # + self.push_gcmap(self.mc, gcmap, push=True, cond=c.HI) + + self.mc.BL(self.malloc_slowpath, c=c.HI) + + self.mc.gen_load_int(r.ip.value, nursery_free_adr) + self.mc.STR_ri(r.r1.value, r.ip.value) + + def malloc_cond_varsize(self, kind, nursery_free_adr, nursery_top_adr, + lengthloc, itemsize, maxlength, gcmap, + arraydescr): + from rpython.jit.backend.llsupport.descr import ArrayDescr + assert isinstance(arraydescr, ArrayDescr) + + # lengthloc is the length of the array, which we must not modify! + assert lengthloc is not r.r0 and lengthloc is not r.r1 + if lengthloc.is_reg(): + varsizeloc = lengthloc + else: + assert lengthloc.is_stack() + self.regalloc_mov(lengthloc, r.r1) + varsizeloc = r.r1 + # + if check_imm_arg(maxlength): + self.mc.CMP_ri(varsizeloc.value, maxlength) + else: + self.mc.gen_load_int(r.ip.value, maxlength) + self.mc.CMP_rr(varsizeloc.value, r.ip.value) + jmp_adr0 = self.mc.currpos() # jump to (large) + self.mc.BKPT() + # + self.mc.gen_load_int(r.r0.value, nursery_free_adr) + self.mc.LDR_ri(r.r0.value, r.r0.value) + + + if valid_addressing_size(itemsize): + shiftsize = get_scale(itemsize) + else: + shiftsize = self._mul_const_scaled(self.mc, r.lr, varsizeloc, + itemsize) + varsizeloc = r.lr + # now varsizeloc is a register != r0. The size of + # the variable part of the array is (varsizeloc << shiftsize) + assert arraydescr.basesize >= self.gc_minimal_size_in_nursery + constsize = arraydescr.basesize + self.gc_size_of_header + force_realignment = (itemsize % WORD) != 0 + if force_realignment: + constsize += WORD - 1 + self.mc.gen_load_int(r.ip.value, constsize) + # constsize + (varsizeloc << shiftsize) + self.mc.ADD_rr(r.r1.value, r.ip.value, varsizeloc.value, + imm=shiftsize, shifttype=shift.LSL) + self.mc.ADD_rr(r.r1.value, r.r1.value, r.r0.value) + if force_realignment: + self.mc.MVN_ri(r.ip.value, imm=(WORD - 1)) + self.mc.AND_rr(r.r1.value, r.r1.value, r.ip.value) + # now r1 contains the total size in bytes, rounded up to a multiple + # of WORD, plus nursery_free_adr + # + self.mc.gen_load_int(r.ip.value, nursery_top_adr) + self.mc.LDR_ri(r.ip.value, r.ip.value) + + self.mc.CMP_rr(r.r1.value, r.ip.value) + jmp_adr1 = self.mc.currpos() # jump to (after-call) + self.mc.BKPT() + # + # (large) + currpos = self.mc.currpos() + pmc = OverwritingBuilder(self.mc, jmp_adr0, WORD) + pmc.B_offs(currpos, c.GT) + # + # save the gcmap + self.push_gcmap(self.mc, gcmap, push=True) + # + if kind == rewrite.FLAG_ARRAY: + self.mc.gen_load_int(r.r0.value, arraydescr.tid) + self.regalloc_mov(lengthloc, r.r1) + self.regalloc_push(imm(itemsize)) + addr = self.malloc_slowpath_varsize + else: + if kind == rewrite.FLAG_STR: + addr = self.malloc_slowpath_str + else: + assert kind == rewrite.FLAG_UNICODE + addr = self.malloc_slowpath_unicode + self.regalloc_mov(lengthloc, r.r1) + self.mc.BL(addr) + # + jmp_location = self.mc.currpos() # jump to (done) + self.mc.BKPT() + # (after-call) + currpos = self.mc.currpos() + pmc = OverwritingBuilder(self.mc, jmp_adr1, WORD) + pmc.B_offs(currpos, c.LS) + # + # write down the tid, but not if it's the result of the CALL + self.mc.gen_load_int(r.ip.value, arraydescr.tid) + self.mc.STR_ri(r.ip.value, r.r0.value) + + # while we're at it, this line is not needed if we've done the CALL + self.mc.gen_load_int(r.ip.value, nursery_free_adr) + self.mc.STR_ri(r.r1.value, r.ip.value) + # (done) + # skip instructions after call + currpos = self.mc.currpos() + pmc = OverwritingBuilder(self.mc, jmp_location, WORD) + pmc.B_offs(currpos) + def push_gcmap(self, mc, gcmap, push=False, store=False, cond=c.AL): ptr = rffi.cast(lltype.Signed, gcmap) if push: @@ -1222,6 +1375,32 @@ mc.gen_load_int(r.ip.value, 0) self.store_reg(mc, r.ip, r.fp, ofs) + def _mul_const_scaled(self, mc, targetreg, sourcereg, itemsize): + """Produce one operation to do roughly + targetreg = sourcereg * itemsize + except that the targetreg may still need shifting by 0,1,2,3. + """ + if (itemsize & 7) == 0: + shiftsize = 3 + elif (itemsize & 3) == 0: + shiftsize = 2 + elif (itemsize & 1) == 0: + shiftsize = 1 + else: + shiftsize = 0 + itemsize >>= shiftsize + # + if valid_addressing_size(itemsize - 1): + self.mc.ADD_rr(targetreg.value, sourcereg.value, sourcereg.value, + imm=get_scale(itemsize - 1), shifttype=shift.LSL) + elif valid_addressing_size(itemsize): + self.mc.LSL_ri(targetreg.value, sourcereg.value, + get_scale(itemsize)) + else: + mc.gen_load_int(targetreg.value, itemsize) + mc.MUL(targetreg.value, sourcereg.value, targetreg.value) + # + return shiftsize def not_implemented(msg): os.write(2, '[ARM/asm] %s\n' % msg) diff --git a/rpython/jit/backend/arm/detect.py b/rpython/jit/backend/arm/detect.py --- a/rpython/jit/backend/arm/detect.py +++ b/rpython/jit/backend/arm/detect.py @@ -1,7 +1,10 @@ +import os + from rpython.translator.tool.cbuild import ExternalCompilationInfo +from rpython.rtyper.tool import rffi_platform from rpython.rlib.clibffi import FFI_DEFAULT_ABI, FFI_SYSV, FFI_VFP -from rpython.rtyper.tool import rffi_platform from rpython.translator.platform import CompilationError +from rpython.rlib.debug import debug_print, debug_start, debug_stop eci = ExternalCompilationInfo( post_include_bits=[""" @@ -26,3 +29,37 @@ return True except CompilationError: return False + + +def detect_arch_version(filename="/proc/cpuinfo"): + fd = os.open(filename, os.O_RDONLY, 0644) + n = 0 + debug_start("jit-backend-arch") + try: + buf = os.read(fd, 2048) + if not buf: + debug_print("Could not detect ARM architecture " + "version, assuming", "ARMv%d" % n) + n = 6 # we asume ARMv6 as base case + finally: + os.close(fd) + # "Processor : ARMv%d-compatible processor rev 7 (v6l)" + i = buf.find('ARMv') + if i == -1: + n = 6 + debug_print("Could not detect architecture version, " + "falling back to", "ARMv%d" % n) + else: + n = int(buf[i + 4]) + + if n < 6: + raise ValueError("Unsupported ARM architecture version") + + debug_print("Detected", "ARMv%d" % n) + + if n > 7: + n = 7 + debug_print("Architecture version not explicitly supported, " + "falling back to", "ARMv%d" % n) + debug_stop("jit-backend-arch") + return n diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -191,7 +191,7 @@ return fcond def _emit_guard(self, op, arglocs, fcond, save_exc, - is_guard_not_invalidated=False, + is_guard_not_invalidated=False, is_guard_not_forced=False): assert isinstance(save_exc, bool) assert isinstance(fcond, int) @@ -297,7 +297,7 @@ return self._emit_guard(op, locs, fcond, save_exc=False, is_guard_not_invalidated=True) - def emit_op_label(self, op, arglocs, regalloc, fcond): + def emit_op_label(self, op, arglocs, regalloc, fcond): self._check_frame_depth_debug(self.mc) return fcond @@ -354,7 +354,7 @@ # whether to worry about a CALL that can collect; this # is always true except in call_release_gil can_collect=True): - if self.hf_abi: + if self.cpu.cpuinfo.hf_abi: stack_args, adr = self._setup_call_hf(adr, arglocs, fcond, resloc, result_info) else: @@ -382,7 +382,7 @@ # ensure the result is wellformed and stored in the correct location if resloc is not None: - if resloc.is_vfp_reg() and not self.hf_abi: + if resloc.is_vfp_reg() and not self.cpu.cpuinfo.hf_abi: # move result to the allocated register self.mov_to_vfp_loc(r.r0, r.r1, resloc) elif resloc.is_reg() and result_info != (-1, -1): @@ -1230,7 +1230,7 @@ baseofs = self.cpu.get_baseofs_of_frame_field() newlooptoken.compiled_loop_token.update_frame_info( oldlooptoken.compiled_loop_token, baseofs) - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) mc.B(target) mc.copy_to_raw_memory(oldadr) @@ -1320,6 +1320,7 @@ with saved_registers(self.mc, regs_to_save, vfp_regs_to_save): self._emit_call(imm(self.reacqgil_addr), [], fcond, can_collect=False) + self._reload_frame_if_necessary(self.mc) def _store_force_index(self, guard_op): faildescr = guard_op.getdescr() @@ -1334,23 +1335,6 @@ self._alignment_check() return fcond - def emit_op_call_malloc_nursery(self, op, arglocs, regalloc, fcond): - # registers r0 and r1 are allocated for this call - assert len(arglocs) == 1 - sizeloc = arglocs[0] - gc_ll_descr = self.cpu.gc_ll_descr - gcmap = regalloc.get_gcmap([r.r0, r.r1]) - self.malloc_cond( - gc_ll_descr.get_nursery_free_addr(), - gc_ll_descr.get_nursery_top_addr(), - sizeloc, - gcmap - ) - self._alignment_check() - return fcond - emit_op_call_malloc_nursery_varsize_frame = emit_op_call_malloc_nursery - - def _alignment_check(self): if not self.debug: return @@ -1436,7 +1420,7 @@ self.mc.VCVT_f64_f32(r.vfp_ip.value, arg.value) self.mc.VMOV_rc(res.value, r.ip.value, r.vfp_ip.value) return fcond - + def emit_op_cast_singlefloat_to_float(self, op, arglocs, regalloc, fcond): arg, res = arglocs assert res.is_vfp_reg() diff --git a/rpython/jit/backend/arm/regalloc.py b/rpython/jit/backend/arm/regalloc.py --- a/rpython/jit/backend/arm/regalloc.py +++ b/rpython/jit/backend/arm/regalloc.py @@ -2,7 +2,8 @@ from rpython.rlib import rgc from rpython.rlib.debug import debug_print, debug_start, debug_stop from rpython.jit.backend.llsupport.regalloc import FrameManager, \ - RegisterManager, TempBox, compute_vars_longevity, BaseRegalloc + RegisterManager, TempBox, compute_vars_longevity, BaseRegalloc, \ + get_scale from rpython.jit.backend.arm import registers as r from rpython.jit.backend.arm import locations from rpython.jit.backend.arm.locations import imm, get_fp_offset @@ -1011,20 +1012,72 @@ self.rm.force_allocate_reg(op.result, selected_reg=r.r0) t = TempInt() self.rm.force_allocate_reg(t, selected_reg=r.r1) + + sizeloc = size_box.getint() + gc_ll_descr = self.cpu.gc_ll_descr + gcmap = self.get_gcmap([r.r0, r.r1]) self.possibly_free_var(t) - return [imm(size)] + self.assembler.malloc_cond( + gc_ll_descr.get_nursery_free_addr(), + gc_ll_descr.get_nursery_top_addr(), + sizeloc, + gcmap + ) + self.assembler._alignment_check() def prepare_op_call_malloc_nursery_varsize_frame(self, op, fcond): size_box = op.getarg(0) - assert isinstance(size_box, BoxInt) - + assert isinstance(size_box, BoxInt) # we cannot have a const here! + # sizeloc must be in a register, but we can free it now + # (we take care explicitly of conflicts with r0 or r1) + sizeloc = self.rm.make_sure_var_in_reg(size_box) + self.rm.possibly_free_var(size_box) + # self.rm.force_allocate_reg(op.result, selected_reg=r.r0) + # t = TempInt() self.rm.force_allocate_reg(t, selected_reg=r.r1) - argloc = self.make_sure_var_in_reg(size_box, - forbidden_vars=[op.result, t]) + # + gcmap = self.get_gcmap([r.r0, r.r1]) self.possibly_free_var(t) - return [argloc] + # + gc_ll_descr = self.assembler.cpu.gc_ll_descr + self.assembler.malloc_cond_varsize_frame( + gc_ll_descr.get_nursery_free_addr(), + gc_ll_descr.get_nursery_top_addr(), + sizeloc, + gcmap + ) + self.assembler._alignment_check() + + def prepare_op_call_malloc_nursery_varsize(self, op, fcond): + gc_ll_descr = self.assembler.cpu.gc_ll_descr + if not hasattr(gc_ll_descr, 'max_size_of_young_obj'): + raise Exception("unreachable code") + # for boehm, this function should never be called + arraydescr = op.getdescr() + length_box = op.getarg(2) + assert isinstance(length_box, BoxInt) # we cannot have a const here! + # the result will be in r0 + self.rm.force_allocate_reg(op.result, selected_reg=r.r0) + # we need r1 as a temporary + tmp_box = TempBox() + self.rm.force_allocate_reg(tmp_box, selected_reg=r.r1) + gcmap = self.get_gcmap([r.r0, r.r1]) # allocate the gcmap *before* + self.rm.possibly_free_var(tmp_box) + # length_box always survives: it's typically also present in the + # next operation that will copy it inside the new array. It's + # fine to load it from the stack too, as long as it's != r0, r1. + lengthloc = self.rm.loc(length_box) + self.rm.possibly_free_var(length_box) + # + itemsize = op.getarg(1).getint() + maxlength = (gc_ll_descr.max_size_of_young_obj - WORD * 2) / itemsize + self.assembler.malloc_cond_varsize( + op.getarg(0).getint(), + gc_ll_descr.get_nursery_free_addr(), + gc_ll_descr.get_nursery_top_addr(), + lengthloc, itemsize, maxlength, gcmap, arraydescr) prepare_op_debug_merge_point = void prepare_op_jit_debug = void @@ -1211,13 +1264,6 @@ operations_with_guard = [notimplemented_with_guard] * (rop._LAST + 1) -def get_scale(size): - scale = 0 - while (1 << scale) < size: - scale += 1 - assert (1 << scale) == size - return scale - for key, value in rop.__dict__.items(): key = key.lower() if key.startswith('_'): diff --git a/rpython/jit/backend/arm/runner.py b/rpython/jit/backend/arm/runner.py --- a/rpython/jit/backend/arm/runner.py +++ b/rpython/jit/backend/arm/runner.py @@ -7,9 +7,14 @@ from rpython.rlib.jit_hooks import LOOP_RUN_CONTAINER from rpython.rtyper.lltypesystem import lltype, llmemory from rpython.jit.backend.arm.detect import detect_hardfloat +from rpython.jit.backend.arm.detect import detect_arch_version jitframe.STATICSIZE = JITFRAME_FIXED_SIZE +class CPUInfo(object): + hf_abi = False + arch_version = 6 + class AbstractARMCPU(AbstractLLCPU): IS_64_BIT = False @@ -18,6 +23,7 @@ supports_longlong = False # XXX requires an implementation of # read_timestamp that works in user mode supports_singlefloats = not detect_hardfloat() + can_inline_varsize_malloc = True from rpython.jit.backend.arm.arch import JITFRAME_FIXED_SIZE all_reg_indexes = range(len(all_regs)) @@ -25,13 +31,11 @@ float_regs = VFPRegisterManager.all_regs frame_reg = fp - hf_abi = False # use hard float abi flag - arch_version = 7 - def __init__(self, rtyper, stats, opts=None, translate_support_code=False, gcdescr=None): AbstractLLCPU.__init__(self, rtyper, stats, opts, translate_support_code, gcdescr) + self.cpuinfo = CPUInfo() def set_debug(self, flag): return self.assembler.set_debug(flag) @@ -46,6 +50,8 @@ self.assembler = AssemblerARM(self, self.translate_support_code) def setup_once(self): + self.cpuinfo.arch_version = detect_arch_version() + self.cpuinfo.hf_abi = detect_hardfloat() self.assembler.setup_once() def finish_once(self): @@ -89,7 +95,7 @@ from rpython.jit.backend.arm.codebuilder import InstrBuilder for jmp, tgt in looptoken.compiled_loop_token.invalidate_positions: - mc = InstrBuilder(self.arch_version) + mc = InstrBuilder(self.cpuinfo.arch_version) mc.B_offs(tgt) mc.copy_to_raw_memory(jmp) # positions invalidated @@ -113,10 +119,5 @@ class CPU_ARM(AbstractARMCPU): - """ARM v7""" - backend_name = "armv7" - -class CPU_ARMv6(AbstractARMCPU): - """ ARM v6, uses hardfp ABI, requires vfp""" - arch_version = 6 - backend_name = "armv6" + """ARM""" + backend_name = "arm" diff --git a/rpython/jit/backend/arm/test/test_detect.py b/rpython/jit/backend/arm/test/test_detect.py new file mode 100644 --- /dev/null +++ b/rpython/jit/backend/arm/test/test_detect.py @@ -0,0 +1,48 @@ +import py +from rpython.tool.udir import udir +from rpython.jit.backend.arm.detect import detect_arch_version + +cpuinfo = "Processor : ARMv%d-compatible processor rev 7 (v6l)""" +cpuinfo2 = """processor : 0 +vendor_id : GenuineIntel +cpu family : 6 +model : 23 +model name : Intel(R) Core(TM)2 Duo CPU E8400 @ 3.00GHz +stepping : 10 +microcode : 0xa07 +cpu MHz : 2997.000 +cache size : 6144 KB +physical id : 0 +siblings : 2 +core id : 0 +cpu cores : 2 +apicid : 0 +initial apicid : 0 +fpu : yes +fpu_exception : yes +cpuid level : 13 +wp : yes +flags : fpu vme ... +bogomips : 5993.08 +clflush size : 64 +cache_alignment : 64 +address sizes : 36 bits physical, 48 bits virtual +power management: +""" + +def write_cpuinfo(info): + filepath = udir.join('get_arch_version') + filepath.write(info) + return str(filepath) + + +def test_detect_arch_version(): + # currently supported cases + for i in (6, 7, ): + filepath = write_cpuinfo(cpuinfo % i) + assert detect_arch_version(filepath) == i + # unsupported cases + assert detect_arch_version(write_cpuinfo(cpuinfo % 8)) == 7 + py.test.raises(ValueError, + 'detect_arch_version(write_cpuinfo(cpuinfo % 5))') + assert detect_arch_version(write_cpuinfo(cpuinfo2)) == 6 diff --git a/rpython/jit/backend/arm/test/test_runner.py b/rpython/jit/backend/arm/test/test_runner.py --- a/rpython/jit/backend/arm/test/test_runner.py +++ b/rpython/jit/backend/arm/test/test_runner.py @@ -10,6 +10,7 @@ from rpython.rtyper.annlowlevel import llhelper from rpython.jit.codewriter.effectinfo import EffectInfo from rpython.jit.metainterp.history import JitCellToken, TargetToken +from rpython.jit.backend.arm.detect import detect_arch_version CPU = getcpuclass() @@ -27,7 +28,8 @@ bridge_loop_instructions = ['ldr', 'mov', 'nop', 'cmp', 'bge', 'push', 'mov', 'mov', 'push', 'mov', 'mov', 'blx', 'mov', 'mov', 'bx'] - if CPU.backend_name.startswith('armv7'): + arch_version = detect_arch_version() + if arch_version == 7: bridge_loop_instructions = ['ldr', 'mov', 'nop', 'cmp', 'bge', 'push', 'mov', 'mov', 'push', 'mov', 'mov', 'blx', 'mov', 'mov', 'bx'] diff --git a/rpython/jit/backend/detect_cpu.py b/rpython/jit/backend/detect_cpu.py --- a/rpython/jit/backend/detect_cpu.py +++ b/rpython/jit/backend/detect_cpu.py @@ -33,8 +33,8 @@ 'x86_64': 'x86', 'amd64': 'x86', # freebsd 'AMD64': 'x86', # win64 - 'armv7l': 'armv7', - 'armv6l': 'armv6', + 'armv7l': 'arm', + 'armv6l': 'arm', }[mach] except KeyError: return mach @@ -75,9 +75,7 @@ return "rpython.jit.backend.x86.runner", "CPU_X86_64" elif backend_name == 'cli': return "rpython.jit.backend.cli.runner", "CliCPU" - elif backend_name.startswith('armv6'): - return "rpython.jit.backend.arm.runner", "CPU_ARMv6" - elif backend_name.startswith('armv7'): + elif backend_name.startswith('arm'): return "rpython.jit.backend.arm.runner", "CPU_ARM" else: raise ProcessorAutodetectError, ( diff --git a/rpython/jit/backend/llsupport/regalloc.py b/rpython/jit/backend/llsupport/regalloc.py --- a/rpython/jit/backend/llsupport/regalloc.py +++ b/rpython/jit/backend/llsupport/regalloc.py @@ -740,6 +740,16 @@ op = Fake(None) return op.is_comparison() or op.is_ovf() +def valid_addressing_size(size): + return size == 1 or size == 2 or size == 4 or size == 8 + +def get_scale(size): + assert valid_addressing_size(size) + if size < 4: + return size - 1 # 1, 2 => 0, 1 + else: + return (size >> 2) + 1 # 4, 8 => 2, 3 + def not_implemented(msg): os.write(2, '[llsupport/regalloc] %s\n' % msg) diff --git a/rpython/jit/backend/test/runner_test.py b/rpython/jit/backend/test/runner_test.py --- a/rpython/jit/backend/test/runner_test.py +++ b/rpython/jit/backend/test/runner_test.py @@ -1057,6 +1057,28 @@ r = self.cpu.bh_getinteriorfield_gc_i(a_box.getref_base(), 4, vsdescr) assert r == 4 + def test_array_of_structs_all_sizes(self): + # x86 has special support that can be used for sizes + # 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 16, 18, 20, 24, 32, 36, 40, 64, 72 + for length in range(1, 75): + ITEM = lltype.FixedSizeArray(lltype.Char, length) + a_box, A = self.alloc_array_of(ITEM, 5) + a = a_box.getref(lltype.Ptr(A)) + middle = length // 2 + a[3][middle] = chr(65 + length) + fdescr = self.cpu.interiorfielddescrof(A, 'item%d' % middle) + r = self.execute_operation(rop.GETINTERIORFIELD_GC, + [a_box, BoxInt(3)], + 'int', descr=fdescr) + r = r.getint() + assert r == 65 + length + self.execute_operation(rop.SETINTERIORFIELD_GC, + [a_box, BoxInt(2), BoxInt(r + 1)], + 'void', descr=fdescr) + r1 = self.cpu.bh_getinteriorfield_gc_i(a_box.getref_base(), 2, + fdescr) + assert r1 == r + 1 + def test_string_basic(self): s_box = self.alloc_string("hello\xfe") r = self.execute_operation(rop.STRLEN, [s_box], 'int') @@ -3913,3 +3935,20 @@ descr = self.cpu.get_latest_descr(frame) assert descr.identifier == 42 assert not self.cpu.grab_exc_value(frame) + + def test_setarrayitem_raw_short(self): + # setarrayitem_raw(140737353744432, 0, 30583, descr=) + A = rffi.CArray(rffi.SHORT) + arraydescr = self.cpu.arraydescrof(A) + a = lltype.malloc(A, 2, flavor='raw') + a[0] = rffi.cast(rffi.SHORT, 666) + a[1] = rffi.cast(rffi.SHORT, 777) + addr = llmemory.cast_ptr_to_adr(a) + a_int = heaptracker.adr2int(addr) + print 'a_int:', a_int + self.execute_operation(rop.SETARRAYITEM_RAW, + [ConstInt(a_int), ConstInt(0), ConstInt(-7654)], + 'void', descr=arraydescr) + assert rffi.cast(lltype.Signed, a[0]) == -7654 + assert rffi.cast(lltype.Signed, a[1]) == 777 + lltype.free(a, flavor='raw') diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -13,8 +13,9 @@ from rpython.rtyper.annlowlevel import llhelper, cast_instance_to_gcref from rpython.rlib.jit import AsmInfo from rpython.jit.backend.model import CompiledLoopToken -from rpython.jit.backend.x86.regalloc import (RegAlloc, get_ebp_ofs, _get_scale, - gpr_reg_mgr_cls, xmm_reg_mgr_cls, _valid_addressing_size) +from rpython.jit.backend.x86.regalloc import (RegAlloc, get_ebp_ofs, + gpr_reg_mgr_cls, xmm_reg_mgr_cls) +from rpython.jit.backend.llsupport.regalloc import (get_scale, valid_addressing_size) from rpython.jit.backend.x86.arch import (FRAME_FIXED_SIZE, WORD, IS_X86_64, JITFRAME_FIXED_SIZE, IS_X86_32, PASS_ON_MY_FRAME) @@ -1523,7 +1524,7 @@ base_loc, ofs_loc, size_loc, ofs, sign_loc = arglocs assert isinstance(ofs, ImmedLoc) assert isinstance(size_loc, ImmedLoc) - scale = _get_scale(size_loc.value) + scale = get_scale(size_loc.value) src_addr = addr_add(base_loc, ofs_loc, ofs.value, scale) self.load_from_mem(resloc, src_addr, size_loc, sign_loc) @@ -1537,22 +1538,50 @@ src_addr = addr_add(base_loc, ofs_loc, ofs.value, 0) self.load_from_mem(resloc, src_addr, size_loc, sign_loc) + def _imul_const_scaled(self, mc, targetreg, sourcereg, itemsize): + """Produce one operation to do roughly + targetreg = sourcereg * itemsize + except that the targetreg may still need shifting by 0,1,2,3. + """ + if (itemsize & 7) == 0: + shift = 3 + elif (itemsize & 3) == 0: + shift = 2 + elif (itemsize & 1) == 0: + shift = 1 + else: + shift = 0 + itemsize >>= shift + # + if valid_addressing_size(itemsize - 1): + mc.LEA_ra(targetreg, (sourcereg, sourcereg, + get_scale(itemsize - 1), 0)) + elif valid_addressing_size(itemsize): + mc.LEA_ra(targetreg, (rx86.NO_BASE_REGISTER, sourcereg, + get_scale(itemsize), 0)) + else: + mc.IMUL_rri(targetreg, sourcereg, itemsize) + # + return shift + def _get_interiorfield_addr(self, temp_loc, index_loc, itemsize_loc, base_loc, ofs_loc): assert isinstance(itemsize_loc, ImmedLoc) + itemsize = itemsize_loc.value if isinstance(index_loc, ImmedLoc): - temp_loc = imm(index_loc.value * itemsize_loc.value) - elif _valid_addressing_size(itemsize_loc.value): - return AddressLoc(base_loc, index_loc, _get_scale(itemsize_loc.value), ofs_loc.value) + temp_loc = imm(index_loc.value * itemsize) + shift = 0 + elif valid_addressing_size(itemsize): + temp_loc = index_loc + shift = get_scale(itemsize) else: - # XXX should not use IMUL in more cases, it can use a clever LEA + assert isinstance(index_loc, RegLoc) assert isinstance(temp_loc, RegLoc) - assert isinstance(index_loc, RegLoc) assert not temp_loc.is_xmm - self.mc.IMUL_rri(temp_loc.value, index_loc.value, - itemsize_loc.value) + shift = self._imul_const_scaled(self.mc, temp_loc.value, + index_loc.value, itemsize) assert isinstance(ofs_loc, ImmedLoc) - return AddressLoc(base_loc, temp_loc, 0, ofs_loc.value) + return AddressLoc(base_loc, temp_loc, shift, ofs_loc.value) def genop_getinteriorfield_gc(self, op, arglocs, resloc): (base_loc, ofs_loc, itemsize_loc, fieldsize_loc, @@ -1582,7 +1611,7 @@ base_loc, ofs_loc, value_loc, size_loc, baseofs = arglocs assert isinstance(baseofs, ImmedLoc) assert isinstance(size_loc, ImmedLoc) - scale = _get_scale(size_loc.value) + scale = get_scale(size_loc.value) dest_addr = AddressLoc(base_loc, ofs_loc, scale, baseofs.value) self.save_into_mem(dest_addr, value_loc, size_loc) @@ -2415,11 +2444,12 @@ jmp_adr0 = self.mc.get_relative_pos() self.mc.MOV(eax, heap(nursery_free_adr)) - shift = size2shift(itemsize) - if shift < 0: - self.mc.IMUL_rri(edi.value, varsizeloc.value, itemsize) + if valid_addressing_size(itemsize): + shift = get_scale(itemsize) + else: + shift = self._imul_const_scaled(self.mc, edi.value, + varsizeloc.value, itemsize) varsizeloc = edi - shift = 0 # now varsizeloc is a register != eax. The size of # the variable part of the array is (varsizeloc << shift) assert arraydescr.basesize >= self.gc_minimal_size_in_nursery @@ -2523,13 +2553,5 @@ os.write(2, '[x86/asm] %s\n' % msg) raise NotImplementedError(msg) -def size2shift(size): - "Return a result 0..3 such that (1< 0, 1 - else: - return (size >> 2) + 1 # 4, 8 => 2, 3 - def not_implemented(msg): os.write(2, '[x86/regalloc] %s\n' % msg) raise NotImplementedError(msg) diff --git a/rpython/jit/backend/x86/regloc.py b/rpython/jit/backend/x86/regloc.py --- a/rpython/jit/backend/x86/regloc.py +++ b/rpython/jit/backend/x86/regloc.py @@ -521,17 +521,6 @@ return func_with_new_name(INSN, "INSN_" + name) - def _16_bit_binaryop(name): - def INSN(self, loc1, loc2): - # Select 16-bit operand mode - self.writechar('\x66') - # XXX: Hack to let immediate() in rx86 know to do a 16-bit encoding - self._use_16_bit_immediate = True - getattr(self, name)(loc1, loc2) - self._use_16_bit_immediate = False - - return INSN - def _addr_as_reg_offset(self, addr): # Encodes a (64-bit) address as an offset from the scratch register. # If we are within a "reuse_scratch_register" block, we remember the @@ -616,10 +605,10 @@ NEG = _unaryop('NEG') CMP = _binaryop('CMP') - CMP16 = _16_bit_binaryop('CMP') + CMP16 = _binaryop('CMP16') MOV = _binaryop('MOV') MOV8 = _binaryop('MOV8') - MOV16 = _16_bit_binaryop('MOV') + MOV16 = _binaryop('MOV16') MOVZX8 = _binaryop('MOVZX8') MOVSX8 = _binaryop('MOVSX8') MOVZX16 = _binaryop('MOVZX16') diff --git a/rpython/jit/backend/x86/rx86.py b/rpython/jit/backend/x86/rx86.py --- a/rpython/jit/backend/x86/rx86.py +++ b/rpython/jit/backend/x86/rx86.py @@ -125,10 +125,7 @@ elif width == 'q' and mc.WORD == 8: mc.writeimm64(immediate) else: - if mc._use_16_bit_immediate: - mc.writeimm16(immediate) - else: - mc.writeimm32(immediate) + mc.writeimm32(immediate) return 0 def immediate(argnum, width='i'): @@ -282,16 +279,20 @@ # (the immediate address itself must be explicitely encoded as well, # with immediate(argnum)). -def encode_abs(mc, _1, _2, orbyte): + at specialize.arg(2) +def encode_abs(mc, immediate, _, orbyte): # expands to either '\x05' on 32-bit, or '\x04\x25' on 64-bit if mc.WORD == 8: mc.writechar(chr(0x04 | orbyte)) mc.writechar(chr(0x25)) else: mc.writechar(chr(0x05 | orbyte)) + # followed by an immediate, always 32 bits + mc.writeimm32(immediate) return 0 -abs_ = encode_abs, 0, None, None +def abs_(argnum): + return encode_abs, argnum, None, None # ____________________________________________________________ # For 64-bits mode: the REX.W, REX.R, REX.X, REG.B prefixes @@ -305,9 +306,6 @@ def encode_rex(mc, rexbyte, basevalue, orbyte): if mc.WORD == 8: assert 0 <= rexbyte < 8 - # XXX: Hack. Ignore REX.W if we are using 16-bit operands - if mc._use_16_bit_immediate: - basevalue &= ~REX_W if basevalue != 0 or rexbyte != 0: if basevalue == 0: basevalue = 0x40 @@ -374,9 +372,8 @@ INSN_br = insn(rex_w, chr(base+1), register(2,8), stack_bp(1)) INSN_rb = insn(rex_w, chr(base+3), register(1,8), stack_bp(2)) INSN_rm = insn(rex_w, chr(base+3), register(1,8), mem_reg_plus_const(2)) - INSN_rj = insn(rex_w, chr(base+3), register(1,8), abs_, immediate(2)) - INSN_ji8 = insn(rex_w, '\x83', orbyte(base), abs_, immediate(1), - immediate(2,'b')) + INSN_rj = insn(rex_w, chr(base+3), register(1,8), abs_(2)) + INSN_ji8 = insn(rex_w, '\x83', orbyte(base), abs_(1), immediate(2,'b')) INSN_mi8 = insn(rex_w, '\x83', orbyte(base), mem_reg_plus_const(1), immediate(2,'b')) INSN_bi8 = insn(rex_w, '\x83', orbyte(base), stack_bp(1), immediate(2,'b')) @@ -449,9 +446,6 @@ class AbstractX86CodeBuilder(object): """Abstract base class.""" - # Used by the 16-bit version of instructions - _use_16_bit_immediate = False - def writechar(self, char): raise NotImplementedError @@ -489,15 +483,13 @@ CMP_mi = select_8_or_32_bit_immed(CMP_mi8, CMP_mi32) CMP_mr = insn(rex_w, '\x39', register(2, 8), mem_reg_plus_const(1)) - CMP_ji8 = insn(rex_w, '\x83', orbyte(7<<3), abs_, - immediate(1), immediate(2, 'b')) - CMP_ji32 = insn(rex_w, '\x81', orbyte(7<<3), abs_, - immediate(1), immediate(2)) + CMP_ji8 = insn(rex_w, '\x83', orbyte(7<<3), abs_(1), immediate(2, 'b')) + CMP_ji32 = insn(rex_w, '\x81', orbyte(7<<3), abs_(1), immediate(2)) CMP_ji = select_8_or_32_bit_immed(CMP_ji8, CMP_ji32) - CMP_jr = insn(rex_w, '\x39', register(2, 8), abs_, immediate(1)) + CMP_jr = insn(rex_w, '\x39', register(2, 8), abs_(1)) CMP32_mi = insn(rex_nw, '\x81', orbyte(7<<3), mem_reg_plus_const(1), immediate(2)) - + CMP16_mi = insn('\x66', rex_nw, '\x81', orbyte(7<<3), mem_reg_plus_const(1), immediate(2, 'h')) CMP8_ri = insn(rex_fw, '\x80', byte_register(1), '\xF8', immediate(2, 'b')) AND8_rr = insn(rex_fw, '\x20', byte_register(1), byte_register(2,8), '\xC0') @@ -505,7 +497,7 @@ OR8_rr = insn(rex_fw, '\x08', byte_register(1), byte_register(2,8), '\xC0') OR8_mi = insn(rex_nw, '\x80', orbyte(1<<3), mem_reg_plus_const(1), immediate(2, 'b')) - OR8_ji = insn(rex_nw, '\x80', orbyte(1<<3), abs_, immediate(1), + OR8_ji = insn(rex_nw, '\x80', orbyte(1<<3), abs_(1), immediate(2, 'b')) NEG_r = insn(rex_w, '\xF7', register(1), '\xD8') @@ -556,7 +548,7 @@ LEA32_rb = insn(rex_w, '\x8D', register(1,8),stack_bp(2,force_32bits=True)) LEA_ra = insn(rex_w, '\x8D', register(1, 8), mem_reg_plus_scaled_reg_plus_const(2)) LEA_rm = insn(rex_w, '\x8D', register(1, 8), mem_reg_plus_const(2)) - LEA_rj = insn(rex_w, '\x8D', register(1, 8), abs_, immediate(2)) + LEA_rj = insn(rex_w, '\x8D', register(1, 8), abs_(2)) CALL_l = insn('\xE8', relative(1)) CALL_r = insn(rex_nw, '\xFF', register(1), chr(0xC0 | (2<<3))) @@ -583,11 +575,11 @@ TEST8_mi = insn(rex_nw, '\xF6', orbyte(0<<3), mem_reg_plus_const(1), immediate(2, 'b')) TEST8_bi = insn(rex_nw, '\xF6', orbyte(0<<3), stack_bp(1), immediate(2, 'b')) - TEST8_ji = insn(rex_nw, '\xF6', orbyte(0<<3), abs_, immediate(1), immediate(2, 'b')) + TEST8_ji = insn(rex_nw, '\xF6', orbyte(0<<3), abs_(1), immediate(2, 'b')) TEST_rr = insn(rex_w, '\x85', register(2,8), register(1), '\xC0') BTS_mr = insn(rex_w, '\x0F\xAB', register(2,8), mem_reg_plus_const(1)) - BTS_jr = insn(rex_w, '\x0F\xAB', register(2,8), abs_, immediate(1)) + BTS_jr = insn(rex_w, '\x0F\xAB', register(2,8), abs_(1)) # x87 instructions FSTPL_b = insn('\xDD', orbyte(3<<3), stack_bp(1)) # rffi.DOUBLE ('as' wants L??) @@ -690,10 +682,12 @@ def define_modrm_modes(insnname_template, before_modrm, after_modrm=[], regtype='GPR'): def add_insn(code, *modrm): - args = before_modrm + list(modrm) + after_modrm + args = before_modrm + list(modrm) methname = insnname_template.replace('*', code) - if methname.endswith('_rr') or methname.endswith('_xx'): + if (methname.endswith('_rr') or methname.endswith('_xx') + or methname.endswith('_ri')): args.append('\xC0') + args += after_modrm if regtype == 'XMM': insn_func = xmminsn(*args) @@ -718,7 +712,7 @@ add_insn('s', stack_sp(modrm_argnum)) add_insn('m', mem_reg_plus_const(modrm_argnum)) add_insn('a', mem_reg_plus_scaled_reg_plus_const(modrm_argnum)) - add_insn('j', abs_, immediate(modrm_argnum)) + add_insn('j', abs_(modrm_argnum)) # Define a regular MOV, and a variant MOV32 that only uses the low 4 bytes of a # register @@ -729,6 +723,8 @@ define_modrm_modes('MOV8_*r', [rex_fw, '\x88', byte_register(2, 8)], regtype='BYTE') define_modrm_modes('MOV8_*i', [rex_fw, '\xC6', orbyte(0<<3)], [immediate(2, 'b')], regtype='BYTE') +define_modrm_modes('MOV16_*r', ['\x66', rex_nw, '\x89', register(2, 8)]) +define_modrm_modes('MOV16_*i', ['\x66', rex_nw, '\xC7', orbyte(0<<3)], [immediate(2, 'h')]) define_modrm_modes('MOVZX8_r*', [rex_w, '\x0F\xB6', register(1, 8)], regtype='BYTE') define_modrm_modes('MOVSX8_r*', [rex_w, '\x0F\xBE', register(1, 8)], regtype='BYTE') @@ -766,7 +762,7 @@ # assert insnname_template.count('*') == 1 add_insn('x', register(2), '\xC0') - add_insn('j', abs_, immediate(2)) + add_insn('j', abs_(2)) add_insn('m', mem_reg_plus_const(2)) define_pxmm_insn('PADDQ_x*', '\xD4') diff --git a/rpython/jit/backend/x86/test/test_regloc.py b/rpython/jit/backend/x86/test/test_regloc.py --- a/rpython/jit/backend/x86/test/test_regloc.py +++ b/rpython/jit/backend/x86/test/test_regloc.py @@ -1,4 +1,5 @@ import struct, sys +from rpython.jit.backend.x86.rx86 import R from rpython.jit.backend.x86.regloc import * from rpython.jit.backend.x86.test.test_rx86 import CodeBuilder32, CodeBuilder64, assert_encodes_as from rpython.jit.backend.x86.assembler import heap @@ -15,36 +16,49 @@ cb32 = LocationCodeBuilder32 cb64 = LocationCodeBuilder64 +def test_mov_8(): + assert_encodes_as(cb32, "MOV8_ri", (R.cl, 25), '\xB1\x19') + def test_mov_16(): + # only 'MOV16_*r' and 'MOV16_*i' are supported # 32-bit assert_encodes_as(cb32, "MOV16", (ecx, ebx), '\x66\x89\xD9') - assert_encodes_as(cb32, "MOV16", (ecx, ImmedLoc(12345)), '\x66\xB9\x39\x30') - + assert_encodes_as(cb32, "MOV16", + (AddressLoc(ecx, ImmedLoc(16), 0, 0), ebx), + '\x66\x89\x59\x10') # 64-bit assert_encodes_as(cb64, "MOV16", (r8, ebx), '\x66\x41\x89\xD8') # 11 011 000 assert_encodes_as(cb64, "MOV16", (ebx, r8), '\x66\x44\x89\xC3') # 11 000 011 - assert_encodes_as(cb64, "MOV16", (ecx, ebx), '\x66\x40\x89\xD9') - assert_encodes_as(cb64, "MOV16", (ecx, ImmedLoc(12345)), '\x66\xB9\x39\x30') + assert_encodes_as(cb64, "MOV16", (ecx, ebx), '\x66\x89\xD9') # for the next case we don't pick the most efficient encoding, but well - expected = '\x66\x40\xC7\xC1\xC7\xCF' # could be '\x66\xB9\xC7\xCF' + expected = '\x66\xC7\xC1\x39\x30' # could be '\x66\xB9\x39\x30' + assert_encodes_as(cb64, "MOV16", (ecx, ImmedLoc(12345)), expected) + # for the next case we don't pick the most efficient encoding, but well + expected = '\x66\xC7\xC1\xC7\xCF' # could be '\x66\xB9\xC7\xCF' assert_encodes_as(cb64, "MOV16", (ecx, ImmedLoc(-12345)), expected) - assert_encodes_as(cb64, "MOV16", (r9, ImmedLoc(12345)), '\x66\x41\xB9\x39\x30') + # for the next case we don't pick the most efficient encoding, but well + expected = '\x66\x41\xC7\xC1\x39\x30' # could be '\x66\x41\xB9\x39\x30' + assert_encodes_as(cb64, "MOV16", (r9, ImmedLoc(12345)), expected) # for the next case we don't pick the most efficient encoding, but well expected = '\x66\x41\xC7\xC1\xC7\xCF' # could be '\x66\x41\xB9\xC7\xCF' assert_encodes_as(cb64, "MOV16", (r9, ImmedLoc(-12345)), expected) - assert_encodes_as(cb64, "MOV16", (AddressLoc(r13, ImmedLoc(0), 0, 0), ImmedLoc(12345)), '\x66\x41\xC7\x45\x00\x39\x30') + assert_encodes_as(cb64, "MOV16", + (AddressLoc(r13, ImmedLoc(0), 0, 0), ImmedLoc(12345)), + '\x66\x41\xC7\x45\x00\x39\x30') def test_cmp_16(): + # only 'CMP16_mi' is supported # 32-bit - assert_encodes_as(cb32, "CMP16", (ecx, ebx), '\x66\x39\xD9') - assert_encodes_as(cb32, "CMP16", (ecx, ImmedLoc(12345)), '\x66\x81\xF9\x39\x30') - + assert_encodes_as(cb32, "CMP16", + (AddressLoc(ecx, ImmedLoc(0), 0, 0), ImmedLoc(21324)), + '\x66\x81\x39\x4c\x53') + assert_encodes_as(cb32, "CMP16", + (AddressLoc(esi, ImmedLoc(2), 0, 0), ImmedLoc(-12345)), + '\x66\x81\x7e\x02\xc7\xcf') # 64-bit - assert_encodes_as(cb64, "CMP16", (r8, ebx), '\x66\x41\x39\xD8') # 11 011 000 - assert_encodes_as(cb64, "CMP16", (ebx, r8), '\x66\x44\x39\xC3') # 11 000 011 - assert_encodes_as(cb64, "CMP16", (ecx, ebx), '\x66\x40\x39\xD9') - assert_encodes_as(cb64, "CMP16", (ecx, ImmedLoc(12345)), '\x66\x40\x81\xF9\x39\x30') - assert_encodes_as(cb64, "CMP16", (AddressLoc(r13, ImmedLoc(0), 0, 0), ImmedLoc(12345)), '\x66\x41\x81\x7D\x00\x39\x30') + assert_encodes_as(cb64, "CMP16", + (AddressLoc(r13, ImmedLoc(0), 0, 0), ImmedLoc(12345)), + '\x66\x41\x81\x7D\x00\x39\x30') def test_relocation(): from rpython.rtyper.lltypesystem import lltype, rffi diff --git a/rpython/memory/gc/env.py b/rpython/memory/gc/env.py --- a/rpython/memory/gc/env.py +++ b/rpython/memory/gc/env.py @@ -149,6 +149,10 @@ else: data = ''.join(data) linepos = 0 + # Currently on ARM-linux we won't find any information about caches in + # cpuinfo + if _detect_arm_cpu(data): + return -1 while True: start = _findend(data, '\ncache size', linepos) if start < 0: @@ -201,6 +205,11 @@ pos += 1 return pos +def _detect_arm_cpu(data): + # check for the presence of a 'Processor' entry + p = _findend(data, 'Processor', 0) + return p >= 0 and _findend(data, 'ARMv', p) > 0 + # ---------- Darwin ---------- sysctlbyname = rffi.llexternal('sysctlbyname', @@ -270,7 +279,7 @@ def best_nursery_size_for_L2cache(L2cache): # Heuristically, the best nursery size to choose is about half # of the L2 cache. - if L2cache > 1024 * 1024: # we don't want to have nursery estimated + if L2cache > 2 * 1024 * 1024: # we don't want to have nursery estimated # on L2 when L3 is present return L2cache // 2 else: diff --git a/rpython/memory/gc/minimark.py b/rpython/memory/gc/minimark.py --- a/rpython/memory/gc/minimark.py +++ b/rpython/memory/gc/minimark.py @@ -130,6 +130,7 @@ FORWARDSTUB = lltype.GcStruct('forwarding_stub', ('forw', llmemory.Address)) FORWARDSTUBPTR = lltype.Ptr(FORWARDSTUB) +NURSARRAY = lltype.Array(llmemory.Address) # ____________________________________________________________ @@ -263,7 +264,7 @@ self.nursery_top = NULL self.nursery_real_top = NULL self.debug_tiny_nursery = -1 - self.debug_rotating_nurseries = None + self.debug_rotating_nurseries = lltype.nullptr(NURSARRAY) self.extra_threshold = 0 # # The ArenaCollection() handles the nonmovable objects allocation. @@ -350,8 +351,6 @@ # hacking at the current nursery position in collect_and_reserve(). if newsize <= 0: newsize = env.estimate_best_nursery_size() - # 4*1024*1024 # fixed to 4MB by default - # (it was env.estimate_best_nursery_size()) if newsize <= 0: newsize = defaultsize if newsize < minsize: @@ -471,23 +470,32 @@ # and use them alternatively, while mprotect()ing the unused # ones to detect invalid access. debug_start("gc-debug") - self.debug_rotating_nurseries = [] - for i in range(22): + self.debug_rotating_nurseries = lltype.malloc( + NURSARRAY, 22, flavor='raw', track_allocation=False) + i = 0 + while i < 22: nurs = self._alloc_nursery() llarena.arena_protect(nurs, self._nursery_memory_size(), True) - self.debug_rotating_nurseries.append(nurs) + self.debug_rotating_nurseries[i] = nurs + i += 1 debug_print("allocated", len(self.debug_rotating_nurseries), "extra nurseries") debug_stop("gc-debug") def debug_rotate_nursery(self): - if self.debug_rotating_nurseries is not None: + if self.debug_rotating_nurseries: debug_start("gc-debug") oldnurs = self.nursery llarena.arena_protect(oldnurs, self._nursery_memory_size(), True) - self.debug_rotating_nurseries.append(oldnurs) # - newnurs = self.debug_rotating_nurseries.pop(0) + newnurs = self.debug_rotating_nurseries[0] + i = 0 + while i < len(self.debug_rotating_nurseries) - 1: + self.debug_rotating_nurseries[i] = ( + self.debug_rotating_nurseries[i + 1]) + i += 1 + self.debug_rotating_nurseries[i] = oldnurs + # llarena.arena_protect(newnurs, self._nursery_memory_size(), False) self.nursery = newnurs self.nursery_top = self.nursery + self.initial_cleanup diff --git a/rpython/memory/gc/test/test_env.py b/rpython/memory/gc/test/test_env.py --- a/rpython/memory/gc/test/test_env.py +++ b/rpython/memory/gc/test/test_env.py @@ -161,3 +161,23 @@ """) result = env.get_L2cache_linux2(str(filepath)) assert result == 3072 * 1024 + +def test_estimate_best_nursery_size_linux2_arm(): + filepath = udir.join('estimate_best_nursery_size_linux2') + filepath.write("""\ +Processor : ARMv6-compatible processor rev 7 (v6l) +# this is not actually from cpuinfo, but here for the test +cache size : 3072 KB +... +""") + result = env.get_L2cache_linux2(str(filepath)) + assert result == -1 + +def test__detect_arm(): + assert env._detect_arm_cpu("Processor : ARMv6-compatible processor rev 7 (v6l)") + assert not env._detect_arm_cpu("""\ +processor : 0 +vendor_id : GenuineIntel +cpu family : 6 +model : 37 +""") diff --git a/rpython/memory/gctransform/framework.py b/rpython/memory/gctransform/framework.py --- a/rpython/memory/gctransform/framework.py +++ b/rpython/memory/gctransform/framework.py @@ -619,6 +619,12 @@ func = getattr(graph, 'func', None) if func and getattr(func, '_gc_no_collect_', False): if self.collect_analyzer.analyze_direct_call(graph): + print '!'*79 + ca = CollectAnalyzer(self.translator) + ca.verbose = True + ca.analyze_direct_call(graph) + # ^^^ for the dump of which operation in which graph actually + # causes it to return True raise Exception("'no_collect' function can trigger collection:" " %s" % func) diff --git a/rpython/rlib/rwin32.py b/rpython/rlib/rwin32.py --- a/rpython/rlib/rwin32.py +++ b/rpython/rlib/rwin32.py @@ -5,6 +5,7 @@ import os import errno +from rpython.rtyper.module.ll_os_environ import make_env_impls from rpython.rtyper.tool import rffi_platform from rpython.tool.udir import udir from rpython.translator.tool.cbuild import ExternalCompilationInfo @@ -390,3 +391,5 @@ raise lastWindowsError('os_kill failed to terminate process') finally: CloseHandle(handle) + + _wenviron_items, _wgetenv, _wputenv = make_env_impls(win32=True) diff --git a/rpython/rlib/test/test_rwin32.py b/rpython/rlib/test/test_rwin32.py --- a/rpython/rlib/test/test_rwin32.py +++ b/rpython/rlib/test/test_rwin32.py @@ -1,3 +1,4 @@ +# encoding: utf-8 import os, py if os.name != 'nt': py.test.skip('tests for win32 only') @@ -47,3 +48,13 @@ rwin32.CloseHandle(handle) assert proc.wait() == signal.SIGTERM + at py.test.mark.dont_track_allocations('putenv intentionally keeps strings alive') +def test_wenviron(): + name, value = u'PYPY_TEST_日本', u'foobar日本' + rwin32._wputenv(name, value) + assert rwin32._wgetenv(name) == value + env = dict(rwin32._wenviron_items()) + assert env[name] == value + for key, value in env.iteritems(): + assert type(key) is unicode + assert type(value) is unicode diff --git a/rpython/rtyper/lltypesystem/rffi.py b/rpython/rtyper/lltypesystem/rffi.py --- a/rpython/rtyper/lltypesystem/rffi.py +++ b/rpython/rtyper/lltypesystem/rffi.py @@ -1059,6 +1059,7 @@ self.buf = str2charp(value) else: self.buf = lltype.nullptr(CCHARP.TO) + __init__._annenforceargs_ = [None, annmodel.SomeString(can_be_None=True)] def __enter__(self): return self.buf def __exit__(self, *args): @@ -1072,6 +1073,8 @@ self.buf = unicode2wcharp(value) else: self.buf = lltype.nullptr(CWCHARP.TO) + __init__._annenforceargs_ = [None, + annmodel.SomeUnicodeString(can_be_None=True)] def __enter__(self): return self.buf def __exit__(self, *args): diff --git a/rpython/rtyper/module/ll_os.py b/rpython/rtyper/module/ll_os.py --- a/rpython/rtyper/module/ll_os.py +++ b/rpython/rtyper/module/ll_os.py @@ -7,14 +7,15 @@ import os, sys, errno import py -from rpython.rtyper.module.support import OOSupport +from rpython.rtyper.module.support import ( + _WIN32, OOSupport, StringTraits, UnicodeTraits, underscore_on_windows) from rpython.tool.sourcetools import func_renamer from rpython.rlib.rarithmetic import r_longlong from rpython.rtyper.extfunc import ( BaseLazyRegistering, register_external) from rpython.rtyper.extfunc import registering, registering_if, extdef from rpython.annotator.model import ( - SomeInteger, SomeString, SomeTuple, SomeFloat, SomeUnicodeString) + SomeInteger, SomeString, SomeTuple, SomeFloat, s_Str0, s_Unicode0) from rpython.annotator.model import s_ImpossibleValue, s_None, s_Bool from rpython.rtyper.lltypesystem import rffi from rpython.rtyper.lltypesystem import lltype @@ -25,8 +26,8 @@ from rpython.rtyper.lltypesystem.rstr import STR from rpython.rlib.objectmodel import specialize -str0 = SomeString(no_nul=True) -unicode0 = SomeUnicodeString(no_nul=True) +str0 = s_Str0 +unicode0 = s_Unicode0 def monkeypatch_rposix(posixfunc, unicodefunc, signature): func_name = posixfunc.__name__ @@ -66,42 +67,6 @@ # Monkeypatch the function in rpython.rlib.rposix setattr(rposix, func_name, new_func) -class StringTraits: - str = str - str0 = str0 - CHAR = rffi.CHAR - CCHARP = rffi.CCHARP - charp2str = staticmethod(rffi.charp2str) - str2charp = staticmethod(rffi.str2charp) - free_charp = staticmethod(rffi.free_charp) - scoped_alloc_buffer = staticmethod(rffi.scoped_alloc_buffer) - - @staticmethod - def posix_function_name(name): - return underscore_on_windows + name - - @staticmethod - def ll_os_name(name): - return 'll_os.ll_os_' + name - -class UnicodeTraits: - str = unicode - str0 = unicode0 - CHAR = rffi.WCHAR_T - CCHARP = rffi.CWCHARP - charp2str = staticmethod(rffi.wcharp2unicode) - str2charp = staticmethod(rffi.unicode2wcharp) - free_charp = staticmethod(rffi.free_wcharp) - scoped_alloc_buffer = staticmethod(rffi.scoped_alloc_unicodebuffer) - - @staticmethod - def posix_function_name(name): - return underscore_on_windows + 'w' + name - - @staticmethod - def ll_os_name(name): - return 'll_os.ll_os_w' + name - def registering_str_unicode(posixfunc, condition=True): if not condition or posixfunc is None: return registering(None, condition=False) @@ -129,16 +94,6 @@ posix = __import__(os.name) -if sys.platform.startswith('win'): - _WIN32 = True -else: - _WIN32 = False - -if _WIN32: - underscore_on_windows = '_' -else: - underscore_on_windows = '' - includes = [] if not _WIN32: # XXX many of these includes are not portable at all diff --git a/rpython/rtyper/module/ll_os_environ.py b/rpython/rtyper/module/ll_os_environ.py --- a/rpython/rtyper/module/ll_os_environ.py +++ b/rpython/rtyper/module/ll_os_environ.py @@ -1,36 +1,42 @@ -import os, sys +import os +import sys from rpython.annotator import model as annmodel from rpython.rtyper.controllerentry import Controller from rpython.rtyper.extfunc import register_external from rpython.rtyper.lltypesystem import rffi, lltype -from rpython.rtyper.module import ll_os -from rpython.rlib import rposix +from rpython.rtyper.module.support import _WIN32, StringTraits, UnicodeTraits +from rpython.translator.tool.cbuild import ExternalCompilationInfo -str0 = ll_os.str0 +str0 = annmodel.s_Str0 # ____________________________________________________________ # -# Annotation support to control access to 'os.environ' in the RPython program +# Annotation support to control access to 'os.environ' in the RPython +# program class OsEnvironController(Controller): knowntype = os.environ.__class__ def convert(self, obj): - return None # 'None' is good enough, there is only one os.environ + # 'None' is good enough, there is only one os.environ + return None def getitem(self, obj, key): - # in the RPython program reads of 'os.environ[key]' are redirected here + # in the RPython program reads of 'os.environ[key]' are + # redirected here result = r_getenv(key) if result is None: raise KeyError return result def setitem(self, obj, key, value): - # in the RPython program, 'os.environ[key] = value' is redirected here + # in the RPython program, 'os.environ[key] = value' is + # redirected here r_putenv(key, value) def delitem(self, obj, key): - # in the RPython program, 'del os.environ[key]' is redirected here + # in the RPython program, 'del os.environ[key]' is redirected + # here absent = r_getenv(key) is None # Always call unsetenv(), to get eventual OSErrors r_unsetenv(key) @@ -38,102 +44,23 @@ raise KeyError def get_keys(self, obj): - # 'os.environ.keys' is redirected here - note that it's the getattr - # that arrives here, not the actual method call! + # 'os.environ.keys' is redirected here - note that it's the + # getattr that arrives here, not the actual method call! return r_envkeys def get_items(self, obj): - # 'os.environ.items' is redirected here (not the actual method call!) + # 'os.environ.items' is redirected here (not the actual method + # call!) return r_envitems def get_get(self, obj): - # 'os.environ.get' is redirected here (not the actual method call!) + # 'os.environ.get' is redirected here (not the actual method + # call!) return r_getenv # ____________________________________________________________ -# -# Lower-level interface: dummy placeholders and external registations - -def r_getenv(name): - just_a_placeholder # should return None if name not found - -os_getenv = rffi.llexternal('getenv', [rffi.CCHARP], rffi.CCHARP, threadsafe=False) - -def getenv_llimpl(name): - l_name = rffi.str2charp(name) - l_result = os_getenv(l_name) - if l_result: - result = rffi.charp2str(l_result) - else: - result = None - rffi.free_charp(l_name) - return result - -register_external(r_getenv, [str0], annmodel.SomeString(can_be_None=True, no_nul=True), - export_name='ll_os.ll_os_getenv', - llimpl=getenv_llimpl) - -# ____________________________________________________________ - -def r_putenv(name, value): - just_a_placeholder - -class EnvKeepalive: - pass -envkeepalive = EnvKeepalive() -envkeepalive.byname = {} - -os_putenv = rffi.llexternal('putenv', [rffi.CCHARP], rffi.INT) - -def putenv_llimpl(name, value): - l_string = rffi.str2charp('%s=%s' % (name, value)) - error = rffi.cast(lltype.Signed, os_putenv(l_string)) - if error: - rffi.free_charp(l_string) - raise OSError(rposix.get_errno(), "os_putenv failed") - # keep 'l_string' alive - we know that the C library needs it - # until the next call to putenv() with the same 'name'. - l_oldstring = envkeepalive.byname.get(name, lltype.nullptr(rffi.CCHARP.TO)) - envkeepalive.byname[name] = l_string - if l_oldstring: - rffi.free_charp(l_oldstring) - -register_external(r_putenv, [str0, str0], annmodel.s_None, - export_name='ll_os.ll_os_putenv', - llimpl=putenv_llimpl) - -# ____________________________________________________________ - -def r_unsetenv(name): - # default implementation for platforms without a real unsetenv() - r_putenv(name, '') - -if hasattr(__import__(os.name), 'unsetenv'): - os_unsetenv = rffi.llexternal('unsetenv', [rffi.CCHARP], rffi.INT) - - def unsetenv_llimpl(name): - l_name = rffi.str2charp(name) - error = rffi.cast(lltype.Signed, os_unsetenv(l_name)) - rffi.free_charp(l_name) - if error: - raise OSError(rposix.get_errno(), "os_unsetenv failed") - try: - l_oldstring = envkeepalive.byname[name] - except KeyError: - pass - else: - del envkeepalive.byname[name] - rffi.free_charp(l_oldstring) - - register_external(r_unsetenv, [str0], annmodel.s_None, - export_name='ll_os.ll_os_unsetenv', - llimpl=unsetenv_llimpl) - -# ____________________________________________________________ # Access to the 'environ' external variable -from rpython.translator.tool.cbuild import ExternalCompilationInfo - if sys.platform.startswith('darwin'): CCHARPPP = rffi.CArrayPtr(rffi.CCHARPP) _os_NSGetEnviron = rffi.llexternal( @@ -142,17 +69,21 @@ ) def os_get_environ(): return _os_NSGetEnviron()[0] -elif sys.platform.startswith('win'): +elif _WIN32: + eci = ExternalCompilationInfo(includes=['stdlib.h']) + CWCHARPP = lltype.Ptr(lltype.Array(rffi.CWCHARP, hints={'nolength': True})) + os_get_environ, _os_set_environ = rffi.CExternVariable( - rffi.CCHARPP, - '_environ', - ExternalCompilationInfo(includes=['stdlib.h'])) + rffi.CCHARPP, '_environ', eci) + get__wenviron, _set__wenviron = rffi.CExternVariable( + CWCHARPP, '_wenviron', eci, c_type='wchar_t **') else: - os_get_environ, _os_set_environ = rffi.CExternVariable(rffi.CCHARPP, - 'environ', - ExternalCompilationInfo()) + os_get_environ, _os_set_environ = rffi.CExternVariable( + rffi.CCHARPP, 'environ', ExternalCompilationInfo()) # ____________________________________________________________ +# +# Lower-level interface: dummy placeholders and external registations def r_envkeys(): just_a_placeholder @@ -178,18 +109,109 @@ def r_envitems(): just_a_placeholder -def envitems_llimpl(): - environ = os_get_environ() - result = [] - i = 0 - while environ[i]: - name_value = rffi.charp2str(environ[i]) - p = name_value.find('=') - if p >= 0: - result.append((name_value[:p], name_value[p+1:])) - i += 1 - return result +def r_getenv(name): + just_a_placeholder # should return None if name not found + +def r_putenv(name, value): + just_a_placeholder + +os_getenv = rffi.llexternal('getenv', [rffi.CCHARP], rffi.CCHARP, + threadsafe=False) +os_putenv = rffi.llexternal('putenv', [rffi.CCHARP], rffi.INT) +if _WIN32: + _wgetenv = rffi.llexternal('_wgetenv', [rffi.CWCHARP], rffi.CWCHARP, + compilation_info=eci, threadsafe=False) + _wputenv = rffi.llexternal('_wputenv', [rffi.CWCHARP], rffi.INT, + compilation_info=eci) + +class EnvKeepalive: + pass +envkeepalive = EnvKeepalive() +envkeepalive.byname = {} From noreply at buildbot.pypy.org Sun Apr 21 03:53:19 2013 From: noreply at buildbot.pypy.org (wlav) Date: Sun, 21 Apr 2013 03:53:19 +0200 (CEST) Subject: [pypy-commit] pypy reflex-support: fix warning about promote being ignored Message-ID: <20130421015319.88A971C1463@cobra.cs.uni-duesseldorf.de> Author: Wim Lavrijsen Branch: reflex-support Changeset: r63532:cd56cc493b68 Date: 2013-04-19 10:46 -0700 http://bitbucket.org/pypy/pypy/changeset/cd56cc493b68/ Log: fix warning about promote being ignored diff --git a/pypy/module/cppyy/capi/builtin_capi.py b/pypy/module/cppyy/capi/builtin_capi.py --- a/pypy/module/cppyy/capi/builtin_capi.py +++ b/pypy/module/cppyy/capi/builtin_capi.py @@ -296,12 +296,11 @@ threadsafe=ts_reflect, compilation_info=backend.eci, elidable_function=True) - at jit.elidable_promote() + at jit.elidable_promote('1,2,4') def c_base_offset(space, derived, base, address, direction): if derived == base: return 0 return _c_base_offset(derived.handle, base.handle, address, direction) - at jit.elidable_promote() def c_base_offset1(space, derived_h, base, address, direction): return _c_base_offset(derived_h, base.handle, address, direction) From noreply at buildbot.pypy.org Sun Apr 21 03:53:25 2013 From: noreply at buildbot.pypy.org (wlav) Date: Sun, 21 Apr 2013 03:53:25 +0200 (CEST) Subject: [pypy-commit] pypy reflex-support: get rid of one more translation warning (ignored promote) Message-ID: <20130421015325.271EC1C148E@cobra.cs.uni-duesseldorf.de> Author: Wim Lavrijsen Branch: reflex-support Changeset: r63536:f1d04df8dd41 Date: 2013-04-19 15:01 -0700 http://bitbucket.org/pypy/pypy/changeset/f1d04df8dd41/ Log: get rid of one more translation warning (ignored promote) diff --git a/pypy/module/cppyy/capi/builtin_capi.py b/pypy/module/cppyy/capi/builtin_capi.py --- a/pypy/module/cppyy/capi/builtin_capi.py +++ b/pypy/module/cppyy/capi/builtin_capi.py @@ -284,7 +284,7 @@ threadsafe=ts_reflect, compilation_info=backend.eci, elidable_function=True) - at jit.elidable_promote() + at jit.elidable_promote('2') def c_is_subtype(space, derived, base): if derived == base: return 1 From noreply at buildbot.pypy.org Sun Apr 21 03:53:26 2013 From: noreply at buildbot.pypy.org (wlav) Date: Sun, 21 Apr 2013 03:53:26 +0200 (CEST) Subject: [pypy-commit] pypy reflex-support: compare to a cast 0 instead of relying on implicit null Message-ID: <20130421015326.50E9D1C1493@cobra.cs.uni-duesseldorf.de> Author: Wim Lavrijsen Branch: reflex-support Changeset: r63537:42bcb364d381 Date: 2013-04-19 15:30 -0700 http://bitbucket.org/pypy/pypy/changeset/42bcb364d381/ Log: compare to a cast 0 instead of relying on implicit null diff --git a/pypy/module/cppyy/executor.py b/pypy/module/cppyy/executor.py --- a/pypy/module/cppyy/executor.py +++ b/pypy/module/cppyy/executor.py @@ -132,10 +132,10 @@ def execute(self, space, cppmethod, cppthis, num_args, args): lresult = capi.c_call_l(space, cppmethod, cppthis, num_args, args) ccpresult = rffi.cast(rffi.CCHARP, lresult) - if ccpresult: - result = rffi.charp2str(ccpresult) # TODO: make it a choice to free - return space.wrap(result) - return space.wrap('') + if ccpresult == rffi.cast(rffi.CCHARP, 0): + return space.wrap("") + result = rffi.charp2str(ccpresult) # TODO: make it a choice to free + return space.wrap(result) class ConstructorExecutor(FunctionExecutor): From noreply at buildbot.pypy.org Sun Apr 21 03:53:20 2013 From: noreply at buildbot.pypy.org (wlav) Date: Sun, 21 Apr 2013 03:53:20 +0200 (CEST) Subject: [pypy-commit] pypy reflex-support: fix type in function declaration Message-ID: <20130421015320.D98A01C1464@cobra.cs.uni-duesseldorf.de> Author: Wim Lavrijsen Branch: reflex-support Changeset: r63533:ec0b8688fe73 Date: 2013-04-19 10:47 -0700 http://bitbucket.org/pypy/pypy/changeset/ec0b8688fe73/ Log: fix type in function declaration diff --git a/pypy/module/cppyy/include/capi.h b/pypy/module/cppyy/include/capi.h --- a/pypy/module/cppyy/include/capi.h +++ b/pypy/module/cppyy/include/capi.h @@ -107,7 +107,7 @@ /* misc helpers ----------------------------------------------------------- */ long long cppyy_strtoll(const char* str); - unsigned long long cppyy_strtuoll(const char* str); + unsigned long long cppyy_strtoull(const char* str); void cppyy_free(void* ptr); cppyy_object_t cppyy_charp2stdstring(const char* str); From noreply at buildbot.pypy.org Sun Apr 21 03:53:22 2013 From: noreply at buildbot.pypy.org (wlav) Date: Sun, 21 Apr 2013 03:53:22 +0200 (CEST) Subject: [pypy-commit] pypy reflex-support: use backend specific name for class "std::string" directly Message-ID: <20130421015322.1BCBD1C1468@cobra.cs.uni-duesseldorf.de> Author: Wim Lavrijsen Branch: reflex-support Changeset: r63534:833745553a7d Date: 2013-04-19 10:48 -0700 http://bitbucket.org/pypy/pypy/changeset/833745553a7d/ Log: use backend specific name for class "std::string" directly diff --git a/pypy/module/cppyy/converter.py b/pypy/module/cppyy/converter.py --- a/pypy/module/cppyy/converter.py +++ b/pypy/module/cppyy/converter.py @@ -506,7 +506,7 @@ def __init__(self, space, extra): from pypy.module.cppyy import interp_cppyy - cppclass = interp_cppyy.scope_byname(space, "std::string") + cppclass = interp_cppyy.scope_byname(space, capi.std_string_name) InstanceConverter.__init__(self, space, cppclass) def _unwrap_object(self, space, w_obj): @@ -534,7 +534,7 @@ def __init__(self, space, extra): from pypy.module.cppyy import interp_cppyy - cppclass = interp_cppyy.scope_byname(space, "std::string") + cppclass = interp_cppyy.scope_byname(space, capi.std_string_name) InstancePtrConverter.__init__(self, space, cppclass) From noreply at buildbot.pypy.org Sun Apr 21 03:53:23 2013 From: noreply at buildbot.pypy.org (wlav) Date: Sun, 21 Apr 2013 03:53:23 +0200 (CEST) Subject: [pypy-commit] pypy reflex-support: merge default into branch; hopefully solves gc crash ... Message-ID: <20130421015323.EA1541C146E@cobra.cs.uni-duesseldorf.de> Author: Wim Lavrijsen Branch: reflex-support Changeset: r63535:608cb355ea66 Date: 2013-04-19 10:48 -0700 http://bitbucket.org/pypy/pypy/changeset/608cb355ea66/ Log: merge default into branch; hopefully solves gc crash ... diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -56,7 +56,7 @@ if we_are_translated(): self.debug = False self.current_clt = looptoken.compiled_loop_token - self.mc = InstrBuilder(self.cpu.arch_version) + self.mc = InstrBuilder(self.cpu.cpuinfo.arch_version) self.pending_guards = [] assert self.datablockwrapper is None allblocks = self.get_asmmemmgr_blocks(looptoken) @@ -80,7 +80,7 @@ if not self.cpu.propagate_exception_descr: return # not supported (for tests, or non-translated) # - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) self._store_and_reset_exception(mc, r.r0) ofs = self.cpu.get_ofs_of_frame_field('jf_guard_exc') # make sure ofs fits into a register @@ -165,7 +165,7 @@ # | my own retaddr | <-- sp # +-----------------------+ # - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) # save argument registers and return address mc.PUSH([reg.value for reg in r.argument_regs] + [r.ip.value, r.lr.value]) # stack is aligned here @@ -206,7 +206,7 @@ # write barriers. It must save all registers, and optionally # all vfp registers. It takes a single argument which is in r0. # It must keep stack alignment accordingly. - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) # exc0 = exc1 = None mc.PUSH([r.ip.value, r.lr.value]) # push two words to keep alignment @@ -249,8 +249,10 @@ else: self.wb_slowpath[withcards + 2 * withfloats] = rawstart - def _build_malloc_slowpath(self): - mc = InstrBuilder(self.cpu.arch_version) + def _build_malloc_slowpath(self, kind): + if kind != 'fixed': + return 0 + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) self._push_all_regs_to_jitframe(mc, [r.r0, r.r1], self.cpu.supports_floats) ofs = self.cpu.get_ofs_of_frame_field('jf_gcmap') # store the gc pattern @@ -287,9 +289,7 @@ self.store_reg(mc, r.ip, r.fp, ofs) # return mc.POP([r.ip.value, r.pc.value]) - - rawstart = mc.materialize(self.cpu.asmmemmgr, []) - self.malloc_slowpath = rawstart + return mc.materialize(self.cpu.asmmemmgr, []) def _reload_frame_if_necessary(self, mc): gcrootmap = self.cpu.gc_ll_descr.gcrootmap @@ -362,7 +362,7 @@ self.load_reg(mc, vfpr, r.fp, ofs) def _build_failure_recovery(self, exc, withfloats=False): - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) self._push_all_regs_to_jitframe(mc, [], withfloats) if exc: @@ -645,7 +645,7 @@ expected_size=expected_size) def _patch_frame_depth(self, adr, allocated_depth): - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) mc.gen_load_int(r.lr.value, allocated_depth) mc.copy_to_raw_memory(adr) @@ -721,7 +721,7 @@ # f) store the address of the new jitframe in the shadowstack # c) set the gcmap field to 0 in the new jitframe # g) restore registers and return - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) self._push_all_regs_to_jitframe(mc, [], self.cpu.supports_floats) # this is the gcmap stored by push_gcmap(mov=True) in _check_stack_frame # and the expected_size pushed in _check_stack_frame @@ -781,7 +781,7 @@ self.target_tokens_currently_compiling = None def _patch_stackadjust(self, adr, allocated_depth): - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) mc.gen_load_int(r.lr.value, allocated_depth) mc.copy_to_raw_memory(adr) @@ -821,7 +821,7 @@ # patch the guard jumpt to the stub # overwrite the generate NOP with a B_offs to the pos of the # stub - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) mc.B_offs(relative_offset, c.get_opposite_of(tok.fcond)) mc.copy_to_raw_memory(guard_pos) else: @@ -900,7 +900,7 @@ self.mc.ASR_ri(resloc.value, resloc.value, 16) def patch_trace(self, faildescr, looptoken, bridge_addr, regalloc): - b = InstrBuilder(self.cpu.arch_version) + b = InstrBuilder(self.cpu.cpuinfo.arch_version) patch_addr = faildescr._arm_failure_recovery_block assert patch_addr != 0 b.B(bridge_addr) diff --git a/rpython/jit/backend/arm/detect.py b/rpython/jit/backend/arm/detect.py --- a/rpython/jit/backend/arm/detect.py +++ b/rpython/jit/backend/arm/detect.py @@ -1,7 +1,6 @@ import os from rpython.translator.tool.cbuild import ExternalCompilationInfo -from rpython.rlib.clibffi import FFI_DEFAULT_ABI, FFI_SYSV, FFI_VFP from rpython.rtyper.tool import rffi_platform from rpython.translator.platform import CompilationError from rpython.rlib.debug import debug_print, debug_start, debug_stop @@ -46,9 +45,11 @@ # "Processor : ARMv%d-compatible processor rev 7 (v6l)" i = buf.find('ARMv') if i == -1: - raise ValueError("Unknown Processor entry") - - n = int(buf[i + 4]) + n = 6 + debug_print("Could not detect architecture version, " + "falling back to", "ARMv%d" % n) + else: + n = int(buf[i + 4]) if n < 6: raise ValueError("Unsupported ARM architecture version") diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -354,7 +354,7 @@ # whether to worry about a CALL that can collect; this # is always true except in call_release_gil can_collect=True): - if self.cpu.hf_abi: + if self.cpu.cpuinfo.hf_abi: stack_args, adr = self._setup_call_hf(adr, arglocs, fcond, resloc, result_info) else: @@ -382,7 +382,7 @@ # ensure the result is wellformed and stored in the correct location if resloc is not None: - if resloc.is_vfp_reg() and not self.cpu.hf_abi: + if resloc.is_vfp_reg() and not self.cpu.cpuinfo.hf_abi: # move result to the allocated register self.mov_to_vfp_loc(r.r0, r.r1, resloc) elif resloc.is_reg() and result_info != (-1, -1): @@ -1230,7 +1230,7 @@ baseofs = self.cpu.get_baseofs_of_frame_field() newlooptoken.compiled_loop_token.update_frame_info( oldlooptoken.compiled_loop_token, baseofs) - mc = InstrBuilder(self.cpu.arch_version) + mc = InstrBuilder(self.cpu.cpuinfo.arch_version) mc.B(target) mc.copy_to_raw_memory(oldadr) diff --git a/rpython/jit/backend/arm/runner.py b/rpython/jit/backend/arm/runner.py --- a/rpython/jit/backend/arm/runner.py +++ b/rpython/jit/backend/arm/runner.py @@ -11,6 +11,10 @@ jitframe.STATICSIZE = JITFRAME_FIXED_SIZE +class CPUInfo(object): + hf_abi = False + arch_version = 6 + class AbstractARMCPU(AbstractLLCPU): IS_64_BIT = False @@ -26,13 +30,11 @@ float_regs = VFPRegisterManager.all_regs frame_reg = fp - hf_abi = False # use hard float abi flag - arch_version = 6 # assume ARMv6 as base case - def __init__(self, rtyper, stats, opts=None, translate_support_code=False, gcdescr=None): AbstractLLCPU.__init__(self, rtyper, stats, opts, translate_support_code, gcdescr) + self.cpuinfo = CPUInfo() def set_debug(self, flag): return self.assembler.set_debug(flag) @@ -47,8 +49,8 @@ self.assembler = AssemblerARM(self, self.translate_support_code) def setup_once(self): - self.arch_version = detect_arch_version() - self.hf_abi = detect_hardfloat() + self.cpuinfo.arch_version = detect_arch_version() + self.cpuinfo.hf_abi = detect_hardfloat() self.assembler.setup_once() def finish_once(self): @@ -92,7 +94,7 @@ from rpython.jit.backend.arm.codebuilder import InstrBuilder for jmp, tgt in looptoken.compiled_loop_token.invalidate_positions: - mc = InstrBuilder(self.arch_version) + mc = InstrBuilder(self.cpuinfo.arch_version) mc.B_offs(tgt) mc.copy_to_raw_memory(jmp) # positions invalidated diff --git a/rpython/jit/backend/arm/test/test_detect.py b/rpython/jit/backend/arm/test/test_detect.py --- a/rpython/jit/backend/arm/test/test_detect.py +++ b/rpython/jit/backend/arm/test/test_detect.py @@ -3,7 +3,32 @@ from rpython.jit.backend.arm.detect import detect_arch_version cpuinfo = "Processor : ARMv%d-compatible processor rev 7 (v6l)""" - +cpuinfo2 = """processor : 0 +vendor_id : GenuineIntel +cpu family : 6 +model : 23 +model name : Intel(R) Core(TM)2 Duo CPU E8400 @ 3.00GHz +stepping : 10 +microcode : 0xa07 +cpu MHz : 2997.000 +cache size : 6144 KB +physical id : 0 +siblings : 2 +core id : 0 +cpu cores : 2 +apicid : 0 +initial apicid : 0 +fpu : yes +fpu_exception : yes +cpuid level : 13 +wp : yes +flags : fpu vme ... +bogomips : 5993.08 +clflush size : 64 +cache_alignment : 64 +address sizes : 36 bits physical, 48 bits virtual +power management: +""" def write_cpuinfo(info): filepath = udir.join('get_arch_version') @@ -20,5 +45,4 @@ assert detect_arch_version(write_cpuinfo(cpuinfo % 8)) == 7 py.test.raises(ValueError, 'detect_arch_version(write_cpuinfo(cpuinfo % 5))') - py.test.raises(ValueError, - 'detect_arch_version(write_cpuinfo("Lorem ipsum dolor sit amet, consectetur"))') + assert detect_arch_version(write_cpuinfo(cpuinfo2)) == 6 diff --git a/rpython/jit/backend/arm/test/test_runner.py b/rpython/jit/backend/arm/test/test_runner.py --- a/rpython/jit/backend/arm/test/test_runner.py +++ b/rpython/jit/backend/arm/test/test_runner.py @@ -10,6 +10,7 @@ from rpython.rtyper.annlowlevel import llhelper from rpython.jit.codewriter.effectinfo import EffectInfo from rpython.jit.metainterp.history import JitCellToken, TargetToken +from rpython.jit.backend.arm.detect import detect_arch_version CPU = getcpuclass() @@ -27,7 +28,8 @@ bridge_loop_instructions = ['ldr', 'mov', 'nop', 'cmp', 'bge', 'push', 'mov', 'mov', 'push', 'mov', 'mov', 'blx', 'mov', 'mov', 'bx'] - if CPU.arch_version == 7: + arch_version = detect_arch_version() + if arch_version == 7: bridge_loop_instructions = ['ldr', 'mov', 'nop', 'cmp', 'bge', 'push', 'mov', 'mov', 'push', 'mov', 'mov', 'blx', 'mov', 'mov', 'bx'] diff --git a/rpython/jit/backend/test/runner_test.py b/rpython/jit/backend/test/runner_test.py --- a/rpython/jit/backend/test/runner_test.py +++ b/rpython/jit/backend/test/runner_test.py @@ -3935,3 +3935,19 @@ descr = self.cpu.get_latest_descr(frame) assert descr.identifier == 42 assert not self.cpu.grab_exc_value(frame) + + def test_setarrayitem_raw_short(self): + # setarrayitem_raw(140737353744432, 0, 30583, descr=) + A = rffi.CArray(rffi.SHORT) + arraydescr = self.cpu.arraydescrof(A) + a = lltype.malloc(A, 2, flavor='raw') + a[0] = rffi.cast(rffi.SHORT, 666) + a[1] = rffi.cast(rffi.SHORT, 777) + a_int = rffi.cast(lltype.Signed, a) + print 'a_int:', a_int + self.execute_operation(rop.SETARRAYITEM_RAW, + [ConstInt(a_int), ConstInt(0), ConstInt(-7654)], + 'void', descr=arraydescr) + assert rffi.cast(lltype.Signed, a[0]) == -7654 + assert rffi.cast(lltype.Signed, a[1]) == 777 + lltype.free(a, flavor='raw') diff --git a/rpython/jit/backend/x86/regloc.py b/rpython/jit/backend/x86/regloc.py --- a/rpython/jit/backend/x86/regloc.py +++ b/rpython/jit/backend/x86/regloc.py @@ -521,17 +521,6 @@ return func_with_new_name(INSN, "INSN_" + name) - def _16_bit_binaryop(name): - def INSN(self, loc1, loc2): - # Select 16-bit operand mode - self.writechar('\x66') - # XXX: Hack to let immediate() in rx86 know to do a 16-bit encoding - self._use_16_bit_immediate = True - getattr(self, name)(loc1, loc2) - self._use_16_bit_immediate = False - - return INSN - def _addr_as_reg_offset(self, addr): # Encodes a (64-bit) address as an offset from the scratch register. # If we are within a "reuse_scratch_register" block, we remember the @@ -616,10 +605,10 @@ NEG = _unaryop('NEG') CMP = _binaryop('CMP') - CMP16 = _16_bit_binaryop('CMP') + CMP16 = _binaryop('CMP16') MOV = _binaryop('MOV') MOV8 = _binaryop('MOV8') - MOV16 = _16_bit_binaryop('MOV') + MOV16 = _binaryop('MOV16') MOVZX8 = _binaryop('MOVZX8') MOVSX8 = _binaryop('MOVSX8') MOVZX16 = _binaryop('MOVZX16') diff --git a/rpython/jit/backend/x86/rx86.py b/rpython/jit/backend/x86/rx86.py --- a/rpython/jit/backend/x86/rx86.py +++ b/rpython/jit/backend/x86/rx86.py @@ -125,10 +125,7 @@ elif width == 'q' and mc.WORD == 8: mc.writeimm64(immediate) else: - if mc._use_16_bit_immediate: - mc.writeimm16(immediate) - else: - mc.writeimm32(immediate) + mc.writeimm32(immediate) return 0 def immediate(argnum, width='i'): @@ -282,16 +279,20 @@ # (the immediate address itself must be explicitely encoded as well, # with immediate(argnum)). -def encode_abs(mc, _1, _2, orbyte): + at specialize.arg(2) +def encode_abs(mc, immediate, _, orbyte): # expands to either '\x05' on 32-bit, or '\x04\x25' on 64-bit if mc.WORD == 8: mc.writechar(chr(0x04 | orbyte)) mc.writechar(chr(0x25)) else: mc.writechar(chr(0x05 | orbyte)) + # followed by an immediate, always 32 bits + mc.writeimm32(immediate) return 0 -abs_ = encode_abs, 0, None, None +def abs_(argnum): + return encode_abs, argnum, None, None # ____________________________________________________________ # For 64-bits mode: the REX.W, REX.R, REX.X, REG.B prefixes @@ -305,9 +306,6 @@ def encode_rex(mc, rexbyte, basevalue, orbyte): if mc.WORD == 8: assert 0 <= rexbyte < 8 - # XXX: Hack. Ignore REX.W if we are using 16-bit operands - if mc._use_16_bit_immediate: - basevalue &= ~REX_W if basevalue != 0 or rexbyte != 0: if basevalue == 0: basevalue = 0x40 @@ -374,9 +372,8 @@ INSN_br = insn(rex_w, chr(base+1), register(2,8), stack_bp(1)) INSN_rb = insn(rex_w, chr(base+3), register(1,8), stack_bp(2)) INSN_rm = insn(rex_w, chr(base+3), register(1,8), mem_reg_plus_const(2)) - INSN_rj = insn(rex_w, chr(base+3), register(1,8), abs_, immediate(2)) - INSN_ji8 = insn(rex_w, '\x83', orbyte(base), abs_, immediate(1), - immediate(2,'b')) + INSN_rj = insn(rex_w, chr(base+3), register(1,8), abs_(2)) + INSN_ji8 = insn(rex_w, '\x83', orbyte(base), abs_(1), immediate(2,'b')) INSN_mi8 = insn(rex_w, '\x83', orbyte(base), mem_reg_plus_const(1), immediate(2,'b')) INSN_bi8 = insn(rex_w, '\x83', orbyte(base), stack_bp(1), immediate(2,'b')) @@ -449,9 +446,6 @@ class AbstractX86CodeBuilder(object): """Abstract base class.""" - # Used by the 16-bit version of instructions - _use_16_bit_immediate = False - def writechar(self, char): raise NotImplementedError @@ -489,15 +483,13 @@ CMP_mi = select_8_or_32_bit_immed(CMP_mi8, CMP_mi32) CMP_mr = insn(rex_w, '\x39', register(2, 8), mem_reg_plus_const(1)) - CMP_ji8 = insn(rex_w, '\x83', orbyte(7<<3), abs_, - immediate(1), immediate(2, 'b')) - CMP_ji32 = insn(rex_w, '\x81', orbyte(7<<3), abs_, - immediate(1), immediate(2)) + CMP_ji8 = insn(rex_w, '\x83', orbyte(7<<3), abs_(1), immediate(2, 'b')) + CMP_ji32 = insn(rex_w, '\x81', orbyte(7<<3), abs_(1), immediate(2)) CMP_ji = select_8_or_32_bit_immed(CMP_ji8, CMP_ji32) - CMP_jr = insn(rex_w, '\x39', register(2, 8), abs_, immediate(1)) + CMP_jr = insn(rex_w, '\x39', register(2, 8), abs_(1)) CMP32_mi = insn(rex_nw, '\x81', orbyte(7<<3), mem_reg_plus_const(1), immediate(2)) - + CMP16_mi = insn('\x66', rex_nw, '\x81', orbyte(7<<3), mem_reg_plus_const(1), immediate(2, 'h')) CMP8_ri = insn(rex_fw, '\x80', byte_register(1), '\xF8', immediate(2, 'b')) AND8_rr = insn(rex_fw, '\x20', byte_register(1), byte_register(2,8), '\xC0') @@ -505,7 +497,7 @@ OR8_rr = insn(rex_fw, '\x08', byte_register(1), byte_register(2,8), '\xC0') OR8_mi = insn(rex_nw, '\x80', orbyte(1<<3), mem_reg_plus_const(1), immediate(2, 'b')) - OR8_ji = insn(rex_nw, '\x80', orbyte(1<<3), abs_, immediate(1), + OR8_ji = insn(rex_nw, '\x80', orbyte(1<<3), abs_(1), immediate(2, 'b')) NEG_r = insn(rex_w, '\xF7', register(1), '\xD8') @@ -556,7 +548,7 @@ LEA32_rb = insn(rex_w, '\x8D', register(1,8),stack_bp(2,force_32bits=True)) LEA_ra = insn(rex_w, '\x8D', register(1, 8), mem_reg_plus_scaled_reg_plus_const(2)) LEA_rm = insn(rex_w, '\x8D', register(1, 8), mem_reg_plus_const(2)) - LEA_rj = insn(rex_w, '\x8D', register(1, 8), abs_, immediate(2)) + LEA_rj = insn(rex_w, '\x8D', register(1, 8), abs_(2)) CALL_l = insn('\xE8', relative(1)) CALL_r = insn(rex_nw, '\xFF', register(1), chr(0xC0 | (2<<3))) @@ -583,11 +575,11 @@ TEST8_mi = insn(rex_nw, '\xF6', orbyte(0<<3), mem_reg_plus_const(1), immediate(2, 'b')) TEST8_bi = insn(rex_nw, '\xF6', orbyte(0<<3), stack_bp(1), immediate(2, 'b')) - TEST8_ji = insn(rex_nw, '\xF6', orbyte(0<<3), abs_, immediate(1), immediate(2, 'b')) + TEST8_ji = insn(rex_nw, '\xF6', orbyte(0<<3), abs_(1), immediate(2, 'b')) TEST_rr = insn(rex_w, '\x85', register(2,8), register(1), '\xC0') BTS_mr = insn(rex_w, '\x0F\xAB', register(2,8), mem_reg_plus_const(1)) - BTS_jr = insn(rex_w, '\x0F\xAB', register(2,8), abs_, immediate(1)) + BTS_jr = insn(rex_w, '\x0F\xAB', register(2,8), abs_(1)) # x87 instructions FSTPL_b = insn('\xDD', orbyte(3<<3), stack_bp(1)) # rffi.DOUBLE ('as' wants L??) @@ -718,7 +710,7 @@ add_insn('s', stack_sp(modrm_argnum)) add_insn('m', mem_reg_plus_const(modrm_argnum)) add_insn('a', mem_reg_plus_scaled_reg_plus_const(modrm_argnum)) - add_insn('j', abs_, immediate(modrm_argnum)) + add_insn('j', abs_(modrm_argnum)) # Define a regular MOV, and a variant MOV32 that only uses the low 4 bytes of a # register @@ -729,6 +721,8 @@ define_modrm_modes('MOV8_*r', [rex_fw, '\x88', byte_register(2, 8)], regtype='BYTE') define_modrm_modes('MOV8_*i', [rex_fw, '\xC6', orbyte(0<<3)], [immediate(2, 'b')], regtype='BYTE') +define_modrm_modes('MOV16_*r', ['\x66', rex_nw, '\x89', register(2, 8)]) +define_modrm_modes('MOV16_*i', ['\x66', rex_nw, '\xC7', orbyte(0<<3)], [immediate(2, 'h')]) define_modrm_modes('MOVZX8_r*', [rex_w, '\x0F\xB6', register(1, 8)], regtype='BYTE') define_modrm_modes('MOVSX8_r*', [rex_w, '\x0F\xBE', register(1, 8)], regtype='BYTE') @@ -766,7 +760,7 @@ # assert insnname_template.count('*') == 1 add_insn('x', register(2), '\xC0') - add_insn('j', abs_, immediate(2)) + add_insn('j', abs_(2)) add_insn('m', mem_reg_plus_const(2)) define_pxmm_insn('PADDQ_x*', '\xD4') diff --git a/rpython/memory/gc/env.py b/rpython/memory/gc/env.py --- a/rpython/memory/gc/env.py +++ b/rpython/memory/gc/env.py @@ -279,7 +279,7 @@ def best_nursery_size_for_L2cache(L2cache): # Heuristically, the best nursery size to choose is about half # of the L2 cache. - if L2cache > 1024 * 1024: # we don't want to have nursery estimated + if L2cache > 2 * 1024 * 1024: # we don't want to have nursery estimated # on L2 when L3 is present return L2cache // 2 else: diff --git a/rpython/memory/gc/minimark.py b/rpython/memory/gc/minimark.py --- a/rpython/memory/gc/minimark.py +++ b/rpython/memory/gc/minimark.py @@ -130,6 +130,7 @@ FORWARDSTUB = lltype.GcStruct('forwarding_stub', ('forw', llmemory.Address)) FORWARDSTUBPTR = lltype.Ptr(FORWARDSTUB) +NURSARRAY = lltype.Array(llmemory.Address) # ____________________________________________________________ @@ -263,7 +264,7 @@ self.nursery_top = NULL self.nursery_real_top = NULL self.debug_tiny_nursery = -1 - self.debug_rotating_nurseries = None + self.debug_rotating_nurseries = lltype.nullptr(NURSARRAY) self.extra_threshold = 0 # # The ArenaCollection() handles the nonmovable objects allocation. @@ -350,8 +351,6 @@ # hacking at the current nursery position in collect_and_reserve(). if newsize <= 0: newsize = env.estimate_best_nursery_size() - # 4*1024*1024 # fixed to 4MB by default - # (it was env.estimate_best_nursery_size()) if newsize <= 0: newsize = defaultsize if newsize < minsize: @@ -471,23 +470,32 @@ # and use them alternatively, while mprotect()ing the unused # ones to detect invalid access. debug_start("gc-debug") - self.debug_rotating_nurseries = [] - for i in range(22): + self.debug_rotating_nurseries = lltype.malloc( + NURSARRAY, 22, flavor='raw', track_allocation=False) + i = 0 + while i < 22: nurs = self._alloc_nursery() llarena.arena_protect(nurs, self._nursery_memory_size(), True) - self.debug_rotating_nurseries.append(nurs) + self.debug_rotating_nurseries[i] = nurs + i += 1 debug_print("allocated", len(self.debug_rotating_nurseries), "extra nurseries") debug_stop("gc-debug") def debug_rotate_nursery(self): - if self.debug_rotating_nurseries is not None: + if self.debug_rotating_nurseries: debug_start("gc-debug") oldnurs = self.nursery llarena.arena_protect(oldnurs, self._nursery_memory_size(), True) - self.debug_rotating_nurseries.append(oldnurs) # - newnurs = self.debug_rotating_nurseries.pop(0) + newnurs = self.debug_rotating_nurseries[0] + i = 0 + while i < len(self.debug_rotating_nurseries) - 1: + self.debug_rotating_nurseries[i] = ( + self.debug_rotating_nurseries[i + 1]) + i += 1 + self.debug_rotating_nurseries[i] = oldnurs + # llarena.arena_protect(newnurs, self._nursery_memory_size(), False) self.nursery = newnurs self.nursery_top = self.nursery + self.initial_cleanup diff --git a/rpython/memory/gctransform/framework.py b/rpython/memory/gctransform/framework.py --- a/rpython/memory/gctransform/framework.py +++ b/rpython/memory/gctransform/framework.py @@ -619,6 +619,12 @@ func = getattr(graph, 'func', None) if func and getattr(func, '_gc_no_collect_', False): if self.collect_analyzer.analyze_direct_call(graph): + print '!'*79 + ca = CollectAnalyzer(self.translator) + ca.verbose = True + ca.analyze_direct_call(graph) + # ^^^ for the dump of which operation in which graph actually + # causes it to return True raise Exception("'no_collect' function can trigger collection:" " %s" % func) diff --git a/rpython/translator/backendopt/graphanalyze.py b/rpython/translator/backendopt/graphanalyze.py --- a/rpython/translator/backendopt/graphanalyze.py +++ b/rpython/translator/backendopt/graphanalyze.py @@ -80,21 +80,21 @@ if graph is None: x = self.analyze_external_call(op, seen) if self.verbose and x: - print '\tanalyze_external_call %s: %r' % (op, x) + self.dump_info('analyze_external_call %s: %r' % (op, x)) return x x = self.analyze_direct_call(graph, seen) if self.verbose and x: - print '\tanalyze_direct_call(%s): %r' % (graph, x) + self.dump_info('analyze_direct_call(%s): %r' % (graph, x)) return x elif op.opname == "indirect_call": graphs = op.args[-1].value if graphs is None: if self.verbose: - print '\t%s to unknown' % (op,) + self.dump_info('%s to unknown' % (op,)) return self.top_result() x = self.analyze_indirect_call(graphs, seen) if self.verbose and x: - print '\tanalyze_indirect_call(%s): %r' % (graphs, x) + self.dump_info('analyze_indirect_call(%s): %r' % (graphs, x)) return x elif op.opname == "oosend": name = op.args[0].value @@ -106,9 +106,12 @@ return self.analyze_oosend(TYPE, name, seen) x = self.analyze_simple_operation(op, graphinfo) if self.verbose and x: - print '\t%s: %r' % (op, x) + self.dump_info('%s: %r' % (op, x)) return x + def dump_info(self, info): + print '[%s] %s' % (self.__class__.__name__, info) + def analyze_direct_call(self, graph, seen=None): if seen is None: seen = DependencyTracker(self) From noreply at buildbot.pypy.org Sun Apr 21 10:30:47 2013 From: noreply at buildbot.pypy.org (bivab) Date: Sun, 21 Apr 2013 10:30:47 +0200 (CEST) Subject: [pypy-commit] pypy default: fix viewcode after arm cpu name change Message-ID: <20130421083047.49E1F1C0328@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63538:3bd0f1414f02 Date: 2013-04-21 09:31 +0200 http://bitbucket.org/pypy/pypy/changeset/3bd0f1414f02/ Log: fix viewcode after arm cpu name change diff --git a/rpython/jit/backend/tool/viewcode.py b/rpython/jit/backend/tool/viewcode.py --- a/rpython/jit/backend/tool/viewcode.py +++ b/rpython/jit/backend/tool/viewcode.py @@ -53,8 +53,7 @@ 'x86_32': 'i386', 'x86_64': 'x86-64', 'i386': 'i386', - 'armv6_32': 'arm', - 'armv7_32': 'arm', + 'arm_32': 'arm', } cmd = find_objdump() objdump = ('%(command)s -M %(backend)s -b binary -m %(machine)s ' From noreply at buildbot.pypy.org Sun Apr 21 10:30:48 2013 From: noreply at buildbot.pypy.org (bivab) Date: Sun, 21 Apr 2013 10:30:48 +0200 (CEST) Subject: [pypy-commit] pypy default: merge heads Message-ID: <20130421083048.9DEE91C0328@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63539:53fcebf7fa52 Date: 2013-04-21 09:39 +0200 http://bitbucket.org/pypy/pypy/changeset/53fcebf7fa52/ Log: merge heads diff --git a/Makefile b/Makefile new file mode 100644 --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ + +all: pypy-c + +pypy-c: + @echo "Building PyPy with JIT, it'll take about 40 minutes and 4G of RAM" + @sleep 3 + rpython/bin/rpython -Ojit pypy/goal/targetpypystandalone.py diff --git a/README.rst b/README.rst --- a/README.rst +++ b/README.rst @@ -22,3 +22,16 @@ and send us feedback! the pypy-dev team + +Building +======== + +build with:: + + rpython/bin/rpython -Ojit pypy/goal/targetpypystandalone.py + +This ends up with ``pypy-c`` binary in the main pypy directory. We suggest +to use virtualenv with the resulting pypy-c as the interpreter, you can +find more details about various installation schemes here: + +http://doc.pypy.org/en/latest/getting-started.html#installing-pypy diff --git a/lib-python/2.7/json/decoder.py b/lib-python/2.7/json/decoder.py --- a/lib-python/2.7/json/decoder.py +++ b/lib-python/2.7/json/decoder.py @@ -162,7 +162,7 @@ if nextchar == '}': if object_pairs_hook is not None: result = object_pairs_hook(pairs) - return result, end + return result, end + 1 pairs = {} if object_hook is not None: pairs = object_hook(pairs) diff --git a/lib-python/2.7/json/tests/test_decode.py b/lib-python/2.7/json/tests/test_decode.py --- a/lib-python/2.7/json/tests/test_decode.py +++ b/lib-python/2.7/json/tests/test_decode.py @@ -44,6 +44,7 @@ object_pairs_hook=OrderedDict, object_hook=lambda x: None), OrderedDict(p)) + self.assertEqual(self.loads("{}", object_pairs_hook=list), []) class TestPyDecode(TestDecode, PyTest): pass diff --git a/pypy/doc/config/translation.gcrootfinder.txt b/pypy/doc/config/translation.gcrootfinder.txt --- a/pypy/doc/config/translation.gcrootfinder.txt +++ b/pypy/doc/config/translation.gcrootfinder.txt @@ -9,7 +9,9 @@ - ``--gcrootfinder=asmgcc``: use assembler hackery to find the roots directly from the normal stack. This is a bit faster, but platform specific. It works so far with GCC or MSVC, - on i386 and x86-64. + on i386 and x86-64. It is tested only on Linux (where it is + the default) so other platforms (as well as MSVC) may need + various fixes before they can be used. You may have to force the use of the shadowstack root finder if you are running into troubles or if you insist on translating diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -87,15 +87,15 @@ ofs = self.cpu.get_ofs_of_frame_field('jf_guard_exc') # make sure ofs fits into a register assert check_imm_arg(ofs) - mc.LDR_ri(r.r0.value, r.fp.value, imm=ofs) + self.store_reg(mc, r.r0, r.fp, ofs) propagate_exception_descr = rffi.cast(lltype.Signed, cast_instance_to_gcref(self.cpu.propagate_exception_descr)) # put propagate_exception_descr into frame ofs = self.cpu.get_ofs_of_frame_field('jf_descr') # make sure ofs fits into a register assert check_imm_arg(ofs) - mc.gen_load_int(r.r0.value, propagate_exception_descr) - mc.STR_ri(r.r0.value, r.fp.value, imm=ofs) + mc.gen_load_int(r.r1.value, propagate_exception_descr) + self.store_reg(mc, r.r0, r.fp, ofs) mc.MOV_rr(r.r0.value, r.fp.value) self.gen_func_epilog(mc) rawstart = mc.materialize(self.cpu.asmmemmgr, []) diff --git a/rpython/jit/backend/test/runner_test.py b/rpython/jit/backend/test/runner_test.py --- a/rpython/jit/backend/test/runner_test.py +++ b/rpython/jit/backend/test/runner_test.py @@ -3943,7 +3943,8 @@ a = lltype.malloc(A, 2, flavor='raw') a[0] = rffi.cast(rffi.SHORT, 666) a[1] = rffi.cast(rffi.SHORT, 777) - a_int = rffi.cast(lltype.Signed, a) + addr = llmemory.cast_ptr_to_adr(a) + a_int = heaptracker.adr2int(addr) print 'a_int:', a_int self.execute_operation(rop.SETARRAYITEM_RAW, [ConstInt(a_int), ConstInt(0), ConstInt(-7654)], diff --git a/rpython/jit/backend/x86/rx86.py b/rpython/jit/backend/x86/rx86.py --- a/rpython/jit/backend/x86/rx86.py +++ b/rpython/jit/backend/x86/rx86.py @@ -682,10 +682,12 @@ def define_modrm_modes(insnname_template, before_modrm, after_modrm=[], regtype='GPR'): def add_insn(code, *modrm): - args = before_modrm + list(modrm) + after_modrm + args = before_modrm + list(modrm) methname = insnname_template.replace('*', code) - if methname.endswith('_rr') or methname.endswith('_xx'): + if (methname.endswith('_rr') or methname.endswith('_xx') + or methname.endswith('_ri')): args.append('\xC0') + args += after_modrm if regtype == 'XMM': insn_func = xmminsn(*args) diff --git a/rpython/jit/backend/x86/test/test_regloc.py b/rpython/jit/backend/x86/test/test_regloc.py --- a/rpython/jit/backend/x86/test/test_regloc.py +++ b/rpython/jit/backend/x86/test/test_regloc.py @@ -1,4 +1,5 @@ import struct, sys +from rpython.jit.backend.x86.rx86 import R from rpython.jit.backend.x86.regloc import * from rpython.jit.backend.x86.test.test_rx86 import CodeBuilder32, CodeBuilder64, assert_encodes_as from rpython.jit.backend.x86.assembler import heap @@ -15,36 +16,49 @@ cb32 = LocationCodeBuilder32 cb64 = LocationCodeBuilder64 +def test_mov_8(): + assert_encodes_as(cb32, "MOV8_ri", (R.cl, 25), '\xB1\x19') + def test_mov_16(): + # only 'MOV16_*r' and 'MOV16_*i' are supported # 32-bit assert_encodes_as(cb32, "MOV16", (ecx, ebx), '\x66\x89\xD9') - assert_encodes_as(cb32, "MOV16", (ecx, ImmedLoc(12345)), '\x66\xB9\x39\x30') - + assert_encodes_as(cb32, "MOV16", + (AddressLoc(ecx, ImmedLoc(16), 0, 0), ebx), + '\x66\x89\x59\x10') # 64-bit assert_encodes_as(cb64, "MOV16", (r8, ebx), '\x66\x41\x89\xD8') # 11 011 000 assert_encodes_as(cb64, "MOV16", (ebx, r8), '\x66\x44\x89\xC3') # 11 000 011 - assert_encodes_as(cb64, "MOV16", (ecx, ebx), '\x66\x40\x89\xD9') - assert_encodes_as(cb64, "MOV16", (ecx, ImmedLoc(12345)), '\x66\xB9\x39\x30') + assert_encodes_as(cb64, "MOV16", (ecx, ebx), '\x66\x89\xD9') # for the next case we don't pick the most efficient encoding, but well - expected = '\x66\x40\xC7\xC1\xC7\xCF' # could be '\x66\xB9\xC7\xCF' + expected = '\x66\xC7\xC1\x39\x30' # could be '\x66\xB9\x39\x30' + assert_encodes_as(cb64, "MOV16", (ecx, ImmedLoc(12345)), expected) + # for the next case we don't pick the most efficient encoding, but well + expected = '\x66\xC7\xC1\xC7\xCF' # could be '\x66\xB9\xC7\xCF' assert_encodes_as(cb64, "MOV16", (ecx, ImmedLoc(-12345)), expected) - assert_encodes_as(cb64, "MOV16", (r9, ImmedLoc(12345)), '\x66\x41\xB9\x39\x30') + # for the next case we don't pick the most efficient encoding, but well + expected = '\x66\x41\xC7\xC1\x39\x30' # could be '\x66\x41\xB9\x39\x30' + assert_encodes_as(cb64, "MOV16", (r9, ImmedLoc(12345)), expected) # for the next case we don't pick the most efficient encoding, but well expected = '\x66\x41\xC7\xC1\xC7\xCF' # could be '\x66\x41\xB9\xC7\xCF' assert_encodes_as(cb64, "MOV16", (r9, ImmedLoc(-12345)), expected) - assert_encodes_as(cb64, "MOV16", (AddressLoc(r13, ImmedLoc(0), 0, 0), ImmedLoc(12345)), '\x66\x41\xC7\x45\x00\x39\x30') + assert_encodes_as(cb64, "MOV16", + (AddressLoc(r13, ImmedLoc(0), 0, 0), ImmedLoc(12345)), + '\x66\x41\xC7\x45\x00\x39\x30') def test_cmp_16(): + # only 'CMP16_mi' is supported # 32-bit - assert_encodes_as(cb32, "CMP16", (ecx, ebx), '\x66\x39\xD9') - assert_encodes_as(cb32, "CMP16", (ecx, ImmedLoc(12345)), '\x66\x81\xF9\x39\x30') - + assert_encodes_as(cb32, "CMP16", + (AddressLoc(ecx, ImmedLoc(0), 0, 0), ImmedLoc(21324)), + '\x66\x81\x39\x4c\x53') + assert_encodes_as(cb32, "CMP16", + (AddressLoc(esi, ImmedLoc(2), 0, 0), ImmedLoc(-12345)), + '\x66\x81\x7e\x02\xc7\xcf') # 64-bit - assert_encodes_as(cb64, "CMP16", (r8, ebx), '\x66\x41\x39\xD8') # 11 011 000 - assert_encodes_as(cb64, "CMP16", (ebx, r8), '\x66\x44\x39\xC3') # 11 000 011 - assert_encodes_as(cb64, "CMP16", (ecx, ebx), '\x66\x40\x39\xD9') - assert_encodes_as(cb64, "CMP16", (ecx, ImmedLoc(12345)), '\x66\x40\x81\xF9\x39\x30') - assert_encodes_as(cb64, "CMP16", (AddressLoc(r13, ImmedLoc(0), 0, 0), ImmedLoc(12345)), '\x66\x41\x81\x7D\x00\x39\x30') + assert_encodes_as(cb64, "CMP16", + (AddressLoc(r13, ImmedLoc(0), 0, 0), ImmedLoc(12345)), + '\x66\x41\x81\x7D\x00\x39\x30') def test_relocation(): from rpython.rtyper.lltypesystem import lltype, rffi From noreply at buildbot.pypy.org Sun Apr 21 10:30:49 2013 From: noreply at buildbot.pypy.org (bivab) Date: Sun, 21 Apr 2013 10:30:49 +0200 (CEST) Subject: [pypy-commit] pypy default: more exception handling fixes Message-ID: <20130421083049.DA1FF1C0328@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63540:52932ddf3852 Date: 2013-04-21 10:29 +0200 http://bitbucket.org/pypy/pypy/changeset/52932ddf3852/ Log: more exception handling fixes diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -94,7 +94,7 @@ ofs = self.cpu.get_ofs_of_frame_field('jf_descr') # make sure ofs fits into a register assert check_imm_arg(ofs) - mc.gen_load_int(r.r1.value, propagate_exception_descr) + mc.gen_load_int(r.r0.value, propagate_exception_descr) self.store_reg(mc, r.r0, r.fp, ofs) mc.MOV_rr(r.r0.value, r.fp.value) self.gen_func_epilog(mc) @@ -117,7 +117,8 @@ # store exc_value in JITFRAME ofs = self.cpu.get_ofs_of_frame_field('jf_guard_exc') assert check_imm_arg(ofs) - self.store_reg(mc, r.ip, r.fp, ofs) + self.load_reg(mc, r.ip, r.ip, helper=tmpreg) + self.store_reg(mc, r.ip, r.fp, ofs, helper=tmpreg) if exctploc is not None: # store pos_exception in exctploc assert exctploc.is_reg() From noreply at buildbot.pypy.org Sun Apr 21 11:45:34 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sun, 21 Apr 2013 11:45:34 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Document the new destructors-and-finalizers world. Message-ID: <20130421094534.9334B1C0400@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63541:2b3eb84aaf5c Date: 2013-04-21 11:43 +0200 http://bitbucket.org/pypy/pypy/changeset/2b3eb84aaf5c/ Log: Document the new destructors-and-finalizers world. diff --git a/pypy/doc/garbage_collection.rst b/pypy/doc/garbage_collection.rst --- a/pypy/doc/garbage_collection.rst +++ b/pypy/doc/garbage_collection.rst @@ -191,14 +191,13 @@ considerably speed up minor collections, because we then only have to scan 128 entries of the array instead of all of them. -- As usual, we need special care about weak references, and objects with - finalizers. Weak references are allocated in the nursery, and if they - survive they move to the old stage, as usual for all objects; the - difference is that the reference they contain must either follow the - object, or be set to NULL if the object dies. And the objects with - finalizers, considered rare enough, are immediately allocated old to - simplify the design. In particular their ``__del__`` method can only - be called just after a major collection. +- As usual, we need special care about weak references. Weak reference + objects are allocated in the nursery, and if they survive they move to + the old stage, as usual for all objects; the difference is that the + reference they contain must either follow the referenced object, or be + set to NULL if the object dies. After a major collection the + referenced object cannot move, but the pointer still needs to be + checked and set to NULL if it dies. - The objects move once only, so we can use a trick to implement id() and hash(). If the object is not in the nursery, it won't move any @@ -210,4 +209,50 @@ are preserved. If the object dies then the pre-reserved location becomes free garbage, to be collected at the next major collection. +Destructors and finalizers +-------------------------- + +A *destructor* is an RPython ``__del__`` method. Destructors are called +when the object really dies, directly from the GC. They cannot do a lot +of operations; for example they may not perform any operation involving +following or changing GC pointers. They are only useful to do things +like freeing some raw-malloced memory. (The content of the ``__del__`` +methods is checked during translation.) + +On the other hand, a *finalizer* is more flexible. You can attach a +finalizer callback to any RPython instance by calling +``rgc.register_finalizer(method)``, where ``method`` is a bound method +of the instance. (You cannot call ``register_finalizer()`` several +times on the same instance.) When such an object is about to die, the +GC keeps it alive, including all objects it points to, and adds it into +a to-be-called queue. If there are several objects with finalizers they +are added in order: if possible, a topological order (so e.g. if, at the +time of the GC, an object A contains a pointer to an object B, then +``A.finalizer`` is added into the queue before ``B.finalizer``). The GC +then goes through the queue in order and invokes the callbacks. + +The objects really die only when they are no longer in the queue (nor +anywhere else). They may have both a finalizer and a destructor; the +latter will be called when the object really dies. + +Note subtle differences with CPython: finalizers are called even if +there is a cycle of objects with finalizers (by randomly ignoring one of +the references and following the rest in topological order); finalizers +are called only once; and it is possible for ``A.finalizer()`` to +resurrect an object ``B`` that was already enqueued, but this is not +checked: as ``B`` is already in the queue, ``B.finalizer()`` is called +anyway when it is its turn. (This is designed to cope with situations +where there are suddenly a lot of objects with finalizers in a chain, +which can occur in Python.) + +In some cases we want finalizers to be called at precise points in time, +rather than when the GC randomly kicks in. To do this, at the start of +the finalizer callback function, we check if we're called at a correct +point in time; if not, we call ``rgc.finalize_later()``, which raises an +exception. This exception tells the GC to stop calling finalizers, +keeping the queue at it is (starting from the object whose finalizer +just raised). Later, at a safe point, we ask the GC to proceed by +calling `rgc.progress_through_finalizer_queue()`. (This safe point is +in the interpreter main loop between two bytecodes, in PyPy.) + .. include:: _ref.txt From noreply at buildbot.pypy.org Sun Apr 21 21:46:32 2013 From: noreply at buildbot.pypy.org (bivab) Date: Sun, 21 Apr 2013 21:46:32 +0200 (CEST) Subject: [pypy-commit] buildbot decouple-builds: separate translation and tests run for nightly linux and linux64 builds Message-ID: <20130421194632.201201C0328@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: decouple-builds Changeset: r791:daca51eda174 Date: 2013-04-21 17:10 +0200 http://bitbucket.org/pypy/buildbot/changeset/daca51eda174/ Log: separate translation and tests run for nightly linux and linux64 builds diff --git a/bot2/pypybuildbot/master.py b/bot2/pypybuildbot/master.py --- a/bot2/pypybuildbot/master.py +++ b/bot2/pypybuildbot/master.py @@ -62,45 +62,70 @@ # OSX 32bit tests require a larger timeout to finish pypyOwnTestFactoryOSX32 = pypybuilds.Own(timeout=3*3600) -pypyTranslatedAppLevelTestFactory = pypybuilds.Translated(lib_python=True, - app_tests=True) -pypyTranslatedAppLevelTestFactory64 = pypybuilds.Translated(lib_python=True, - app_tests=True, - platform='linux64') + +# Translation builds +# Triggers +TRIGGER_LINUX32 = 'pypy-c-linux-x86-32-completed' +TRIGGER_LINUX64 = 'pypy-c-linux-x86-x64-completed' +TRIGGER_JITLINUX32 = 'pypy-c-jit-linux-x86-32-completed' +TRIGGER_JITLINUX64 = 'pypy-c-jit-linux-x86-64-completed' +jit_translation_args = ['-Ojit'] +# linux +# x86 +pypyTranslatedFactory = pypybuilds.NightlyBuild( + trigger=TRIGGER_LINUX32, + platform='linux') +pypyJitTranslatedFactory = pypybuilds.NightlyBuild( + trigger=TRIGGER_LINUX64, + translationArgs=jit_translation_args, + platform='linux') +# x86_64 +pypyTranslatedFactory64 = pypybuilds.NightlyBuild( + trigger=TRIGGER_JITLINUX32, + platform='linux64') +pypyJitTranslatedFactory64 = pypybuilds.NightlyBuild( + translationArgs=jit_translation_args, + trigger=TRIGGER_JITLINUX64, + platform='linux64') + +# App and JIT test builds +# App level test builds +pypyTranslatedAppLevelTestFactory = pypybuilds.TranslatedTests( + lib_python=True, + app_tests=True, + platform='linux') +pypyTranslatedAppLevelTestFactory64 = pypybuilds.TranslatedTests( + lib_python=True, + app_tests=True, + platform='linux64') # these are like the two above: the only difference is that they only run # lib-python tests,not -A tests -pypyTranslatedLibPythonTestFactory = pypybuilds.Translated(lib_python=True, - app_tests=False) -pypyTranslatedLibPythonTestFactory64 = pypybuilds.Translated(lib_python=True, - app_tests=False, - platform='linux64') +pypyTranslatedLibPythonTestFactory = pypybuilds.TranslatedTests( + lib_python=True, + app_tests=False, + platform='linux') +pypyTranslatedLibPythonTestFactory64 = pypybuilds.TranslatedTests( + lib_python=True, + app_tests=False, + platform='linux64') -pypyTranslatedAppLevelTestFactoryWin = pypybuilds.Translated( - platform="win32", - lib_python=True, - app_tests=True, - ) - -jit_translation_args = ['-Ojit'] - -pypyJITTranslatedTestFactory = pypybuilds.Translated( +pypyJITTranslatedTestFactory = pypybuilds.TranslatedTests( translationArgs=jit_translation_args, - targetArgs=[], lib_python=True, pypyjit=True, app_tests=True, - ) + platform='linux') -pypyJITTranslatedTestFactory64 = pypybuilds.Translated( +pypyJITTranslatedTestFactory64 = pypybuilds.TranslatedTests( translationArgs=jit_translation_args, - targetArgs=[], lib_python=True, pypyjit=True, app_tests=True, platform='linux64', ) +# other platforms pypyJITTranslatedTestFactoryIndiana = pypybuilds.Translated( translationArgs=jit_translation_args, targetArgs=[], @@ -110,6 +135,12 @@ platform='openindiana32', ) +pypyTranslatedAppLevelTestFactoryWin = pypybuilds.Translated( + platform="win32", + lib_python=True, + app_tests=True, + ) + pypyJITTranslatedTestFactoryOSX = pypybuilds.Translated( platform='osx', translationArgs=jit_translation_args + ['--make-jobs=1'], @@ -183,6 +214,12 @@ JITBENCH64_2 = 'jit-benchmark-linux-x86-64-2' CPYTHON_64 = "cpython-2-benchmark-x86-64" +# build only +BUILDLINUX32 = "build-pypy-c-linux-x86-32" +BUILDJITLINUX32 = "build-pypy-c-jit-linux-x86-32" +BUILDLINUX64 = "build-pypy-c-linux-x86-64" +BUILDJITLINUX64 = "build-pypy-c-jit-linux-x86-64" + extra_opts= {'xerxes': {'keepalive_interval': 15}, 'aurora': {'max_builds': 1}, @@ -202,10 +239,6 @@ # linux tests LINUX32, # on tannit32, uses all cores LINUX64, # on allegro64, uses all cores - JITLINUX32, # on tannit32, uses 1 core - JITLINUX64, # on allegro64, uses 1 core - APPLVLLINUX32, # on tannit32, uses 1 core - APPLVLLINUX64, # on allegro64, uses 1 core # other platforms MACOSX32, # on minime JITWIN32, # on aurora @@ -228,6 +261,19 @@ Nightly("nighly-ppc", [ JITONLYLINUXPPC64, # on gcc1 ], branch='ppc-jit-backend', hour=1, minute=0), + + Triggerable(TRIGGER_LINUX32, [ + APPLVLLINUX32, # on tannit32, uses 1 core + ]), + Triggerable(TRIGGER_LINUX64, [ + APPLVLLINUX64, # on allegro64, uses 1 core + ]), + Triggerable(TRIGGER_JITLINUX32, [ + JITLINUX32, # on tannit32, uses 1 core + ]), + Triggerable(TRIGGER_JITLINUX64, [ + JITLINUX64, # on allegro64, uses 1 core + ]), ] + ARM.schedulers, 'status': [status, ircbot], @@ -237,6 +283,35 @@ in passwords.iteritems()], 'builders': [ + # Translation builders + {"name": BUILDLINUX32, + "slavenames": ["tannit32"], + "builddir": BUILDLINUX32, + "factory": pypyTranslatedFactory, + 'category': 'linux32', + "locks": [TannitCPU.access('counting')], + }, + {"name": BUILDLINUX64, + "slavenames": ["allegro64"], + "builddir": BUILDLINUX64, + "factory": pypyTranslatedFactory64, + "category": "linux64", + }, + {"name" : BUILDJITLINUX32, + "slavenames": ["tannit32"], + 'builddir' : BUILDJITLINUX32, + 'factory' : pypyJitTranslatedFactory, + 'category' : 'linux32', + "locks": [TannitCPU.access('counting')], + }, + {'name': BUILDJITLINUX64, + 'slavenames': ["allegro64"], + 'builddir': BUILDJITLINUX64, + 'factory': pypyJitTranslatedFactory64, + 'category': 'linux64', + #"locks": [TannitCPU.access('counting')], + }, + # {"name": LINUX32, "slavenames": ["tannit32"], "builddir": LINUX32, From noreply at buildbot.pypy.org Sun Apr 21 21:46:33 2013 From: noreply at buildbot.pypy.org (bivab) Date: Sun, 21 Apr 2013 21:46:33 +0200 (CEST) Subject: [pypy-commit] buildbot decouple-builds: Avoid copying files and instead symlink the nigtly pypy build into pypy/goal/pypy-c Message-ID: <20130421194633.5E3C71C0328@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: decouple-builds Changeset: r792:4a99cfab8997 Date: 2013-04-21 21:45 +0200 http://bitbucket.org/pypy/buildbot/changeset/4a99cfab8997/ Log: Avoid copying files and instead symlink the nigtly pypy build into pypy/goal/pypy-c diff --git a/bot2/pypybuildbot/builds.py b/bot2/pypybuildbot/builds.py --- a/bot2/pypybuildbot/builds.py +++ b/bot2/pypybuildbot/builds.py @@ -452,17 +452,23 @@ setup_steps(platform, self) # download corresponding nightly build + basepath = '%(workdir)s/%(buildnumber)s/' + nightlydir = WithProperties(basepath) + nightly_pypy_c = WithProperties(basepath + 'bin/pypy') + extension = get_extension(platform) + name = build_name(platform, pypyjit, translationArgs, + placeholder='%(revision)s') + extension + localname = 'pypy_build' + extension self.addStep(ShellCmd( - description="Clear pypy-c", - command=['rm', '-rf', 'pypy-c'], - workdir='.')) - extension = get_extension(platform) - name = build_name(platform, pypyjit, translationArgs, placeholder='%(revision)s') + extension + description="Clear pypy-c", + command=['rm', '-rf', 'pypy-c'], + workdir='.')) + # self.addStep(PyPyDownload( basename=name, mastersrc='~/nightly', - slavedest='pypy_build' + extension, - workdir='pypy-c')) + slavedest=localname, + workdir=nightlydir)) # extract downloaded file if platform.startswith('win'): @@ -470,27 +476,28 @@ else: self.addStep(ShellCmd( description="decompress pypy-c", - command=['tar', '--extract', '--file=pypy_build'+ extension, '--strip-components=1', '--directory=.'], - workdir='pypy-c')) + command=['tar', '--extract', '--file=' + localname, + '--strip-components=1', '--directory=.'], + workdir=nightlydir)) - # copy pypy-c to the expected location within the pypy source checkout + # link pypy-c to the expected location within the pypy source checkout self.addStep(ShellCmd( - description="move pypy-c", - command=['cp', '-v', 'pypy-c/bin/pypy', 'build/pypy/goal/pypy-c'], - workdir='.')) - # copy generated and copied header files to build/include - self.addStep(ShellCmd( - description="move header files", - command=['cp', '-vr', 'pypy-c/include', 'build'], - workdir='.')) - # copy ctypes_resource_cache generated during translation - self.addStep(ShellCmd( - description="move ctypes resource cache", - command=['cp', '-rv', 'pypy-c/lib_pypy/ctypes_config_cache', 'build/lib_pypy'], - workdir='.')) + description="Symlink pypy-c", + command=['ln', '-sf', nightly_pypy_c, 'pypy/goal/pypy-c'], + workdir='build/')) add_translated_tests(self, prefix, platform, app_tests, lib_python, pypyjit) + self.addStep(ShellCmd( + description="Clear symlink to pypy-c", + command=['rm', 'pypy/goal/pypy-c'], + workdir='build/')) + + self.addStep(ShellCmd( + description="Clear downloaded nightly build", + command=['rm', '-rf', nightlydir])) + + class NightlyBuild(factory.BuildFactory): def __init__(self, platform='linux', From noreply at buildbot.pypy.org Mon Apr 22 01:50:10 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Mon, 22 Apr 2013 01:50:10 +0200 (CEST) Subject: [pypy-commit] pypy py3k: more appropriate name Message-ID: <20130421235010.DCCC91C0328@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63542:af59d23bb99a Date: 2013-04-21 16:46 -0700 http://bitbucket.org/pypy/pypy/changeset/af59d23bb99a/ Log: more appropriate name diff --git a/pypy/interpreter/unicodehelper.py b/pypy/interpreter/unicodehelper.py --- a/pypy/interpreter/unicodehelper.py +++ b/pypy/interpreter/unicodehelper.py @@ -53,9 +53,9 @@ # Python we cannot use it before the codecs are ready. use the # locale codec instead from pypy.module._codecs.locale import ( - unicode_decode_locale_surrogateescape) + str_decode_locale_surrogateescape) bytes = space.bytes_w(w_string) - uni = unicode_decode_locale_surrogateescape( + uni = str_decode_locale_surrogateescape( bytes, errorhandler=decode_error_handler(space)) else: from pypy.module.sys.interp_encoding import getfilesystemencoding diff --git a/pypy/module/_codecs/locale.py b/pypy/module/_codecs/locale.py --- a/pypy/module/_codecs/locale.py +++ b/pypy/module/_codecs/locale.py @@ -70,7 +70,7 @@ pypy_wchar2char_free(sbuf) -def unicode_decode_locale_surrogateescape(s, errorhandler=None): +def str_decode_locale_surrogateescape(s, errorhandler=None): """Decode strs via the locale codecs (POSIX mrbtowc) with the surrogateescape handler. diff --git a/pypy/module/_codecs/test/test_locale.py b/pypy/module/_codecs/test/test_locale.py --- a/pypy/module/_codecs/test/test_locale.py +++ b/pypy/module/_codecs/test/test_locale.py @@ -2,7 +2,7 @@ import py from pypy.module._codecs import interp_codecs from pypy.module._codecs.locale import ( - unicode_decode_locale_surrogateescape, + str_decode_locale_surrogateescape, unicode_encode_locale_surrogateescape) from rpython.rlib import rlocale, runicode @@ -54,7 +54,7 @@ def test_decode_locale(self): self.setlocale("en_US.UTF-8") - locale_decoder = unicode_decode_locale_surrogateescape + locale_decoder = str_decode_locale_surrogateescape utf8_decoder = self.getdecoder('utf-8') for val in 'foo', ' \xe6\x97\xa5\xe6\x9c\xac', '\xf0\x93\x88\x8c': assert (locale_decoder(val) == @@ -62,7 +62,7 @@ def test_decode_locale_errorhandler(self): self.setlocale("en_US.UTF-8") - locale_decoder = unicode_decode_locale_surrogateescape + locale_decoder = str_decode_locale_surrogateescape utf8_decoder = self.getdecoder('utf-8') decode_error_handler = self.getstate().decode_error_handler val = 'foo\xe3bar' From noreply at buildbot.pypy.org Mon Apr 22 06:55:42 2013 From: noreply at buildbot.pypy.org (wlav) Date: Mon, 22 Apr 2013 06:55:42 +0200 (CEST) Subject: [pypy-commit] pypy reflex-support: more warnings removed (about 'promote' being ignored) Message-ID: <20130422045542.0FEC61C1464@cobra.cs.uni-duesseldorf.de> Author: Wim Lavrijsen Branch: reflex-support Changeset: r63543:f28cfcf366f2 Date: 2013-04-21 21:54 -0700 http://bitbucket.org/pypy/pypy/changeset/f28cfcf366f2/ Log: more warnings removed (about 'promote' being ignored) diff --git a/pypy/module/cppyy/capi/loadable_capi.py b/pypy/module/cppyy/capi/loadable_capi.py --- a/pypy/module/cppyy/capi/loadable_capi.py +++ b/pypy/module/cppyy/capi/loadable_capi.py @@ -332,7 +332,6 @@ args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs), _Arg(l=cppclass.handle)] return _cdata_to_cobject(space, call_capi(space, 'call_o', args)) - at jit.elidable_promote() def c_get_methptr_getter(space, cppscope, index): args = [_Arg(l=cppscope.handle), _Arg(l=index)] return rffi.cast(C_METHPTRGETTER_PTR, @@ -343,10 +342,10 @@ return _cdata_to_ptr(space, call_capi(space, 'allocate_function_args', [_Arg(l=size)])) def c_deallocate_function_args(space, cargs): call_capi(space, 'deallocate_function_args', [_Arg(vp=cargs)]) - at jit.elidable_promote() + at jit.elidable def c_function_arg_sizeof(space): return _cdata_to_size_t(space, call_capi(space, 'function_arg_sizeof', [])) - at jit.elidable_promote() + at jit.elidable def c_function_arg_typeoffset(space): return _cdata_to_size_t(space, call_capi(space, 'function_arg_typeoffset', [])) @@ -368,22 +367,20 @@ def c_base_name(space, cppclass, base_index): args = [_Arg(l=cppclass.handle), _Arg(l=base_index)] return charp2str_free(space, call_capi(space, 'base_name', args)) - at jit.elidable_promote() + at jit.elidable_promote('2') def c_is_subtype(space, derived, base): if derived == base: return bool(1) return space.bool_w(call_capi(space, 'is_subtype', [_Arg(l=derived.handle), _Arg(l=base.handle)])) - at jit.elidable_promote() + at jit.elidable_promote('1,2,4') def _c_base_offset(space, derived_h, base_h, address, direction): args = [_Arg(l=derived_h), _Arg(l=base_h), _Arg(l=address), _Arg(l=direction)] return _cdata_to_size_t(space, call_capi(space, 'base_offset', args)) - at jit.elidable_promote() def c_base_offset(space, derived, base, address, direction): if derived == base: return rffi.cast(rffi.SIZE_T, 0) return _c_base_offset(space, derived.handle, base.handle, address, direction) - at jit.elidable_promote() def c_base_offset1(space, derived_h, base, address, direction): return _c_base_offset(space, derived_h, base.handle, address, direction) From noreply at buildbot.pypy.org Mon Apr 22 08:30:37 2013 From: noreply at buildbot.pypy.org (wlav) Date: Mon, 22 Apr 2013 08:30:37 +0200 (CEST) Subject: [pypy-commit] pypy default: Merge reflex-support into default; this affects only module cppyy, other than Message-ID: <20130422063037.34D421C138E@cobra.cs.uni-duesseldorf.de> Author: Wim Lavrijsen Branch: Changeset: r63544:438fd1328e83 Date: 2013-04-21 23:30 -0700 http://bitbucket.org/pypy/pypy/changeset/438fd1328e83/ Log: Merge reflex-support into default; this affects only module cppyy, other than that a rule .cxx -> .s has been added to rpython/translator/c/genc.py . Major new feature is the ability to load the Reflex-linked lib dynamically, so the build of pypy-c no longer needs to link with libReflex.so for cppyy to be available (this is not on by default yet, but neither is cppyy enabled yet). Other features include: cleanup of module startup, better template support (functions, methods), STL pythonizations, improved support for enums, better error messages, and general code cleanup/quality improvements. diff too long, truncating to 2000 out of 6220 lines diff --git a/pypy/module/cppyy/__init__.py b/pypy/module/cppyy/__init__.py --- a/pypy/module/cppyy/__init__.py +++ b/pypy/module/cppyy/__init__.py @@ -10,15 +10,17 @@ '_resolve_name' : 'interp_cppyy.resolve_name', '_scope_byname' : 'interp_cppyy.scope_byname', '_template_byname' : 'interp_cppyy.template_byname', + '_std_string_name' : 'interp_cppyy.std_string_name', '_set_class_generator' : 'interp_cppyy.set_class_generator', '_register_class' : 'interp_cppyy.register_class', + '_is_static' : 'interp_cppyy.is_static', 'CPPInstance' : 'interp_cppyy.W_CPPInstance', 'addressof' : 'interp_cppyy.addressof', 'bind_object' : 'interp_cppyy.bind_object', } appleveldefs = { - 'gbl' : 'pythonify.gbl', + '_init_pythonify' : 'pythonify._init_pythonify', 'load_reflection_info' : 'pythonify.load_reflection_info', 'add_pythonization' : 'pythonify.add_pythonization', } @@ -31,3 +33,9 @@ # code generation is not, so give it a chance to run now from pypy.module.cppyy import capi capi.register_pythonizations(space) + + def startup(self, space): + from pypy.module.cppyy import capi + capi.verify_backend(space) # may raise ImportError + + space.call_method(space.wrap(self), '_init_pythonify') diff --git a/pypy/module/cppyy/capi/__init__.py b/pypy/module/cppyy/capi/__init__.py --- a/pypy/module/cppyy/capi/__init__.py +++ b/pypy/module/cppyy/capi/__init__.py @@ -1,37 +1,19 @@ from rpython.rtyper.lltypesystem import rffi, lltype -from rpython.rlib import jit -import reflex_capi as backend -#import cint_capi as backend +# There are two possible ways of accessing the backend through the reflection +# C-API: built it into pypy-c, or load it dynamically. The latter is preferred +# (and is the default) for use with Reflex. B/c of some builtin pythonizations, +# the former is recommended (for now) with CINT. -identify = backend.identify -pythonize = backend.pythonize -register_pythonizations = backend.register_pythonizations +# Note: if builtin_capi is chosen, then inside builtin_capi.py, there is still +# the selection of the desired backend (default is Reflex). -ts_reflect = backend.ts_reflect -ts_call = backend.ts_call -ts_memory = backend.ts_memory -ts_helper = backend.ts_helper +# choose C-API access method: +#from pypy.module.cppyy.capi.loadable_capi import * +from pypy.module.cppyy.capi.builtin_capi import * -_C_OPAQUE_PTR = rffi.LONG -_C_OPAQUE_NULL = lltype.nullptr(rffi.LONGP.TO)# ALT: _C_OPAQUE_PTR.TO - -C_SCOPE = _C_OPAQUE_PTR -C_NULL_SCOPE = rffi.cast(C_SCOPE, _C_OPAQUE_NULL) - -C_TYPE = C_SCOPE -C_NULL_TYPE = C_NULL_SCOPE - -C_OBJECT = _C_OPAQUE_PTR -C_NULL_OBJECT = rffi.cast(C_OBJECT, _C_OPAQUE_NULL) - -C_METHOD = _C_OPAQUE_PTR -C_INDEX = rffi.LONG -C_INDEX_ARRAY = rffi.LONGP -WLAVC_INDEX = rffi.LONG - -C_METHPTRGETTER = lltype.FuncType([C_OBJECT], rffi.VOIDP) -C_METHPTRGETTER_PTR = lltype.Ptr(C_METHPTRGETTER) +from pypy.module.cppyy.capi.capi_types import C_OBJECT,\ + C_NULL_TYPE, C_NULL_OBJECT def direct_ptradd(ptr, offset): offset = rffi.cast(rffi.SIZE_T, offset) @@ -42,457 +24,3 @@ def exchange_address(ptr, cif_descr, index): return rffi.ptradd(ptr, cif_descr.exchange_args[index]) - -c_load_dictionary = backend.c_load_dictionary - -# name to opaque C++ scope representation ------------------------------------ -_c_num_scopes = rffi.llexternal( - "cppyy_num_scopes", - [C_SCOPE], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_num_scopes(cppscope): - return _c_num_scopes(cppscope.handle) -_c_scope_name = rffi.llexternal( - "cppyy_scope_name", - [C_SCOPE, rffi.INT], rffi.CCHARP, - compilation_info = backend.eci) -def c_scope_name(cppscope, iscope): - return charp2str_free(_c_scope_name(cppscope.handle, iscope)) - -_c_resolve_name = rffi.llexternal( - "cppyy_resolve_name", - [rffi.CCHARP], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_resolve_name(name): - return charp2str_free(_c_resolve_name(name)) -c_get_scope_opaque = rffi.llexternal( - "cppyy_get_scope", - [rffi.CCHARP], C_SCOPE, - threadsafe=ts_reflect, - compilation_info=backend.eci) -c_get_template = rffi.llexternal( - "cppyy_get_template", - [rffi.CCHARP], C_TYPE, - threadsafe=ts_reflect, - compilation_info=backend.eci) -_c_actual_class = rffi.llexternal( - "cppyy_actual_class", - [C_TYPE, C_OBJECT], C_TYPE, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_actual_class(cppclass, cppobj): - return _c_actual_class(cppclass.handle, cppobj) - -# memory management ---------------------------------------------------------- -_c_allocate = rffi.llexternal( - "cppyy_allocate", - [C_TYPE], C_OBJECT, - threadsafe=ts_memory, - compilation_info=backend.eci) -def c_allocate(cppclass): - return _c_allocate(cppclass.handle) -_c_deallocate = rffi.llexternal( - "cppyy_deallocate", - [C_TYPE, C_OBJECT], lltype.Void, - threadsafe=ts_memory, - compilation_info=backend.eci) -def c_deallocate(cppclass, cppobject): - _c_deallocate(cppclass.handle, cppobject) -_c_destruct = rffi.llexternal( - "cppyy_destruct", - [C_TYPE, C_OBJECT], lltype.Void, - threadsafe=ts_call, - compilation_info=backend.eci) -def c_destruct(cppclass, cppobject): - _c_destruct(cppclass.handle, cppobject) - -# method/function dispatching ------------------------------------------------ -c_call_v = rffi.llexternal( - "cppyy_call_v", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], lltype.Void, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_b = rffi.llexternal( - "cppyy_call_b", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.UCHAR, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_c = rffi.llexternal( - "cppyy_call_c", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.CHAR, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_h = rffi.llexternal( - "cppyy_call_h", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.SHORT, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_i = rffi.llexternal( - "cppyy_call_i", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.INT, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_l = rffi.llexternal( - "cppyy_call_l", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.LONG, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_ll = rffi.llexternal( - "cppyy_call_ll", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.LONGLONG, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_f = rffi.llexternal( - "cppyy_call_f", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.FLOAT, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_d = rffi.llexternal( - "cppyy_call_d", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.DOUBLE, - threadsafe=ts_call, - compilation_info=backend.eci) - -c_call_r = rffi.llexternal( - "cppyy_call_r", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.VOIDP, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_s = rffi.llexternal( - "cppyy_call_s", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.CCHARP, - threadsafe=ts_call, - compilation_info=backend.eci) - -c_constructor = rffi.llexternal( - "cppyy_constructor", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], lltype.Void, - threadsafe=ts_call, - compilation_info=backend.eci) -_c_call_o = rffi.llexternal( - "cppyy_call_o", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP, C_TYPE], rffi.LONG, - threadsafe=ts_call, - compilation_info=backend.eci) -def c_call_o(method, cppobj, nargs, args, cppclass): - return _c_call_o(method, cppobj, nargs, args, cppclass.handle) - -_c_get_methptr_getter = rffi.llexternal( - "cppyy_get_methptr_getter", - [C_SCOPE, C_INDEX], C_METHPTRGETTER_PTR, - threadsafe=ts_reflect, - compilation_info=backend.eci, - elidable_function=True) -def c_get_methptr_getter(cppscope, index): - return _c_get_methptr_getter(cppscope.handle, index) - -# handling of function argument buffer --------------------------------------- -c_allocate_function_args = rffi.llexternal( - "cppyy_allocate_function_args", - [rffi.SIZE_T], rffi.VOIDP, - threadsafe=ts_memory, - compilation_info=backend.eci) -c_deallocate_function_args = rffi.llexternal( - "cppyy_deallocate_function_args", - [rffi.VOIDP], lltype.Void, - threadsafe=ts_memory, - compilation_info=backend.eci) -c_function_arg_sizeof = rffi.llexternal( - "cppyy_function_arg_sizeof", - [], rffi.SIZE_T, - threadsafe=ts_memory, - compilation_info=backend.eci, - elidable_function=True) -c_function_arg_typeoffset = rffi.llexternal( - "cppyy_function_arg_typeoffset", - [], rffi.SIZE_T, - threadsafe=ts_memory, - compilation_info=backend.eci, - elidable_function=True) - -# scope reflection information ----------------------------------------------- -c_is_namespace = rffi.llexternal( - "cppyy_is_namespace", - [C_SCOPE], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -c_is_enum = rffi.llexternal( - "cppyy_is_enum", - [rffi.CCHARP], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) - -# type/class reflection information ------------------------------------------ -_c_final_name = rffi.llexternal( - "cppyy_final_name", - [C_TYPE], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_final_name(cpptype): - return charp2str_free(_c_final_name(cpptype)) -_c_scoped_final_name = rffi.llexternal( - "cppyy_scoped_final_name", - [C_TYPE], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_scoped_final_name(cpptype): - return charp2str_free(_c_scoped_final_name(cpptype)) -c_has_complex_hierarchy = rffi.llexternal( - "cppyy_has_complex_hierarchy", - [C_TYPE], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -_c_num_bases = rffi.llexternal( - "cppyy_num_bases", - [C_TYPE], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_num_bases(cppclass): - return _c_num_bases(cppclass.handle) -_c_base_name = rffi.llexternal( - "cppyy_base_name", - [C_TYPE, rffi.INT], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_base_name(cppclass, base_index): - return charp2str_free(_c_base_name(cppclass.handle, base_index)) -_c_is_subtype = rffi.llexternal( - "cppyy_is_subtype", - [C_TYPE, C_TYPE], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci, - elidable_function=True) - at jit.elidable_promote() -def c_is_subtype(derived, base): - if derived == base: - return 1 - return _c_is_subtype(derived.handle, base.handle) - -_c_base_offset = rffi.llexternal( - "cppyy_base_offset", - [C_TYPE, C_TYPE, C_OBJECT, rffi.INT], rffi.SIZE_T, - threadsafe=ts_reflect, - compilation_info=backend.eci, - elidable_function=True) - at jit.elidable_promote() -def c_base_offset(derived, base, address, direction): - if derived == base: - return 0 - return _c_base_offset(derived.handle, base.handle, address, direction) - -# method/function reflection information ------------------------------------- -_c_num_methods = rffi.llexternal( - "cppyy_num_methods", - [C_SCOPE], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_num_methods(cppscope): - return _c_num_methods(cppscope.handle) -_c_method_index_at = rffi.llexternal( - "cppyy_method_index_at", - [C_SCOPE, rffi.INT], C_INDEX, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_index_at(cppscope, imethod): - return _c_method_index_at(cppscope.handle, imethod) -_c_method_indices_from_name = rffi.llexternal( - "cppyy_method_indices_from_name", - [C_SCOPE, rffi.CCHARP], C_INDEX_ARRAY, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_indices_from_name(cppscope, name): - indices = _c_method_indices_from_name(cppscope.handle, name) - if not indices: - return [] - py_indices = [] - i = 0 - index = indices[i] - while index != -1: - i += 1 - py_indices.append(index) - index = indices[i] - c_free(rffi.cast(rffi.VOIDP, indices)) # c_free defined below - return py_indices - -_c_method_name = rffi.llexternal( - "cppyy_method_name", - [C_SCOPE, C_INDEX], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_name(cppscope, index): - return charp2str_free(_c_method_name(cppscope.handle, index)) -_c_method_result_type = rffi.llexternal( - "cppyy_method_result_type", - [C_SCOPE, C_INDEX], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_result_type(cppscope, index): - return charp2str_free(_c_method_result_type(cppscope.handle, index)) -_c_method_num_args = rffi.llexternal( - "cppyy_method_num_args", - [C_SCOPE, C_INDEX], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_num_args(cppscope, index): - return _c_method_num_args(cppscope.handle, index) -_c_method_req_args = rffi.llexternal( - "cppyy_method_req_args", - [C_SCOPE, C_INDEX], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_req_args(cppscope, index): - return _c_method_req_args(cppscope.handle, index) -_c_method_arg_type = rffi.llexternal( - "cppyy_method_arg_type", - [C_SCOPE, C_INDEX, rffi.INT], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_arg_type(cppscope, index, arg_index): - return charp2str_free(_c_method_arg_type(cppscope.handle, index, arg_index)) -_c_method_arg_default = rffi.llexternal( - "cppyy_method_arg_default", - [C_SCOPE, C_INDEX, rffi.INT], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_arg_default(cppscope, index, arg_index): - return charp2str_free(_c_method_arg_default(cppscope.handle, index, arg_index)) -_c_method_signature = rffi.llexternal( - "cppyy_method_signature", - [C_SCOPE, C_INDEX], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_signature(cppscope, index): - return charp2str_free(_c_method_signature(cppscope.handle, index)) - -_c_get_method = rffi.llexternal( - "cppyy_get_method", - [C_SCOPE, C_INDEX], C_METHOD, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_get_method(cppscope, index): - return _c_get_method(cppscope.handle, index) -_c_get_global_operator = rffi.llexternal( - "cppyy_get_global_operator", - [C_SCOPE, C_SCOPE, C_SCOPE, rffi.CCHARP], WLAVC_INDEX, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_get_global_operator(nss, lc, rc, op): - if nss is not None: - return _c_get_global_operator(nss.handle, lc.handle, rc.handle, op) - return rffi.cast(WLAVC_INDEX, -1) - -# method properties ---------------------------------------------------------- -_c_is_constructor = rffi.llexternal( - "cppyy_is_constructor", - [C_TYPE, C_INDEX], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_is_constructor(cppclass, index): - return _c_is_constructor(cppclass.handle, index) -_c_is_staticmethod = rffi.llexternal( - "cppyy_is_staticmethod", - [C_TYPE, C_INDEX], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_is_staticmethod(cppclass, index): - return _c_is_staticmethod(cppclass.handle, index) - -# data member reflection information ----------------------------------------- -_c_num_datamembers = rffi.llexternal( - "cppyy_num_datamembers", - [C_SCOPE], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_num_datamembers(cppscope): - return _c_num_datamembers(cppscope.handle) -_c_datamember_name = rffi.llexternal( - "cppyy_datamember_name", - [C_SCOPE, rffi.INT], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_datamember_name(cppscope, datamember_index): - return charp2str_free(_c_datamember_name(cppscope.handle, datamember_index)) -_c_datamember_type = rffi.llexternal( - "cppyy_datamember_type", - [C_SCOPE, rffi.INT], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_datamember_type(cppscope, datamember_index): - return charp2str_free(_c_datamember_type(cppscope.handle, datamember_index)) -_c_datamember_offset = rffi.llexternal( - "cppyy_datamember_offset", - [C_SCOPE, rffi.INT], rffi.SIZE_T, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_datamember_offset(cppscope, datamember_index): - return _c_datamember_offset(cppscope.handle, datamember_index) - -_c_datamember_index = rffi.llexternal( - "cppyy_datamember_index", - [C_SCOPE, rffi.CCHARP], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_datamember_index(cppscope, name): - return _c_datamember_index(cppscope.handle, name) - -# data member properties ----------------------------------------------------- -_c_is_publicdata = rffi.llexternal( - "cppyy_is_publicdata", - [C_SCOPE, rffi.INT], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_is_publicdata(cppscope, datamember_index): - return _c_is_publicdata(cppscope.handle, datamember_index) -_c_is_staticdata = rffi.llexternal( - "cppyy_is_staticdata", - [C_SCOPE, rffi.INT], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_is_staticdata(cppscope, datamember_index): - return _c_is_staticdata(cppscope.handle, datamember_index) - -# misc helpers --------------------------------------------------------------- -c_strtoll = rffi.llexternal( - "cppyy_strtoll", - [rffi.CCHARP], rffi.LONGLONG, - threadsafe=ts_helper, - compilation_info=backend.eci) -c_strtoull = rffi.llexternal( - "cppyy_strtoull", - [rffi.CCHARP], rffi.ULONGLONG, - threadsafe=ts_helper, - compilation_info=backend.eci) -c_free = rffi.llexternal( - "cppyy_free", - [rffi.VOIDP], lltype.Void, - threadsafe=ts_memory, - compilation_info=backend.eci) - -def charp2str_free(charp): - string = rffi.charp2str(charp) - voidp = rffi.cast(rffi.VOIDP, charp) - c_free(voidp) - return string - -c_charp2stdstring = rffi.llexternal( - "cppyy_charp2stdstring", - [rffi.CCHARP], C_OBJECT, - threadsafe=ts_helper, - compilation_info=backend.eci) -c_stdstring2stdstring = rffi.llexternal( - "cppyy_stdstring2stdstring", - [C_OBJECT], C_OBJECT, - threadsafe=ts_helper, - compilation_info=backend.eci) -c_assign2stdstring = rffi.llexternal( - "cppyy_assign2stdstring", - [C_OBJECT, rffi.CCHARP], lltype.Void, - threadsafe=ts_helper, - compilation_info=backend.eci) -c_free_stdstring = rffi.llexternal( - "cppyy_free_stdstring", - [C_OBJECT], lltype.Void, - threadsafe=ts_helper, - compilation_info=backend.eci) diff --git a/pypy/module/cppyy/capi/builtin_capi.py b/pypy/module/cppyy/capi/builtin_capi.py new file mode 100644 --- /dev/null +++ b/pypy/module/cppyy/capi/builtin_capi.py @@ -0,0 +1,561 @@ +from rpython.rtyper.lltypesystem import rffi, lltype +from rpython.rlib import jit + +import reflex_capi as backend +#import cint_capi as backend + +from pypy.module.cppyy.capi.capi_types import C_SCOPE, C_TYPE, C_OBJECT,\ + C_METHOD, C_INDEX, C_INDEX_ARRAY, WLAVC_INDEX,\ + C_METHPTRGETTER, C_METHPTRGETTER_PTR + +identify = backend.identify +pythonize = backend.pythonize +register_pythonizations = backend.register_pythonizations +std_string_name = backend.std_string_name + +ts_reflect = backend.ts_reflect +ts_call = backend.ts_call +ts_memory = backend.ts_memory +ts_helper = backend.ts_helper + +def verify_backend(space): + return True # by definition + +c_load_dictionary = backend.c_load_dictionary + +# name to opaque C++ scope representation ------------------------------------ +_c_num_scopes = rffi.llexternal( + "cppyy_num_scopes", + [C_SCOPE], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_num_scopes(space, cppscope): + return _c_num_scopes(cppscope.handle) +_c_scope_name = rffi.llexternal( + "cppyy_scope_name", + [C_SCOPE, rffi.INT], rffi.CCHARP, + compilation_info = backend.eci) +def c_scope_name(space, cppscope, iscope): + return charp2str_free(space, _c_scope_name(cppscope.handle, iscope)) + +_c_resolve_name = rffi.llexternal( + "cppyy_resolve_name", + [rffi.CCHARP], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_resolve_name(space, name): + return charp2str_free(space, _c_resolve_name(name)) +_c_get_scope_opaque = rffi.llexternal( + "cppyy_get_scope", + [rffi.CCHARP], C_SCOPE, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_get_scope_opaque(space, name): + return _c_get_scope_opaque(name) +_c_get_template = rffi.llexternal( + "cppyy_get_template", + [rffi.CCHARP], C_TYPE, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_get_template(space, name): + return _c_get_template(name) +_c_actual_class = rffi.llexternal( + "cppyy_actual_class", + [C_TYPE, C_OBJECT], C_TYPE, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_actual_class(space, cppclass, cppobj): + return _c_actual_class(cppclass.handle, cppobj) + +# memory management ---------------------------------------------------------- +_c_allocate = rffi.llexternal( + "cppyy_allocate", + [C_TYPE], C_OBJECT, + threadsafe=ts_memory, + compilation_info=backend.eci) +def c_allocate(space, cppclass): + return _c_allocate(cppclass.handle) +_c_deallocate = rffi.llexternal( + "cppyy_deallocate", + [C_TYPE, C_OBJECT], lltype.Void, + threadsafe=ts_memory, + compilation_info=backend.eci) +def c_deallocate(space, cppclass, cppobject): + _c_deallocate(cppclass.handle, cppobject) +_c_destruct = rffi.llexternal( + "cppyy_destruct", + [C_TYPE, C_OBJECT], lltype.Void, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_destruct(space, cppclass, cppobject): + _c_destruct(cppclass.handle, cppobject) + +# method/function dispatching ------------------------------------------------ +_c_call_v = rffi.llexternal( + "cppyy_call_v", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], lltype.Void, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_v(space, cppmethod, cppobject, nargs, args): + _c_call_v(cppmethod, cppobject, nargs, args) +_c_call_b = rffi.llexternal( + "cppyy_call_b", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.UCHAR, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_b(space, cppmethod, cppobject, nargs, args): + return _c_call_b(cppmethod, cppobject, nargs, args) +_c_call_c = rffi.llexternal( + "cppyy_call_c", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.CHAR, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_c(space, cppmethod, cppobject, nargs, args): + return _c_call_c(cppmethod, cppobject, nargs, args) +_c_call_h = rffi.llexternal( + "cppyy_call_h", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.SHORT, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_h(space, cppmethod, cppobject, nargs, args): + return _c_call_h(cppmethod, cppobject, nargs, args) +_c_call_i = rffi.llexternal( + "cppyy_call_i", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.INT, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_i(space, cppmethod, cppobject, nargs, args): + return _c_call_i(cppmethod, cppobject, nargs, args) +_c_call_l = rffi.llexternal( + "cppyy_call_l", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.LONG, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_l(space, cppmethod, cppobject, nargs, args): + return _c_call_l(cppmethod, cppobject, nargs, args) +_c_call_ll = rffi.llexternal( + "cppyy_call_ll", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.LONGLONG, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_ll(space, cppmethod, cppobject, nargs, args): + return _c_call_ll(cppmethod, cppobject, nargs, args) +_c_call_f = rffi.llexternal( + "cppyy_call_f", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.FLOAT, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_f(space, cppmethod, cppobject, nargs, args): + return _c_call_f(cppmethod, cppobject, nargs, args) +_c_call_d = rffi.llexternal( + "cppyy_call_d", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.DOUBLE, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_d(space, cppmethod, cppobject, nargs, args): + return _c_call_d(cppmethod, cppobject, nargs, args) + +_c_call_r = rffi.llexternal( + "cppyy_call_r", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.VOIDP, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_r(space, cppmethod, cppobject, nargs, args): + return _c_call_r(cppmethod, cppobject, nargs, args) +_c_call_s = rffi.llexternal( + "cppyy_call_s", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.CCHARP, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_s(space, cppmethod, cppobject, nargs, args): + return _c_call_s(cppmethod, cppobject, nargs, args) + +_c_constructor = rffi.llexternal( + "cppyy_constructor", + [C_METHOD, C_TYPE, rffi.INT, rffi.VOIDP], C_OBJECT, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_constructor(space, cppmethod, cppobject, nargs, args): + return _c_constructor(cppmethod, cppobject, nargs, args) +_c_call_o = rffi.llexternal( + "cppyy_call_o", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP, C_TYPE], rffi.LONG, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_o(space, method, cppobj, nargs, args, cppclass): + return _c_call_o(method, cppobj, nargs, args, cppclass.handle) + +_c_get_methptr_getter = rffi.llexternal( + "cppyy_get_methptr_getter", + [C_SCOPE, C_INDEX], C_METHPTRGETTER_PTR, + threadsafe=ts_reflect, + compilation_info=backend.eci, + elidable_function=True) +def c_get_methptr_getter(space, cppscope, index): + return _c_get_methptr_getter(cppscope.handle, index) + +# handling of function argument buffer --------------------------------------- +_c_allocate_function_args = rffi.llexternal( + "cppyy_allocate_function_args", + [rffi.SIZE_T], rffi.VOIDP, + threadsafe=ts_memory, + compilation_info=backend.eci) +def c_allocate_function_args(space, size): + return _c_allocate_function_args(size) +_c_deallocate_function_args = rffi.llexternal( + "cppyy_deallocate_function_args", + [rffi.VOIDP], lltype.Void, + threadsafe=ts_memory, + compilation_info=backend.eci) +def c_deallocate_function_args(space, args): + _c_deallocate_function_args(args) +_c_function_arg_sizeof = rffi.llexternal( + "cppyy_function_arg_sizeof", + [], rffi.SIZE_T, + threadsafe=ts_memory, + compilation_info=backend.eci, + elidable_function=True) +def c_function_arg_sizeof(space): + return _c_function_arg_sizeof() +_c_function_arg_typeoffset = rffi.llexternal( + "cppyy_function_arg_typeoffset", + [], rffi.SIZE_T, + threadsafe=ts_memory, + compilation_info=backend.eci, + elidable_function=True) +def c_function_arg_typeoffset(space): + return _c_function_arg_typeoffset() + +# scope reflection information ----------------------------------------------- +_c_is_namespace = rffi.llexternal( + "cppyy_is_namespace", + [C_SCOPE], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_is_namespace(space, scope): + return _c_is_namespace(scope) +_c_is_enum = rffi.llexternal( + "cppyy_is_enum", + [rffi.CCHARP], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_is_enum(space, name): + return _c_is_enum(name) + +# type/class reflection information ------------------------------------------ +_c_final_name = rffi.llexternal( + "cppyy_final_name", + [C_TYPE], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_final_name(space, cpptype): + return charp2str_free(space, _c_final_name(cpptype)) +_c_scoped_final_name = rffi.llexternal( + "cppyy_scoped_final_name", + [C_TYPE], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_scoped_final_name(space, cpptype): + return charp2str_free(space, _c_scoped_final_name(cpptype)) +_c_has_complex_hierarchy = rffi.llexternal( + "cppyy_has_complex_hierarchy", + [C_TYPE], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_has_complex_hierarchy(space, cpptype): + return _c_has_complex_hierarchy(cpptype) +_c_num_bases = rffi.llexternal( + "cppyy_num_bases", + [C_TYPE], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_num_bases(space, cppclass): + return _c_num_bases(cppclass.handle) +_c_base_name = rffi.llexternal( + "cppyy_base_name", + [C_TYPE, rffi.INT], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_base_name(space, cppclass, base_index): + return charp2str_free(space, _c_base_name(cppclass.handle, base_index)) +_c_is_subtype = rffi.llexternal( + "cppyy_is_subtype", + [C_TYPE, C_TYPE], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci, + elidable_function=True) + at jit.elidable_promote('2') +def c_is_subtype(space, derived, base): + if derived == base: + return 1 + return _c_is_subtype(derived.handle, base.handle) + +_c_base_offset = rffi.llexternal( + "cppyy_base_offset", + [C_TYPE, C_TYPE, C_OBJECT, rffi.INT], rffi.SIZE_T, + threadsafe=ts_reflect, + compilation_info=backend.eci, + elidable_function=True) + at jit.elidable_promote('1,2,4') +def c_base_offset(space, derived, base, address, direction): + if derived == base: + return 0 + return _c_base_offset(derived.handle, base.handle, address, direction) +def c_base_offset1(space, derived_h, base, address, direction): + return _c_base_offset(derived_h, base.handle, address, direction) + +# method/function reflection information ------------------------------------- +_c_num_methods = rffi.llexternal( + "cppyy_num_methods", + [C_SCOPE], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_num_methods(space, cppscope): + return _c_num_methods(cppscope.handle) +_c_method_index_at = rffi.llexternal( + "cppyy_method_index_at", + [C_SCOPE, rffi.INT], C_INDEX, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_index_at(space, cppscope, imethod): + return _c_method_index_at(cppscope.handle, imethod) +_c_method_indices_from_name = rffi.llexternal( + "cppyy_method_indices_from_name", + [C_SCOPE, rffi.CCHARP], C_INDEX_ARRAY, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_indices_from_name(space, cppscope, name): + indices = _c_method_indices_from_name(cppscope.handle, name) + if not indices: + return [] + py_indices = [] + i = 0 + index = indices[i] + while index != -1: + i += 1 + py_indices.append(index) + index = indices[i] + c_free(rffi.cast(rffi.VOIDP, indices)) # c_free defined below + return py_indices + +_c_method_name = rffi.llexternal( + "cppyy_method_name", + [C_SCOPE, C_INDEX], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_name(space, cppscope, index): + return charp2str_free(space, _c_method_name(cppscope.handle, index)) +_c_method_result_type = rffi.llexternal( + "cppyy_method_result_type", + [C_SCOPE, C_INDEX], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_result_type(space, cppscope, index): + return charp2str_free(space, _c_method_result_type(cppscope.handle, index)) +_c_method_num_args = rffi.llexternal( + "cppyy_method_num_args", + [C_SCOPE, C_INDEX], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_num_args(space, cppscope, index): + return _c_method_num_args(cppscope.handle, index) +_c_method_req_args = rffi.llexternal( + "cppyy_method_req_args", + [C_SCOPE, C_INDEX], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_req_args(space, cppscope, index): + return _c_method_req_args(cppscope.handle, index) +_c_method_arg_type = rffi.llexternal( + "cppyy_method_arg_type", + [C_SCOPE, C_INDEX, rffi.INT], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_arg_type(space, cppscope, index, arg_index): + return charp2str_free(space, _c_method_arg_type(cppscope.handle, index, arg_index)) +_c_method_arg_default = rffi.llexternal( + "cppyy_method_arg_default", + [C_SCOPE, C_INDEX, rffi.INT], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_arg_default(space, cppscope, index, arg_index): + return charp2str_free(space, _c_method_arg_default(cppscope.handle, index, arg_index)) +_c_method_signature = rffi.llexternal( + "cppyy_method_signature", + [C_SCOPE, C_INDEX], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_signature(space, cppscope, index): + return charp2str_free(space, _c_method_signature(cppscope.handle, index)) + +_c_method_is_template = rffi.llexternal( + "cppyy_method_is_template", + [C_SCOPE, C_INDEX], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_is_template(space, cppscope, index): + return _c_method_is_template(cppscope.handle, index) +_c_method_num_template_args = rffi.llexternal( + "cppyy_method_num_template_args", + [C_SCOPE, C_INDEX], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +_c_method_template_arg_name = rffi.llexternal( + "cppyy_method_template_arg_name", + [C_SCOPE, C_INDEX, C_INDEX], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_template_args(space, cppscope, index): + nargs = _c_method_num_template_args(cppscope.handle, index) + args = [c_resolve_name(space, + charp2str_free(space, _c_method_template_arg_name(cppscope.handle, index, iarg))) + for iarg in range(nargs)] + return args + +_c_get_method = rffi.llexternal( + "cppyy_get_method", + [C_SCOPE, C_INDEX], C_METHOD, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_get_method(space, cppscope, index): + return _c_get_method(cppscope.handle, index) +_c_get_global_operator = rffi.llexternal( + "cppyy_get_global_operator", + [C_SCOPE, C_SCOPE, C_SCOPE, rffi.CCHARP], WLAVC_INDEX, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_get_global_operator(space, nss, lc, rc, op): + if nss is not None: + return _c_get_global_operator(nss.handle, lc.handle, rc.handle, op) + return rffi.cast(WLAVC_INDEX, -1) + +# method properties ---------------------------------------------------------- +_c_is_constructor = rffi.llexternal( + "cppyy_is_constructor", + [C_TYPE, C_INDEX], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_is_constructor(space, cppclass, index): + return _c_is_constructor(cppclass.handle, index) +_c_is_staticmethod = rffi.llexternal( + "cppyy_is_staticmethod", + [C_TYPE, C_INDEX], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_is_staticmethod(space, cppclass, index): + return _c_is_staticmethod(cppclass.handle, index) + +# data member reflection information ----------------------------------------- +_c_num_datamembers = rffi.llexternal( + "cppyy_num_datamembers", + [C_SCOPE], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_num_datamembers(space, cppscope): + return _c_num_datamembers(cppscope.handle) +_c_datamember_name = rffi.llexternal( + "cppyy_datamember_name", + [C_SCOPE, rffi.INT], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_datamember_name(space, cppscope, datamember_index): + return charp2str_free(space, _c_datamember_name(cppscope.handle, datamember_index)) +_c_datamember_type = rffi.llexternal( + "cppyy_datamember_type", + [C_SCOPE, rffi.INT], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_datamember_type(space, cppscope, datamember_index): + return charp2str_free(space, _c_datamember_type(cppscope.handle, datamember_index)) +_c_datamember_offset = rffi.llexternal( + "cppyy_datamember_offset", + [C_SCOPE, rffi.INT], rffi.SIZE_T, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_datamember_offset(space, cppscope, datamember_index): + return _c_datamember_offset(cppscope.handle, datamember_index) + +_c_datamember_index = rffi.llexternal( + "cppyy_datamember_index", + [C_SCOPE, rffi.CCHARP], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_datamember_index(space, cppscope, name): + return _c_datamember_index(cppscope.handle, name) + +# data member properties ----------------------------------------------------- +_c_is_publicdata = rffi.llexternal( + "cppyy_is_publicdata", + [C_SCOPE, rffi.INT], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_is_publicdata(space, cppscope, datamember_index): + return _c_is_publicdata(cppscope.handle, datamember_index) +_c_is_staticdata = rffi.llexternal( + "cppyy_is_staticdata", + [C_SCOPE, rffi.INT], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_is_staticdata(space, cppscope, datamember_index): + return _c_is_staticdata(cppscope.handle, datamember_index) + +# misc helpers --------------------------------------------------------------- +_c_strtoll = rffi.llexternal( + "cppyy_strtoll", + [rffi.CCHARP], rffi.LONGLONG, + threadsafe=ts_helper, + compilation_info=backend.eci) +def c_strtoll(space, svalue): + return _c_strtoll(svalue) +_c_strtoull = rffi.llexternal( + "cppyy_strtoull", + [rffi.CCHARP], rffi.ULONGLONG, + threadsafe=ts_helper, + compilation_info=backend.eci) +def c_strtoull(space, svalue): + return _c_strtoull(svalue) +c_free = rffi.llexternal( + "cppyy_free", + [rffi.VOIDP], lltype.Void, + threadsafe=ts_memory, + compilation_info=backend.eci) + +def charp2str_free(space, charp): + string = rffi.charp2str(charp) + voidp = rffi.cast(rffi.VOIDP, charp) + c_free(voidp) + return string + +_c_charp2stdstring = rffi.llexternal( + "cppyy_charp2stdstring", + [rffi.CCHARP], C_OBJECT, + threadsafe=ts_helper, + compilation_info=backend.eci) +def c_charp2stdstring(space, svalue): + charp = rffi.str2charp(svalue) + result = _c_charp2stdstring(charp) + rffi.free_charp(charp) + return result +_c_stdstring2stdstring = rffi.llexternal( + "cppyy_stdstring2stdstring", + [C_OBJECT], C_OBJECT, + threadsafe=ts_helper, + compilation_info=backend.eci) +def c_stdstring2stdstring(space, cppobject): + return _c_stdstring2stdstring(cppobject) +_c_assign2stdstring = rffi.llexternal( + "cppyy_assign2stdstring", + [C_OBJECT, rffi.CCHARP], lltype.Void, + threadsafe=ts_helper, + compilation_info=backend.eci) +def c_assign2stdstring(space, cppobject, svalue): + charp = rffi.str2charp(svalue) + _c_assign2stdstring(cppobject, charp) + rffi.free_charp(charp) +_c_free_stdstring = rffi.llexternal( + "cppyy_free_stdstring", + [C_OBJECT], lltype.Void, + threadsafe=ts_helper, + compilation_info=backend.eci) +def c_free_stdstring(space, cppobject): + _c_free_stdstring(cppobject) diff --git a/pypy/module/cppyy/capi/capi_types.py b/pypy/module/cppyy/capi/capi_types.py new file mode 100644 --- /dev/null +++ b/pypy/module/cppyy/capi/capi_types.py @@ -0,0 +1,22 @@ +from rpython.rtyper.lltypesystem import rffi, lltype + +# shared ll definitions +_C_OPAQUE_PTR = rffi.LONG +_C_OPAQUE_NULL = lltype.nullptr(rffi.LONGP.TO)# ALT: _C_OPAQUE_PTR.TO + +C_SCOPE = _C_OPAQUE_PTR +C_NULL_SCOPE = rffi.cast(C_SCOPE, _C_OPAQUE_NULL) + +C_TYPE = C_SCOPE +C_NULL_TYPE = C_NULL_SCOPE + +C_OBJECT = _C_OPAQUE_PTR +C_NULL_OBJECT = rffi.cast(C_OBJECT, _C_OPAQUE_NULL) + +C_METHOD = _C_OPAQUE_PTR +C_INDEX = rffi.LONG +C_INDEX_ARRAY = rffi.LONGP +WLAVC_INDEX = rffi.LONG + +C_METHPTRGETTER = lltype.FuncType([C_OBJECT], rffi.VOIDP) +C_METHPTRGETTER_PTR = lltype.Ptr(C_METHPTRGETTER) diff --git a/pypy/module/cppyy/capi/cint_capi.py b/pypy/module/cppyy/capi/cint_capi.py --- a/pypy/module/cppyy/capi/cint_capi.py +++ b/pypy/module/cppyy/capi/cint_capi.py @@ -9,10 +9,8 @@ from rpython.rtyper.lltypesystem import rffi from rpython.rlib import libffi, rdynload -from pypy.module.itertools import interp_itertools - -__all__ = ['identify', 'eci', 'c_load_dictionary'] +__all__ = ['identify', 'std_string_name', 'eci', 'c_load_dictionary'] pkgpath = py.path.local(__file__).dirpath().join(os.pardir) srcpath = pkgpath.join("src") @@ -36,8 +34,10 @@ ts_reflect = False ts_call = False -ts_memory = 'auto' -ts_helper = 'auto' +ts_memory = False +ts_helper = False + +std_string_name = 'string' # force loading in global mode of core libraries, rather than linking with # them as PyPy uses various version of dlopen in various places; note that @@ -120,7 +120,7 @@ classname = space.str_w(args_w[1]) addr_idx = 2 w_address = args_w[addr_idx] - except OperationError: + except (OperationError, TypeError): addr_idx = 1 w_address = args_w[addr_idx] @@ -138,14 +138,14 @@ # call the helper stub to by-pass CINT vbranch = _ttree_Branch(vtree, branchname, klassname, address, bufsize, splitlevel) branch_class = interp_cppyy.scope_byname(space, "TBranch") - w_branch = interp_cppyy.wrap_cppobject( - space, space.w_None, branch_class, vbranch, isref=False, python_owns=False) + w_branch = interp_cppyy.wrap_cppobject(space, vbranch, branch_class) return w_branch - except (OperationError, TypeError, IndexError), e: + except (OperationError, TypeError, IndexError): pass # return control back to the original, unpythonized overload - return tree_class.get_overload("Branch").call(w_self, args_w) + ol = tree_class.get_overload("Branch") + return ol.call(w_self, args_w) def activate_branch(space, w_branch): w_branches = space.call_method(w_branch, "GetListOfBranches") @@ -155,6 +155,12 @@ space.call_method(w_branch, "SetStatus", space.wrap(1)) space.call_method(w_branch, "ResetReadEntry") +c_ttree_GetEntry = rffi.llexternal( + "cppyy_ttree_GetEntry", + [rffi.VOIDP, rffi.LONGLONG], rffi.LONGLONG, + threadsafe=False, + compilation_info=eci) + @unwrap_spec(args_w='args_w') def ttree_getattr(space, w_self, args_w): """Specialized __getattr__ for TTree's that allows switching on/off the @@ -163,28 +169,75 @@ from pypy.module.cppyy import interp_cppyy tree = space.interp_w(interp_cppyy.W_CPPInstance, w_self) + space = tree.space # holds the class cache in State + + # prevent recursion + attr = space.str_w(args_w[0]) + if attr and attr[0] == '_': + raise OperationError(space.w_AttributeError, args_w[0]) + + # try the saved cdata (for builtin types) + try: + w_cdata = space.getattr(w_self, space.wrap('_'+attr)) + from pypy.module._cffi_backend import cdataobj + cdata = space.interp_w(cdataobj.W_CData, w_cdata, can_be_None=False) + return cdata.convert_to_object() + except OperationError: + pass + # setup branch as a data member and enable it for reading - space = tree.space # holds the class cache in State w_branch = space.call_method(w_self, "GetBranch", args_w[0]) + if not space.is_true(w_branch): + raise OperationError(space.w_AttributeError, args_w[0]) + activate_branch(space, w_branch) + + # figure out from where we're reading + entry = space.int_w(space.call_method(w_self, "GetReadEntry")) + if entry == -1: + entry = 0 + + # setup cache structure w_klassname = space.call_method(w_branch, "GetClassName") - klass = interp_cppyy.scope_byname(space, space.str_w(w_klassname)) - w_obj = klass.construct() - #space.call_method(w_branch, "SetStatus", space.wrap(1)) - activate_branch(space, w_branch) - space.call_method(w_branch, "SetObject", w_obj) - space.call_method(w_branch, "GetEntry", space.wrap(0)) - space.setattr(w_self, args_w[0], w_obj) - return w_obj + if space.is_true(w_klassname): + # some instance + klass = interp_cppyy.scope_byname(space, space.str_w(w_klassname)) + w_obj = klass.construct() + space.call_method(w_branch, "SetObject", w_obj) + space.call_method(w_branch, "GetEntry", space.wrap(entry)) + space.setattr(w_self, args_w[0], w_obj) + return w_obj + else: + # builtin data + w_leaf = space.call_method(w_self, "GetLeaf", args_w[0]) + space.call_method(w_branch, "GetEntry", space.wrap(entry)) + + # location + w_address = space.call_method(w_leaf, "GetValuePointer") + buf = space.buffer_w(w_address) + from pypy.module._rawffi import buffer + assert isinstance(buf, buffer.RawFFIBuffer) + address = rffi.cast(rffi.CCHARP, buf.datainstance.ll_buffer) + + # placeholder + w_typename = space.call_method(w_leaf, "GetTypeName" ) + from pypy.module.cppyy import capi + typename = capi.c_resolve_name(space, space.str_w(w_typename)) + if typename == 'bool': typename = '_Bool' + w_address = space.call_method(w_leaf, "GetValuePointer") + from pypy.module._cffi_backend import cdataobj, newtype + cdata = cdataobj.W_CData(space, address, newtype.new_primitive_type(space, typename)) + + # cache result + space.setattr(w_self, space.wrap('_'+attr), space.wrap(cdata)) + return space.getattr(w_self, args_w[0]) class W_TTreeIter(W_Root): def __init__(self, space, w_tree): - from pypy.module.cppyy import interp_cppyy tree = space.interp_w(interp_cppyy.W_CPPInstance, w_tree) - self.tree = tree.get_cppthis(tree.cppclass) + self.vtree = rffi.cast(rffi.VOIDP, tree.get_cppthis(tree.cppclass)) self.w_tree = w_tree - self.getentry = tree.cppclass.get_overload("GetEntry").functions[0] self.current = 0 self.maxentry = space.int_w(space.call_method(w_tree, "GetEntriesFast")) @@ -198,8 +251,8 @@ if self.current == self.maxentry: raise OperationError(self.space.w_StopIteration, self.space.w_None) # TODO: check bytes read? - self.getentry.call(self.tree, [self.space.wrap(self.current)]) - self.current += 1 + c_ttree_GetEntry(self.vtree, self.current) + self.current += 1 return self.w_tree W_TTreeIter.typedef = TypeDef( diff --git a/pypy/module/cppyy/capi/loadable_capi.py b/pypy/module/cppyy/capi/loadable_capi.py new file mode 100644 --- /dev/null +++ b/pypy/module/cppyy/capi/loadable_capi.py @@ -0,0 +1,519 @@ +from rpython.rtyper.lltypesystem import rffi, lltype +from rpython.rlib import jit, jit_libffi, libffi, rdynload, objectmodel +from rpython.rlib.rarithmetic import r_singlefloat +from rpython.tool import leakfinder + +from pypy.interpreter.error import OperationError + +from pypy.module._cffi_backend import ctypefunc, ctypeprim, cdataobj, misc + +from pypy.module.cppyy.capi.capi_types import C_SCOPE, C_TYPE, C_OBJECT,\ + C_METHOD, C_INDEX, C_INDEX_ARRAY, WLAVC_INDEX, C_METHPTRGETTER_PTR + + +reflection_library = 'rflxlib.so' + +def identify(): + return 'loadable_capi' + +# this is not technically correct, but will do for now +std_string_name = 'std::basic_string' + +class _Arg: # poor man's union + _immutable_ = True + def __init__(self, l = 0, s = '', vp = rffi.cast(rffi.VOIDP, 0) ): + self._long = l + self._string = s + self._voidp = vp + +# For the loadable CAPI, the calls start and end in RPython. Therefore, the standard +# _call of W_CTypeFunc, which expects wrapped objects, does not quite work: some +# vars (e.g. void* equivalent) can not be wrapped, and others (such as rfloat) risk +# rounding problems. This W_RCTypeFun then, takes args, instead of args_w. Note that +# rcall() is a new method, so as to not interfere with the base class call and _call +# when rtyping. It is also called directly (see call_capi below). +class W_RCTypeFunc(ctypefunc.W_CTypeFunc): + @jit.unroll_safe + def rcall(self, funcaddr, args): + assert self.cif_descr + self = jit.promote(self) + # no checking of len(args) needed, as calls in this context are not dynamic + + # The following code is functionally similar to W_CTypeFunc._call, but its + # implementation is tailored to the restricted use (include memory handling) + # of the CAPI calls. + space = self.space + cif_descr = self.cif_descr + size = cif_descr.exchange_size + raw_string = rffi.cast(rffi.CCHARP, 0) # only ever have one in the CAPI + buffer = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') + try: + for i in range(len(args)): + data = rffi.ptradd(buffer, cif_descr.exchange_args[i]) + obj = args[i] + argtype = self.fargs[i] + # the following is clumsy, but the data types used as arguments are + # very limited, so it'll do for now + if isinstance(argtype, ctypeprim.W_CTypePrimitiveSigned): + misc.write_raw_signed_data(data, rffi.cast(rffi.LONG, obj._long), argtype.size) + elif isinstance(argtype, ctypeprim.W_CTypePrimitiveUnsigned): + misc.write_raw_unsigned_data(data, rffi.cast(rffi.ULONG, obj._long), argtype.size) + elif obj._voidp != rffi.cast(rffi.VOIDP, 0): + data = rffi.cast(rffi.VOIDPP, data) + data[0] = obj._voidp + else: # only other use is sring + n = len(obj._string) + assert raw_string == rffi.cast(rffi.CCHARP, 0) + raw_string = rffi.str2charp(obj._string) + data = rffi.cast(rffi.CCHARPP, data) + data[0] = raw_string + + jit_libffi.jit_ffi_call(cif_descr, + rffi.cast(rffi.VOIDP, funcaddr), + buffer) + + resultdata = rffi.ptradd(buffer, cif_descr.exchange_result) + # this wrapping is unnecessary, but the assumption is that given the + # immediate unwrapping, the round-trip is removed + w_res = self.ctitem.copy_and_convert_to_object(resultdata) + finally: + if raw_string != rffi.cast(rffi.CCHARP, 0): + rffi.free_charp(raw_string) + lltype.free(buffer, flavor='raw') + return w_res + +class State(object): + def __init__(self, space): + self.library = None + self.capi_calls = {} + + import pypy.module._cffi_backend.newtype as nt + + # TODO: the following need to match up with the globally defined C_XYZ low-level + # types (see capi/__init__.py), but by using strings here, that isn't guaranteed + c_opaque_ptr = nt.new_primitive_type(space, 'long') + + c_scope = c_opaque_ptr + c_type = c_scope + c_object = c_opaque_ptr + c_method = c_opaque_ptr + c_index = nt.new_primitive_type(space, 'long') + + c_void = nt.new_void_type(space) + c_char = nt.new_primitive_type(space, 'char') + c_uchar = nt.new_primitive_type(space, 'unsigned char') + c_short = nt.new_primitive_type(space, 'short') + c_int = nt.new_primitive_type(space, 'int') + c_long = nt.new_primitive_type(space, 'long') + c_llong = nt.new_primitive_type(space, 'long long') + c_ullong = nt.new_primitive_type(space, 'unsigned long long') + c_float = nt.new_primitive_type(space, 'float') + c_double = nt.new_primitive_type(space, 'double') + + c_ccharp = nt.new_pointer_type(space, c_char) + c_index_array = nt.new_pointer_type(space, c_void) + + c_voidp = nt.new_pointer_type(space, c_void) + c_size_t = nt.new_primitive_type(space, 'size_t') + + self.capi_call_ifaces = { + # name to opaque C++ scope representation + 'num_scopes' : ([c_scope], c_int), + 'scope_name' : ([c_scope, c_int], c_ccharp), + + 'resolve_name' : ([c_ccharp], c_ccharp), + 'get_scope' : ([c_ccharp], c_scope), + 'get_template' : ([c_ccharp], c_type), + 'actual_class' : ([c_type, c_object], c_type), + + # memory management + 'allocate' : ([c_type], c_object), + 'deallocate' : ([c_type, c_object], c_void), + 'destruct' : ([c_type, c_object], c_void), + + # method/function dispatching + 'call_v' : ([c_method, c_object, c_int, c_voidp], c_void), + 'call_b' : ([c_method, c_object, c_int, c_voidp], c_uchar), + 'call_c' : ([c_method, c_object, c_int, c_voidp], c_char), + + 'call_h' : ([c_method, c_object, c_int, c_voidp], c_short), + 'call_i' : ([c_method, c_object, c_int, c_voidp], c_int), + 'call_l' : ([c_method, c_object, c_int, c_voidp], c_long), + 'call_ll' : ([c_method, c_object, c_int, c_voidp], c_llong), + 'call_f' : ([c_method, c_object, c_int, c_voidp], c_float), + 'call_d' : ([c_method, c_object, c_int, c_voidp], c_double), + + 'call_r' : ([c_method, c_object, c_int, c_voidp], c_voidp), + 'call_s' : ([c_method, c_object, c_int, c_voidp], c_ccharp), + + 'constructor' : ([c_method, c_object, c_int, c_voidp], c_object), + 'call_o' : ([c_method, c_object, c_int, c_voidp, c_type], c_object), + + 'get_methptr_getter' : ([c_scope, c_index], c_voidp), # TODO: verify + + # handling of function argument buffer + 'allocate_function_args' : ([c_size_t], c_voidp), + 'deallocate_function_args' : ([c_voidp], c_void), + 'function_arg_sizeof' : ([], c_size_t), + 'function_arg_typeoffset' : ([], c_size_t), + + # scope reflection information + 'is_namespace' : ([c_scope], c_int), + 'is_enum' : ([c_ccharp], c_int), + + # type/class reflection information + 'final_name' : ([c_type], c_ccharp), + 'scoped_final_name' : ([c_type], c_ccharp), + 'has_complex_hierarchy' : ([c_type], c_int), + 'num_bases' : ([c_type], c_int), + 'base_name' : ([c_type, c_int], c_ccharp), + 'is_subtype' : ([c_type, c_type], c_int), + + 'base_offset' : ([c_type, c_type, c_object, c_int], c_long), + + # method/function reflection information + 'num_methods' : ([c_scope], c_int), + 'method_index_at' : ([c_scope, c_int], c_index), + 'method_indices_from_name' : ([c_scope, c_ccharp], c_index_array), + + 'method_name' : ([c_scope, c_index], c_ccharp), + 'method_result_type' : ([c_scope, c_index], c_ccharp), + 'method_num_args' : ([c_scope, c_index], c_int), + 'method_req_args' : ([c_scope, c_index], c_int), + 'method_arg_type' : ([c_scope, c_index, c_int], c_ccharp), + 'method_arg_default' : ([c_scope, c_index, c_int], c_ccharp), + 'method_signature' : ([c_scope, c_index], c_ccharp), + + 'method_is_template' : ([c_scope, c_index], c_int), + 'method_num_template_args' : ([c_scope, c_index], c_int), + 'method_template_arg_name' : ([c_scope, c_index, c_index], c_ccharp), + + 'get_method' : ([c_scope, c_index], c_method), + 'get_global_operator' : ([c_scope, c_scope, c_scope, c_ccharp], c_index), + + # method properties + 'is_constructor' : ([c_type, c_index], c_int), + 'is_staticmethod' : ([c_type, c_index], c_int), + + # data member reflection information + 'num_datamembers' : ([c_scope], c_int), + 'datamember_name' : ([c_scope, c_int], c_ccharp), + 'datamember_type' : ([c_scope, c_int], c_ccharp), + 'datamember_offset' : ([c_scope, c_int], c_size_t), + + 'datamember_index' : ([c_scope, c_ccharp], c_int), + + # data member properties + 'is_publicdata' : ([c_scope, c_int], c_int), + 'is_staticdata' : ([c_scope, c_int], c_int), + + # misc helpers + 'strtoll' : ([c_ccharp], c_llong), + 'strtoull' : ([c_ccharp], c_ullong), + 'free' : ([c_voidp], c_void), + + 'charp2stdstring' : ([c_ccharp], c_object), + 'stdstring2stdstring' : ([c_object], c_object), + 'assign2stdstring' : ([c_object, c_ccharp], c_void), + 'free_stdstring' : ([c_object], c_void), + } + +def load_reflection_library(space): + state = space.fromcache(State) + if state.library is None: + from pypy.module._cffi_backend.libraryobj import W_Library + state.library = W_Library(space, reflection_library, rdynload.RTLD_LOCAL | rdynload.RTLD_LAZY) + return state.library + +def verify_backend(space): + try: + load_reflection_library(space) + except Exception: + if objectmodel.we_are_translated(): + raise OperationError(space.w_ImportError, + space.wrap("missing reflection library rflxlib.so")) + return False + return True + +def call_capi(space, name, args): + state = space.fromcache(State) + try: + c_call = state.capi_calls[name] + except KeyError: + if state.library is None: + load_reflection_library(space) + iface = state.capi_call_ifaces[name] + cfunc = W_RCTypeFunc(space, iface[0], iface[1], False) + c_call = state.library.load_function(cfunc, 'cppyy_'+name) + # TODO: there must be a better way to trick the leakfinder ... + if not objectmodel.we_are_translated(): + leakfinder.remember_free(c_call.ctype.cif_descr._obj0) + state.capi_calls[name] = c_call + return c_call.ctype.rcall(c_call._cdata, args) + +def _cdata_to_cobject(space, w_cdata): + return rffi.cast(C_OBJECT, space.int_w(w_cdata)) + +def _cdata_to_size_t(space, w_cdata): + return rffi.cast(rffi.SIZE_T, space.int_w(w_cdata)) + +def _cdata_to_ptr(space, w_cdata): # TODO: this is both a hack and dreadfully slow + return rffi.cast(rffi.VOIDP, + space.interp_w(cdataobj.W_CData, w_cdata, can_be_None=False)._cdata) + +def c_load_dictionary(name): + return libffi.CDLL(name) + +# name to opaque C++ scope representation ------------------------------------ +def c_num_scopes(space, cppscope): + return space.int_w(call_capi(space, 'num_scopes', [_Arg(l=cppscope.handle)])) +def c_scope_name(space, cppscope, iscope): + args = [_Arg(l=cppscope.handle), _Arg(l=iscope)] + return charp2str_free(space, call_capi(space, 'scope_name', args)) + +def c_resolve_name(space, name): + return charp2str_free(space, call_capi(space, 'resolve_name', [_Arg(s=name)])) +def c_get_scope_opaque(space, name): + return rffi.cast(C_SCOPE, space.int_w(call_capi(space, 'get_scope', [_Arg(s=name)]))) +def c_get_template(space, name): + return rffi.cast(C_TYPE, space.int_w(call_capi(space, 'get_template', [_Arg(s=name)]))) +def c_actual_class(space, cppclass, cppobj): + args = [_Arg(l=cppclass.handle), _Arg(l=cppobj)] + return rffi.cast(C_TYPE, space.int_w(call_capi(space, 'actual_class', args))) + +# memory management ---------------------------------------------------------- +def c_allocate(space, cppclass): + return _cdata_to_cobject(space, call_capi(space, 'allocate', [_Arg(l=cppclass.handle)])) +def c_deallocate(space, cppclass, cppobject): + call_capi(space, 'deallocate', [_Arg(l=cppclass.handle), _Arg(l=cppobject)]) +def c_destruct(space, cppclass, cppobject): + call_capi(space, 'destruct', [_Arg(l=cppclass.handle), _Arg(l=cppobject)]) + +# method/function dispatching ------------------------------------------------ +def c_call_v(space, cppmethod, cppobject, nargs, cargs): + args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)] + call_capi(space, 'call_v', args) +def c_call_b(space, cppmethod, cppobject, nargs, cargs): + args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)] + return rffi.cast(rffi.UCHAR, space.c_int_w(call_capi(space, 'call_b', args))) +def c_call_c(space, cppmethod, cppobject, nargs, cargs): + args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)] + return rffi.cast(rffi.CHAR, space.str_w(call_capi(space, 'call_c', args))[0]) +def c_call_h(space, cppmethod, cppobject, nargs, cargs): + args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)] + return rffi.cast(rffi.SHORT, space.int_w(call_capi(space, 'call_h', args))) +def c_call_i(space, cppmethod, cppobject, nargs, cargs): + args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)] + return rffi.cast(rffi.INT, space.c_int_w(call_capi(space, 'call_i', args))) +def c_call_l(space, cppmethod, cppobject, nargs, cargs): + args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)] + return rffi.cast(rffi.LONG, space.int_w(call_capi(space, 'call_l', args))) +def c_call_ll(space, cppmethod, cppobject, nargs, cargs): + args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)] + return rffi.cast(rffi.LONGLONG, space.r_longlong_w(call_capi(space, 'call_ll', args))) +def c_call_f(space, cppmethod, cppobject, nargs, cargs): + args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)] + return rffi.cast(rffi.FLOAT, r_singlefloat(space.float_w(call_capi(space, 'call_f', args)))) +def c_call_d(space, cppmethod, cppobject, nargs, cargs): + args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)] + return rffi.cast(rffi.DOUBLE, space.float_w(call_capi(space, 'call_d', args))) + +def c_call_r(space, cppmethod, cppobject, nargs, cargs): + args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)] + return _cdata_to_ptr(space, call_capi(space, 'call_r', args)) +def c_call_s(space, cppmethod, cppobject, nargs, cargs): + args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)] + return call_capi(space, 'call_s', args) + +def c_constructor(space, cppmethod, cppobject, nargs, cargs): + args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)] + return _cdata_to_cobject(space, call_capi(space, 'constructor', args)) +def c_call_o(space, cppmethod, cppobject, nargs, cargs, cppclass): + args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs), _Arg(l=cppclass.handle)] + return _cdata_to_cobject(space, call_capi(space, 'call_o', args)) + +def c_get_methptr_getter(space, cppscope, index): + args = [_Arg(l=cppscope.handle), _Arg(l=index)] + return rffi.cast(C_METHPTRGETTER_PTR, + _cdata_to_ptr(space, call_capi(space, 'get_methptr_getter', args))) + +# handling of function argument buffer --------------------------------------- +def c_allocate_function_args(space, size): + return _cdata_to_ptr(space, call_capi(space, 'allocate_function_args', [_Arg(l=size)])) +def c_deallocate_function_args(space, cargs): + call_capi(space, 'deallocate_function_args', [_Arg(vp=cargs)]) + at jit.elidable +def c_function_arg_sizeof(space): + return _cdata_to_size_t(space, call_capi(space, 'function_arg_sizeof', [])) + at jit.elidable +def c_function_arg_typeoffset(space): + return _cdata_to_size_t(space, call_capi(space, 'function_arg_typeoffset', [])) + +# scope reflection information ----------------------------------------------- +def c_is_namespace(space, scope): + return space.bool_w(call_capi(space, 'is_namespace', [_Arg(l=scope)])) +def c_is_enum(space, name): + return space.bool_w(call_capi(space, 'is_enum', [_Arg(s=name)])) + +# type/class reflection information ------------------------------------------ +def c_final_name(space, cpptype): + return charp2str_free(space, call_capi(space, 'final_name', [_Arg(l=cpptype)])) +def c_scoped_final_name(space, cpptype): + return charp2str_free(space, call_capi(space, 'scoped_final_name', [_Arg(l=cpptype)])) +def c_has_complex_hierarchy(space, handle): + return space.bool_w(call_capi(space, 'has_complex_hierarchy', [_Arg(l=handle)])) +def c_num_bases(space, cppclass): + return space.int_w(call_capi(space, 'num_bases', [_Arg(l=cppclass.handle)])) +def c_base_name(space, cppclass, base_index): + args = [_Arg(l=cppclass.handle), _Arg(l=base_index)] + return charp2str_free(space, call_capi(space, 'base_name', args)) + at jit.elidable_promote('2') +def c_is_subtype(space, derived, base): + if derived == base: + return bool(1) + return space.bool_w(call_capi(space, 'is_subtype', [_Arg(l=derived.handle), _Arg(l=base.handle)])) + + at jit.elidable_promote('1,2,4') +def _c_base_offset(space, derived_h, base_h, address, direction): + args = [_Arg(l=derived_h), _Arg(l=base_h), _Arg(l=address), _Arg(l=direction)] + return _cdata_to_size_t(space, call_capi(space, 'base_offset', args)) +def c_base_offset(space, derived, base, address, direction): + if derived == base: + return rffi.cast(rffi.SIZE_T, 0) + return _c_base_offset(space, derived.handle, base.handle, address, direction) +def c_base_offset1(space, derived_h, base, address, direction): + return _c_base_offset(space, derived_h, base.handle, address, direction) + +# method/function reflection information ------------------------------------- +def c_num_methods(space, cppscope): + args = [_Arg(l=cppscope.handle)] + return space.int_w(call_capi(space, 'num_methods', args)) +def c_method_index_at(space, cppscope, imethod): + args = [_Arg(l=cppscope.handle), _Arg(l=imethod)] + return space.int_w(call_capi(space, 'method_index_at', args)) +def c_method_indices_from_name(space, cppscope, name): + args = [_Arg(l=cppscope.handle), _Arg(s=name)] + indices = rffi.cast(C_INDEX_ARRAY, + _cdata_to_ptr(space, call_capi(space, 'method_indices_from_name', args))) + if not indices: + return [] + py_indices = [] + i = 0 + index = indices[i] + while index != -1: + i += 1 + py_indices.append(index) + index = indices[i] + c_free(space, rffi.cast(rffi.VOIDP, indices)) # c_free defined below + return py_indices + +def c_method_name(space, cppscope, index): + args = [_Arg(l=cppscope.handle), _Arg(l=index)] + return charp2str_free(space, call_capi(space, 'method_name', args)) +def c_method_result_type(space, cppscope, index): + args = [_Arg(l=cppscope.handle), _Arg(l=index)] + return charp2str_free(space, call_capi(space, 'method_result_type', args)) +def c_method_num_args(space, cppscope, index): + args = [_Arg(l=cppscope.handle), _Arg(l=index)] + return space.int_w(call_capi(space, 'method_num_args', args)) +def c_method_req_args(space, cppscope, index): + args = [_Arg(l=cppscope.handle), _Arg(l=index)] + return space.int_w(call_capi(space, 'method_req_args', args)) +def c_method_arg_type(space, cppscope, index, arg_index): + args = [_Arg(l=cppscope.handle), _Arg(l=index), _Arg(l=arg_index)] + return charp2str_free(space, call_capi(space, 'method_arg_type', args)) +def c_method_arg_default(space, cppscope, index, arg_index): + args = [_Arg(l=cppscope.handle), _Arg(l=index), _Arg(l=arg_index)] + return charp2str_free(space, call_capi(space, 'method_arg_default', args)) +def c_method_signature(space, cppscope, index): + args = [_Arg(l=cppscope.handle), _Arg(l=index)] + return charp2str_free(space, call_capi(space, 'method_signature', args)) + +def c_method_is_template(space, cppscope, index): + args = [_Arg(l=cppscope.handle), _Arg(l=index)] + return space.bool_w(call_capi(space, 'method_is_template', args)) +def _c_method_num_template_args(space, cppscope, index): + args = [_Arg(l=cppscope.handle), _Arg(l=index)] + return space.int_w(call_capi(space, 'method_num_template_args', args)) +def c_template_args(space, cppscope, index): + nargs = _c_method_num_template_args(space, cppscope, index) + arg1 = _Arg(l=cppscope.handle) + arg2 = _Arg(l=index) + args = [c_resolve_name(space, charp2str_free(space, + call_capi(space, 'method_template_arg_name', [arg1, arg2, _Arg(l=iarg)])) + ) for iarg in range(nargs)] + return args + +def c_get_method(space, cppscope, index): + args = [_Arg(l=cppscope.handle), _Arg(l=index)] + return rffi.cast(C_METHOD, space.int_w(call_capi(space, 'get_method', args))) +def c_get_global_operator(space, nss, lc, rc, op): + if nss is not None: + args = [_Arg(l=nss.handle), _Arg(l=lc.handle), _Arg(l=rc.handle), _Arg(s=op)] + return rffi.cast(WLAVC_INDEX, space.int_w(call_capi(space, 'get_global_operator', args))) + return rffi.cast(WLAVC_INDEX, -1) + +# method properties ---------------------------------------------------------- +def c_is_constructor(space, cppclass, index): + args = [_Arg(l=cppclass.handle), _Arg(l=index)] + return space.bool_w(call_capi(space, 'is_constructor', args)) +def c_is_staticmethod(space, cppclass, index): + args = [_Arg(l=cppclass.handle), _Arg(l=index)] + return space.bool_w(call_capi(space, 'is_staticmethod', args)) + +# data member reflection information ----------------------------------------- +def c_num_datamembers(space, cppscope): + return space.int_w(call_capi(space, 'num_datamembers', [_Arg(l=cppscope.handle)])) +def c_datamember_name(space, cppscope, datamember_index): + args = [_Arg(l=cppscope.handle), _Arg(l=datamember_index)] + return charp2str_free(space, call_capi(space, 'datamember_name', args)) +def c_datamember_type(space, cppscope, datamember_index): + args = [_Arg(l=cppscope.handle), _Arg(l=datamember_index)] + return charp2str_free(space, call_capi(space, 'datamember_type', args)) +def c_datamember_offset(space, cppscope, datamember_index): + args = [_Arg(l=cppscope.handle), _Arg(l=datamember_index)] + return _cdata_to_size_t(space, call_capi(space, 'datamember_offset', args)) + +def c_datamember_index(space, cppscope, name): + args = [_Arg(l=cppscope.handle), _Arg(s=name)] + return space.int_w(call_capi(space, 'datamember_index', args)) + +# data member properties ----------------------------------------------------- +def c_is_publicdata(space, cppscope, datamember_index): + args = [_Arg(l=cppscope.handle), _Arg(l=datamember_index)] + return space.bool_w(call_capi(space, 'is_publicdata', args)) +def c_is_staticdata(space, cppscope, datamember_index): + args = [_Arg(l=cppscope.handle), _Arg(l=datamember_index)] + return space.bool_w(call_capi(space, 'is_staticdata', args)) + +# misc helpers --------------------------------------------------------------- +def c_strtoll(space, svalue): + return space.r_longlong_w(call_capi(space, 'strtoll', [_Arg(s=svalue)])) +def c_strtoull(space, svalue): + return space.r_ulonglong_w(call_capi(space, 'strtoull', [_Arg(s=svalue)])) +def c_free(space, voidp): + call_capi(space, 'free', [_Arg(vp=voidp)]) + +def charp2str_free(space, cdata): + charp = rffi.cast(rffi.CCHARP, _cdata_to_ptr(space, cdata)) + pystr = rffi.charp2str(charp) + c_free(space, rffi.cast(rffi.VOIDP, charp)) + return pystr + +def c_charp2stdstring(space, svalue): + return _cdata_to_cobject(space, call_capi(space, 'charp2stdstring', [_Arg(s=svalue)])) +def c_stdstring2stdstring(space, cppobject): + return _cdata_to_cobject(space, call_capi(space, 'stdstring2stdstring', [_Arg(l=cppobject)])) +def c_assign2stdstring(space, cppobject, svalue): + args = [_Arg(l=cppobject), _Arg(s=svalue)] + call_capi(space, 'assign2stdstring', args) +def c_free_stdstring(space, cppobject): + call_capi(space, 'free_stdstring', [_Arg(l=cppobject)]) + +# loadable-capi-specific pythonizations (none, as the capi isn't known until runtime) +def register_pythonizations(space): + "NOT_RPYTHON" + pass + +def pythonize(space, name, w_pycppclass): + pass diff --git a/pypy/module/cppyy/capi/reflex_capi.py b/pypy/module/cppyy/capi/reflex_capi.py --- a/pypy/module/cppyy/capi/reflex_capi.py +++ b/pypy/module/cppyy/capi/reflex_capi.py @@ -3,7 +3,7 @@ from rpython.rlib import libffi from rpython.translator.tool.cbuild import ExternalCompilationInfo -__all__ = ['identify', 'eci', 'c_load_dictionary'] +__all__ = ['identify', 'std_string_name', 'eci', 'c_load_dictionary'] pkgpath = py.path.local(__file__).dirpath().join(os.pardir) srcpath = pkgpath.join("src") @@ -35,6 +35,8 @@ ts_memory = 'auto' ts_helper = 'auto' +std_string_name = 'std::basic_string' + eci = ExternalCompilationInfo( separate_module_files=[srcpath.join("reflexcwrapper.cxx")], include_dirs=[incpath] + rootincpath, diff --git a/pypy/module/cppyy/converter.py b/pypy/module/cppyy/converter.py --- a/pypy/module/cppyy/converter.py +++ b/pypy/module/cppyy/converter.py @@ -178,7 +178,7 @@ raise OperationError(space.w_TypeError, space.wrap("raw buffer interface not supported")) ba = rffi.cast(rffi.CCHARP, address) - ba[capi.c_function_arg_typeoffset()] = 'o' + ba[capi.c_function_arg_typeoffset(space)] = 'o' def from_memory(self, space, w_obj, w_pycppclass, offset): # read access, so no copy needed @@ -249,7 +249,7 @@ x = rffi.cast(self.c_ptrtype, address) x[0] = self._unwrap_object(space, w_obj) ba = rffi.cast(rffi.CCHARP, address) - ba[capi.c_function_arg_typeoffset()] = self.typecode + ba[capi.c_function_arg_typeoffset(space)] = self.typecode class VoidConverter(TypeConverter): @@ -352,7 +352,7 @@ arg = space.str_w(w_obj) x[0] = rffi.cast(rffi.LONG, rffi.str2charp(arg)) ba = rffi.cast(rffi.CCHARP, address) - ba[capi.c_function_arg_typeoffset()] = 'o' + ba[capi.c_function_arg_typeoffset(space)] = 'o' def from_memory(self, space, w_obj, w_pycppclass, offset): address = self._get_raw_address(space, w_obj, offset) @@ -379,7 +379,7 @@ x = rffi.cast(rffi.VOIDPP, address) x[0] = self._unwrap_object(space, w_obj) ba = rffi.cast(rffi.CCHARP, address) - ba[capi.c_function_arg_typeoffset()] = 'o' + ba[capi.c_function_arg_typeoffset(space)] = 'o' def convert_argument_libffi(self, space, w_obj, address, call_local): x = rffi.cast(rffi.VOIDPP, address) @@ -399,7 +399,7 @@ except TypeError: r[0] = rffi.cast(rffi.VOIDP, get_rawobject(space, w_obj)) x[0] = rffi.cast(rffi.VOIDP, call_local) - ba[capi.c_function_arg_typeoffset()] = 'a' + ba[capi.c_function_arg_typeoffset(space)] = 'a' def finalize_call(self, space, w_obj, call_local): r = rffi.cast(rffi.VOIDPP, call_local) @@ -425,9 +425,9 @@ def _unwrap_object(self, space, w_obj): from pypy.module.cppyy.interp_cppyy import W_CPPInstance if isinstance(w_obj, W_CPPInstance): - if capi.c_is_subtype(w_obj.cppclass, self.cppclass): + if capi.c_is_subtype(space, w_obj.cppclass, self.cppclass): rawobject = w_obj.get_rawobject() - offset = capi.c_base_offset(w_obj.cppclass, self.cppclass, rawobject, 1) + offset = capi.c_base_offset(space, w_obj.cppclass, self.cppclass, rawobject, 1) obj_address = capi.direct_ptradd(rawobject, offset) return rffi.cast(capi.C_OBJECT, obj_address) raise OperationError(space.w_TypeError, @@ -439,7 +439,7 @@ x[0] = rffi.cast(rffi.VOIDP, self._unwrap_object(space, w_obj)) address = rffi.cast(capi.C_OBJECT, address) ba = rffi.cast(rffi.CCHARP, address) - ba[capi.c_function_arg_typeoffset()] = 'o' + ba[capi.c_function_arg_typeoffset(space)] = 'o' def convert_argument_libffi(self, space, w_obj, address, call_local): x = rffi.cast(rffi.VOIDPP, address) @@ -448,8 +448,8 @@ def from_memory(self, space, w_obj, w_pycppclass, offset): address = rffi.cast(capi.C_OBJECT, self._get_raw_address(space, w_obj, offset)) from pypy.module.cppyy import interp_cppyy - return interp_cppyy.wrap_cppobject_nocast( - space, w_pycppclass, self.cppclass, address, isref=True, python_owns=False) + return interp_cppyy.wrap_cppobject(space, address, self.cppclass, + do_cast=False, is_ref=True) def to_memory(self, space, w_obj, w_value, offset): address = rffi.cast(rffi.VOIDPP, self._get_raw_address(space, w_obj, offset)) @@ -464,8 +464,7 @@ def from_memory(self, space, w_obj, w_pycppclass, offset): address = rffi.cast(capi.C_OBJECT, self._get_raw_address(space, w_obj, offset)) from pypy.module.cppyy import interp_cppyy - return interp_cppyy.wrap_cppobject_nocast( - space, w_pycppclass, self.cppclass, address, isref=False, python_owns=False) + return interp_cppyy.wrap_cppobject(space, address, self.cppclass, do_cast=False) def to_memory(self, space, w_obj, w_value, offset): self._is_abstract(space) @@ -482,7 +481,7 @@ x[0] = rffi.cast(rffi.VOIDP, call_local) address = rffi.cast(capi.C_OBJECT, address) ba = rffi.cast(rffi.CCHARP, address) - ba[capi.c_function_arg_typeoffset()] = 'o' + ba[capi.c_function_arg_typeoffset(space)] = 'o' def convert_argument_libffi(self, space, w_obj, address, call_local): # TODO: finalize_call not yet called for fast call (see interp_cppyy.py) @@ -507,39 +506,35 @@ def __init__(self, space, extra): from pypy.module.cppyy import interp_cppyy - cppclass = interp_cppyy.scope_byname(space, "std::string") + cppclass = interp_cppyy.scope_byname(space, capi.std_string_name) InstanceConverter.__init__(self, space, cppclass) def _unwrap_object(self, space, w_obj): try: - charp = rffi.str2charp(space.str_w(w_obj)) - arg = capi.c_charp2stdstring(charp) - rffi.free_charp(charp) - return arg - except OperationError: + return capi.c_charp2stdstring(space, space.str_w(w_obj)) + except Exception, e: arg = InstanceConverter._unwrap_object(self, space, w_obj) - return capi.c_stdstring2stdstring(arg) + result = capi.c_stdstring2stdstring(space, arg) + return result def to_memory(self, space, w_obj, w_value, offset): try: address = rffi.cast(capi.C_OBJECT, self._get_raw_address(space, w_obj, offset)) - charp = rffi.str2charp(space.str_w(w_value)) - capi.c_assign2stdstring(address, charp) - rffi.free_charp(charp) + capi.c_assign2stdstring(space, address, space.str_w(w_value)) return except Exception: pass return InstanceConverter.to_memory(self, space, w_obj, w_value, offset) def free_argument(self, space, arg, call_local): - capi.c_free_stdstring(rffi.cast(capi.C_OBJECT, rffi.cast(rffi.VOIDPP, arg)[0])) + capi.c_free_stdstring(space, rffi.cast(capi.C_OBJECT, rffi.cast(rffi.VOIDPP, arg)[0])) class StdStringRefConverter(InstancePtrConverter): _immutable_fields_ = ['cppclass'] def __init__(self, space, extra): from pypy.module.cppyy import interp_cppyy - cppclass = interp_cppyy.scope_byname(space, "std::string") + cppclass = interp_cppyy.scope_byname(space, capi.std_string_name) InstancePtrConverter.__init__(self, space, cppclass) @@ -557,7 +552,7 @@ x = rffi.cast(rffi.VOIDPP, address) x[0] = rffi.cast(rffi.VOIDP, ref) ba = rffi.cast(rffi.CCHARP, address) - ba[capi.c_function_arg_typeoffset()] = 'a' From noreply at buildbot.pypy.org Mon Apr 22 08:35:49 2013 From: noreply at buildbot.pypy.org (wlav) Date: Mon, 22 Apr 2013 08:35:49 +0200 (CEST) Subject: [pypy-commit] pypy default: document whatsnew after reflex-support branch merge into default Message-ID: <20130422063549.E0E411C0328@cobra.cs.uni-duesseldorf.de> Author: Wim Lavrijsen Branch: Changeset: r63545:46c2ba0666ec Date: 2013-04-21 23:35 -0700 http://bitbucket.org/pypy/pypy/changeset/46c2ba0666ec/ Log: document whatsnew after reflex-support branch merge into default diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -57,10 +57,12 @@ Inline the fast path of newarray in the assembler. Disabled on ARM until we fix issues. +.. branch: reflex-support +Allow dynamic loading of a (Reflex) backend that implements the C-API needed +to provide reflection information .. branches we don't care about .. branch: autoreds -.. branch: reflex-support .. branch: kill-faking .. branch: improved_ebnfparse_error .. branch: task-decorator From noreply at buildbot.pypy.org Mon Apr 22 14:07:27 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Mon, 22 Apr 2013 14:07:27 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: changed beCursorWithMask: to also accept forms as argument (BE_CURSOR primitive) Message-ID: <20130422120727.6E5221C1464@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r304:e1d89224e688 Date: 2013-04-21 13:32 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/e1d89224e688/ Log: changed beCursorWithMask: to also accept forms as argument (BE_CURSOR primitive) diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -587,9 +587,17 @@ if argcount == 1: # TODO: use mask w_mask = s_frame.peek(0) - if not isinstance(w_mask, model.W_WordsObject): + if isinstance(w_mask, model.W_WordsObject): + mask_words = w_mask.words + elif isinstance(w_mask, model.W_PointersObject): + # mask is a form object + w_contents = w_mask.fetch(interp.space, 0) + if isinstance(w_contents, model.W_WordsObject): + w_mask = w_contents.words + else: + raise PrimitiveFailedError + else: raise PrimitiveFailedError() - mask_words = w_mask.words w_bitmap = w_rcvr.fetch(interp.space, 0) if not isinstance(w_bitmap, model.W_WordsObject): raise PrimitiveFailedError() From noreply at buildbot.pypy.org Mon Apr 22 14:07:26 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Mon, 22 Apr 2013 14:07:26 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: added as_repr_string to word_objects to have the correct class-string part Message-ID: <20130422120726.4934F1C140A@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r303:825096a81bc1 Date: 2013-04-21 13:31 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/825096a81bc1/ Log: added as_repr_string to word_objects to have the correct class- string part diff --git a/spyvm/model.py b/spyvm/model.py --- a/spyvm/model.py +++ b/spyvm/model.py @@ -442,8 +442,8 @@ def as_embellished_string(self, className, additionalInformation): from rpython.rlib.objectmodel import current_object_addr_as_int name = self.shadow_of_my_class(self.space).name or "?" - return "<%s (a %s) %s>" % (className, name, - #hex(current_object_addr_as_int(self)), + return "<%s (a %s) %s>" % (className, name, + #hex(current_object_addr_as_int(self)), additionalInformation) def invariant(self): @@ -634,8 +634,8 @@ @jit.elidable def as_repr_string(self): - return W_AbstractObjectWithClassReference.as_embellished_string(self, - className='W_PointersObject', + return W_AbstractObjectWithClassReference.as_embellished_string(self, + className='W_PointersObject', additionalInformation='len=%d' % self.size()) def fieldtype(self): @@ -676,7 +676,7 @@ return self.as_string() def as_repr_string(self): - return W_AbstractObjectWithClassReference.as_embellished_string(self, + return W_AbstractObjectWithClassReference.as_embellished_string(self, className='W_BytesObject', additionalInformation=self.as_string()) def as_string(self): @@ -706,7 +706,7 @@ # XXX Probably we want to allow all subclasses if not self.getclass(space).is_same_object(space.w_LargePositiveInteger): raise error.UnwrappingError("Failed to convert bytes to word") - word = 0 + word = 0 for i in range(self.size()): word += r_uint(ord(self.getchar(i))) << 8*i return word @@ -750,6 +750,10 @@ w_result.words = list(self.words) return w_result + def as_repr_string(self): + return W_AbstractObjectWithClassReference.as_embellished_string(self, + className='W_WordsObject', additionalInformation=('len=%d' % self.size())) + NATIVE_DEPTH = 32 class W_DisplayBitmap(W_AbstractObjectWithClassReference): From noreply at buildbot.pypy.org Mon Apr 22 14:07:28 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Mon, 22 Apr 2013 14:07:28 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: added VM_PARAMETERS primitive Message-ID: <20130422120728.8915E1C140A@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r305:9cd2c1e6430f Date: 2013-04-21 13:33 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/9cd2c1e6430f/ Log: added VM_PARAMETERS primitive the behavior is wrong in that all arguments are ignored and all return values are 0, but it doesn't fail anymore and during startup, return values are not checked diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -1302,6 +1302,79 @@ w_prev_bitmap.flush_to_screen() return w_rcvr +# ___________________________________________________________________________ +# VM implementor primitives +VM_CLEAR_PROFILE = 250 +VM_CONTROL_PROFILING = 251 +VM_PROFILE_SAMPLES_INTO = 252 +VM_PROFILE_INFO_INTO = 253 +VM_PARAMETERS = 254 +INST_VARS_PUT_FROM_STACK = 255 # Never used except in Disney tests. Remove after 2.3 release. + + at expose_primitive(VM_PARAMETERS) +def func(interp, s_frame, argcount): + """Behaviour depends on argument count: + 0 args: return an Array of VM parameter values; + 1 arg: return the indicated VM parameter; + 2 args: set the VM indicated parameter. + VM parameters are numbered as follows: + 1 end of old-space (0-based, read-only) + 2 end of young-space (read-only) + 3 end of memory (read-only) + 4 allocationCount (read-only) + 5 allocations between GCs (read-write) + 6 survivor count tenuring threshold (read-write) + 7 full GCs since startup (read-only) + 8 total milliseconds in full GCs since startup (read-only) + 9 incremental GCs since startup (read-only) + 10 total milliseconds in incremental GCs since startup (read-only) + 11 tenures of surving objects since startup (read-only) + 12-20 specific to the translating VM + 21 root table size (read-only) + 22 root table overflows since startup (read-only) + 23 bytes of extra memory to reserve for VM buffers, plugins, etc. + 24 memory threshold above which shrinking object memory (rw) + 25 memory headroom when growing object memory (rw) + 26 interruptChecksEveryNms - force an ioProcessEvents every N milliseconds, in case the image is not calling getNextEvent often (rw) + 27 number of times mark loop iterated for current IGC/FGC (read-only) includes ALL marking + 28 number of times sweep loop iterated for current IGC/FGC (read-only) + 29 number of times make forward loop iterated for current IGC/FGC (read-only) + 30 number of times compact move loop iterated for current IGC/FGC (read-only) + 31 number of grow memory requests (read-only) + 32 number of shrink memory requests (read-only) + 33 number of root table entries used for current IGC/FGC (read-only) + 34 number of allocations done before current IGC/FGC (read-only) + 35 number of survivor objects after current IGC/FGC (read-only) + 36 millisecond clock when current IGC/FGC completed (read-only) + 37 number of marked objects for Roots of the world, not including Root Table entries for current IGC/FGC (read-only) + 38 milliseconds taken by current IGC (read-only) + 39 Number of finalization signals for Weak Objects pending when current IGC/FGC completed (read-only) + 40 BytesPerWord for this image + 41 imageFormatVersion for the VM + 42 nil (number of stack pages in use in Stack VM) + 43 nil (desired number of stack pages in Stack VM) + 44 nil (size of eden, in bytes in Stack VM) + 45 nil (desired size of eden in Stack VM) + 46-55 nil; reserved for VM parameters that persist in the image (such as eden above) + 56 number of process switches since startup (read-only) + 57 number of ioProcessEvents calls since startup (read-only) + 58 number of ForceInterruptCheck calls since startup (read-only) + 59 number of check event calls since startup (read-only) + + Note: Thanks to Ian Piumarta for this primitive.""" + if not 0 <= argcount <= 2: + raise PrimitiveFailedError + + s_frame.pop() # receiver + if argcount == 0: + return interp.space.wrap_list([interp.space.wrap_int(0)]*59) + s_frame.pop() # index (really the receiver, index has been removed above) + if argcount == 1: + return interp.space.wrap_int(0) + s_frame.pop() # new value + if argcount == 2: + # return the 'old value' + return interp.space.wrap_int(0) # ___________________________________________________________________________ # PrimitiveLoadInstVar From noreply at buildbot.pypy.org Mon Apr 22 14:07:29 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Mon, 22 Apr 2013 14:07:29 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: added CTXT at:, at:put:, size primitives the same way they are added in COG, by using the AT, AT_PUT, SIZE primitive functions which should dispatch onto the W_Object methods. Message-ID: <20130422120729.AA4D31C140A@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r306:913316b6cb4c Date: 2013-04-21 13:36 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/913316b6cb4c/ Log: added CTXT at:, at:put:, size primitives the same way they are added in COG, by using the AT, AT_PUT, SIZE primitive functions which should dispatch onto the W_Object methods. The result is that infinite debugger loops are replaced by an out-of-bounds access ... diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -1288,6 +1288,9 @@ CTXT_AT_PUT = 211 CTXT_SIZE = 212 +prim_table[CTXT_AT] = prim_table[AT] +prim_table[CTXT_AT_PUT] = prim_table[AT_PUT] +prim_table[CTXT_SIZE] = prim_table[SIZE] # ___________________________________________________________________________ # Drawing From noreply at buildbot.pypy.org Mon Apr 22 14:07:30 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Mon, 22 Apr 2013 14:07:30 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: fixed whitespace Message-ID: <20130422120730.C0E391C140A@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r307:c988d5a86694 Date: 2013-04-22 13:56 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/c988d5a86694/ Log: fixed whitespace diff --git a/spyvm/fieldtypes.py b/spyvm/fieldtypes.py --- a/spyvm/fieldtypes.py +++ b/spyvm/fieldtypes.py @@ -165,4 +165,4 @@ if start < end: mid = partition(an_array, start, end) sort_quick_inplace(an_array, start, mid) - sort_quick_inplace(an_array, mid + 1, end) \ No newline at end of file + sort_quick_inplace(an_array, mid + 1, end) diff --git a/spyvm/interpreter.py b/spyvm/interpreter.py --- a/spyvm/interpreter.py +++ b/spyvm/interpreter.py @@ -83,7 +83,7 @@ if not jit.we_are_jitted(): self.quick_check_for_interrupt(s_context) while True: - pc = s_context._pc + pc = s_context.pc() method = s_context.s_method() if pc < old_pc: if jit.we_are_jitted(): diff --git a/spyvm/objspace.py b/spyvm/objspace.py --- a/spyvm/objspace.py +++ b/spyvm/objspace.py @@ -19,7 +19,7 @@ name=name[2:]) self.classtable[name] = w_class return w_class - + # A complete minimal setup (including Behavior) would look like this # # class: superclass: metaclass: @@ -34,7 +34,7 @@ # 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 @@ -61,7 +61,7 @@ for nm, w_cls_obj in self.classtable.items(): if w_cls_obj.s_class is None: w_cls_obj.s_class = s_Metaclass - + def define_cls(cls_nm, supercls_nm, instvarsize=0, format=shadow.POINTERS, varsized=False): assert cls_nm.startswith("w_") @@ -295,7 +295,7 @@ if not w_array.getclass(self).is_same_object(self.w_Array): raise UnwrappingError() assert isinstance(w_array, model.W_PointersObject) - + return [w_array.at0(self, i) for i in range(w_array.size())] def get_display(self): diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -825,7 +825,6 @@ @expose_primitive(DRAW_RECTANGLE, unwrap_spec=[object, int, int, int, int]) def func(interp, s_frame, w_rcvr, left, right, top, bottom): - # import pdb; pdb.set_trace() raise PrimitiveNotYetWrittenError() diff --git a/spyvm/shadow.py b/spyvm/shadow.py --- a/spyvm/shadow.py +++ b/spyvm/shadow.py @@ -18,7 +18,7 @@ can be attached at run-time to any Smalltalk object. """ _attr_ = ['_w_self'] - + def __init__(self, space, w_self): self.space = space self._w_self = w_self @@ -64,7 +64,7 @@ class Version: pass -# ____________________________________________________________ +# ____________________________________________________________ POINTERS = 0 BYTES = 1 @@ -266,9 +266,9 @@ self._s_superclass = None else: s_scls = w_class.as_class_get_shadow(self.space) - if self._s_superclass is s_scls: + if self._s_superclass is s_scls: return - elif (self._s_superclass is not None + elif (self._s_superclass is not None and self._s_superclass is not s_scls): self._s_superclass.detach_s_class(self) self._s_superclass = s_scls @@ -428,11 +428,11 @@ 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 - _attr_ = ['_s_sender', '_pc', '_temps_and_stack', + _attr_ = ['_s_sender', '_pc', '_temps_and_stack', '_stack_ptr', 'instances_w'] _virtualizable2_ = [ @@ -504,7 +504,7 @@ self.push(self.space.w_nil) def wrap_stackpointer(self): - return self.space.wrap_int(self.stackdepth() + + return self.space.wrap_int(self.stackdepth() + self.tempsize()) def external_stackpointer(self): @@ -515,7 +515,7 @@ def s_home(self): return self.w_home().as_methodcontext_get_shadow(self.space) - + def stackstart(self): raise NotImplementedError() @@ -563,6 +563,7 @@ return self._pc def store_pc(self, newpc): + assert newpc >= -1 self._pc = newpc def stackpointer_offset(self): @@ -601,7 +602,7 @@ # Temporary Variables # # Are always fetched relative to the home method context. - + def gettemp(self, index): return self.s_home().gettemp(index) @@ -619,7 +620,7 @@ # ______________________________________________________________________ # Stack Manipulation - + def stack(self): """NOT_RPYTHON""" # purely for testing return self._temps_and_stack[self.tempsize():self._stack_ptr] @@ -681,7 +682,7 @@ raise NotImplementedError() # ______________________________________________________________________ # Marriage of Context Shadows with PointerObjects only when required - + def w_self(self): if self._w_self is not None: return self._w_self @@ -762,7 +763,7 @@ def unwrap_store_eargc(self, w_value): self.store_expected_argument_count(self.space.unwrap_int(w_value)) - + def wrap_eargc(self): return self.space.wrap_int(self.expected_argument_count()) @@ -774,10 +775,10 @@ def initialip(self): return self._initialip - + def store_initialip(self, initialip): self._initialip = initialip - + def store_w_home(self, w_home): assert isinstance(w_home, model.W_PointersObject) self._w_home = w_home @@ -824,21 +825,21 @@ s_new_context._w_self_size = size s_new_context_non_fresh = s_new_context # XXX: find a better solution to translation err s_new_context = jit.hint(s_new_context, access_directly=True, fresh_virtualizable=True) - - if closure is not None: + + if closure is not None: s_new_context.w_closure_or_nil = closure._w_self - + s_new_context.store_w_method(s_method.w_self()) if s_sender: s_new_context.store_s_sender(s_sender) s_new_context.store_w_receiver(w_receiver) s_new_context.store_pc(pc) s_new_context.init_stack_and_temps() - + argc = len(arguments) for i0 in range(argc): s_new_context.settemp(i0, arguments[i0]) - if closure is not None: + if closure is not None: for i0 in range(closure.size()): s_new_context.settemp(i0+argc, closure.at0(i0)) return s_new_context_non_fresh @@ -870,7 +871,7 @@ return self.settemp(temp_i, w_value) else: return ContextPartShadow.store(self, n0, w_value) - + @jit.dont_look_inside def attach_shadow(self): # Make sure the method and closure_or_nil are updated first, @@ -884,7 +885,7 @@ if not self.is_closure_context(): return self.s_method().tempsize() else: - return wrapper.BlockClosureWrapper(self.space, + return wrapper.BlockClosureWrapper(self.space, self.w_closure_or_nil).tempsize() def w_method(self): @@ -927,7 +928,7 @@ def returnTopFromMethod(self, interp, current_bytecode): if self.is_closure_context(): # this is a context for a blockClosure - w_outerContext = self.w_closure_or_nil.fetch(self.space, + w_outerContext = self.w_closure_or_nil.fetch(self.space, constants.BLKCLSR_OUTER_CONTEXT) assert isinstance(w_outerContext, model.W_PointersObject) s_outerContext = w_outerContext.as_context_get_shadow(self.space) @@ -1008,7 +1009,7 @@ if self.literals: # (Blue book, p 607) All CompiledMethods that contain # extended-super bytecodes have the clain which they are found as - # their last literal variable. + # their last literal variable. # Last of the literals is an association with compiledin # as a class w_association = self.literals[-1] diff --git a/spyvm/wrapper.py b/spyvm/wrapper.py --- a/spyvm/wrapper.py +++ b/spyvm/wrapper.py @@ -170,7 +170,7 @@ class SchedulerWrapper(Wrapper): priority_list = make_getter(0) active_process, store_active_process = make_getter_setter(1) - + def get_process_list(self, priority): lists = Wrapper(self.space, self.priority_list()) @@ -178,9 +178,9 @@ def highest_priority_process(self): w_lists = self.priority_list() - # Asserts as W_PointersObjectonion in the varnish. + # Asserts as W_PointersObjectonion in the varnish. lists = Wrapper(self.space, w_lists) - + for i in range(w_lists.size() - 1, -1, -1): process_list = ProcessListWrapper(self.space, lists.read(i)) if not process_list.is_empty_list(): @@ -222,7 +222,7 @@ x, store_x = make_int_getter_setter(0) y, store_y = make_int_getter_setter(1) - + class BlockClosureWrapper(VarsizedWrapper): outerContext, store_outerContext = make_getter_setter(constants.BLKCLSR_OUTER_CONTEXT) startpc, store_startpc = make_int_getter_setter(constants.BLKCLSR_STARTPC) @@ -242,13 +242,13 @@ return w_new_frame def tempsize(self): - # We ignore the number of temps a block has, because the first - # bytecodes of the block will initialize them for us. We will only - # use this information for decinding where the stack pointer should be + # We ignore the number of temps a block has, because the first + # bytecodes of the block will initialize them for us. We will only + # use this information for decinding where the stack pointer should be # initialy. # For a finding the correct number, see BlockClosure>#numTemps in an Image. return self.size() + self.numArgs() - + def size(self): return self._w_self.size() - constants.BLKCLSR_SIZE From noreply at buildbot.pypy.org Mon Apr 22 14:07:31 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Mon, 22 Apr 2013 14:07:31 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: added interrupt_key primitive (133) Message-ID: <20130422120731.F0E5B1C140A@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r308:4111579f1cea Date: 2013-04-22 14:00 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/4111579f1cea/ Log: added interrupt_key primitive (133) refactored mod-keys to also apply to normal keys beside mouse-klicks diff --git a/spyvm/display.py b/spyvm/display.py --- a/spyvm/display.py +++ b/spyvm/display.py @@ -9,13 +9,13 @@ MOUSE_BTN_RIGHT = 1 MOUSE_BTN_MIDDLE = 2 MOUSE_BTN_LEFT = 4 -MOD_SHIFT = 8 -MOD_CONTROL = 16 -MOD_ALT = 64 +MOD_SHIFT = 1 +MOD_CONTROL = 2 +MOD_ALT = 16 class SDLDisplay(object): _attrs_ = ["screen", "width", "height", "depth", "surface", "has_surface", - "mouse_position", "button", "key"] + "mouse_position", "button", "key", "interrupt_key"] def __init__(self, title): assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 @@ -77,6 +77,10 @@ if len(chars) == 1: if c_type == RSDL.KEYDOWN: self.key = ord(chars[0]) + interrupt = self.interrupt_key + if (interrupt & 0xFF == self.key and + interrupt >> 8 == self.get_modifier_mask(0)): + raise KeyboardInterrupt else: pass # XXX: Todo? elif c_type == RSDL.QUIT: @@ -85,7 +89,7 @@ finally: lltype.free(event, flavor='raw') - def get_modifier_mask(self): + def get_modifier_mask(self, shift): RSDL.PumpEvents() mod = RSDL.GetModState() modifier = 0 @@ -95,7 +99,7 @@ modifier |= MOD_SHIFT if mod & RSDL.KMOD_ALT != 0: modifier |= MOD_ALT - return modifier + return modifier << shift def mouse_point(self): self.get_next_event() @@ -103,16 +107,19 @@ def mouse_button(self): self.get_next_event() - return self.button | self.get_modifier_mask() + return self.button | self.get_modifier_mask(3) def next_keycode(self): key = self.key self.key = 0 - return key + return key | self.get_modifier_mask(8) def peek_keycode(self): self.get_next_event() - return self.key + return self.key | self.get_modifier_mask(8) + + def set_interrupt_key(self, space, encoded_key): + self.interrupt_key = encoded_key class SDLCursorClass(object): diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -834,6 +834,7 @@ SPECIAL_OBJECTS_ARRAY = 129 FULL_GC = 130 INC_GC = 131 +SET_INTERRUPT_KEY = 133 INTERRUPT_SEMAPHORE = 134 @expose_primitive(BECOME, unwrap_spec=[object, object]) @@ -869,6 +870,11 @@ rgc.collect() return fake_bytes_left(interp) + at expose_primitive(SET_INTERRUPT_KEY, unwrap_spec=[object, int]) +def func(interp, s_frame, w_rcvr, encoded_key): + interp.space.get_display().set_interrupt_key(interp.space, encoded_key) + return w_rcvr + @expose_primitive(INTERRUPT_SEMAPHORE, unwrap_spec=[object, object]) def func(interp, s_frame, w_rcvr, w_semaphore): if w_semaphore.getclass(interp.space).is_same_object(interp.space.w_Semaphore): From noreply at buildbot.pypy.org Mon Apr 22 14:07:33 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Mon, 22 Apr 2013 14:07:33 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: added 32bit bitblit form Message-ID: <20130422120733.1497B1C140A@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r309:6b3637ecc396 Date: 2013-04-22 14:01 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/6b3637ecc396/ Log: added 32bit bitblit form diff --git a/spyvm/model.py b/spyvm/model.py --- a/spyvm/model.py +++ b/spyvm/model.py @@ -757,13 +757,15 @@ NATIVE_DEPTH = 32 class W_DisplayBitmap(W_AbstractObjectWithClassReference): - _attrs_ = ['pixelbuffer', '_realsize', 'display'] + _attrs_ = ['pixelbuffer', '_realsize', '_real_depth_buffer', 'display'] _immutable_fields_ = ['_realsize', 'display'] @staticmethod def create(space, w_class, size, depth, display): if depth == 1: return W_DisplayBitmap1Bit(space, w_class, size, depth, display) + elif depth == 32: + return W_DisplayBitmap32Bit(space, w_class, size, depth, display) else: raise NotImplementedError("non B/W squeak") @@ -823,6 +825,14 @@ mask >>= 1 pos += 1 +class W_DisplayBitmap32Bit(W_DisplayBitmap): + def getword(self, n): + return self._real_depth_buffer[n] + + @jit.unroll_safe + def setword(self, n, word): + self._real_depth_buffer[n] = word + self.pixelbuffer[n] = word # XXX Shouldn't compiledmethod have class reference for subclassed compiled # methods? From noreply at buildbot.pypy.org Mon Apr 22 14:07:34 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Mon, 22 Apr 2013 14:07:34 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: fixed the infect of creating blockclosures with non-st-compliant pc offsets Message-ID: <20130422120734.427071C140A@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r310:bfa8d3f29095 Date: 2013-04-22 14:03 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/bfa8d3f29095/ Log: fixed the infect of creating blockclosures with non-st-compliant pc offsets diff --git a/spyvm/objspace.py b/spyvm/objspace.py --- a/spyvm/objspace.py +++ b/spyvm/objspace.py @@ -309,13 +309,15 @@ def _freeze_(self): return True - def newClosure(self, outerContext, pc, numArgs, copiedValues): + def newClosure(self, w_outer_ctxt, pc, numArgs, copiedValues): + assert isinstance(w_outer_ctxt, model.W_PointersObject) + pc_with_bytecodeoffset = pc + w_outer_ctxt.as_context_get_shadow(self).s_method().bytecodeoffset + 1 BlockClosureShadow = self.w_BlockClosure.as_class_get_shadow(self) numCopied = len(copiedValues) w_closure = BlockClosureShadow.new(numCopied) closure = wrapper.BlockClosureWrapper(self, w_closure) - closure.store_outerContext(outerContext) - closure.store_startpc(pc) + closure.store_outerContext(w_outer_ctxt) + closure.store_startpc(pc_with_bytecodeoffset) closure.store_numArgs(numArgs) for i0 in range(numCopied): closure.atput0(i0, copiedValues[i0]) diff --git a/spyvm/wrapper.py b/spyvm/wrapper.py --- a/spyvm/wrapper.py +++ b/spyvm/wrapper.py @@ -228,7 +228,7 @@ startpc, store_startpc = make_int_getter_setter(constants.BLKCLSR_STARTPC) numArgs, store_numArgs = make_int_getter_setter(constants.BLKCLSR_NUMARGS) - def asContextWithSender(self, w_aContext, arguments): + def asContextWithSender(self, w_context, arguments): from spyvm import shadow w_outerContext = self.outerContext() if not isinstance(w_outerContext, model.W_PointersObject): @@ -236,9 +236,10 @@ s_outerContext = w_outerContext.as_context_get_shadow(self.space) s_method = s_outerContext.w_method().as_compiledmethod_get_shadow(self.space) w_receiver = s_outerContext.w_receiver() + pc = self.startpc() - s_method.bytecodeoffset - 1 w_new_frame = shadow.MethodContextShadow.make_context(self.space, s_method, w_receiver, - arguments, s_sender=w_aContext.get_shadow(self.space), - pc=self.startpc(), closure=self) + arguments, s_sender=w_context.get_shadow(self.space), + pc=pc, closure=self) return w_new_frame def tempsize(self): From noreply at buildbot.pypy.org Mon Apr 22 14:07:35 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Mon, 22 Apr 2013 14:07:35 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: added store stackpointer primitive Message-ID: <20130422120735.496A31C140A@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r311:6ce27d176682 Date: 2013-04-22 14:04 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/6ce27d176682/ Log: added store stackpointer primitive in later squeak versions, instead of having in alternative implementation in case of primitive-failure an error is raised. diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -458,11 +458,14 @@ raise PrimitiveFailedError() return interp.space.wrap_int(w_rcvr.gethash()) - at expose_primitive(STORE_STACKP, unwrap_spec=[object, object]) -def func(interp, s_frame, w_obj1, w_obj2): - # This primitive seems to resize the stack. I don't think this is - # really relevant in our implementation. - raise PrimitiveNotYetWrittenError() + at expose_primitive(STORE_STACKP, unwrap_spec=[object, int]) +def func(interp, s_frame, w_frame, stackp): + assert stackp >= 0 + if not isinstance(w_frame, model.W_PointersObject): + raise PrimitiveFailedError + s_frame = w_frame.as_context_get_shadow(interp.space) + s_frame.store_stackpointer(stackp) + return w_frame @expose_primitive(SOME_INSTANCE, unwrap_spec=[object]) def func(interp, s_frame, w_class): From noreply at buildbot.pypy.org Mon Apr 22 14:07:36 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Mon, 22 Apr 2013 14:07:36 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: added IDLE_FOR_MICROSECONDS primitive, prolonging the idle-waiting minimaly Message-ID: <20130422120736.5A8D61C140A@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r312:388713badc5f Date: 2013-04-22 14:05 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/388713badc5f/ Log: added IDLE_FOR_MICROSECONDS primitive, prolonging the idle-waiting minimaly fixed the signature of GET_NEXT_EVENT diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -554,8 +554,8 @@ w_point.store(interp.space, 1, interp.space.wrap_int(y)) return w_point - at expose_primitive(GET_NEXT_EVENT, unwrap_spec=[object]) -def func(interp, s_frame, w_rcvr): + at expose_primitive(GET_NEXT_EVENT, unwrap_spec=[object, object]) +def func(interp, s_frame, w_rcvr, w_into): raise PrimitiveNotYetWrittenError() @expose_primitive(BITBLT_COPY_BITS, unwrap_spec=[object], clean_stack=False) @@ -1302,8 +1302,16 @@ # ___________________________________________________________________________ # Drawing +IDLE_FOR_MICROSECONDS = 230 FORCE_DISPLAY_UPDATE = 231 + at expose_primitive(IDLE_FOR_MICROSECONDS, unwrap_spec=[object, int]) +def func(interp, s_frame, w_rcvr, time_mu_s): + import time + time_s = time_mu_s / 1000000.0 + time.sleep(time_s) + return w_rcvr + @expose_primitive(FORCE_DISPLAY_UPDATE, unwrap_spec=[object]) def func(interp, s_frame, w_rcvr): w_prev_display = interp.space.objtable['w_display'] From noreply at buildbot.pypy.org Mon Apr 22 14:07:37 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Mon, 22 Apr 2013 14:07:37 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: signal and wait primitives return the receiver, not the context... Message-ID: <20130422120737.6280E1C1464@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r313:9f5bcc07fb33 Date: 2013-04-22 14:07 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/9f5bcc07fb33/ Log: signal and wait primitives return the receiver, not the context... diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -1170,21 +1170,21 @@ s_frame._sendSelector(w_selector, argcount, interp, w_rcvr, w_rcvr.shadow_of_my_class(interp.space)) - at expose_primitive(SIGNAL, unwrap_spec=[object], clean_stack=False) + at expose_primitive(SIGNAL, unwrap_spec=[object], clean_stack=False, no_result=True) def func(interp, s_frame, w_rcvr): # XXX we might want to disable this check if not w_rcvr.getclass(interp.space).is_same_object( interp.space.w_Semaphore): raise PrimitiveFailedError() - return wrapper.SemaphoreWrapper(interp.space, w_rcvr).signal(s_frame.w_self()) + wrapper.SemaphoreWrapper(interp.space, w_rcvr).signal(s_frame.w_self()) - at expose_primitive(WAIT, unwrap_spec=[object], clean_stack=False) + at expose_primitive(WAIT, unwrap_spec=[object], clean_stack=False, no_result=True) def func(interp, s_frame, w_rcvr): # XXX we might want to disable this check if not w_rcvr.getclass(interp.space).is_same_object( interp.space.w_Semaphore): raise PrimitiveFailedError() - return wrapper.SemaphoreWrapper(interp.space, w_rcvr).wait(s_frame.w_self()) + wrapper.SemaphoreWrapper(interp.space, w_rcvr).wait(s_frame.w_self()) @expose_primitive(RESUME, unwrap_spec=[object], result_is_new_frame=True, clean_stack=False) def func(interp, s_frame, w_rcvr): From noreply at buildbot.pypy.org Mon Apr 22 14:29:27 2013 From: noreply at buildbot.pypy.org (arigo) Date: Mon, 22 Apr 2013 14:29:27 +0200 (CEST) Subject: [pypy-commit] pypy stm-gc-2: Progress, but annoyed by the constant awkward interfacing between Message-ID: <20130422122927.1868E1C1464@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: stm-gc-2 Changeset: r63546:f48a4dfa5400 Date: 2013-04-21 17:33 +0200 http://bitbucket.org/pypy/pypy/changeset/f48a4dfa5400/ Log: Progress, but annoyed by the constant awkward interfacing between C code and various pieces of RPython. :-/ diff --git a/rpython/memory/gc/stmgc.py b/rpython/memory/gc/stmgc.py --- a/rpython/memory/gc/stmgc.py +++ b/rpython/memory/gc/stmgc.py @@ -238,8 +238,8 @@ stmtls = self.get_tls() stmtls.stop_transaction() self.stm_operations.commit_transaction() + self.stm_operations.begin_inevitable_transaction() self.remove_from_linked_list(stmtls) - self.stm_operations.begin_inevitable_transaction() stmtls.delete() teardown_thread._dont_inline_ = True @@ -535,6 +535,7 @@ return mangle_hash(i) def can_move(self, addr): + raise NotImplementedError("stmgc.can_move") tls = self.get_tls() if tls.is_in_nursery(addr): return True diff --git a/rpython/memory/gc/stmshared.py b/rpython/memory/gc/stmshared.py --- a/rpython/memory/gc/stmshared.py +++ b/rpython/memory/gc/stmshared.py @@ -106,19 +106,36 @@ debug_start("gc-collect") debug_print() debug_print(".----------- Full collection ------------------") - debug_print("| used before collection:", + debug_print("| used before collection: ", self.fetch_count_total_bytes(), "bytes") # - fatalerror("do_major_collection: in-progress") + # Note that a major collection is non-moving. The goal is only to + # find and free some of the objects allocated by the ArenaCollection. + # We first visit all objects and set the flag GCFLAG_VISITED on them. + self.objects_to_trace = self.AddressStack() + # + # The stacks... + self.collect_stack_roots_from_every_thread() # self.num_major_collects += 1 - debug_print("| used after collection:", + debug_print("| used after collection: ", self.fetch_count_total_bytes(), "bytes") - debug_print("| number of major collects: ", + debug_print("| number of major collects: ", self.num_major_collects) debug_print("`----------------------------------------------") debug_stop("gc-collect") + def collect_stack_roots_from_every_thread(self): + self.gc.root_walker.walk_all_stack_roots(self._collect_stack_root, + None) + + def _collect_stack_root(self, ignored, root): + self.visit(root.address[0]) + + def visit(self, obj): + hdr = self.gc.header(obj) + XXX + # ------------------------------------------------------------ @@ -133,7 +150,6 @@ def __init__(self, sharedarea): self.gc = sharedarea.gc self.sharedarea = sharedarea - self.chained_list = NULL # # The array 'pages_for_size' contains 'length' chained lists # of pages currently managed by this thread. @@ -242,12 +258,6 @@ llarena.arena_reserve(addr, _dummy_size(totalsize)) return addr + self.gc.gcheaderbuilder.size_gc_header - def add_regular(self, obj): - """After malloc_object(), register the object in the internal chained - list. For objects whose 'revision' field is not otherwise needed.""" - self.gc.set_obj_revision(obj, self.chained_list) - self.chained_list = obj - def free_object(self, obj): adr1 = obj - self.gc.gcheaderbuilder.size_gc_header totalsize = (self.gc.gcheaderbuilder.size_gc_header + @@ -262,18 +272,6 @@ self.sharedarea.fetch_count_total_bytes_and_add(-totalsize) llarena.arena_free(llarena.getfakearenaaddress(adr1)) - def free_and_clear(self): - obj = self.chained_list - self.chained_list = NULL - while obj: - next = self.gc.obj_revision(obj) - self.free_object(obj) - obj = next - - def free_and_clear_list(self, lst): - while lst.non_empty(): - self.free_object(lst.pop()) - def gift_all_pages_to_shared_area(self): """Send to the shared area all my pages. For now we don't extract the information about which locations are free or not; we just stick diff --git a/rpython/memory/gc/stmtls.py b/rpython/memory/gc/stmtls.py --- a/rpython/memory/gc/stmtls.py +++ b/rpython/memory/gc/stmtls.py @@ -41,9 +41,6 @@ llmemory.Address) self.adr_of_stack_top = llop.gc_adr_of_root_stack_top( llmemory.Address) - if StmGCThreadLocalAllocator is None: - from rpython.memory.gc.stmshared import StmGCThreadLocalAllocator - self.StmGCThreadLocalAllocator = StmGCThreadLocalAllocator # # --- current position, or NULL when mallocs are forbidden self.nursery_free = NULL @@ -62,8 +59,12 @@ self.nursery_top = self.nursery_stop # # --- a thread-local allocator for the shared area - self.sharedarea_tls = self.StmGCThreadLocalAllocator( + if StmGCThreadLocalAllocator is None: + from rpython.memory.gc.stmshared import StmGCThreadLocalAllocator + self.sharedarea_tls = StmGCThreadLocalAllocator( self.gc.sharedarea) + # --- a chained list of regular local objects, linked via 'revision'. + self.regular_chained_list = NULL # --- the LOCAL objects which are weakrefs. They are also listed # in the appropriate place, like sharedarea_tls, if needed. self.local_weakrefs = self.AddressStack() @@ -199,10 +200,9 @@ else: self.detect_flag_combination = -1 # - # Move away the previous sharedarea_tls and start a new one. - previous_sharedarea_tls = self.sharedarea_tls - self.sharedarea_tls = self.StmGCThreadLocalAllocator( - self.gc.sharedarea) + # Move away the previous chained_list and start a new one. + previous_chained_list = self.regular_chained_list + self.regular_chained_list = NULL # # List of LOCAL objects pending a visit. Note that no GLOBAL # object can at any point contain a reference to a LOCAL object. @@ -238,7 +238,7 @@ # # Visit all previous OLD objects. Free the ones that have not been # visited above, and reset GCFLAG_VISITED on the others. - self.mass_free_old_local(previous_sharedarea_tls) + self.mass_free_old_local(previous_chained_list) # # Note that the last step guarantees the invariant that between # collections, all the objects linked within 'self.sharedarea_tls' @@ -310,10 +310,10 @@ def _promote_locals_to_globals(self): ll_assert(self.local_nursery_is_empty(), "nursery must be empty [1]") # - # Promote all objects in sharedarea_tls to global. + # Promote all objects in 'regular_chained_list' to global. # This is the "real" equivalent of _FakeReach() in et.c. - obj = self.sharedarea_tls.chained_list - self.sharedarea_tls.chained_list = NULL + obj = self.regular_chained_list + self.regular_chained_list = NULL # while obj: hdr = self.gc.header(obj) @@ -338,9 +338,13 @@ #if self.rawmalloced_objects: # xxx # free the rawmalloced_objects still around - # free the old unused local objects still allocated in the - # StmGCThreadLocalAllocator - self.sharedarea_tls.free_and_clear() + # free the old unused local objects still in the chained list + obj = self.regular_chained_list + self.regular_chained_list = NULL + while obj: + next = self.gc.obj_revision(obj) + self.sharedarea_tls.free_object(obj) + obj = next # forget the local weakrefs. self.local_weakrefs.clear() @@ -483,7 +487,7 @@ # # Register the object here, not before the memcopy() that would # overwrite its 'revision' field - self._register_newly_malloced_obj(newobj) + self._register_regular_obj(newobj) # # Set the YOUNG copy's GCFLAG_VISITED and set its revision to # point to the OLD copy. @@ -579,8 +583,9 @@ # return newobj - def _register_newly_malloced_obj(self, obj): - self.sharedarea_tls.add_regular(obj) + def _register_regular_obj(self, obj): + self.gc.set_obj_revision(obj, self.regular_chained_list) + self.regular_chained_list = obj def collect_roots_from_tldict(self): if not we_are_translated(): @@ -658,16 +663,14 @@ self.local_weakrefs = new old.delete() - def mass_free_old_local(self, previous_sharedarea_tls): - obj = previous_sharedarea_tls.chained_list - previous_sharedarea_tls.delete() + def mass_free_old_local(self, obj): while obj != NULL: hdr = self.gc.header(obj) next = hdr_revision(hdr) if hdr.tid & GCFLAG_VISITED: - # survives: relink in the new sharedarea_tls + # survives: relink in the new chained list hdr.tid -= GCFLAG_VISITED - self.sharedarea_tls.add_regular(obj) + self._register_regular_obj(obj) else: # dies self.sharedarea_tls.free_object(obj) diff --git a/rpython/memory/gc/test/test_stmshared.py b/rpython/memory/gc/test/test_stmshared.py --- a/rpython/memory/gc/test/test_stmshared.py +++ b/rpython/memory/gc/test/test_stmshared.py @@ -1,6 +1,7 @@ from rpython.memory.gc.stmshared import WORD from rpython.memory.gc.stmshared import StmGCSharedArea from rpython.memory.gc.stmshared import StmGCThreadLocalAllocator +from rpython.rtyper.lltypesystem import lltype, llmemory, rffi SGH = 3 @@ -20,6 +21,17 @@ def release_global_lock(self): pass +class FakeRootWalker: + def __init__(self, rootobjlist): + self._rootobjlist = rootobjlist + def walk_all_stack_roots(self, collect_stack_root, arg): + for obj in self._rootobjlist: + p = lltype.malloc(rffi.CArray(llmemory.Address), 1, flavor='raw') + p[0] = obj + collect_stack_root(arg, llmemory.cast_ptr_to_adr(p)) + assert p[0] == obj # should not move + lltype.free(p) + def test_simple(): gc = FakeGC() @@ -93,3 +105,16 @@ assert shared.count_global_pages == 0 thl1.delete() assert shared.count_global_pages == 1 + +def test_do_major_collection(): + gc = FakeGC() + shared = StmGCSharedArea(gc, 9*WORD, 2*WORD) + shared.setup() + thl1 = StmGCThreadLocalAllocator(shared) + obj1 = thl1.malloc_object(2*WORD-SGH) + obj2 = thl1.malloc_object(2*WORD-SGH) + # + gc.root_walker = FakeRootWalker([obj2]) + shared.do_major_collection() + # + xxx From noreply at buildbot.pypy.org Mon Apr 22 15:03:29 2013 From: noreply at buildbot.pypy.org (bivab) Date: Mon, 22 Apr 2013 15:03:29 +0200 (CEST) Subject: [pypy-commit] pypy default: do not overwrite r.ip when loading pos_exception before resetting it Message-ID: <20130422130329.C75F51C1284@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63547:c13457babbfb Date: 2013-04-22 15:02 +0200 http://bitbucket.org/pypy/pypy/changeset/c13457babbfb/ Log: do not overwrite r.ip when loading pos_exception before resetting it diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -122,8 +122,8 @@ if exctploc is not None: # store pos_exception in exctploc assert exctploc.is_reg() - mc.gen_load_int(r.ip.value, self.cpu.pos_exception()) - self.load_reg(mc, exctploc, r.ip) + mc.gen_load_int(tmpreg.value, self.cpu.pos_exception()) + self.load_reg(mc, exctploc, tmpreg) # reset exception mc.gen_load_int(tmpreg.value, 0) From noreply at buildbot.pypy.org Mon Apr 22 17:19:07 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Mon, 22 Apr 2013 17:19:07 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: added external call primitive and support BitBltPlugin>>primitiveCopyBits (redirecting to primitive BITBLT_COPY) Message-ID: <20130422151907.C31A11C0014@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r314:df9ce72ccb76 Date: 2013-04-22 17:15 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/df9ce72ccb76/ Log: added external call primitive and support BitBltPlugin>>primitiveCopyBits (redirecting to primitive BITBLT_COPY) diff --git a/spyvm/interpreter.py b/spyvm/interpreter.py --- a/spyvm/interpreter.py +++ b/spyvm/interpreter.py @@ -346,13 +346,13 @@ code, self.w_method()._likely_methodname, w_selector.as_string()) try: # note: argcount does not include rcvr - return func(interp, self, argcount) + return func(interp, self, argcount, s_method) except primitives.PrimitiveFailedError: # ############################################################## # if interp.trace and func.func_name != 'raise_failing_default' and code != 83: # # import pdb; pdb.set_trace() # try: - # func(interp, self, argcount) # will fail again + # func(interp, self, argcount, s_method) # will fail again # except primitives.PrimitiveFailedError: # pass if interp.trace: diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -27,7 +27,7 @@ # arguments, an interp and an argument_count # completes, and returns a result, or throws a PrimitiveFailedError. def make_failing(code): - def raise_failing_default(interp, s_frame, argument_count): + def raise_failing_default(interp, s_frame, argument_count, s_method=None): raise PrimitiveFailedError return raise_failing_default @@ -50,7 +50,8 @@ char = object() pos_32bit_int = object() -def expose_primitive(code, unwrap_spec=None, no_result=False, result_is_new_frame=False, clean_stack=True): +def expose_primitive(code, unwrap_spec=None, no_result=False, + result_is_new_frame=False, clean_stack=True, compiled_method=False): # some serious magic, don't look from rpython.rlib.unroll import unrolling_iterable # heuristics to give it a nice name @@ -71,8 +72,11 @@ assert code not in prim_table func.func_name = "prim_" + name if unwrap_spec is None: - def wrapped(interp, s_frame, argument_count_m1): - w_result = func(interp, s_frame, argument_count_m1) + def wrapped(interp, s_frame, argument_count_m1, s_method=None): + if compiled_method: + w_result = func(interp, s_frame, argument_count_m1, s_method) + else: + w_result = func(interp, s_frame, argument_count_m1) if result_is_new_frame: return interp.stack_frame(w_result) if not no_result: @@ -83,7 +87,7 @@ assert (len_unwrap_spec == len(inspect.getargspec(func)[0]) + 1, "wrong number of arguments") unrolling_unwrap_spec = unrolling_iterable(enumerate(unwrap_spec)) - def wrapped(interp, s_frame, argument_count_m1): + def wrapped(interp, s_frame, argument_count_m1, s_method=None): argument_count = argument_count_m1 + 1 # to account for the rcvr assert argument_count == len_unwrap_spec if s_frame.stackdepth() < len_unwrap_spec: @@ -738,6 +742,7 @@ QUIT = 113 EXIT_TO_DEBUGGER = 114 CHANGE_CLASS = 115 # Blue Book: primitiveOopsLeft +EXTERNAL_CALL = 117 @expose_primitive(EQUIVALENT, unwrap_spec=[object, object]) def func(interp, s_frame, w_arg, w_rcvr): @@ -791,6 +796,23 @@ w_rcvr.s_class = w_arg.s_class + at expose_primitive(EXTERNAL_CALL, clean_stack=False, no_result=True, compiled_method=True) +def func(interp, s_frame, argcount, s_method): + space = interp.space + w_description = s_method.w_self().literalat0(space, 1) + if not isinstance(w_description, model.W_PointersObject) or w_description.size() < 2: + raise PrimitiveFailedError + w_modulename = w_description.at0(space, 0) + w_functionname = w_description.at0(space, 1) + if not (isinstance(w_modulename, model.W_BytesObject) and + isinstance(w_functionname, model.W_BytesObject)): + raise PrimitiveFailedError + signature = (w_modulename.as_string(), w_functionname.as_string()) + + if signature == ('BitBltPlugin', 'primitiveCopyBits'): + return prim_holder.prim_table[BITBLT_COPY_BITS](interp, s_frame, argcount, s_method) + raise PrimitiveFailedError + # ___________________________________________________________________________ # Miscellaneous Primitives (120-127) CALLOUT_TO_FFI = 120 From noreply at buildbot.pypy.org Mon Apr 22 17:19:08 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Mon, 22 Apr 2013 17:19:08 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: (tfel, lwassermann): added 16 Bit BitBlt Form Message-ID: <20130422151908.E30641C0014@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r315:04d66459eb57 Date: 2013-04-22 17:16 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/04d66459eb57/ Log: (tfel, lwassermann): added 16 Bit BitBlt Form diff --git a/spyvm/model.py b/spyvm/model.py --- a/spyvm/model.py +++ b/spyvm/model.py @@ -764,6 +764,8 @@ def create(space, w_class, size, depth, display): if depth == 1: return W_DisplayBitmap1Bit(space, w_class, size, depth, display) + elif depth == 16: + return W_DisplayBitmap32Bit(space, w_class, size, depth, display) elif depth == 32: return W_DisplayBitmap32Bit(space, w_class, size, depth, display) else: @@ -825,6 +827,22 @@ mask >>= 1 pos += 1 +class W_DisplayBitmap16Bit(W_DisplayBitmap): + def getword(self, n): + return self._real_depth_buffer[n] + + @jit.unroll_safe + def setword(self, n, word): + self._real_depth_buffer[n] = word + pos = n * NATIVE_DEPTH / 16 + mask = 0xf + for i in range(2): + pixel = 0 + for j in range(4): + pixel |= r_uint(word & mask << (8 * j + 4)) + mask <<= 4 + self.pixelbuffer[pos + i] = pixel + class W_DisplayBitmap32Bit(W_DisplayBitmap): def getword(self, n): return self._real_depth_buffer[n] From noreply at buildbot.pypy.org Mon Apr 22 17:19:10 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Mon, 22 Apr 2013 17:19:10 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: (tfel, lwassermann): refactored force_display_update primitive to use space>>get_display() Message-ID: <20130422151910.0ED041C0014@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r316:2791f4637a77 Date: 2013-04-22 17:16 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/2791f4637a77/ Log: (tfel, lwassermann): refactored force_display_update primitive to use space>>get_display() diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -1336,11 +1336,7 @@ @expose_primitive(FORCE_DISPLAY_UPDATE, unwrap_spec=[object]) def func(interp, s_frame, w_rcvr): - w_prev_display = interp.space.objtable['w_display'] - assert w_prev_display - w_prev_bitmap = w_prev_display.fetch(interp.space, 0) - assert isinstance(w_prev_bitmap, model.W_DisplayBitmap) - w_prev_bitmap.flush_to_screen() + interp.space.get_display().flip() return w_rcvr # ___________________________________________________________________________ From noreply at buildbot.pypy.org Mon Apr 22 17:19:11 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Mon, 22 Apr 2013 17:19:11 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: - renamed __w_method to _w_method to comply with python naming scheme again Message-ID: <20130422151911.201441C0014@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r317:03aba64bfbaa Date: 2013-04-22 17:18 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/03aba64bfbaa/ Log: - renamed __w_method to _w_method to comply with python naming scheme again - enlarged small contexts to 16 and large contexts to 56 maximal stackdepth those are the numbers used by Squeak 4.4 diff --git a/spyvm/shadow.py b/spyvm/shadow.py --- a/spyvm/shadow.py +++ b/spyvm/shadow.py @@ -807,12 +807,12 @@ ) class MethodContextShadow(ContextPartShadow): - _attr_ = ['w_closure_or_nil', '_w_receiver', '__w_method'] + _attr_ = ['w_closure_or_nil', '_w_receiver', '_w_method'] def __init__(self, space, w_self): self.w_closure_or_nil = space.w_nil self._w_receiver = space.w_nil - self.__w_method = None + self._w_method = None ContextPartShadow.__init__(self, space, w_self) @staticmethod @@ -889,13 +889,13 @@ self.w_closure_or_nil).tempsize() def w_method(self): - retval = self.__w_method + retval = self._w_method assert isinstance(retval, model.W_CompiledMethod) return retval def store_w_method(self, w_method): assert isinstance(w_method, model.W_CompiledMethod) - self.__w_method = w_method + self._w_method = w_method def w_receiver(self): return self._w_receiver @@ -986,7 +986,7 @@ def compute_frame_size(self): # From blue book: normal mc have place for 12 temps+maxstack # mc for methods with islarge flag turned on 32 - return 12 + self.islarge * 20 + self.argsize + return 16 + self.islarge * 40 + self.argsize def getliteralsymbol(self, index): w_literal = self.getliteral(index) From noreply at buildbot.pypy.org Mon Apr 22 17:19:12 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Mon, 22 Apr 2013 17:19:12 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: fixed the test problems Message-ID: <20130422151912.572F61C0014@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r318:aa3adce87571 Date: 2013-04-22 17:18 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/aa3adce87571/ Log: fixed the test problems diff --git a/spyvm/test/test_interpreter.py b/spyvm/test/test_interpreter.py --- a/spyvm/test/test_interpreter.py +++ b/spyvm/test/test_interpreter.py @@ -271,13 +271,13 @@ step_in_interp(s_frame) assert s_frame.pop() == w_frame assert s_frame.stack() == [] - + def test_duplicateTopBytecode(): w_frame, s_frame = new_frame(pushConstantZeroBytecode + duplicateTopBytecode) step_in_interp(s_frame) step_in_interp(s_frame) assert s_frame.stack() == [space.w_zero, space.w_zero] - + def test_bytecodePrimBitAnd(): w_frame, s_frame = new_frame(pushConstantOneBytecode + pushConstantTwoBytecode + bytecodePrimBitAnd) step_in_interp(s_frame) @@ -285,7 +285,7 @@ step_in_interp(s_frame) assert s_frame.pop().value == 0 assert s_frame.stack() == [] - + def test_bytecodePrimBitOr(): w_frame, s_frame = new_frame(pushConstantOneBytecode + pushConstantTwoBytecode + bytecodePrimBitOr) step_in_interp(s_frame) @@ -301,14 +301,14 @@ step_in_interp(s_frame) assert s_frame.pop().value == 4 assert s_frame.stack() == [] - + def test_bytecodePrimClass(): w_frame, s_frame = new_frame(pushConstantOneBytecode + bytecodePrimClass) step_in_interp(s_frame) step_in_interp(s_frame) assert s_frame.pop() == space.w_SmallInteger assert s_frame.stack() == [] - + def test_bytecodePrimSubtract(): w_frame, s_frame = new_frame(pushConstantOneBytecode + pushConstantTwoBytecode + bytecodePrimSubtract) step_in_interp(s_frame) @@ -324,15 +324,15 @@ step_in_interp(s_frame) assert s_frame.pop().value == -2 assert s_frame.stack() == [] - + def test_bytecodePrimDivide(): w_frame, s_frame = new_frame(pushConstantTwoBytecode + pushConstantMinusOneBytecode + bytecodePrimDivide) step_in_interp(s_frame) step_in_interp(s_frame) step_in_interp(s_frame) - assert s_frame.pop().value == -2 + assert s_frame.pop().value == -2 assert s_frame.stack() == [] - + def test_bytecodePrimDiv(): w_frame, s_frame = new_frame(pushConstantTwoBytecode + pushConstantMinusOneBytecode + bytecodePrimDiv) step_in_interp(s_frame) @@ -356,14 +356,14 @@ step_in_interp(s_frame) assert s_frame.pop() == space.w_false assert s_frame.stack() == [] - + w_frame, s_frame = new_frame(pushConstantOneBytecode + pushConstantOneBytecode + bytecodePrimEquivalent) step_in_interp(s_frame) step_in_interp(s_frame) step_in_interp(s_frame) assert s_frame.pop() == space.w_true assert s_frame.stack() == [] - + def test_bytecodePrimNew(): w_fakeclassclass = mockclass(space, 10, name='fakeclassclass') w_fakeclass = mockclass(space, 1, name='fakeclass', varsized=False, @@ -378,7 +378,7 @@ assert s_frame.stack() == [] assert w_fakeinst.getclass(space).is_same_object(w_fakeclass) assert w_fakeinst.size() == 1 - + def test_bytecodePrimNewWithArg(): w_fakeclassclass = mockclass(space, 10, name='fakeclassclass') w_fakeclass = mockclass(space, 1, name='fakeclass', varsized=True, @@ -394,7 +394,7 @@ assert s_frame.stack() == [] assert w_fakeinst.getclass(space).is_same_object(w_fakeclass) assert w_fakeinst.size() == 3 - + def test_bytecodePrimSize(): w_fakeclass = mockclass(space, 2, name='fakeclass', varsized=True) w_fakeinst = w_fakeclass.as_class_get_shadow(space).new(5) @@ -412,8 +412,8 @@ # w_object - the actual object we will be sending the method to # bytecodes - the bytecode to be executed def sendBytecodesTest(w_class, w_object, bytecodes): - for bytecode, result in [ (returnReceiver, w_object), - (returnTrue, space.w_true), + for bytecode, result in [ (returnReceiver, w_object), + (returnTrue, space.w_true), (returnFalse, space.w_false), (returnNil, space.w_nil), (returnTopFromMethod, space.w_one) ]: @@ -443,7 +443,7 @@ 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(space, 0).as_class_get_shadow(space) @@ -475,7 +475,7 @@ assert len(s_frame.stack()) == 1 w_result = s_frame.pop() assert space.unwrap_int(w_result) == 42 - + run_with_faked_primitive_methods( [[space.w_SmallInteger, primitives.SUBTRACT, 1, "-"]], @@ -576,7 +576,7 @@ def test_extendedStoreAndPopBytecode(): test_storeAndPopReceiverVariableBytecode(lambda index: extendedStoreAndPopBytecode + chr((0<<6) + index)) - + test_storeAndPopTemporaryVariableBytecode(lambda index: extendedStoreAndPopBytecode + chr((1<<6) + index)) py.test.raises(interpreter.IllegalStoreError, @@ -669,7 +669,7 @@ def test_secondExtendedSendBytecode(): w_class = mockclass(space, 0) w_object = w_class.as_class_get_shadow(space).new() - sendBytecodesTest(w_class, w_object, secondExtendedSendBytecode + chr(0)) + sendBytecodesTest(w_class, w_object, secondExtendedSendBytecode + chr(0)) def test_doubleExtendedDoAnythinBytecode(): w_class = mockclass(space, 0) @@ -706,7 +706,7 @@ # value0 # " (self >> #value0) byteCode " # " (self >> #value0) literals " - # + # # ^ [ 3 + 4 ] value assert interpret_bc( [ 137, 117, 200, 164, 4, 32, 33, 176, 125, 201, 124], @@ -717,7 +717,7 @@ # value1 # " (self >> #value1) byteCode " # " (self >> #value1) literals " - # + # # ^ [ :x | x + x + 1 ] value: 3 assert interpret_bc( [ 137, 118, 200, 164, 7, 104, 16, 16, @@ -728,7 +728,7 @@ # value2 # " (self >> #value2) byteCode " # " (self >> #value2) literals " - # + # # ^ [ :x :y | x + y ] value: 3 value: 4 def test(): @@ -745,7 +745,7 @@ # value1 # " (self >> #value1) byteCode " # " (self >> #value1) literals " - # + # # ^ [ self ] value assert interpret_bc( [ 137, 117, 200, 164, 2, 112, 125, 201, 124 ], @@ -755,7 +755,7 @@ # valueReturn # " (self >> #value1) byteCode " # " (self >> #value1) literals " - # + # # [ ^ 1 ] value. ^ 2 assert interpret_bc( [ 137, 117, 200, 164, 2, 118, 124, 201, 135, 119, 124 ], @@ -765,7 +765,7 @@ # valueWithArgs # " (self >> #value1) byteCode " # " (self >> #value1) literals " - # + # # [ :a :b | a - b ] valueWithArguments: #(3 2) def test(): val = interpret_bc( @@ -789,7 +789,7 @@ run_with_faked_primitive_methods( [[space.w_String, primitives.STRING_AT, 1, "at:"]], test) - + def test_bc_primBytecodeAtPut_string(): # ^ 'a' at: 1 put:'b' def test(): @@ -922,7 +922,7 @@ step_in_interp(s_frame) assert s_frame.pc() == pc + 4 + i closure = wrapper.BlockClosureWrapper(space, s_frame.top()) - assert closure.startpc() == pc + 4 + assert closure.startpc() == pc + 4 + 4 + 1 # pc + offset + headerword + smalltalk 1-indexing assert closure.outerContext() is s_frame._w_self def test_bc_pushClosureCopyCopied2ValuesBytecode(bytecode = pushClosureCopyCopiedValuesBytecode): @@ -933,7 +933,7 @@ step_in_interp(s_frame) assert s_frame.pc() == pc + 4 closure = wrapper.BlockClosureWrapper(space, s_frame.top()) - assert closure.startpc() == pc + 4 + assert closure.startpc() == pc + 4 + 5 assert closure.outerContext() is s_frame._w_self assert closure.at0(0) == "english" assert closure.at0(1) == "bar" @@ -956,7 +956,7 @@ # ^ 1 def test(): assert interpret_bc( - [ 0x8f, 2, 0, 4, 16, 17, 0xb0, 0x7c, + [ 0x8f, 2, 0, 4, 16, 17, 0xb0, 0x7c, 0x76, 0x77, 0xf0, 0x87, 0x76, 0x7c ], fakeliterals(space, "value:value:", )).value == 3 run_with_faked_primitive_methods( @@ -966,7 +966,7 @@ def test_stacking_interpreter(): # | testBlock | - # testBlock := [ :aNumber | + # testBlock := [ :aNumber | # aNumber = 0 # ifTrue: [ 0 ] # ifFalse: [ (testBlock value: aNumber - 1) + aNumber ]]. @@ -974,9 +974,9 @@ import operator interp = interpreter.Interpreter(space, max_stack_depth=3) #create a method with the correct bytecodes and a literal - bytes = reduce(operator.add, map(chr, [0x8a, 0x01, 0x68, 0x10, 0x8f, 0x11, - 0x00, 0x11, 0x10, 0x75, 0xb6, 0x9a, 0x75, 0xa4, 0x09, 0x8c, 0x00, 0x01, - 0x10, 0x76, 0xb1, 0xca, 0x10, 0xb0, 0x7d, 0x8e, 0x00, 0x00, 0x8c, 0x00, + bytes = reduce(operator.add, map(chr, [0x8a, 0x01, 0x68, 0x10, 0x8f, 0x11, + 0x00, 0x11, 0x10, 0x75, 0xb6, 0x9a, 0x75, 0xa4, 0x09, 0x8c, 0x00, 0x01, + 0x10, 0x76, 0xb1, 0xca, 0x10, 0xb0, 0x7d, 0x8e, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x20, 0xca, 0x7c])) w_method = model.W_CompiledMethod(len(bytes)) w_method.islarge = 1 @@ -1040,4 +1040,4 @@ except interpreter.ReturnFromTopLevel, e: assert space.unwrap_int(e.object) == 68 except interpreter.StackOverflow, e: - assert False \ No newline at end of file + assert False diff --git a/spyvm/test/test_model.py b/spyvm/test/test_model.py --- a/spyvm/test/test_model.py +++ b/spyvm/test/test_model.py @@ -17,7 +17,7 @@ for each, length in reversed(zip(values, lengths)): result = result << length result += each - return result + return result def test_new(): @@ -56,7 +56,7 @@ assert w_bytes.size() == 20 assert w_class.as_class_get_shadow(space).instsize() == 0 assert w_bytes.getword(3) == 0 - w_bytes.setword(3, 42) + w_bytes.setword(3, 42) assert w_bytes.getword(3) == 42 assert w_bytes.getword(0) == 0 py.test.raises(IndexError, lambda: w_bytes.getword(20)) @@ -153,7 +153,7 @@ w_o2 = w_o1 assert w_o1.is_same_object(w_o2) assert w_o2.is_same_object(w_o1) - + def test_not_is_same_object(w_o1=model.W_PointersObject(space, None,0),w_o2=model.W_PointersObject(space, None,0)): assert not w_o1.is_same_object(w_o2) assert not w_o2.is_same_object(w_o1) @@ -190,13 +190,13 @@ w_clsb = mockclass(space, 4) w_b = w_clsb.as_class_get_shadow(space).new() - + hasha = w_a.gethash() hashb = w_b.gethash() w_a.store(space, 0, w_b) w_b.store(space, 1, w_a) - + res = w_a.become(w_b) assert res assert w_a.gethash() == hashb @@ -288,7 +288,7 @@ assert target.at0(space, i) == source.at0(space, i) assert hex(r_uint(target.value)) == hex(r_uint(source.value)) - at pytest.mark.skipif("socket.gethostname() == 'precise32'") + at py.test.mark.skipif("socket.gethostname() == 'precise32'") def test_display_bitmap(): # XXX: Patch SDLDisplay -> get_pixelbuffer() to circumvent # double-free bug diff --git a/spyvm/test/test_primitives.py b/spyvm/test/test_primitives.py --- a/spyvm/test/test_primitives.py +++ b/spyvm/test/test_primitives.py @@ -20,7 +20,7 @@ s_self.push_all(stack) s_self.store_expected_argument_count(0) self.s_class = space.w_MethodContext.as_class_get_shadow(space) - + def as_blockcontext_get_shadow(self): self._shadow = shadow.BlockContextShadow(space, self) return self._shadow @@ -60,7 +60,7 @@ with py.test.raises(PrimitiveFailedError): prim_table[code](interp, w_frame.as_context_get_shadow(space), argument_count - 1) assert w_frame.as_context_get_shadow(space).stack() == orig_stack - + # smallinteger tests def test_small_int_add(): assert prim(primitives.ADD, [1,2]).value == 3 @@ -79,7 +79,7 @@ prim_fails(primitives.SUBTRACT, [constants.TAGGED_MININT,1]) prim_fails(primitives.SUBTRACT, [constants.TAGGED_MININT, constants.TAGGED_MAXINT]) - + def test_small_int_multiply(): assert prim(primitives.MULTIPLY, [6,3]).value == 18 @@ -91,40 +91,40 @@ prim_fails(primitives.MULTIPLY, [constants.TAGGED_MAXINT, -4]) prim_fails(primitives.MULTIPLY, [constants.TAGGED_MININT, constants.TAGGED_MAXINT]) prim_fails(primitives.MULTIPLY, [constants.TAGGED_MININT, 2]) - + def test_small_int_divide(): assert prim(primitives.DIVIDE, [6,3]).value == 2 - + def test_small_int_divide_fail(): prim_fails(primitives.DIVIDE, [12, 0]) prim_fails(primitives.DIVIDE, [12, 7]) - + def test_small_int_mod(): assert prim(primitives.MOD, [12,7]).value == 5 def test_small_int_mod_fail(): prim_fails(primitives.MOD, [12, 0]) - + def test_small_int_div(): assert prim(primitives.DIV, [12,3]).value == 4 assert prim(primitives.DIV, [12,7]).value == 1 def test_small_int_div_fail(): prim_fails(primitives.DIV, [12, 0]) - + def test_small_int_quo(): assert prim(primitives.QUO, [12,3]).value == 4 assert prim(primitives.QUO, [12,7]).value == 1 def test_small_int_quo_fail(): prim_fails(primitives.QUO, [12, 0]) - + def test_small_int_bit_and(): assert prim(primitives.BIT_AND, [2, 4]).value == 0 assert prim(primitives.BIT_AND, [2, 3]).value == 2 assert prim(primitives.BIT_AND, [3, 4]).value == 0 assert prim(primitives.BIT_AND, [4, 4]).value == 4 - + def test_small_int_bit_or(): assert prim(primitives.BIT_OR, [2, 4]).value == 6 assert prim(primitives.BIT_OR, [2, 3]).value == 3 @@ -145,7 +145,7 @@ assert prim(primitives.BIT_SHIFT, [0, 1]).value == 0 assert prim(primitives.BIT_SHIFT, [0, 2]).value == 0 assert prim(primitives.BIT_SHIFT, [0, 3]).value == 0 - + def test_small_int_bit_shift_positive(): assert prim(primitives.BIT_SHIFT, [4, -3]).value == 0 assert prim(primitives.BIT_SHIFT, [4, -2]).value == 1 @@ -155,7 +155,7 @@ assert prim(primitives.BIT_SHIFT, [4, 2]).value == 16 assert prim(primitives.BIT_SHIFT, [4, 3]).value == 32 assert prim(primitives.BIT_SHIFT, [4, 27]).value == 536870912 - + def test_small_int_bit_shift_negative(): assert prim(primitives.BIT_SHIFT, [-4, -3]).value == -1 assert prim(primitives.BIT_SHIFT, [-4, -2]).value == -1 @@ -165,7 +165,7 @@ assert prim(primitives.BIT_SHIFT, [-4, 2]).value == -16 assert prim(primitives.BIT_SHIFT, [-4, 3]).value == -32 assert prim(primitives.BIT_SHIFT, [-4, 27]).value == -536870912 - + def test_small_int_bit_shift_fail(): from rpython.rlib.rarithmetic import intmask prim_fails(primitives.BIT_SHIFT, [4, 32]) @@ -224,7 +224,7 @@ 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 - + def test_at_and_at_put_bytes(): w_str = wrap("abc") prim_fails(primitives.AT_PUT, [w_str, 1, "d"]) @@ -236,7 +236,7 @@ def test_invalid_at_put(): 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(space, 0, varsized=True).as_class_get_shadow(space).new(0) assert prim(primitives.SIZE, [w_obj]).value == 0 @@ -262,11 +262,11 @@ def test_invalid_object_at(): prim_fails(primitives.OBJECT_AT, ["q", constants.CHARACTER_VALUE_INDEX+2]) - + def test_invalid_object_at_put(): 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(): test_str = wrap("foobar") assert prim(primitives.STRING_AT_PUT, [test_str, 4, "c"]) == wrap("c") @@ -278,19 +278,19 @@ w_Object = space.classtable['w_Object'] w_res = prim(primitives.NEW, [w_Object]) assert w_res.getclass(space).is_same_object(w_Object) - + def test_invalid_new(): prim_fails(primitives.NEW, [space.w_String]) def test_new_with_arg(): 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 + assert w_res.size() == 20 def test_invalid_new_with_arg(): w_Object = space.classtable['w_Object'] prim_fails(primitives.NEW_WITH_ARG, [w_Object, 20]) - + def test_inst_var_at(): # n.b.: 1-based indexing! w_v = prim(primitives.INST_VAR_AT, @@ -314,7 +314,7 @@ # n.b.: 1-based indexing! (and an invalid index) prim_fails(primitives.INST_VAR_AT_PUT, ["q", constants.CHARACTER_VALUE_INDEX+2, "t"]) - + def test_class(): assert prim(primitives.CLASS, ["string"]).is_same_object(space.w_String) assert prim(primitives.CLASS, [1]).is_same_object(space.w_SmallInteger) @@ -357,7 +357,7 @@ 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 return @@ -406,7 +406,7 @@ assert equals_ttp(-1,2,-4) assert equals_ttp(1.5,0,1.5) assert equals_ttp(1.5,-1,0.75) - + def test_primitive_milliseconds_clock(): import time start = prim(primitives.MILLISECOND_CLOCK, [0]).value @@ -472,7 +472,7 @@ def test_image_name(): w_v = prim(primitives.IMAGE_NAME, [2]) assert w_v.bytes == list(IMAGENAME) - + def test_clone(): w_obj = mockclass(space, 1, varsized=True).as_class_get_shadow(space).new(1) w_obj.atput0(space, 0, space.wrap_int(1)) @@ -480,7 +480,7 @@ assert space.unwrap_int(w_v.at0(space, 0)) == 1 w_obj.atput0(space, 0, space.wrap_int(2)) assert space.unwrap_int(w_v.at0(space, 0)) == 1 - + def test_file_open_write(monkeypatch): def open_write(filename, mode, perm): assert filename == "nonexistant" @@ -548,11 +548,13 @@ from test_interpreter import new_frame w_frame, s_frame = new_frame("", space=space) - w_block = prim(primitives.CLOSURE_COPY_WITH_COPIED_VALUES, map(wrap, - ["anActiveContext", 2, [wrap(1), wrap(2)]]), w_frame) + w_outer_frame, s_initial_context = new_frame("", + space=space) + w_block = prim(primitives.CLOSURE_COPY_WITH_COPIED_VALUES, map(wrap, + [w_outer_frame, 2, [wrap(1), wrap(2)]]), w_frame) assert w_block is not space.w_nil w_w_block = wrapper.BlockClosureWrapper(space, w_block) - assert w_w_block.startpc() is 0 + assert w_w_block.startpc() is 5 assert w_w_block.at0(0) == wrap(1) assert w_w_block.at0(1) == wrap(2) assert w_w_block.numArgs() is 2 @@ -575,9 +577,9 @@ from test_interpreter import new_frame w_frame, s_initial_context = new_frame("", space=space) - + size_arguments = len(args) - closure = space.newClosure(w_frame, 4, #pc + closure = space.newClosure(w_frame, 4, #pc size_arguments, copiedValues) s_initial_context.push_all([closure] + args) interp = interpreter.Interpreter(space) @@ -695,11 +697,11 @@ class DisplayFlush(Exception): pass - def flush_to_screen_mock(): + def flush_to_screen_mock(self): raise DisplayFlush try: - monkeypatch.setattr(mock_display.fetch(space, 0), "flush_to_screen", flush_to_screen_mock) + monkeypatch.setattr(space.get_display().__class__, "flip", flush_to_screen_mock) with py.test.raises(DisplayFlush): prim(primitives.FORCE_DISPLAY_UPDATE, [mock_display]) finally: diff --git a/spyvm/test/test_shadow.py b/spyvm/test/test_shadow.py --- a/spyvm/test/test_shadow.py +++ b/spyvm/test/test_shadow.py @@ -83,7 +83,7 @@ w_m.literalsize = 2 return w_m -def methodcontext(w_sender=space.w_nil, pc=1, stackpointer=0, stacksize=5, +def methodcontext(w_sender=space.w_nil, pc=13, stackpointer=0, stacksize=5, method=method()): w_object = model.W_PointersObject(space, space.w_MethodContext, constants.MTHDCTX_TEMP_FRAME_START+method.tempsize+stacksize) w_object.store(space, constants.CTXPART_SENDER_INDEX, w_sender) @@ -97,7 +97,7 @@ w_object.store(space, constants.MTHDCTX_TEMP_FRAME_START, space.wrap_string('el')) return w_object -def blockcontext(w_sender=space.w_nil, pc=1, stackpointer=1, stacksize=5, +def blockcontext(w_sender=space.w_nil, pc=13, stackpointer=1, stacksize=5, home=methodcontext()): w_object = model.W_PointersObject(space, space.w_MethodContext, constants.MTHDCTX_TEMP_FRAME_START+stacksize) w_object.store(space, constants.CTXPART_SENDER_INDEX, w_sender) From noreply at buildbot.pypy.org Mon Apr 22 17:30:36 2013 From: noreply at buildbot.pypy.org (arigo) Date: Mon, 22 Apr 2013 17:30:36 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Transplant from "default" the fixes done to dotviewer. Message-ID: <20130422153036.9D1571C0014@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63548:31de31576e68 Date: 2013-04-22 17:19 +0200 http://bitbucket.org/pypy/pypy/changeset/31de31576e68/ Log: Transplant from "default" the fixes done to dotviewer. diff --git a/dotviewer/drawgraph.py b/dotviewer/drawgraph.py --- a/dotviewer/drawgraph.py +++ b/dotviewer/drawgraph.py @@ -7,9 +7,9 @@ import re, os, math import pygame from pygame.locals import * +from strunicode import forceunicode -RAW_ENCODING = "utf-8" this_dir = os.path.dirname(os.path.abspath(__file__)) FONT = os.path.join(this_dir, 'font', 'DroidSans.ttf') FIXEDFONT = os.path.join(this_dir, 'font', 'DroidSansMono.ttf') @@ -52,12 +52,6 @@ else: return default -def forceunicode(name): - return name if isinstance(name, unicode) else name.decode(RAW_ENCODING) - -def forcestr(name): - return name if isinstance(name, str) else name.encode(RAW_ENCODING) - class GraphLayout: fixedfont = False diff --git a/dotviewer/graphclient.py b/dotviewer/graphclient.py --- a/dotviewer/graphclient.py +++ b/dotviewer/graphclient.py @@ -1,6 +1,7 @@ import os, sys, re import subprocess import msgstruct +from strunicode import forcestr this_dir = os.path.dirname(os.path.abspath(__file__)) GRAPHSERVER = os.path.join(this_dir, 'graphserver.py') @@ -33,7 +34,6 @@ def reload(graph_id): page = getpage(graph_id) if save_tmp_file: - from drawgraph import forcestr f = open(save_tmp_file, 'w') f.write(forcestr(page.source)) f.close() @@ -76,7 +76,6 @@ def page_messages(page, graph_id): import graphparse - from drawgraph import forcestr return graphparse.parse_dot(graph_id, forcestr(page.source), page.links, getattr(page, 'fixedfont', False)) @@ -129,7 +128,14 @@ def spawn_local_handler(): if hasattr(sys, 'pypy_objspaceclass'): - python = '/usr/bin/python' + # if 'python' is actually PyPy, e.g. in a virtualenv, then + # try hard to find a real CPython + try: + python = subprocess.check_output( + 'env -i $SHELL -l -c "which python"', shell=True).strip() + except subprocess.CalledProcessError: + # did not work, fall back to 'python' + python = 'python' else: python = sys.executable args = [python, '-u', GRAPHSERVER, '--stdio'] diff --git a/dotviewer/graphdisplay.py b/dotviewer/graphdisplay.py --- a/dotviewer/graphdisplay.py +++ b/dotviewer/graphdisplay.py @@ -4,7 +4,8 @@ from pygame.locals import * from drawgraph import GraphRenderer, FIXEDFONT from drawgraph import Node, Edge -from drawgraph import EventQueue, wait_for_events, forceunicode, forcestr +from drawgraph import EventQueue, wait_for_events +from strunicode import forceunicode, forcestr METAKEYS = dict([ diff --git a/dotviewer/graphpage.py b/dotviewer/graphpage.py --- a/dotviewer/graphpage.py +++ b/dotviewer/graphpage.py @@ -45,7 +45,7 @@ class DotFileGraphPage(GraphPage): def compute(self, dotfile): import codecs - from drawgraph import RAW_ENCODING + from strunicode import RAW_ENCODING f = codecs.open(dotfile, 'r', RAW_ENCODING) self.source = f.read() f.close() diff --git a/dotviewer/msgstruct.py b/dotviewer/msgstruct.py --- a/dotviewer/msgstruct.py +++ b/dotviewer/msgstruct.py @@ -1,5 +1,6 @@ import sys, os from struct import pack, unpack, calcsize +from strunicode import tryencode MAGIC = -0x3b83728b @@ -27,6 +28,7 @@ def message(tp, *values): #print >> sys.stderr, tp, values typecodes = [''] + values = map(tryencode, values) for v in values: if type(v) is str: typecodes.append('%ds' % len(v)) diff --git a/dotviewer/test/test_interactive_unicode.py b/dotviewer/test/test_interactive_unicode.py --- a/dotviewer/test/test_interactive_unicode.py +++ b/dotviewer/test/test_interactive_unicode.py @@ -4,7 +4,7 @@ import py import sys, os, signal, thread, time, codecs from dotviewer.conftest import option -from dotviewer.drawgraph import RAW_ENCODING +from dotviewer.strunicode import RAW_ENCODING SOURCE1 = u"""digraph G{ λ -> b diff --git a/dotviewer/test/test_unicode_util.py b/dotviewer/test/test_unicode_util.py --- a/dotviewer/test/test_unicode_util.py +++ b/dotviewer/test/test_unicode_util.py @@ -3,7 +3,7 @@ # import py import codecs -from dotviewer.drawgraph import RAW_ENCODING, forcestr, forceunicode +from dotviewer.strunicode import RAW_ENCODING, forcestr, forceunicode, tryencode SOURCE1 = u"""digraph G{ λ -> b @@ -18,7 +18,7 @@ def test_idempotent(self): x = u"a" assert forceunicode(forcestr(x)) == x - + x = u"λ" assert forceunicode(forcestr(x)) == x @@ -40,7 +40,7 @@ x_u = forceunicode(x_e) assert forceunicode(x_u) == x_u - def test_file(self): + def test_file(self): udir = py.path.local.make_numbered_dir(prefix='usession-dot-', keep=3) full_filename = str(udir.join(FILENAME)) f = codecs.open(full_filename, 'wb', RAW_ENCODING) @@ -55,3 +55,19 @@ f3.close() result = (c == SOURCE1) assert result + + def test_only_unicode_encode(self): + sut = [1, u"a", "miau", u"λ"] + expected = [int, str, str, str ] + + results = map(tryencode, sut) + for result, expected_type in zip(results, expected): + assert isinstance(result, expected_type) + + def test_forceunicode_should_not_fail(self): + garbage = "\xef\xff\xbb\xbf\xce\xbb\xff\xff" # garbage with a lambda + result = forceunicode(garbage) # should not raise + + def test_forcestr_should_not_fail(self): + garbage = u"\xef\xff\xbb\xbf\xce\xbb\xff\xff" # garbage + result = forcestr(garbage) # should not raise From noreply at buildbot.pypy.org Mon Apr 22 17:30:38 2013 From: noreply at buildbot.pypy.org (arigo) Date: Mon, 22 Apr 2013 17:30:38 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Added missing file Message-ID: <20130422153038.0FCC61C0014@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63549:fda200fcdd55 Date: 2013-04-22 17:20 +0200 http://bitbucket.org/pypy/pypy/changeset/fda200fcdd55/ Log: Added missing file diff --git a/dotviewer/strunicode.py b/dotviewer/strunicode.py new file mode 100644 --- /dev/null +++ b/dotviewer/strunicode.py @@ -0,0 +1,17 @@ +RAW_ENCODING = "utf-8" +ENCODING_ERROR_HANDLING = "replace" + + +def forceunicode(name): + """ returns `name` as unicode, even if it wasn't before """ + return name if isinstance(name, unicode) else name.decode(RAW_ENCODING, ENCODING_ERROR_HANDLING) + + +def forcestr(name): + """ returns `name` as string, even if it wasn't before """ + return name if isinstance(name, str) else name.encode(RAW_ENCODING, ENCODING_ERROR_HANDLING) + + +def tryencode(name): + """ returns `name` as encoded string if it was unicode before """ + return name.encode(RAW_ENCODING, ENCODING_ERROR_HANDLING) if isinstance(name, unicode) else name From noreply at buildbot.pypy.org Mon Apr 22 17:30:39 2013 From: noreply at buildbot.pypy.org (arigo) Date: Mon, 22 Apr 2013 17:30:39 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Fix old-style classes for the new model of __del__ Message-ID: <20130422153039.3BB751C0014@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63550:ea7053cee8b3 Date: 2013-04-22 17:32 +0200 http://bitbucket.org/pypy/pypy/changeset/ea7053cee8b3/ Log: Fix old-style classes for the new model of __del__ diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py --- a/pypy/interpreter/baseobjspace.py +++ b/pypy/interpreter/baseobjspace.py @@ -26,7 +26,7 @@ class W_Root(object): """This is the abstract root class of all wrapped objects that live in a 'normal' object space like StdObjSpace.""" - __slots__ = () + _attrs_ = () _settled_ = True user_overridden_class = False @@ -220,7 +220,7 @@ class Wrappable(W_Root): """A subclass of Wrappable is an internal, interpreter-level class that can nevertheless be exposed at application-level by space.wrap().""" - __slots__ = () + _attrs_ = () _settled_ = True def __spacebind__(self, space): diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py --- a/pypy/interpreter/typedef.py +++ b/pypy/interpreter/typedef.py @@ -638,9 +638,6 @@ def make_weakref_descr(cls): """Make instances of the Wrappable subclass 'cls' weakrefable. This returns the '__weakref__' desctriptor to use for the TypeDef. - Note that if the class also defines a custom '__del__', the - __del__ should call self.clear_all_weakrefs() before it clears - the resources used by the object. """ # force the interface into the given cls def getweakref(self): diff --git a/pypy/module/__builtin__/interp_classobj.py b/pypy/module/__builtin__/interp_classobj.py --- a/pypy/module/__builtin__/interp_classobj.py +++ b/pypy/module/__builtin__/interp_classobj.py @@ -6,7 +6,7 @@ from pypy.interpreter.typedef import GetSetProperty, descr_get_dict, descr_set_dict from rpython.rlib.objectmodel import compute_identity_hash from rpython.rlib.debug import make_sure_not_resized -from rpython.rlib import jit +from rpython.rlib import rgc, jit def raise_type_err(space, argument, expected, w_obj): @@ -57,10 +57,7 @@ def instantiate(self, space): cache = space.fromcache(Cache) - if self.lookup(space, '__del__') is not None: - w_inst = cache.cls_with_del(space, self) - else: - w_inst = cache.cls_without_del(space, self) + w_inst = cache.class_of_instance(space, self) return w_inst def getdict(self, space): @@ -152,11 +149,6 @@ elif name == "__bases__": self.setbases(space, w_value) return - elif name == "__del__": - if self.lookup(space, name) is None: - msg = ("a __del__ method added to an existing class will " - "not be called") - space.warn(space.wrap(msg), space.w_RuntimeWarning) space.setitem(self.w_dict, w_attr, w_value) def descr_delattr(self, space, w_attr): @@ -204,11 +196,10 @@ class Cache: def __init__(self, space): from pypy.interpreter.typedef import _usersubclswithfeature - # evil - self.cls_without_del = _usersubclswithfeature( + # evil: "class_of_instance" is a subclass of W_InstanceObject + # which has additionally the "dict" and "weakref" capabilities + self.class_of_instance = _usersubclswithfeature( space.config, W_InstanceObject, "dict", "weakref") - self.cls_with_del = _usersubclswithfeature( - space.config, self.cls_without_del, "del") def class_descr_call(space, w_self, __args__): @@ -321,6 +312,8 @@ self.user_setup(space, space.gettypeobject(self.typedef)) assert isinstance(w_class, W_ClassObject) self.w_class = w_class + if self.getattr_from_class(space, '__del__') is not None: + rgc.register_finalizer(self.finalizer) def user_setup(self, space, w_subtype): self.space = space @@ -391,13 +384,8 @@ if name == '__class__': self.set_oldstyle_class(space, w_value) return - if name == '__del__' and w_meth is None: - cache = space.fromcache(Cache) - if (not isinstance(self, cache.cls_with_del) - and self.getdictvalue(space, '__del__') is None): - msg = ("a __del__ method added to an instance with no " - "__del__ in the class will not be called") - space.warn(space.wrap(msg), space.w_RuntimeWarning) + if name == '__del__': + rgc.register_finalizer(self.finalizer) if w_meth is not None: space.call_function(w_meth, w_name, w_value) else: @@ -700,9 +688,8 @@ space.wrap("instance has no next() method")) return space.call_function(w_func) - def descr_del(self, space): - # Note that this is called from executioncontext.UserDelAction - # via the space.userdel() method. + def finalizer(self): + space = self.space w_func = self.getdictvalue(space, '__del__') if w_func is None: w_func = self.getattr_from_class(space, '__del__') @@ -783,7 +770,6 @@ __pow__ = interp2app(W_InstanceObject.descr_pow), __rpow__ = interp2app(W_InstanceObject.descr_rpow), next = interp2app(W_InstanceObject.descr_next), - __del__ = interp2app(W_InstanceObject.descr_del), __exit__ = interp2app(W_InstanceObject.descr_exit), __dict__ = dict_descr, **rawdict diff --git a/pypy/module/__builtin__/test/test_classobj.py b/pypy/module/__builtin__/test/test_classobj.py --- a/pypy/module/__builtin__/test/test_classobj.py +++ b/pypy/module/__builtin__/test/test_classobj.py @@ -670,6 +670,22 @@ gc.collect() gc.collect() assert l == [1, 1] + class C: + pass + c = C() + c.__del__ = lambda: l.append(2) + c = None + gc.collect() + gc.collect() + gc.collect() + assert l == [1, 1, 2] + d = A() + d.__del__ = lambda: l.append(3) + d = None + gc.collect() + gc.collect() + gc.collect() + assert l == [1, 1, 2, 3] def test_catch_attributeerror_of_descriptor(self): def booh(self): @@ -745,21 +761,16 @@ assert Y() != X() def test_assignment_to_del(self): - import sys - if not hasattr(sys, 'pypy_objspaceclass'): - skip("assignment to __del__ doesn't give a warning in CPython") - + # assignment to __del__ no longer gives a warning import warnings - warnings.simplefilter('error', RuntimeWarning) try: class X: pass - raises(RuntimeWarning, "X.__del__ = lambda self: None") + X.__del__ = lambda self: None class Y: pass - raises(RuntimeWarning, "Y().__del__ = lambda self: None") - # but the following works + Y().__del__ = lambda self: None class Z: def __del__(self): pass diff --git a/pypy/module/_cffi_backend/cdataobj.py b/pypy/module/_cffi_backend/cdataobj.py --- a/pypy/module/_cffi_backend/cdataobj.py +++ b/pypy/module/_cffi_backend/cdataobj.py @@ -318,7 +318,6 @@ cdata = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw', zero=True) W_CData.__init__(self, space, cdata, ctype) - @rgc.must_be_light_finalizer def __del__(self): lltype.free(self._cdata, flavor='raw') diff --git a/pypy/module/_cffi_backend/libraryobj.py b/pypy/module/_cffi_backend/libraryobj.py --- a/pypy/module/_cffi_backend/libraryobj.py +++ b/pypy/module/_cffi_backend/libraryobj.py @@ -7,6 +7,7 @@ from rpython.rtyper.lltypesystem import rffi from rpython.rlib.rdynload import DLLHANDLE, dlopen, dlsym, dlclose, DLOpenError +from rpython.rlib import rgc from pypy.module._cffi_backend.cdataobj import W_CData from pypy.module._cffi_backend.ctypeobj import W_CType @@ -28,8 +29,9 @@ "cannot load library %s: %s", filename, e.msg) self.name = filename + rgc.register_finalizer(self.finalizer) - def __del__(self): + def finalizer(self): h = self.handle if h != rffi.cast(DLLHANDLE, 0): self.handle = rffi.cast(DLLHANDLE, 0) diff --git a/pypy/module/_file/interp_file.py b/pypy/module/_file/interp_file.py --- a/pypy/module/_file/interp_file.py +++ b/pypy/module/_file/interp_file.py @@ -2,7 +2,7 @@ import os import stat import errno -from rpython.rlib import streamio +from rpython.rlib import streamio, rgc from rpython.rlib.rarithmetic import r_longlong from rpython.rlib.rstring import StringBuilder from pypy.module._file.interp_stream import W_AbstractStream, StreamErrors @@ -38,7 +38,7 @@ def __init__(self, space): self.space = space - self.register_finalizer() + rgc.register_finalizer(self.finalizer) def finalizer(self): try: From noreply at buildbot.pypy.org Mon Apr 22 17:41:38 2013 From: noreply at buildbot.pypy.org (arigo) Date: Mon, 22 Apr 2013 17:41:38 +0200 (CEST) Subject: [pypy-commit] pypy stm-gc-2: intermediate check-in Message-ID: <20130422154138.E0E0C1C022B@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: stm-gc-2 Changeset: r63551:022708a2e72c Date: 2013-04-22 17:40 +0200 http://bitbucket.org/pypy/pypy/changeset/022708a2e72c/ Log: intermediate check-in diff --git a/rpython/memory/gc/stmshared.py b/rpython/memory/gc/stmshared.py --- a/rpython/memory/gc/stmshared.py +++ b/rpython/memory/gc/stmshared.py @@ -115,7 +115,15 @@ self.objects_to_trace = self.AddressStack() # # The stacks... - self.collect_stack_roots_from_every_thread() + self.collect_roots_from_stacks() + # + # The raw structures... + self.collect_from_raw_structures() + # + # The tldicts... + self.collect_roots_from_tldicts() + # + self.visit_all_objects() # self.num_major_collects += 1 debug_print("| used after collection: ", @@ -125,16 +133,62 @@ debug_print("`----------------------------------------------") debug_stop("gc-collect") - def collect_stack_roots_from_every_thread(self): - self.gc.root_walker.walk_all_stack_roots(self._collect_stack_root, - None) + def collect_roots_from_stacks(self): + self.gc.root_walker.walk_all_stack_roots(StmGCSharedArea._collect_stack_root, + self) - def _collect_stack_root(self, ignored, root): - self.visit(root.address[0]) + def collect_from_raw_structures(self): + self.gc.root_walker.walk_current_nongc_roots( + StmGCSharedArea._collect_stack_root, self) + + def _collect_stack_root(self, root): + self.objects_to_trace.append(root.address[0]) + + def collect_roots_from_tldicts(self): + CALLBACK = self.gc.stm_operations.CALLBACK_ENUM + llop.nop(lltype.Void, llhelper(CALLBACK, + StmGCSharedArea._stm_enum_external_callback)) + # The previous line causes the _stm_enum_external_callback() function to be + # generated in the C source with a specific signature, where it + # can be called by the C code. + stmtls = self.gc.linked_list_stmtls + while stmtls is not None: + self.visit_all_objects() # empty the list first + # for every stmtls: + self.gc.stm_operations.tldict_enum_external(stmtls.thread_descriptor) + stmtls = stmtls.linked_list_next + + @staticmethod + def _stm_enum_external_callback(globalobj, localobj): + localhdr = self.gc.header(localobj) + ll_assert(localhdr.tid & GCFLAG_VISITED != 0, + "[shared] in a root: missing GCFLAG_VISITED") + localhdr.tid &= ~GCFLAG_VISITED + self.objects_to_trace.append(localobj) + self.objects_to_trace.append(globalobj) + + def visit_all_objects(self): + pending = self.objects_to_trace + while pending.non_empty(): + obj = pending.pop() + self.visit(obj) def visit(self, obj): + # 'obj' is a live object. Check GCFLAG_VISITED to know if we + # have already seen it before. hdr = self.gc.header(obj) - XXX + if hdr.tid & GCFLAG_VISITED: + return + # + # It's the first time. We set the flag. + hdr.tid |= GCFLAG_VISITED + # + # Trace the content of the object and put all objects it references + # into the 'objects_to_trace' list. + self.gc.trace(obj, self._collect_ref_rec, None) + + def _collect_ref_rec(self, root, ignored): + self.objects_to_trace.append(root.address[0]) # ------------------------------------------------------------ diff --git a/rpython/memory/gc/stmtls.py b/rpython/memory/gc/stmtls.py --- a/rpython/memory/gc/stmtls.py +++ b/rpython/memory/gc/stmtls.py @@ -103,7 +103,7 @@ n = 10000 + len(StmGCTLS.nontranslated_dict) tlsaddr = rffi.cast(llmemory.Address, n) StmGCTLS.nontranslated_dict[n] = self - self.stm_operations.set_tls(tlsaddr) + self.thread_descriptor = self.stm_operations.set_tls(tlsaddr) def _unregister_with_C_code(self): ll_assert(self.gc.get_tls() is self, diff --git a/rpython/translator/stm/src_stm/et.h b/rpython/translator/stm/src_stm/et.h --- a/rpython/translator/stm/src_stm/et.h +++ b/rpython/translator/stm/src_stm/et.h @@ -105,12 +105,13 @@ extern void *pypy_g__stm_duplicate(void *); extern void pypy_g__stm_enum_callback(void *, void *); -void stm_set_tls(void *newtls); +void *stm_set_tls(void *newtls); void *stm_get_tls(void); void stm_del_tls(void); gcptr stm_tldict_lookup(gcptr); /* for tests only */ void stm_tldict_add(gcptr, gcptr); /* for tests only */ void stm_tldict_enum(void); +void stm_tldict_enum_external(void *l_thread_descriptor); long stm_in_transaction(void); long stm_is_inevitable(void); void stm_add_atomic(long delta); diff --git a/rpython/translator/stm/src_stm/rpyintf.c b/rpython/translator/stm/src_stm/rpyintf.c --- a/rpython/translator/stm/src_stm/rpyintf.c +++ b/rpython/translator/stm/src_stm/rpyintf.c @@ -1,9 +1,10 @@ static __thread void *rpython_tls_object; -void stm_set_tls(void *newtls) +void *stm_set_tls(void *newtls) { rpython_tls_object = newtls; + return (void *)thread_descriptor; } void *stm_get_tls(void) @@ -50,6 +51,20 @@ } G2L_LOOP_END; } +void stm_tldict_enum_external(void *l_thread_descriptor) +{ + struct tx_descriptor *d = (struct tx_descriptor *)l_thread_descriptor; + wlog_t *item; + + G2L_LOOP_FORWARD(d->global_to_local, item) + { + gcptr R = item->addr; + gcptr L = item->val; + assert(L->h_revision == (revision_t)R); + pypy_g__stm_enum_external_callback(R, L); + } G2L_LOOP_END; +} + long stm_in_transaction(void) { struct tx_descriptor *d = thread_descriptor; diff --git a/rpython/translator/stm/stmgcintf.py b/rpython/translator/stm/stmgcintf.py --- a/rpython/translator/stm/stmgcintf.py +++ b/rpython/translator/stm/stmgcintf.py @@ -55,13 +55,15 @@ lltype.Void) # for the GC: store and read a thread-local-storage field - set_tls = smexternal('stm_set_tls', [llmemory.Address], lltype.Void) + set_tls = smexternal('stm_set_tls', [llmemory.Address], llmemory.Address) get_tls = smexternal('stm_get_tls', [], llmemory.Address) del_tls = smexternal('stm_del_tls', [], lltype.Void) # calls FindRootsForLocalCollect() and invokes for each such root # the callback set in CALLBACK_ENUM. tldict_enum = smexternal('stm_tldict_enum', [], lltype.Void) + tldict_enum_external = smexternal('stm_tldict_enum_external', + [llmemory.Address], lltype.Void) # sets the transaction length, after which should_break_transaction() # returns True From noreply at buildbot.pypy.org Mon Apr 22 18:53:44 2013 From: noreply at buildbot.pypy.org (bivab) Date: Mon, 22 Apr 2013 18:53:44 +0200 (CEST) Subject: [pypy-commit] pypy default: port simplifications to _emit_copystrcontent from x86 backend Message-ID: <20130422165344.AAF351C0328@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63552:ffda98c2141b Date: 2013-04-22 18:50 +0200 http://bitbucket.org/pypy/pypy/changeset/ffda98c2141b/ Log: port simplifications to _emit_copystrcontent from x86 backend diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -18,7 +18,7 @@ from rpython.jit.backend.arm.helper.regalloc import check_imm_arg from rpython.jit.backend.arm.codebuilder import InstrBuilder, OverwritingBuilder from rpython.jit.backend.arm.jump import remap_frame_layout -from rpython.jit.backend.arm.regalloc import TempInt, TempPtr +from rpython.jit.backend.arm.regalloc import TempBox from rpython.jit.backend.arm.locations import imm from rpython.jit.backend.llsupport import symbolic from rpython.jit.backend.llsupport.gcmap import allocate_gcmap @@ -1003,57 +1003,33 @@ def _emit_copystrcontent(self, op, regalloc, fcond, is_unicode): # compute the source address args = op.getarglist() - base_loc = regalloc.make_sure_var_in_reg(args[0], args) - ofs_loc = regalloc.make_sure_var_in_reg(args[2], args) + base_loc = regalloc.rm.make_sure_var_in_reg(args[0], args) + ofs_loc = regalloc.rm.make_sure_var_in_reg(args[2], args) assert args[0] is not args[1] # forbidden case of aliasing - regalloc.possibly_free_var(args[0]) - regalloc.free_temp_vars() - if args[3] is not args[2] is not args[4]: # MESS MESS MESS: don't free - regalloc.possibly_free_var(args[2]) # it if ==args[3] or args[4] - regalloc.free_temp_vars() - srcaddr_box = TempPtr() + srcaddr_box = TempBox() forbidden_vars = [args[1], args[3], args[4], srcaddr_box] - srcaddr_loc = regalloc.force_allocate_reg(srcaddr_box, - selected_reg=r.r1) + srcaddr_loc = regalloc.rm.force_allocate_reg(srcaddr_box, forbidden_vars) self._gen_address_inside_string(base_loc, ofs_loc, srcaddr_loc, is_unicode=is_unicode) - # compute the destination address - forbidden_vars = [args[4], args[3], srcaddr_box] - dstaddr_box = TempPtr() - dstaddr_loc = regalloc.force_allocate_reg(dstaddr_box, - selected_reg=r.r0) - forbidden_vars.append(dstaddr_box) - base_loc = regalloc.make_sure_var_in_reg(args[1], forbidden_vars) - ofs_loc = regalloc.make_sure_var_in_reg(args[3], forbidden_vars) - assert base_loc.is_reg() - assert ofs_loc.is_reg() - regalloc.possibly_free_var(args[1]) - if args[3] is not args[4]: # more of the MESS described above - regalloc.possibly_free_var(args[3]) - regalloc.free_temp_vars() + base_loc = regalloc.rm.make_sure_var_in_reg(args[1], forbidden_vars) + ofs_loc = regalloc.rm.make_sure_var_in_reg(args[3], forbidden_vars) + forbidden_vars = [args[4], srcaddr_box] + dstaddr_box = TempBox() + dstaddr_loc = regalloc.rm.force_allocate_reg(dstaddr_box, forbidden_vars) self._gen_address_inside_string(base_loc, ofs_loc, dstaddr_loc, is_unicode=is_unicode) - # compute the length in bytes - forbidden_vars = [srcaddr_box, dstaddr_box] - # XXX basically duplicates regalloc.ensure_value_is_boxed, but we - # need the box here - if isinstance(args[4], Box): - length_box = args[4] - length_loc = regalloc.make_sure_var_in_reg(args[4], - forbidden_vars) - else: - length_box = TempInt() - length_loc = regalloc.force_allocate_reg(length_box, - forbidden_vars, selected_reg=r.r2) - immloc = regalloc.convert_to_imm(args[4]) - self.load(length_loc, immloc) + length_box = args[4] + length_loc = regalloc.loc(length_box) if is_unicode: - bytes_box = TempPtr() - bytes_loc = regalloc.force_allocate_reg(bytes_box, - forbidden_vars, selected_reg=r.r2) + forbidden_vars = [srcaddr_box, dstaddr_box] + bytes_box = TempBox() + bytes_loc = regalloc.rm.force_allocate_reg(bytes_box, forbidden_vars) scale = self._get_unicode_item_scale() + if not length_loc.is_reg(): + self.regalloc_mov(length_loc, bytes_loc) + length_loc = bytes_loc assert length_loc.is_reg() self.mc.MOV_ri(r.ip.value, 1 << scale) self.mc.MUL(bytes_loc.value, r.ip.value, length_loc.value) @@ -1062,12 +1038,11 @@ # call memcpy() regalloc.before_call() self._emit_call(imm(self.memcpy_addr), - [dstaddr_loc, srcaddr_loc, length_loc], - can_collect=False) - - regalloc.possibly_free_var(length_box) - regalloc.possibly_free_var(dstaddr_box) - regalloc.possibly_free_var(srcaddr_box) + [dstaddr_loc, srcaddr_loc, length_loc], + can_collect=False) + regalloc.rm.possibly_free_var(length_box) + regalloc.rm.possibly_free_var(dstaddr_box) + regalloc.rm.possibly_free_var(srcaddr_box) def _gen_address_inside_string(self, baseloc, ofsloc, resloc, is_unicode): if is_unicode: @@ -1079,21 +1054,21 @@ self.cpu.translate_support_code) assert itemsize == 1 scale = 0 - self._gen_address(ofsloc, ofs_items, scale, resloc, baseloc) + self._gen_address(resloc, baseloc, ofsloc, scale, ofs_items) - def _gen_address(self, sizereg, baseofs, scale, result, baseloc=None): - assert sizereg.is_reg() + # result = base_loc + (scaled_loc << scale) + static_offset + def _gen_address(self, result, base_loc, scaled_loc, scale=0, static_offset=0): + assert scaled_loc.is_reg() + assert base_loc.is_reg() + assert check_imm_arg(scale) + assert check_imm_arg(static_offset) if scale > 0: + self.mc.LSL_ri(r.ip.value, scaled_loc.value, scale) scaled_loc = r.ip - self.mc.LSL_ri(r.ip.value, sizereg.value, scale) else: - scaled_loc = sizereg - if baseloc is not None: - assert baseloc.is_reg() - self.mc.ADD_rr(result.value, baseloc.value, scaled_loc.value) - self.mc.ADD_ri(result.value, result.value, baseofs) - else: - self.mc.ADD_ri(result.value, scaled_loc.value, baseofs) + scaled_loc = scaled_loc + self.mc.ADD_rr(result.value, base_loc.value, scaled_loc.value) + self.mc.ADD_ri(result.value, result.value, static_offset) def _get_unicode_item_scale(self): _, itemsize, _ = symbolic.get_array_token(rstr.UNICODE, From noreply at buildbot.pypy.org Mon Apr 22 18:53:45 2013 From: noreply at buildbot.pypy.org (bivab) Date: Mon, 22 Apr 2013 18:53:45 +0200 (CEST) Subject: [pypy-commit] pypy default: reload pos_exc_value after possibly clobbering the register holding the value Message-ID: <20130422165345.D91771C0328@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63553:aa7b56060ddd Date: 2013-04-22 18:52 +0200 http://bitbucket.org/pypy/pypy/changeset/aa7b56060ddd/ Log: reload pos_exc_value after possibly clobbering the register holding the value diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -109,9 +109,9 @@ assert excvalloc is not r.ip assert exctploc is not r.ip tmpreg = r.lr - mc.gen_load_int(r.ip.value, self.cpu.pos_exc_value()) if excvalloc is not None: # store assert excvalloc.is_reg() + mc.gen_load_int(r.ip.value, self.cpu.pos_exc_value()) self.load_reg(mc, excvalloc, r.ip) if on_frame: # store exc_value in JITFRAME @@ -119,11 +119,13 @@ assert check_imm_arg(ofs) self.load_reg(mc, r.ip, r.ip, helper=tmpreg) self.store_reg(mc, r.ip, r.fp, ofs, helper=tmpreg) + mc.gen_load_int(r.ip.value, self.cpu.pos_exc_value()) if exctploc is not None: # store pos_exception in exctploc assert exctploc.is_reg() mc.gen_load_int(tmpreg.value, self.cpu.pos_exception()) self.load_reg(mc, exctploc, tmpreg) + mc.gen_load_int(r.ip.value, self.cpu.pos_exc_value()) # reset exception mc.gen_load_int(tmpreg.value, 0) From noreply at buildbot.pypy.org Mon Apr 22 20:55:09 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Mon, 22 Apr 2013 20:55:09 +0200 (CEST) Subject: [pypy-commit] pypy py3k: skip writing py.test.mark decorators in appdirect tests Message-ID: <20130422185509.9E4C41C02DA@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63554:baf81810885e Date: 2013-04-22 10:42 -0700 http://bitbucket.org/pypy/pypy/changeset/baf81810885e/ Log: skip writing py.test.mark decorators in appdirect tests diff --git a/pypy/tool/pytest/apptest.py b/pypy/tool/pytest/apptest.py --- a/pypy/tool/pytest/apptest.py +++ b/pypy/tool/pytest/apptest.py @@ -117,7 +117,12 @@ elif isinstance(value, (str, unicode, int, long, float, list, tuple, dict)) or value is None: defs.append("self.%s = %s\n" % (symbol, py3k_repr(value))) - source = py.code.Source(target_)[1:] + + source = list(py.code.Source(target_)) + while source[0].startswith(('@py.test.mark.', '@pytest.mark.')): + source.pop(0) + source = source[1:] + pyfile = udir.join('src.py') if isinstance(target_, str): # Special case of a docstring; the function name is the first word. @@ -128,7 +133,7 @@ f.write(helpers) f.write('\n'.join(defs)) f.write('def %s():\n' % target_name) - f.write(str(source)) + f.write('\n'.join(source)) f.write("\n%s()\n" % target_name) res, stdout, stderr = runsubprocess.run_subprocess( python_, [str(pyfile)]) From noreply at buildbot.pypy.org Mon Apr 22 20:55:10 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Mon, 22 Apr 2013 20:55:10 +0200 (CEST) Subject: [pypy-commit] pypy py3k: check for usemodules in appdirect tests Message-ID: <20130422185510.E5C7C1C02DA@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63555:a0e9d0c4bc94 Date: 2013-04-22 11:50 -0700 http://bitbucket.org/pypy/pypy/changeset/a0e9d0c4bc94/ Log: check for usemodules in appdirect tests diff --git a/pypy/tool/pytest/apptest.py b/pypy/tool/pytest/apptest.py --- a/pypy/tool/pytest/apptest.py +++ b/pypy/tool/pytest/apptest.py @@ -18,6 +18,13 @@ from pypy.conftest import PyPyClassCollector from inspect import getmro +RENAMED_USEMODULES = dict( + _winreg='winreg', + exceptions='__exceptions__', + rctime='time', + struct='_struct', + thread='_thread', + ) class AppError(Exception): def __init__(self, excinfo): @@ -53,7 +60,7 @@ return repr(value) -def run_with_python(python_, target_, **definitions): +def run_with_python(python_, target_, usemodules, **definitions): if python_ is None: py.test.skip("Cannot find the default python3 interpreter to run with -A") # we assume that the source of target_ is in utf-8. Unfortunately, we don't @@ -62,6 +69,7 @@ helpers = r"""# -*- encoding: utf-8 -*- if 1: import sys +%s def skip(message): print(message) raise SystemExit(0) @@ -118,6 +126,14 @@ dict)) or value is None: defs.append("self.%s = %s\n" % (symbol, py3k_repr(value))) + check_usemodules = '' + if usemodules: + usemodules = [RENAMED_USEMODULES.get(name, name) + for name in usemodules] + check_usemodules = """\ + if not set(%r).issubset(sys.builtin_module_names): + sys.exit(81)""" % usemodules + source = list(py.code.Source(target_)) while source[0].startswith(('@py.test.mark.', '@pytest.mark.')): source.pop(0) @@ -130,7 +146,7 @@ else: target_name = target_.__name__ with pyfile.open('w') as f: - f.write(helpers) + f.write(helpers % check_usemodules) f.write('\n'.join(defs)) f.write('def %s():\n' % target_name) f.write('\n'.join(source)) @@ -140,7 +156,10 @@ print pyfile.read() print >> sys.stdout, stdout print >> sys.stderr, stderr - if res > 0: + if res == 81: + py.test.skip('%r was not compiled w/ required usemodules: %r' % + (python_, usemodules)) + elif res > 0: raise AssertionError("Subprocess failed:\n" + stderr) @@ -183,7 +202,7 @@ target = self.obj src = extract_docstring_if_empty_function(target) if self.config.option.runappdirect: - return run_with_python(self.config.option.python, src) + return run_with_python(self.config.option.python, src, None) space = gettestobjspace() filename = self._getdynfilename(target) func = app2interp_temp(src, filename=filename) @@ -230,7 +249,9 @@ space = target.im_self.space if self.config.option.runappdirect: appexec_definitions = self.parent.obj.__dict__ - return run_with_python(self.config.option.python, src, + spaceconfig = getattr(self.parent.obj, 'spaceconfig', None) + usemodules = spaceconfig.get('usemodules') if spaceconfig else None + return run_with_python(self.config.option.python, src, usemodules, **appexec_definitions) filename = self._getdynfilename(target) func = app2interp_temp(src, filename=filename) From noreply at buildbot.pypy.org Tue Apr 23 00:05:46 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Tue, 23 Apr 2013 00:05:46 +0200 (CEST) Subject: [pypy-commit] pypy default: skip test_recursive_call for now, it deadlocks windows Message-ID: <20130422220546.6A34D1C0328@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: Changeset: r63556:03a8eaf4b441 Date: 2013-04-22 14:52 -0700 http://bitbucket.org/pypy/pypy/changeset/03a8eaf4b441/ Log: skip test_recursive_call for now, it deadlocks windows diff --git a/lib-python/2.7/test/test_descr.py b/lib-python/2.7/test/test_descr.py --- a/lib-python/2.7/test/test_descr.py +++ b/lib-python/2.7/test/test_descr.py @@ -3592,6 +3592,9 @@ list.__init__(a, sequence=[0, 1, 2]) self.assertEqual(a, [0, 1, 2]) + @unittest.skipIf(test_support.check_impl_detail(pypy=True) and + sys.platform == 'win32', + "XXX: https://bugs.pypy.org/issue1461") def test_recursive_call(self): # Testing recursive __call__() by setting to instance of class... class A(object): From noreply at buildbot.pypy.org Tue Apr 23 00:05:48 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Tue, 23 Apr 2013 00:05:48 +0200 (CEST) Subject: [pypy-commit] pypy py3k: merge default Message-ID: <20130422220548.BA07D1C0328@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63557:dfdb45034727 Date: 2013-04-22 15:03 -0700 http://bitbucket.org/pypy/pypy/changeset/dfdb45034727/ Log: merge default diff too long, truncating to 2000 out of 7237 lines diff --git a/Makefile b/Makefile new file mode 100644 --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ + +all: pypy-c + +pypy-c: + @echo "Building PyPy with JIT, it'll take about 40 minutes and 4G of RAM" + @sleep 3 + rpython/bin/rpython -Ojit pypy/goal/targetpypystandalone.py diff --git a/README.rst b/README.rst --- a/README.rst +++ b/README.rst @@ -22,3 +22,16 @@ and send us feedback! the pypy-dev team + +Building +======== + +build with:: + + rpython/bin/rpython -Ojit pypy/goal/targetpypystandalone.py + +This ends up with ``pypy-c`` binary in the main pypy directory. We suggest +to use virtualenv with the resulting pypy-c as the interpreter, you can +find more details about various installation schemes here: + +http://doc.pypy.org/en/latest/getting-started.html#installing-pypy diff --git a/lib-python/2.7/json/decoder.py b/lib-python/2.7/json/decoder.py --- a/lib-python/2.7/json/decoder.py +++ b/lib-python/2.7/json/decoder.py @@ -162,7 +162,7 @@ if nextchar == '}': if object_pairs_hook is not None: result = object_pairs_hook(pairs) - return result, end + return result, end + 1 pairs = {} if object_hook is not None: pairs = object_hook(pairs) diff --git a/lib-python/2.7/json/tests/test_decode.py b/lib-python/2.7/json/tests/test_decode.py --- a/lib-python/2.7/json/tests/test_decode.py +++ b/lib-python/2.7/json/tests/test_decode.py @@ -44,6 +44,7 @@ object_pairs_hook=OrderedDict, object_hook=lambda x: None), OrderedDict(p)) + self.assertEqual(self.loads("{}", object_pairs_hook=list), []) class TestPyDecode(TestDecode, PyTest): pass diff --git a/lib-python/2.7/test/test_descr.py b/lib-python/2.7/test/test_descr.py --- a/lib-python/2.7/test/test_descr.py +++ b/lib-python/2.7/test/test_descr.py @@ -3592,6 +3592,9 @@ list.__init__(a, sequence=[0, 1, 2]) self.assertEqual(a, [0, 1, 2]) + @unittest.skipIf(test_support.check_impl_detail(pypy=True) and + sys.platform == 'win32', + "XXX: https://bugs.pypy.org/issue1461") def test_recursive_call(self): # Testing recursive __call__() by setting to instance of class... class A(object): diff --git a/pypy/doc/config/translation.gcrootfinder.txt b/pypy/doc/config/translation.gcrootfinder.txt --- a/pypy/doc/config/translation.gcrootfinder.txt +++ b/pypy/doc/config/translation.gcrootfinder.txt @@ -9,7 +9,9 @@ - ``--gcrootfinder=asmgcc``: use assembler hackery to find the roots directly from the normal stack. This is a bit faster, but platform specific. It works so far with GCC or MSVC, - on i386 and x86-64. + on i386 and x86-64. It is tested only on Linux (where it is + the default) so other platforms (as well as MSVC) may need + various fixes before they can be used. You may have to force the use of the shadowstack root finder if you are running into troubles or if you insist on translating diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -57,10 +57,12 @@ Inline the fast path of newarray in the assembler. Disabled on ARM until we fix issues. +.. branch: reflex-support +Allow dynamic loading of a (Reflex) backend that implements the C-API needed +to provide reflection information .. branches we don't care about .. branch: autoreds -.. branch: reflex-support .. branch: kill-faking .. branch: improved_ebnfparse_error .. branch: task-decorator diff --git a/pypy/module/cppyy/__init__.py b/pypy/module/cppyy/__init__.py --- a/pypy/module/cppyy/__init__.py +++ b/pypy/module/cppyy/__init__.py @@ -10,15 +10,17 @@ '_resolve_name' : 'interp_cppyy.resolve_name', '_scope_byname' : 'interp_cppyy.scope_byname', '_template_byname' : 'interp_cppyy.template_byname', + '_std_string_name' : 'interp_cppyy.std_string_name', '_set_class_generator' : 'interp_cppyy.set_class_generator', '_register_class' : 'interp_cppyy.register_class', + '_is_static' : 'interp_cppyy.is_static', 'CPPInstance' : 'interp_cppyy.W_CPPInstance', 'addressof' : 'interp_cppyy.addressof', 'bind_object' : 'interp_cppyy.bind_object', } appleveldefs = { - 'gbl' : 'pythonify.gbl', + '_init_pythonify' : 'pythonify._init_pythonify', 'load_reflection_info' : 'pythonify.load_reflection_info', 'add_pythonization' : 'pythonify.add_pythonization', } @@ -31,3 +33,9 @@ # code generation is not, so give it a chance to run now from pypy.module.cppyy import capi capi.register_pythonizations(space) + + def startup(self, space): + from pypy.module.cppyy import capi + capi.verify_backend(space) # may raise ImportError + + space.call_method(space.wrap(self), '_init_pythonify') diff --git a/pypy/module/cppyy/capi/__init__.py b/pypy/module/cppyy/capi/__init__.py --- a/pypy/module/cppyy/capi/__init__.py +++ b/pypy/module/cppyy/capi/__init__.py @@ -1,37 +1,19 @@ from rpython.rtyper.lltypesystem import rffi, lltype -from rpython.rlib import jit -import reflex_capi as backend -#import cint_capi as backend +# There are two possible ways of accessing the backend through the reflection +# C-API: built it into pypy-c, or load it dynamically. The latter is preferred +# (and is the default) for use with Reflex. B/c of some builtin pythonizations, +# the former is recommended (for now) with CINT. -identify = backend.identify -pythonize = backend.pythonize -register_pythonizations = backend.register_pythonizations +# Note: if builtin_capi is chosen, then inside builtin_capi.py, there is still +# the selection of the desired backend (default is Reflex). -ts_reflect = backend.ts_reflect -ts_call = backend.ts_call -ts_memory = backend.ts_memory -ts_helper = backend.ts_helper +# choose C-API access method: +#from pypy.module.cppyy.capi.loadable_capi import * +from pypy.module.cppyy.capi.builtin_capi import * -_C_OPAQUE_PTR = rffi.LONG -_C_OPAQUE_NULL = lltype.nullptr(rffi.LONGP.TO)# ALT: _C_OPAQUE_PTR.TO - -C_SCOPE = _C_OPAQUE_PTR -C_NULL_SCOPE = rffi.cast(C_SCOPE, _C_OPAQUE_NULL) - -C_TYPE = C_SCOPE -C_NULL_TYPE = C_NULL_SCOPE - -C_OBJECT = _C_OPAQUE_PTR -C_NULL_OBJECT = rffi.cast(C_OBJECT, _C_OPAQUE_NULL) - -C_METHOD = _C_OPAQUE_PTR -C_INDEX = rffi.LONG -C_INDEX_ARRAY = rffi.LONGP -WLAVC_INDEX = rffi.LONG - -C_METHPTRGETTER = lltype.FuncType([C_OBJECT], rffi.VOIDP) -C_METHPTRGETTER_PTR = lltype.Ptr(C_METHPTRGETTER) +from pypy.module.cppyy.capi.capi_types import C_OBJECT,\ + C_NULL_TYPE, C_NULL_OBJECT def direct_ptradd(ptr, offset): offset = rffi.cast(rffi.SIZE_T, offset) @@ -42,457 +24,3 @@ def exchange_address(ptr, cif_descr, index): return rffi.ptradd(ptr, cif_descr.exchange_args[index]) - -c_load_dictionary = backend.c_load_dictionary - -# name to opaque C++ scope representation ------------------------------------ -_c_num_scopes = rffi.llexternal( - "cppyy_num_scopes", - [C_SCOPE], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_num_scopes(cppscope): - return _c_num_scopes(cppscope.handle) -_c_scope_name = rffi.llexternal( - "cppyy_scope_name", - [C_SCOPE, rffi.INT], rffi.CCHARP, - compilation_info = backend.eci) -def c_scope_name(cppscope, iscope): - return charp2str_free(_c_scope_name(cppscope.handle, iscope)) - -_c_resolve_name = rffi.llexternal( - "cppyy_resolve_name", - [rffi.CCHARP], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_resolve_name(name): - return charp2str_free(_c_resolve_name(name)) -c_get_scope_opaque = rffi.llexternal( - "cppyy_get_scope", - [rffi.CCHARP], C_SCOPE, - threadsafe=ts_reflect, - compilation_info=backend.eci) -c_get_template = rffi.llexternal( - "cppyy_get_template", - [rffi.CCHARP], C_TYPE, - threadsafe=ts_reflect, - compilation_info=backend.eci) -_c_actual_class = rffi.llexternal( - "cppyy_actual_class", - [C_TYPE, C_OBJECT], C_TYPE, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_actual_class(cppclass, cppobj): - return _c_actual_class(cppclass.handle, cppobj) - -# memory management ---------------------------------------------------------- -_c_allocate = rffi.llexternal( - "cppyy_allocate", - [C_TYPE], C_OBJECT, - threadsafe=ts_memory, - compilation_info=backend.eci) -def c_allocate(cppclass): - return _c_allocate(cppclass.handle) -_c_deallocate = rffi.llexternal( - "cppyy_deallocate", - [C_TYPE, C_OBJECT], lltype.Void, - threadsafe=ts_memory, - compilation_info=backend.eci) -def c_deallocate(cppclass, cppobject): - _c_deallocate(cppclass.handle, cppobject) -_c_destruct = rffi.llexternal( - "cppyy_destruct", - [C_TYPE, C_OBJECT], lltype.Void, - threadsafe=ts_call, - compilation_info=backend.eci) -def c_destruct(cppclass, cppobject): - _c_destruct(cppclass.handle, cppobject) - -# method/function dispatching ------------------------------------------------ -c_call_v = rffi.llexternal( - "cppyy_call_v", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], lltype.Void, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_b = rffi.llexternal( - "cppyy_call_b", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.UCHAR, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_c = rffi.llexternal( - "cppyy_call_c", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.CHAR, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_h = rffi.llexternal( - "cppyy_call_h", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.SHORT, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_i = rffi.llexternal( - "cppyy_call_i", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.INT, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_l = rffi.llexternal( - "cppyy_call_l", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.LONG, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_ll = rffi.llexternal( - "cppyy_call_ll", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.LONGLONG, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_f = rffi.llexternal( - "cppyy_call_f", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.FLOAT, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_d = rffi.llexternal( - "cppyy_call_d", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.DOUBLE, - threadsafe=ts_call, - compilation_info=backend.eci) - -c_call_r = rffi.llexternal( - "cppyy_call_r", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.VOIDP, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_s = rffi.llexternal( - "cppyy_call_s", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.CCHARP, - threadsafe=ts_call, - compilation_info=backend.eci) - -c_constructor = rffi.llexternal( - "cppyy_constructor", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], lltype.Void, - threadsafe=ts_call, - compilation_info=backend.eci) -_c_call_o = rffi.llexternal( - "cppyy_call_o", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP, C_TYPE], rffi.LONG, - threadsafe=ts_call, - compilation_info=backend.eci) -def c_call_o(method, cppobj, nargs, args, cppclass): - return _c_call_o(method, cppobj, nargs, args, cppclass.handle) - -_c_get_methptr_getter = rffi.llexternal( - "cppyy_get_methptr_getter", - [C_SCOPE, C_INDEX], C_METHPTRGETTER_PTR, - threadsafe=ts_reflect, - compilation_info=backend.eci, - elidable_function=True) -def c_get_methptr_getter(cppscope, index): - return _c_get_methptr_getter(cppscope.handle, index) - -# handling of function argument buffer --------------------------------------- -c_allocate_function_args = rffi.llexternal( - "cppyy_allocate_function_args", - [rffi.SIZE_T], rffi.VOIDP, - threadsafe=ts_memory, - compilation_info=backend.eci) -c_deallocate_function_args = rffi.llexternal( - "cppyy_deallocate_function_args", - [rffi.VOIDP], lltype.Void, - threadsafe=ts_memory, - compilation_info=backend.eci) -c_function_arg_sizeof = rffi.llexternal( - "cppyy_function_arg_sizeof", - [], rffi.SIZE_T, - threadsafe=ts_memory, - compilation_info=backend.eci, - elidable_function=True) -c_function_arg_typeoffset = rffi.llexternal( - "cppyy_function_arg_typeoffset", - [], rffi.SIZE_T, - threadsafe=ts_memory, - compilation_info=backend.eci, - elidable_function=True) - -# scope reflection information ----------------------------------------------- -c_is_namespace = rffi.llexternal( - "cppyy_is_namespace", - [C_SCOPE], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -c_is_enum = rffi.llexternal( - "cppyy_is_enum", - [rffi.CCHARP], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) - -# type/class reflection information ------------------------------------------ -_c_final_name = rffi.llexternal( - "cppyy_final_name", - [C_TYPE], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_final_name(cpptype): - return charp2str_free(_c_final_name(cpptype)) -_c_scoped_final_name = rffi.llexternal( - "cppyy_scoped_final_name", - [C_TYPE], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_scoped_final_name(cpptype): - return charp2str_free(_c_scoped_final_name(cpptype)) -c_has_complex_hierarchy = rffi.llexternal( - "cppyy_has_complex_hierarchy", - [C_TYPE], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -_c_num_bases = rffi.llexternal( - "cppyy_num_bases", - [C_TYPE], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_num_bases(cppclass): - return _c_num_bases(cppclass.handle) -_c_base_name = rffi.llexternal( - "cppyy_base_name", - [C_TYPE, rffi.INT], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_base_name(cppclass, base_index): - return charp2str_free(_c_base_name(cppclass.handle, base_index)) -_c_is_subtype = rffi.llexternal( - "cppyy_is_subtype", - [C_TYPE, C_TYPE], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci, - elidable_function=True) - at jit.elidable_promote() -def c_is_subtype(derived, base): - if derived == base: - return 1 - return _c_is_subtype(derived.handle, base.handle) - -_c_base_offset = rffi.llexternal( - "cppyy_base_offset", - [C_TYPE, C_TYPE, C_OBJECT, rffi.INT], rffi.SIZE_T, - threadsafe=ts_reflect, - compilation_info=backend.eci, - elidable_function=True) - at jit.elidable_promote() -def c_base_offset(derived, base, address, direction): - if derived == base: - return 0 - return _c_base_offset(derived.handle, base.handle, address, direction) - -# method/function reflection information ------------------------------------- -_c_num_methods = rffi.llexternal( - "cppyy_num_methods", - [C_SCOPE], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_num_methods(cppscope): - return _c_num_methods(cppscope.handle) -_c_method_index_at = rffi.llexternal( - "cppyy_method_index_at", - [C_SCOPE, rffi.INT], C_INDEX, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_index_at(cppscope, imethod): - return _c_method_index_at(cppscope.handle, imethod) -_c_method_indices_from_name = rffi.llexternal( - "cppyy_method_indices_from_name", - [C_SCOPE, rffi.CCHARP], C_INDEX_ARRAY, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_indices_from_name(cppscope, name): - indices = _c_method_indices_from_name(cppscope.handle, name) - if not indices: - return [] - py_indices = [] - i = 0 - index = indices[i] - while index != -1: - i += 1 - py_indices.append(index) - index = indices[i] - c_free(rffi.cast(rffi.VOIDP, indices)) # c_free defined below - return py_indices - -_c_method_name = rffi.llexternal( - "cppyy_method_name", - [C_SCOPE, C_INDEX], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_name(cppscope, index): - return charp2str_free(_c_method_name(cppscope.handle, index)) -_c_method_result_type = rffi.llexternal( - "cppyy_method_result_type", - [C_SCOPE, C_INDEX], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_result_type(cppscope, index): - return charp2str_free(_c_method_result_type(cppscope.handle, index)) -_c_method_num_args = rffi.llexternal( - "cppyy_method_num_args", - [C_SCOPE, C_INDEX], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_num_args(cppscope, index): - return _c_method_num_args(cppscope.handle, index) -_c_method_req_args = rffi.llexternal( - "cppyy_method_req_args", - [C_SCOPE, C_INDEX], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_req_args(cppscope, index): - return _c_method_req_args(cppscope.handle, index) -_c_method_arg_type = rffi.llexternal( - "cppyy_method_arg_type", - [C_SCOPE, C_INDEX, rffi.INT], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_arg_type(cppscope, index, arg_index): - return charp2str_free(_c_method_arg_type(cppscope.handle, index, arg_index)) -_c_method_arg_default = rffi.llexternal( - "cppyy_method_arg_default", - [C_SCOPE, C_INDEX, rffi.INT], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_arg_default(cppscope, index, arg_index): - return charp2str_free(_c_method_arg_default(cppscope.handle, index, arg_index)) -_c_method_signature = rffi.llexternal( - "cppyy_method_signature", - [C_SCOPE, C_INDEX], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_signature(cppscope, index): - return charp2str_free(_c_method_signature(cppscope.handle, index)) - -_c_get_method = rffi.llexternal( - "cppyy_get_method", - [C_SCOPE, C_INDEX], C_METHOD, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_get_method(cppscope, index): - return _c_get_method(cppscope.handle, index) -_c_get_global_operator = rffi.llexternal( - "cppyy_get_global_operator", - [C_SCOPE, C_SCOPE, C_SCOPE, rffi.CCHARP], WLAVC_INDEX, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_get_global_operator(nss, lc, rc, op): - if nss is not None: - return _c_get_global_operator(nss.handle, lc.handle, rc.handle, op) - return rffi.cast(WLAVC_INDEX, -1) - -# method properties ---------------------------------------------------------- -_c_is_constructor = rffi.llexternal( - "cppyy_is_constructor", - [C_TYPE, C_INDEX], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_is_constructor(cppclass, index): - return _c_is_constructor(cppclass.handle, index) -_c_is_staticmethod = rffi.llexternal( - "cppyy_is_staticmethod", - [C_TYPE, C_INDEX], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_is_staticmethod(cppclass, index): - return _c_is_staticmethod(cppclass.handle, index) - -# data member reflection information ----------------------------------------- -_c_num_datamembers = rffi.llexternal( - "cppyy_num_datamembers", - [C_SCOPE], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_num_datamembers(cppscope): - return _c_num_datamembers(cppscope.handle) -_c_datamember_name = rffi.llexternal( - "cppyy_datamember_name", - [C_SCOPE, rffi.INT], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_datamember_name(cppscope, datamember_index): - return charp2str_free(_c_datamember_name(cppscope.handle, datamember_index)) -_c_datamember_type = rffi.llexternal( - "cppyy_datamember_type", - [C_SCOPE, rffi.INT], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_datamember_type(cppscope, datamember_index): - return charp2str_free(_c_datamember_type(cppscope.handle, datamember_index)) -_c_datamember_offset = rffi.llexternal( - "cppyy_datamember_offset", - [C_SCOPE, rffi.INT], rffi.SIZE_T, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_datamember_offset(cppscope, datamember_index): - return _c_datamember_offset(cppscope.handle, datamember_index) - -_c_datamember_index = rffi.llexternal( - "cppyy_datamember_index", - [C_SCOPE, rffi.CCHARP], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_datamember_index(cppscope, name): - return _c_datamember_index(cppscope.handle, name) - -# data member properties ----------------------------------------------------- -_c_is_publicdata = rffi.llexternal( - "cppyy_is_publicdata", - [C_SCOPE, rffi.INT], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_is_publicdata(cppscope, datamember_index): - return _c_is_publicdata(cppscope.handle, datamember_index) -_c_is_staticdata = rffi.llexternal( - "cppyy_is_staticdata", - [C_SCOPE, rffi.INT], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_is_staticdata(cppscope, datamember_index): - return _c_is_staticdata(cppscope.handle, datamember_index) - -# misc helpers --------------------------------------------------------------- -c_strtoll = rffi.llexternal( - "cppyy_strtoll", - [rffi.CCHARP], rffi.LONGLONG, - threadsafe=ts_helper, - compilation_info=backend.eci) -c_strtoull = rffi.llexternal( - "cppyy_strtoull", - [rffi.CCHARP], rffi.ULONGLONG, - threadsafe=ts_helper, - compilation_info=backend.eci) -c_free = rffi.llexternal( - "cppyy_free", - [rffi.VOIDP], lltype.Void, - threadsafe=ts_memory, - compilation_info=backend.eci) - -def charp2str_free(charp): - string = rffi.charp2str(charp) - voidp = rffi.cast(rffi.VOIDP, charp) - c_free(voidp) - return string - -c_charp2stdstring = rffi.llexternal( - "cppyy_charp2stdstring", - [rffi.CCHARP], C_OBJECT, - threadsafe=ts_helper, - compilation_info=backend.eci) -c_stdstring2stdstring = rffi.llexternal( - "cppyy_stdstring2stdstring", - [C_OBJECT], C_OBJECT, - threadsafe=ts_helper, - compilation_info=backend.eci) -c_assign2stdstring = rffi.llexternal( - "cppyy_assign2stdstring", - [C_OBJECT, rffi.CCHARP], lltype.Void, - threadsafe=ts_helper, - compilation_info=backend.eci) -c_free_stdstring = rffi.llexternal( - "cppyy_free_stdstring", - [C_OBJECT], lltype.Void, - threadsafe=ts_helper, - compilation_info=backend.eci) diff --git a/pypy/module/cppyy/capi/builtin_capi.py b/pypy/module/cppyy/capi/builtin_capi.py new file mode 100644 --- /dev/null +++ b/pypy/module/cppyy/capi/builtin_capi.py @@ -0,0 +1,561 @@ +from rpython.rtyper.lltypesystem import rffi, lltype +from rpython.rlib import jit + +import reflex_capi as backend +#import cint_capi as backend + +from pypy.module.cppyy.capi.capi_types import C_SCOPE, C_TYPE, C_OBJECT,\ + C_METHOD, C_INDEX, C_INDEX_ARRAY, WLAVC_INDEX,\ + C_METHPTRGETTER, C_METHPTRGETTER_PTR + +identify = backend.identify +pythonize = backend.pythonize +register_pythonizations = backend.register_pythonizations +std_string_name = backend.std_string_name + +ts_reflect = backend.ts_reflect +ts_call = backend.ts_call +ts_memory = backend.ts_memory +ts_helper = backend.ts_helper + +def verify_backend(space): + return True # by definition + +c_load_dictionary = backend.c_load_dictionary + +# name to opaque C++ scope representation ------------------------------------ +_c_num_scopes = rffi.llexternal( + "cppyy_num_scopes", + [C_SCOPE], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_num_scopes(space, cppscope): + return _c_num_scopes(cppscope.handle) +_c_scope_name = rffi.llexternal( + "cppyy_scope_name", + [C_SCOPE, rffi.INT], rffi.CCHARP, + compilation_info = backend.eci) +def c_scope_name(space, cppscope, iscope): + return charp2str_free(space, _c_scope_name(cppscope.handle, iscope)) + +_c_resolve_name = rffi.llexternal( + "cppyy_resolve_name", + [rffi.CCHARP], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_resolve_name(space, name): + return charp2str_free(space, _c_resolve_name(name)) +_c_get_scope_opaque = rffi.llexternal( + "cppyy_get_scope", + [rffi.CCHARP], C_SCOPE, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_get_scope_opaque(space, name): + return _c_get_scope_opaque(name) +_c_get_template = rffi.llexternal( + "cppyy_get_template", + [rffi.CCHARP], C_TYPE, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_get_template(space, name): + return _c_get_template(name) +_c_actual_class = rffi.llexternal( + "cppyy_actual_class", + [C_TYPE, C_OBJECT], C_TYPE, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_actual_class(space, cppclass, cppobj): + return _c_actual_class(cppclass.handle, cppobj) + +# memory management ---------------------------------------------------------- +_c_allocate = rffi.llexternal( + "cppyy_allocate", + [C_TYPE], C_OBJECT, + threadsafe=ts_memory, + compilation_info=backend.eci) +def c_allocate(space, cppclass): + return _c_allocate(cppclass.handle) +_c_deallocate = rffi.llexternal( + "cppyy_deallocate", + [C_TYPE, C_OBJECT], lltype.Void, + threadsafe=ts_memory, + compilation_info=backend.eci) +def c_deallocate(space, cppclass, cppobject): + _c_deallocate(cppclass.handle, cppobject) +_c_destruct = rffi.llexternal( + "cppyy_destruct", + [C_TYPE, C_OBJECT], lltype.Void, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_destruct(space, cppclass, cppobject): + _c_destruct(cppclass.handle, cppobject) + +# method/function dispatching ------------------------------------------------ +_c_call_v = rffi.llexternal( + "cppyy_call_v", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], lltype.Void, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_v(space, cppmethod, cppobject, nargs, args): + _c_call_v(cppmethod, cppobject, nargs, args) +_c_call_b = rffi.llexternal( + "cppyy_call_b", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.UCHAR, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_b(space, cppmethod, cppobject, nargs, args): + return _c_call_b(cppmethod, cppobject, nargs, args) +_c_call_c = rffi.llexternal( + "cppyy_call_c", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.CHAR, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_c(space, cppmethod, cppobject, nargs, args): + return _c_call_c(cppmethod, cppobject, nargs, args) +_c_call_h = rffi.llexternal( + "cppyy_call_h", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.SHORT, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_h(space, cppmethod, cppobject, nargs, args): + return _c_call_h(cppmethod, cppobject, nargs, args) +_c_call_i = rffi.llexternal( + "cppyy_call_i", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.INT, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_i(space, cppmethod, cppobject, nargs, args): + return _c_call_i(cppmethod, cppobject, nargs, args) +_c_call_l = rffi.llexternal( + "cppyy_call_l", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.LONG, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_l(space, cppmethod, cppobject, nargs, args): + return _c_call_l(cppmethod, cppobject, nargs, args) +_c_call_ll = rffi.llexternal( + "cppyy_call_ll", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.LONGLONG, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_ll(space, cppmethod, cppobject, nargs, args): + return _c_call_ll(cppmethod, cppobject, nargs, args) +_c_call_f = rffi.llexternal( + "cppyy_call_f", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.FLOAT, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_f(space, cppmethod, cppobject, nargs, args): + return _c_call_f(cppmethod, cppobject, nargs, args) +_c_call_d = rffi.llexternal( + "cppyy_call_d", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.DOUBLE, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_d(space, cppmethod, cppobject, nargs, args): + return _c_call_d(cppmethod, cppobject, nargs, args) + +_c_call_r = rffi.llexternal( + "cppyy_call_r", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.VOIDP, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_r(space, cppmethod, cppobject, nargs, args): + return _c_call_r(cppmethod, cppobject, nargs, args) +_c_call_s = rffi.llexternal( + "cppyy_call_s", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.CCHARP, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_s(space, cppmethod, cppobject, nargs, args): + return _c_call_s(cppmethod, cppobject, nargs, args) + +_c_constructor = rffi.llexternal( + "cppyy_constructor", + [C_METHOD, C_TYPE, rffi.INT, rffi.VOIDP], C_OBJECT, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_constructor(space, cppmethod, cppobject, nargs, args): + return _c_constructor(cppmethod, cppobject, nargs, args) +_c_call_o = rffi.llexternal( + "cppyy_call_o", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP, C_TYPE], rffi.LONG, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_o(space, method, cppobj, nargs, args, cppclass): + return _c_call_o(method, cppobj, nargs, args, cppclass.handle) + +_c_get_methptr_getter = rffi.llexternal( + "cppyy_get_methptr_getter", + [C_SCOPE, C_INDEX], C_METHPTRGETTER_PTR, + threadsafe=ts_reflect, + compilation_info=backend.eci, + elidable_function=True) +def c_get_methptr_getter(space, cppscope, index): + return _c_get_methptr_getter(cppscope.handle, index) + +# handling of function argument buffer --------------------------------------- +_c_allocate_function_args = rffi.llexternal( + "cppyy_allocate_function_args", + [rffi.SIZE_T], rffi.VOIDP, + threadsafe=ts_memory, + compilation_info=backend.eci) +def c_allocate_function_args(space, size): + return _c_allocate_function_args(size) +_c_deallocate_function_args = rffi.llexternal( + "cppyy_deallocate_function_args", + [rffi.VOIDP], lltype.Void, + threadsafe=ts_memory, + compilation_info=backend.eci) +def c_deallocate_function_args(space, args): + _c_deallocate_function_args(args) +_c_function_arg_sizeof = rffi.llexternal( + "cppyy_function_arg_sizeof", + [], rffi.SIZE_T, + threadsafe=ts_memory, + compilation_info=backend.eci, + elidable_function=True) +def c_function_arg_sizeof(space): + return _c_function_arg_sizeof() +_c_function_arg_typeoffset = rffi.llexternal( + "cppyy_function_arg_typeoffset", + [], rffi.SIZE_T, + threadsafe=ts_memory, + compilation_info=backend.eci, + elidable_function=True) +def c_function_arg_typeoffset(space): + return _c_function_arg_typeoffset() + +# scope reflection information ----------------------------------------------- +_c_is_namespace = rffi.llexternal( + "cppyy_is_namespace", + [C_SCOPE], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_is_namespace(space, scope): + return _c_is_namespace(scope) +_c_is_enum = rffi.llexternal( + "cppyy_is_enum", + [rffi.CCHARP], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_is_enum(space, name): + return _c_is_enum(name) + +# type/class reflection information ------------------------------------------ +_c_final_name = rffi.llexternal( + "cppyy_final_name", + [C_TYPE], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_final_name(space, cpptype): + return charp2str_free(space, _c_final_name(cpptype)) +_c_scoped_final_name = rffi.llexternal( + "cppyy_scoped_final_name", + [C_TYPE], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_scoped_final_name(space, cpptype): + return charp2str_free(space, _c_scoped_final_name(cpptype)) +_c_has_complex_hierarchy = rffi.llexternal( + "cppyy_has_complex_hierarchy", + [C_TYPE], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_has_complex_hierarchy(space, cpptype): + return _c_has_complex_hierarchy(cpptype) +_c_num_bases = rffi.llexternal( + "cppyy_num_bases", + [C_TYPE], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_num_bases(space, cppclass): + return _c_num_bases(cppclass.handle) +_c_base_name = rffi.llexternal( + "cppyy_base_name", + [C_TYPE, rffi.INT], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_base_name(space, cppclass, base_index): + return charp2str_free(space, _c_base_name(cppclass.handle, base_index)) +_c_is_subtype = rffi.llexternal( + "cppyy_is_subtype", + [C_TYPE, C_TYPE], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci, + elidable_function=True) + at jit.elidable_promote('2') +def c_is_subtype(space, derived, base): + if derived == base: + return 1 + return _c_is_subtype(derived.handle, base.handle) + +_c_base_offset = rffi.llexternal( + "cppyy_base_offset", + [C_TYPE, C_TYPE, C_OBJECT, rffi.INT], rffi.SIZE_T, + threadsafe=ts_reflect, + compilation_info=backend.eci, + elidable_function=True) + at jit.elidable_promote('1,2,4') +def c_base_offset(space, derived, base, address, direction): + if derived == base: + return 0 + return _c_base_offset(derived.handle, base.handle, address, direction) +def c_base_offset1(space, derived_h, base, address, direction): + return _c_base_offset(derived_h, base.handle, address, direction) + +# method/function reflection information ------------------------------------- +_c_num_methods = rffi.llexternal( + "cppyy_num_methods", + [C_SCOPE], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_num_methods(space, cppscope): + return _c_num_methods(cppscope.handle) +_c_method_index_at = rffi.llexternal( + "cppyy_method_index_at", + [C_SCOPE, rffi.INT], C_INDEX, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_index_at(space, cppscope, imethod): + return _c_method_index_at(cppscope.handle, imethod) +_c_method_indices_from_name = rffi.llexternal( + "cppyy_method_indices_from_name", + [C_SCOPE, rffi.CCHARP], C_INDEX_ARRAY, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_indices_from_name(space, cppscope, name): + indices = _c_method_indices_from_name(cppscope.handle, name) + if not indices: + return [] + py_indices = [] + i = 0 + index = indices[i] + while index != -1: + i += 1 + py_indices.append(index) + index = indices[i] + c_free(rffi.cast(rffi.VOIDP, indices)) # c_free defined below + return py_indices + +_c_method_name = rffi.llexternal( + "cppyy_method_name", + [C_SCOPE, C_INDEX], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_name(space, cppscope, index): + return charp2str_free(space, _c_method_name(cppscope.handle, index)) +_c_method_result_type = rffi.llexternal( + "cppyy_method_result_type", + [C_SCOPE, C_INDEX], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_result_type(space, cppscope, index): + return charp2str_free(space, _c_method_result_type(cppscope.handle, index)) +_c_method_num_args = rffi.llexternal( + "cppyy_method_num_args", + [C_SCOPE, C_INDEX], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_num_args(space, cppscope, index): + return _c_method_num_args(cppscope.handle, index) +_c_method_req_args = rffi.llexternal( + "cppyy_method_req_args", + [C_SCOPE, C_INDEX], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_req_args(space, cppscope, index): + return _c_method_req_args(cppscope.handle, index) +_c_method_arg_type = rffi.llexternal( + "cppyy_method_arg_type", + [C_SCOPE, C_INDEX, rffi.INT], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_arg_type(space, cppscope, index, arg_index): + return charp2str_free(space, _c_method_arg_type(cppscope.handle, index, arg_index)) +_c_method_arg_default = rffi.llexternal( + "cppyy_method_arg_default", + [C_SCOPE, C_INDEX, rffi.INT], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_arg_default(space, cppscope, index, arg_index): + return charp2str_free(space, _c_method_arg_default(cppscope.handle, index, arg_index)) +_c_method_signature = rffi.llexternal( + "cppyy_method_signature", + [C_SCOPE, C_INDEX], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_signature(space, cppscope, index): + return charp2str_free(space, _c_method_signature(cppscope.handle, index)) + +_c_method_is_template = rffi.llexternal( + "cppyy_method_is_template", + [C_SCOPE, C_INDEX], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_is_template(space, cppscope, index): + return _c_method_is_template(cppscope.handle, index) +_c_method_num_template_args = rffi.llexternal( + "cppyy_method_num_template_args", + [C_SCOPE, C_INDEX], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +_c_method_template_arg_name = rffi.llexternal( + "cppyy_method_template_arg_name", + [C_SCOPE, C_INDEX, C_INDEX], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_template_args(space, cppscope, index): + nargs = _c_method_num_template_args(cppscope.handle, index) + args = [c_resolve_name(space, + charp2str_free(space, _c_method_template_arg_name(cppscope.handle, index, iarg))) + for iarg in range(nargs)] + return args + +_c_get_method = rffi.llexternal( + "cppyy_get_method", + [C_SCOPE, C_INDEX], C_METHOD, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_get_method(space, cppscope, index): + return _c_get_method(cppscope.handle, index) +_c_get_global_operator = rffi.llexternal( + "cppyy_get_global_operator", + [C_SCOPE, C_SCOPE, C_SCOPE, rffi.CCHARP], WLAVC_INDEX, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_get_global_operator(space, nss, lc, rc, op): + if nss is not None: + return _c_get_global_operator(nss.handle, lc.handle, rc.handle, op) + return rffi.cast(WLAVC_INDEX, -1) + +# method properties ---------------------------------------------------------- +_c_is_constructor = rffi.llexternal( + "cppyy_is_constructor", + [C_TYPE, C_INDEX], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_is_constructor(space, cppclass, index): + return _c_is_constructor(cppclass.handle, index) +_c_is_staticmethod = rffi.llexternal( + "cppyy_is_staticmethod", + [C_TYPE, C_INDEX], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_is_staticmethod(space, cppclass, index): + return _c_is_staticmethod(cppclass.handle, index) + +# data member reflection information ----------------------------------------- +_c_num_datamembers = rffi.llexternal( + "cppyy_num_datamembers", + [C_SCOPE], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_num_datamembers(space, cppscope): + return _c_num_datamembers(cppscope.handle) +_c_datamember_name = rffi.llexternal( + "cppyy_datamember_name", + [C_SCOPE, rffi.INT], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_datamember_name(space, cppscope, datamember_index): + return charp2str_free(space, _c_datamember_name(cppscope.handle, datamember_index)) +_c_datamember_type = rffi.llexternal( + "cppyy_datamember_type", + [C_SCOPE, rffi.INT], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_datamember_type(space, cppscope, datamember_index): + return charp2str_free(space, _c_datamember_type(cppscope.handle, datamember_index)) +_c_datamember_offset = rffi.llexternal( + "cppyy_datamember_offset", + [C_SCOPE, rffi.INT], rffi.SIZE_T, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_datamember_offset(space, cppscope, datamember_index): + return _c_datamember_offset(cppscope.handle, datamember_index) + +_c_datamember_index = rffi.llexternal( + "cppyy_datamember_index", + [C_SCOPE, rffi.CCHARP], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_datamember_index(space, cppscope, name): + return _c_datamember_index(cppscope.handle, name) + +# data member properties ----------------------------------------------------- +_c_is_publicdata = rffi.llexternal( + "cppyy_is_publicdata", + [C_SCOPE, rffi.INT], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_is_publicdata(space, cppscope, datamember_index): + return _c_is_publicdata(cppscope.handle, datamember_index) +_c_is_staticdata = rffi.llexternal( + "cppyy_is_staticdata", + [C_SCOPE, rffi.INT], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_is_staticdata(space, cppscope, datamember_index): + return _c_is_staticdata(cppscope.handle, datamember_index) + +# misc helpers --------------------------------------------------------------- +_c_strtoll = rffi.llexternal( + "cppyy_strtoll", + [rffi.CCHARP], rffi.LONGLONG, + threadsafe=ts_helper, + compilation_info=backend.eci) +def c_strtoll(space, svalue): + return _c_strtoll(svalue) +_c_strtoull = rffi.llexternal( + "cppyy_strtoull", + [rffi.CCHARP], rffi.ULONGLONG, + threadsafe=ts_helper, + compilation_info=backend.eci) +def c_strtoull(space, svalue): + return _c_strtoull(svalue) +c_free = rffi.llexternal( + "cppyy_free", + [rffi.VOIDP], lltype.Void, + threadsafe=ts_memory, + compilation_info=backend.eci) + +def charp2str_free(space, charp): + string = rffi.charp2str(charp) + voidp = rffi.cast(rffi.VOIDP, charp) + c_free(voidp) + return string + +_c_charp2stdstring = rffi.llexternal( + "cppyy_charp2stdstring", + [rffi.CCHARP], C_OBJECT, + threadsafe=ts_helper, + compilation_info=backend.eci) +def c_charp2stdstring(space, svalue): + charp = rffi.str2charp(svalue) + result = _c_charp2stdstring(charp) + rffi.free_charp(charp) + return result +_c_stdstring2stdstring = rffi.llexternal( + "cppyy_stdstring2stdstring", + [C_OBJECT], C_OBJECT, + threadsafe=ts_helper, + compilation_info=backend.eci) +def c_stdstring2stdstring(space, cppobject): + return _c_stdstring2stdstring(cppobject) +_c_assign2stdstring = rffi.llexternal( + "cppyy_assign2stdstring", + [C_OBJECT, rffi.CCHARP], lltype.Void, + threadsafe=ts_helper, + compilation_info=backend.eci) +def c_assign2stdstring(space, cppobject, svalue): + charp = rffi.str2charp(svalue) + _c_assign2stdstring(cppobject, charp) + rffi.free_charp(charp) +_c_free_stdstring = rffi.llexternal( + "cppyy_free_stdstring", + [C_OBJECT], lltype.Void, + threadsafe=ts_helper, + compilation_info=backend.eci) +def c_free_stdstring(space, cppobject): + _c_free_stdstring(cppobject) diff --git a/pypy/module/cppyy/capi/capi_types.py b/pypy/module/cppyy/capi/capi_types.py new file mode 100644 --- /dev/null +++ b/pypy/module/cppyy/capi/capi_types.py @@ -0,0 +1,22 @@ +from rpython.rtyper.lltypesystem import rffi, lltype + +# shared ll definitions +_C_OPAQUE_PTR = rffi.LONG +_C_OPAQUE_NULL = lltype.nullptr(rffi.LONGP.TO)# ALT: _C_OPAQUE_PTR.TO + +C_SCOPE = _C_OPAQUE_PTR +C_NULL_SCOPE = rffi.cast(C_SCOPE, _C_OPAQUE_NULL) + +C_TYPE = C_SCOPE +C_NULL_TYPE = C_NULL_SCOPE + +C_OBJECT = _C_OPAQUE_PTR +C_NULL_OBJECT = rffi.cast(C_OBJECT, _C_OPAQUE_NULL) + +C_METHOD = _C_OPAQUE_PTR +C_INDEX = rffi.LONG +C_INDEX_ARRAY = rffi.LONGP +WLAVC_INDEX = rffi.LONG + +C_METHPTRGETTER = lltype.FuncType([C_OBJECT], rffi.VOIDP) +C_METHPTRGETTER_PTR = lltype.Ptr(C_METHPTRGETTER) diff --git a/pypy/module/cppyy/capi/cint_capi.py b/pypy/module/cppyy/capi/cint_capi.py --- a/pypy/module/cppyy/capi/cint_capi.py +++ b/pypy/module/cppyy/capi/cint_capi.py @@ -9,10 +9,8 @@ from rpython.rtyper.lltypesystem import rffi from rpython.rlib import libffi, rdynload -from pypy.module.itertools import interp_itertools - -__all__ = ['identify', 'eci', 'c_load_dictionary'] +__all__ = ['identify', 'std_string_name', 'eci', 'c_load_dictionary'] pkgpath = py.path.local(__file__).dirpath().join(os.pardir) srcpath = pkgpath.join("src") @@ -36,8 +34,10 @@ ts_reflect = False ts_call = False -ts_memory = 'auto' -ts_helper = 'auto' +ts_memory = False +ts_helper = False + +std_string_name = 'string' # force loading in global mode of core libraries, rather than linking with # them as PyPy uses various version of dlopen in various places; note that @@ -120,7 +120,7 @@ classname = space.str_w(args_w[1]) addr_idx = 2 w_address = args_w[addr_idx] - except OperationError: + except (OperationError, TypeError): addr_idx = 1 w_address = args_w[addr_idx] @@ -138,14 +138,14 @@ # call the helper stub to by-pass CINT vbranch = _ttree_Branch(vtree, branchname, klassname, address, bufsize, splitlevel) branch_class = interp_cppyy.scope_byname(space, "TBranch") - w_branch = interp_cppyy.wrap_cppobject( - space, space.w_None, branch_class, vbranch, isref=False, python_owns=False) + w_branch = interp_cppyy.wrap_cppobject(space, vbranch, branch_class) return w_branch - except (OperationError, TypeError, IndexError), e: + except (OperationError, TypeError, IndexError): pass # return control back to the original, unpythonized overload - return tree_class.get_overload("Branch").call(w_self, args_w) + ol = tree_class.get_overload("Branch") + return ol.call(w_self, args_w) def activate_branch(space, w_branch): w_branches = space.call_method(w_branch, "GetListOfBranches") @@ -155,6 +155,12 @@ space.call_method(w_branch, "SetStatus", space.wrap(1)) space.call_method(w_branch, "ResetReadEntry") +c_ttree_GetEntry = rffi.llexternal( + "cppyy_ttree_GetEntry", + [rffi.VOIDP, rffi.LONGLONG], rffi.LONGLONG, + threadsafe=False, + compilation_info=eci) + @unwrap_spec(args_w='args_w') def ttree_getattr(space, w_self, args_w): """Specialized __getattr__ for TTree's that allows switching on/off the @@ -163,28 +169,75 @@ from pypy.module.cppyy import interp_cppyy tree = space.interp_w(interp_cppyy.W_CPPInstance, w_self) + space = tree.space # holds the class cache in State + + # prevent recursion + attr = space.str_w(args_w[0]) + if attr and attr[0] == '_': + raise OperationError(space.w_AttributeError, args_w[0]) + + # try the saved cdata (for builtin types) + try: + w_cdata = space.getattr(w_self, space.wrap('_'+attr)) + from pypy.module._cffi_backend import cdataobj + cdata = space.interp_w(cdataobj.W_CData, w_cdata, can_be_None=False) + return cdata.convert_to_object() + except OperationError: + pass + # setup branch as a data member and enable it for reading - space = tree.space # holds the class cache in State w_branch = space.call_method(w_self, "GetBranch", args_w[0]) + if not space.is_true(w_branch): + raise OperationError(space.w_AttributeError, args_w[0]) + activate_branch(space, w_branch) + + # figure out from where we're reading + entry = space.int_w(space.call_method(w_self, "GetReadEntry")) + if entry == -1: + entry = 0 + + # setup cache structure w_klassname = space.call_method(w_branch, "GetClassName") - klass = interp_cppyy.scope_byname(space, space.str_w(w_klassname)) - w_obj = klass.construct() - #space.call_method(w_branch, "SetStatus", space.wrap(1)) - activate_branch(space, w_branch) - space.call_method(w_branch, "SetObject", w_obj) - space.call_method(w_branch, "GetEntry", space.wrap(0)) - space.setattr(w_self, args_w[0], w_obj) - return w_obj + if space.is_true(w_klassname): + # some instance + klass = interp_cppyy.scope_byname(space, space.str_w(w_klassname)) + w_obj = klass.construct() + space.call_method(w_branch, "SetObject", w_obj) + space.call_method(w_branch, "GetEntry", space.wrap(entry)) + space.setattr(w_self, args_w[0], w_obj) + return w_obj + else: + # builtin data + w_leaf = space.call_method(w_self, "GetLeaf", args_w[0]) + space.call_method(w_branch, "GetEntry", space.wrap(entry)) + + # location + w_address = space.call_method(w_leaf, "GetValuePointer") + buf = space.buffer_w(w_address) + from pypy.module._rawffi import buffer + assert isinstance(buf, buffer.RawFFIBuffer) + address = rffi.cast(rffi.CCHARP, buf.datainstance.ll_buffer) + + # placeholder + w_typename = space.call_method(w_leaf, "GetTypeName" ) + from pypy.module.cppyy import capi + typename = capi.c_resolve_name(space, space.str_w(w_typename)) + if typename == 'bool': typename = '_Bool' + w_address = space.call_method(w_leaf, "GetValuePointer") + from pypy.module._cffi_backend import cdataobj, newtype + cdata = cdataobj.W_CData(space, address, newtype.new_primitive_type(space, typename)) + + # cache result + space.setattr(w_self, space.wrap('_'+attr), space.wrap(cdata)) + return space.getattr(w_self, args_w[0]) class W_TTreeIter(W_Root): def __init__(self, space, w_tree): - from pypy.module.cppyy import interp_cppyy tree = space.interp_w(interp_cppyy.W_CPPInstance, w_tree) - self.tree = tree.get_cppthis(tree.cppclass) + self.vtree = rffi.cast(rffi.VOIDP, tree.get_cppthis(tree.cppclass)) self.w_tree = w_tree - self.getentry = tree.cppclass.get_overload("GetEntry").functions[0] self.current = 0 self.maxentry = space.int_w(space.call_method(w_tree, "GetEntriesFast")) @@ -198,8 +251,8 @@ if self.current == self.maxentry: raise OperationError(self.space.w_StopIteration, self.space.w_None) # TODO: check bytes read? - self.getentry.call(self.tree, [self.space.wrap(self.current)]) - self.current += 1 + c_ttree_GetEntry(self.vtree, self.current) + self.current += 1 return self.w_tree W_TTreeIter.typedef = TypeDef( diff --git a/pypy/module/cppyy/capi/loadable_capi.py b/pypy/module/cppyy/capi/loadable_capi.py new file mode 100644 --- /dev/null +++ b/pypy/module/cppyy/capi/loadable_capi.py @@ -0,0 +1,519 @@ +from rpython.rtyper.lltypesystem import rffi, lltype +from rpython.rlib import jit, jit_libffi, libffi, rdynload, objectmodel +from rpython.rlib.rarithmetic import r_singlefloat +from rpython.tool import leakfinder + +from pypy.interpreter.error import OperationError + +from pypy.module._cffi_backend import ctypefunc, ctypeprim, cdataobj, misc + +from pypy.module.cppyy.capi.capi_types import C_SCOPE, C_TYPE, C_OBJECT,\ + C_METHOD, C_INDEX, C_INDEX_ARRAY, WLAVC_INDEX, C_METHPTRGETTER_PTR + + +reflection_library = 'rflxlib.so' + +def identify(): + return 'loadable_capi' + +# this is not technically correct, but will do for now +std_string_name = 'std::basic_string' + +class _Arg: # poor man's union + _immutable_ = True + def __init__(self, l = 0, s = '', vp = rffi.cast(rffi.VOIDP, 0) ): + self._long = l + self._string = s + self._voidp = vp + +# For the loadable CAPI, the calls start and end in RPython. Therefore, the standard +# _call of W_CTypeFunc, which expects wrapped objects, does not quite work: some +# vars (e.g. void* equivalent) can not be wrapped, and others (such as rfloat) risk +# rounding problems. This W_RCTypeFun then, takes args, instead of args_w. Note that +# rcall() is a new method, so as to not interfere with the base class call and _call +# when rtyping. It is also called directly (see call_capi below). +class W_RCTypeFunc(ctypefunc.W_CTypeFunc): + @jit.unroll_safe + def rcall(self, funcaddr, args): + assert self.cif_descr + self = jit.promote(self) + # no checking of len(args) needed, as calls in this context are not dynamic + + # The following code is functionally similar to W_CTypeFunc._call, but its + # implementation is tailored to the restricted use (include memory handling) + # of the CAPI calls. + space = self.space + cif_descr = self.cif_descr + size = cif_descr.exchange_size + raw_string = rffi.cast(rffi.CCHARP, 0) # only ever have one in the CAPI + buffer = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') + try: + for i in range(len(args)): + data = rffi.ptradd(buffer, cif_descr.exchange_args[i]) + obj = args[i] + argtype = self.fargs[i] + # the following is clumsy, but the data types used as arguments are + # very limited, so it'll do for now + if isinstance(argtype, ctypeprim.W_CTypePrimitiveSigned): + misc.write_raw_signed_data(data, rffi.cast(rffi.LONG, obj._long), argtype.size) + elif isinstance(argtype, ctypeprim.W_CTypePrimitiveUnsigned): + misc.write_raw_unsigned_data(data, rffi.cast(rffi.ULONG, obj._long), argtype.size) + elif obj._voidp != rffi.cast(rffi.VOIDP, 0): + data = rffi.cast(rffi.VOIDPP, data) + data[0] = obj._voidp + else: # only other use is sring + n = len(obj._string) + assert raw_string == rffi.cast(rffi.CCHARP, 0) + raw_string = rffi.str2charp(obj._string) + data = rffi.cast(rffi.CCHARPP, data) + data[0] = raw_string + + jit_libffi.jit_ffi_call(cif_descr, + rffi.cast(rffi.VOIDP, funcaddr), + buffer) + + resultdata = rffi.ptradd(buffer, cif_descr.exchange_result) + # this wrapping is unnecessary, but the assumption is that given the + # immediate unwrapping, the round-trip is removed + w_res = self.ctitem.copy_and_convert_to_object(resultdata) + finally: + if raw_string != rffi.cast(rffi.CCHARP, 0): + rffi.free_charp(raw_string) + lltype.free(buffer, flavor='raw') + return w_res + +class State(object): + def __init__(self, space): + self.library = None + self.capi_calls = {} + + import pypy.module._cffi_backend.newtype as nt + + # TODO: the following need to match up with the globally defined C_XYZ low-level + # types (see capi/__init__.py), but by using strings here, that isn't guaranteed + c_opaque_ptr = nt.new_primitive_type(space, 'long') + + c_scope = c_opaque_ptr + c_type = c_scope + c_object = c_opaque_ptr + c_method = c_opaque_ptr + c_index = nt.new_primitive_type(space, 'long') + + c_void = nt.new_void_type(space) + c_char = nt.new_primitive_type(space, 'char') + c_uchar = nt.new_primitive_type(space, 'unsigned char') + c_short = nt.new_primitive_type(space, 'short') + c_int = nt.new_primitive_type(space, 'int') + c_long = nt.new_primitive_type(space, 'long') + c_llong = nt.new_primitive_type(space, 'long long') + c_ullong = nt.new_primitive_type(space, 'unsigned long long') + c_float = nt.new_primitive_type(space, 'float') + c_double = nt.new_primitive_type(space, 'double') + + c_ccharp = nt.new_pointer_type(space, c_char) + c_index_array = nt.new_pointer_type(space, c_void) + + c_voidp = nt.new_pointer_type(space, c_void) + c_size_t = nt.new_primitive_type(space, 'size_t') + + self.capi_call_ifaces = { + # name to opaque C++ scope representation + 'num_scopes' : ([c_scope], c_int), + 'scope_name' : ([c_scope, c_int], c_ccharp), + + 'resolve_name' : ([c_ccharp], c_ccharp), + 'get_scope' : ([c_ccharp], c_scope), + 'get_template' : ([c_ccharp], c_type), + 'actual_class' : ([c_type, c_object], c_type), + + # memory management + 'allocate' : ([c_type], c_object), + 'deallocate' : ([c_type, c_object], c_void), + 'destruct' : ([c_type, c_object], c_void), + + # method/function dispatching + 'call_v' : ([c_method, c_object, c_int, c_voidp], c_void), + 'call_b' : ([c_method, c_object, c_int, c_voidp], c_uchar), + 'call_c' : ([c_method, c_object, c_int, c_voidp], c_char), + + 'call_h' : ([c_method, c_object, c_int, c_voidp], c_short), + 'call_i' : ([c_method, c_object, c_int, c_voidp], c_int), + 'call_l' : ([c_method, c_object, c_int, c_voidp], c_long), + 'call_ll' : ([c_method, c_object, c_int, c_voidp], c_llong), + 'call_f' : ([c_method, c_object, c_int, c_voidp], c_float), + 'call_d' : ([c_method, c_object, c_int, c_voidp], c_double), + + 'call_r' : ([c_method, c_object, c_int, c_voidp], c_voidp), + 'call_s' : ([c_method, c_object, c_int, c_voidp], c_ccharp), + + 'constructor' : ([c_method, c_object, c_int, c_voidp], c_object), + 'call_o' : ([c_method, c_object, c_int, c_voidp, c_type], c_object), + + 'get_methptr_getter' : ([c_scope, c_index], c_voidp), # TODO: verify + + # handling of function argument buffer + 'allocate_function_args' : ([c_size_t], c_voidp), + 'deallocate_function_args' : ([c_voidp], c_void), + 'function_arg_sizeof' : ([], c_size_t), + 'function_arg_typeoffset' : ([], c_size_t), + + # scope reflection information + 'is_namespace' : ([c_scope], c_int), + 'is_enum' : ([c_ccharp], c_int), + + # type/class reflection information + 'final_name' : ([c_type], c_ccharp), + 'scoped_final_name' : ([c_type], c_ccharp), + 'has_complex_hierarchy' : ([c_type], c_int), + 'num_bases' : ([c_type], c_int), + 'base_name' : ([c_type, c_int], c_ccharp), + 'is_subtype' : ([c_type, c_type], c_int), + + 'base_offset' : ([c_type, c_type, c_object, c_int], c_long), + + # method/function reflection information + 'num_methods' : ([c_scope], c_int), + 'method_index_at' : ([c_scope, c_int], c_index), + 'method_indices_from_name' : ([c_scope, c_ccharp], c_index_array), + + 'method_name' : ([c_scope, c_index], c_ccharp), + 'method_result_type' : ([c_scope, c_index], c_ccharp), + 'method_num_args' : ([c_scope, c_index], c_int), + 'method_req_args' : ([c_scope, c_index], c_int), + 'method_arg_type' : ([c_scope, c_index, c_int], c_ccharp), + 'method_arg_default' : ([c_scope, c_index, c_int], c_ccharp), + 'method_signature' : ([c_scope, c_index], c_ccharp), + + 'method_is_template' : ([c_scope, c_index], c_int), + 'method_num_template_args' : ([c_scope, c_index], c_int), + 'method_template_arg_name' : ([c_scope, c_index, c_index], c_ccharp), + + 'get_method' : ([c_scope, c_index], c_method), + 'get_global_operator' : ([c_scope, c_scope, c_scope, c_ccharp], c_index), + + # method properties + 'is_constructor' : ([c_type, c_index], c_int), + 'is_staticmethod' : ([c_type, c_index], c_int), + + # data member reflection information + 'num_datamembers' : ([c_scope], c_int), + 'datamember_name' : ([c_scope, c_int], c_ccharp), + 'datamember_type' : ([c_scope, c_int], c_ccharp), + 'datamember_offset' : ([c_scope, c_int], c_size_t), + + 'datamember_index' : ([c_scope, c_ccharp], c_int), + + # data member properties + 'is_publicdata' : ([c_scope, c_int], c_int), + 'is_staticdata' : ([c_scope, c_int], c_int), + + # misc helpers + 'strtoll' : ([c_ccharp], c_llong), + 'strtoull' : ([c_ccharp], c_ullong), + 'free' : ([c_voidp], c_void), + + 'charp2stdstring' : ([c_ccharp], c_object), + 'stdstring2stdstring' : ([c_object], c_object), + 'assign2stdstring' : ([c_object, c_ccharp], c_void), + 'free_stdstring' : ([c_object], c_void), + } + +def load_reflection_library(space): + state = space.fromcache(State) + if state.library is None: + from pypy.module._cffi_backend.libraryobj import W_Library + state.library = W_Library(space, reflection_library, rdynload.RTLD_LOCAL | rdynload.RTLD_LAZY) + return state.library + +def verify_backend(space): + try: + load_reflection_library(space) + except Exception: + if objectmodel.we_are_translated(): + raise OperationError(space.w_ImportError, + space.wrap("missing reflection library rflxlib.so")) + return False + return True + +def call_capi(space, name, args): + state = space.fromcache(State) + try: + c_call = state.capi_calls[name] + except KeyError: + if state.library is None: + load_reflection_library(space) + iface = state.capi_call_ifaces[name] + cfunc = W_RCTypeFunc(space, iface[0], iface[1], False) + c_call = state.library.load_function(cfunc, 'cppyy_'+name) + # TODO: there must be a better way to trick the leakfinder ... + if not objectmodel.we_are_translated(): + leakfinder.remember_free(c_call.ctype.cif_descr._obj0) + state.capi_calls[name] = c_call + return c_call.ctype.rcall(c_call._cdata, args) + +def _cdata_to_cobject(space, w_cdata): + return rffi.cast(C_OBJECT, space.int_w(w_cdata)) + +def _cdata_to_size_t(space, w_cdata): + return rffi.cast(rffi.SIZE_T, space.int_w(w_cdata)) + +def _cdata_to_ptr(space, w_cdata): # TODO: this is both a hack and dreadfully slow + return rffi.cast(rffi.VOIDP, + space.interp_w(cdataobj.W_CData, w_cdata, can_be_None=False)._cdata) + +def c_load_dictionary(name): + return libffi.CDLL(name) + +# name to opaque C++ scope representation ------------------------------------ +def c_num_scopes(space, cppscope): + return space.int_w(call_capi(space, 'num_scopes', [_Arg(l=cppscope.handle)])) +def c_scope_name(space, cppscope, iscope): + args = [_Arg(l=cppscope.handle), _Arg(l=iscope)] + return charp2str_free(space, call_capi(space, 'scope_name', args)) + +def c_resolve_name(space, name): + return charp2str_free(space, call_capi(space, 'resolve_name', [_Arg(s=name)])) +def c_get_scope_opaque(space, name): + return rffi.cast(C_SCOPE, space.int_w(call_capi(space, 'get_scope', [_Arg(s=name)]))) +def c_get_template(space, name): + return rffi.cast(C_TYPE, space.int_w(call_capi(space, 'get_template', [_Arg(s=name)]))) +def c_actual_class(space, cppclass, cppobj): + args = [_Arg(l=cppclass.handle), _Arg(l=cppobj)] + return rffi.cast(C_TYPE, space.int_w(call_capi(space, 'actual_class', args))) + +# memory management ---------------------------------------------------------- +def c_allocate(space, cppclass): + return _cdata_to_cobject(space, call_capi(space, 'allocate', [_Arg(l=cppclass.handle)])) +def c_deallocate(space, cppclass, cppobject): + call_capi(space, 'deallocate', [_Arg(l=cppclass.handle), _Arg(l=cppobject)]) +def c_destruct(space, cppclass, cppobject): + call_capi(space, 'destruct', [_Arg(l=cppclass.handle), _Arg(l=cppobject)]) + +# method/function dispatching ------------------------------------------------ +def c_call_v(space, cppmethod, cppobject, nargs, cargs): + args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)] + call_capi(space, 'call_v', args) +def c_call_b(space, cppmethod, cppobject, nargs, cargs): + args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)] + return rffi.cast(rffi.UCHAR, space.c_int_w(call_capi(space, 'call_b', args))) +def c_call_c(space, cppmethod, cppobject, nargs, cargs): + args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)] + return rffi.cast(rffi.CHAR, space.str_w(call_capi(space, 'call_c', args))[0]) +def c_call_h(space, cppmethod, cppobject, nargs, cargs): + args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)] + return rffi.cast(rffi.SHORT, space.int_w(call_capi(space, 'call_h', args))) +def c_call_i(space, cppmethod, cppobject, nargs, cargs): + args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)] + return rffi.cast(rffi.INT, space.c_int_w(call_capi(space, 'call_i', args))) +def c_call_l(space, cppmethod, cppobject, nargs, cargs): + args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)] + return rffi.cast(rffi.LONG, space.int_w(call_capi(space, 'call_l', args))) +def c_call_ll(space, cppmethod, cppobject, nargs, cargs): + args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)] + return rffi.cast(rffi.LONGLONG, space.r_longlong_w(call_capi(space, 'call_ll', args))) +def c_call_f(space, cppmethod, cppobject, nargs, cargs): + args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)] + return rffi.cast(rffi.FLOAT, r_singlefloat(space.float_w(call_capi(space, 'call_f', args)))) +def c_call_d(space, cppmethod, cppobject, nargs, cargs): + args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)] + return rffi.cast(rffi.DOUBLE, space.float_w(call_capi(space, 'call_d', args))) + +def c_call_r(space, cppmethod, cppobject, nargs, cargs): + args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)] + return _cdata_to_ptr(space, call_capi(space, 'call_r', args)) +def c_call_s(space, cppmethod, cppobject, nargs, cargs): + args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)] + return call_capi(space, 'call_s', args) + +def c_constructor(space, cppmethod, cppobject, nargs, cargs): + args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs)] + return _cdata_to_cobject(space, call_capi(space, 'constructor', args)) +def c_call_o(space, cppmethod, cppobject, nargs, cargs, cppclass): + args = [_Arg(l=cppmethod), _Arg(l=cppobject), _Arg(l=nargs), _Arg(vp=cargs), _Arg(l=cppclass.handle)] + return _cdata_to_cobject(space, call_capi(space, 'call_o', args)) + +def c_get_methptr_getter(space, cppscope, index): + args = [_Arg(l=cppscope.handle), _Arg(l=index)] + return rffi.cast(C_METHPTRGETTER_PTR, + _cdata_to_ptr(space, call_capi(space, 'get_methptr_getter', args))) + +# handling of function argument buffer --------------------------------------- +def c_allocate_function_args(space, size): + return _cdata_to_ptr(space, call_capi(space, 'allocate_function_args', [_Arg(l=size)])) +def c_deallocate_function_args(space, cargs): + call_capi(space, 'deallocate_function_args', [_Arg(vp=cargs)]) + at jit.elidable +def c_function_arg_sizeof(space): + return _cdata_to_size_t(space, call_capi(space, 'function_arg_sizeof', [])) + at jit.elidable +def c_function_arg_typeoffset(space): + return _cdata_to_size_t(space, call_capi(space, 'function_arg_typeoffset', [])) + +# scope reflection information ----------------------------------------------- +def c_is_namespace(space, scope): + return space.bool_w(call_capi(space, 'is_namespace', [_Arg(l=scope)])) +def c_is_enum(space, name): + return space.bool_w(call_capi(space, 'is_enum', [_Arg(s=name)])) + +# type/class reflection information ------------------------------------------ +def c_final_name(space, cpptype): + return charp2str_free(space, call_capi(space, 'final_name', [_Arg(l=cpptype)])) +def c_scoped_final_name(space, cpptype): + return charp2str_free(space, call_capi(space, 'scoped_final_name', [_Arg(l=cpptype)])) +def c_has_complex_hierarchy(space, handle): + return space.bool_w(call_capi(space, 'has_complex_hierarchy', [_Arg(l=handle)])) +def c_num_bases(space, cppclass): + return space.int_w(call_capi(space, 'num_bases', [_Arg(l=cppclass.handle)])) +def c_base_name(space, cppclass, base_index): + args = [_Arg(l=cppclass.handle), _Arg(l=base_index)] + return charp2str_free(space, call_capi(space, 'base_name', args)) + at jit.elidable_promote('2') +def c_is_subtype(space, derived, base): + if derived == base: + return bool(1) + return space.bool_w(call_capi(space, 'is_subtype', [_Arg(l=derived.handle), _Arg(l=base.handle)])) + + at jit.elidable_promote('1,2,4') +def _c_base_offset(space, derived_h, base_h, address, direction): + args = [_Arg(l=derived_h), _Arg(l=base_h), _Arg(l=address), _Arg(l=direction)] + return _cdata_to_size_t(space, call_capi(space, 'base_offset', args)) +def c_base_offset(space, derived, base, address, direction): + if derived == base: + return rffi.cast(rffi.SIZE_T, 0) + return _c_base_offset(space, derived.handle, base.handle, address, direction) +def c_base_offset1(space, derived_h, base, address, direction): + return _c_base_offset(space, derived_h, base.handle, address, direction) + +# method/function reflection information ------------------------------------- +def c_num_methods(space, cppscope): + args = [_Arg(l=cppscope.handle)] + return space.int_w(call_capi(space, 'num_methods', args)) +def c_method_index_at(space, cppscope, imethod): + args = [_Arg(l=cppscope.handle), _Arg(l=imethod)] + return space.int_w(call_capi(space, 'method_index_at', args)) +def c_method_indices_from_name(space, cppscope, name): + args = [_Arg(l=cppscope.handle), _Arg(s=name)] + indices = rffi.cast(C_INDEX_ARRAY, + _cdata_to_ptr(space, call_capi(space, 'method_indices_from_name', args))) + if not indices: + return [] + py_indices = [] + i = 0 + index = indices[i] + while index != -1: + i += 1 + py_indices.append(index) + index = indices[i] + c_free(space, rffi.cast(rffi.VOIDP, indices)) # c_free defined below + return py_indices + +def c_method_name(space, cppscope, index): + args = [_Arg(l=cppscope.handle), _Arg(l=index)] + return charp2str_free(space, call_capi(space, 'method_name', args)) +def c_method_result_type(space, cppscope, index): + args = [_Arg(l=cppscope.handle), _Arg(l=index)] + return charp2str_free(space, call_capi(space, 'method_result_type', args)) +def c_method_num_args(space, cppscope, index): + args = [_Arg(l=cppscope.handle), _Arg(l=index)] + return space.int_w(call_capi(space, 'method_num_args', args)) +def c_method_req_args(space, cppscope, index): + args = [_Arg(l=cppscope.handle), _Arg(l=index)] + return space.int_w(call_capi(space, 'method_req_args', args)) +def c_method_arg_type(space, cppscope, index, arg_index): + args = [_Arg(l=cppscope.handle), _Arg(l=index), _Arg(l=arg_index)] + return charp2str_free(space, call_capi(space, 'method_arg_type', args)) +def c_method_arg_default(space, cppscope, index, arg_index): + args = [_Arg(l=cppscope.handle), _Arg(l=index), _Arg(l=arg_index)] + return charp2str_free(space, call_capi(space, 'method_arg_default', args)) +def c_method_signature(space, cppscope, index): + args = [_Arg(l=cppscope.handle), _Arg(l=index)] + return charp2str_free(space, call_capi(space, 'method_signature', args)) + +def c_method_is_template(space, cppscope, index): + args = [_Arg(l=cppscope.handle), _Arg(l=index)] + return space.bool_w(call_capi(space, 'method_is_template', args)) +def _c_method_num_template_args(space, cppscope, index): + args = [_Arg(l=cppscope.handle), _Arg(l=index)] + return space.int_w(call_capi(space, 'method_num_template_args', args)) +def c_template_args(space, cppscope, index): + nargs = _c_method_num_template_args(space, cppscope, index) + arg1 = _Arg(l=cppscope.handle) + arg2 = _Arg(l=index) + args = [c_resolve_name(space, charp2str_free(space, + call_capi(space, 'method_template_arg_name', [arg1, arg2, _Arg(l=iarg)])) + ) for iarg in range(nargs)] + return args + +def c_get_method(space, cppscope, index): + args = [_Arg(l=cppscope.handle), _Arg(l=index)] + return rffi.cast(C_METHOD, space.int_w(call_capi(space, 'get_method', args))) +def c_get_global_operator(space, nss, lc, rc, op): + if nss is not None: + args = [_Arg(l=nss.handle), _Arg(l=lc.handle), _Arg(l=rc.handle), _Arg(s=op)] + return rffi.cast(WLAVC_INDEX, space.int_w(call_capi(space, 'get_global_operator', args))) + return rffi.cast(WLAVC_INDEX, -1) + +# method properties ---------------------------------------------------------- +def c_is_constructor(space, cppclass, index): + args = [_Arg(l=cppclass.handle), _Arg(l=index)] + return space.bool_w(call_capi(space, 'is_constructor', args)) +def c_is_staticmethod(space, cppclass, index): + args = [_Arg(l=cppclass.handle), _Arg(l=index)] + return space.bool_w(call_capi(space, 'is_staticmethod', args)) + +# data member reflection information ----------------------------------------- +def c_num_datamembers(space, cppscope): + return space.int_w(call_capi(space, 'num_datamembers', [_Arg(l=cppscope.handle)])) +def c_datamember_name(space, cppscope, datamember_index): + args = [_Arg(l=cppscope.handle), _Arg(l=datamember_index)] + return charp2str_free(space, call_capi(space, 'datamember_name', args)) +def c_datamember_type(space, cppscope, datamember_index): + args = [_Arg(l=cppscope.handle), _Arg(l=datamember_index)] + return charp2str_free(space, call_capi(space, 'datamember_type', args)) +def c_datamember_offset(space, cppscope, datamember_index): + args = [_Arg(l=cppscope.handle), _Arg(l=datamember_index)] + return _cdata_to_size_t(space, call_capi(space, 'datamember_offset', args)) + +def c_datamember_index(space, cppscope, name): + args = [_Arg(l=cppscope.handle), _Arg(s=name)] + return space.int_w(call_capi(space, 'datamember_index', args)) + +# data member properties ----------------------------------------------------- +def c_is_publicdata(space, cppscope, datamember_index): + args = [_Arg(l=cppscope.handle), _Arg(l=datamember_index)] + return space.bool_w(call_capi(space, 'is_publicdata', args)) +def c_is_staticdata(space, cppscope, datamember_index): + args = [_Arg(l=cppscope.handle), _Arg(l=datamember_index)] + return space.bool_w(call_capi(space, 'is_staticdata', args)) + +# misc helpers --------------------------------------------------------------- +def c_strtoll(space, svalue): + return space.r_longlong_w(call_capi(space, 'strtoll', [_Arg(s=svalue)])) +def c_strtoull(space, svalue): + return space.r_ulonglong_w(call_capi(space, 'strtoull', [_Arg(s=svalue)])) +def c_free(space, voidp): + call_capi(space, 'free', [_Arg(vp=voidp)]) + +def charp2str_free(space, cdata): + charp = rffi.cast(rffi.CCHARP, _cdata_to_ptr(space, cdata)) + pystr = rffi.charp2str(charp) + c_free(space, rffi.cast(rffi.VOIDP, charp)) + return pystr + +def c_charp2stdstring(space, svalue): + return _cdata_to_cobject(space, call_capi(space, 'charp2stdstring', [_Arg(s=svalue)])) +def c_stdstring2stdstring(space, cppobject): + return _cdata_to_cobject(space, call_capi(space, 'stdstring2stdstring', [_Arg(l=cppobject)])) +def c_assign2stdstring(space, cppobject, svalue): + args = [_Arg(l=cppobject), _Arg(s=svalue)] + call_capi(space, 'assign2stdstring', args) +def c_free_stdstring(space, cppobject): + call_capi(space, 'free_stdstring', [_Arg(l=cppobject)]) + +# loadable-capi-specific pythonizations (none, as the capi isn't known until runtime) +def register_pythonizations(space): + "NOT_RPYTHON" + pass + +def pythonize(space, name, w_pycppclass): + pass diff --git a/pypy/module/cppyy/capi/reflex_capi.py b/pypy/module/cppyy/capi/reflex_capi.py --- a/pypy/module/cppyy/capi/reflex_capi.py +++ b/pypy/module/cppyy/capi/reflex_capi.py @@ -3,7 +3,7 @@ from rpython.rlib import libffi from rpython.translator.tool.cbuild import ExternalCompilationInfo -__all__ = ['identify', 'eci', 'c_load_dictionary'] +__all__ = ['identify', 'std_string_name', 'eci', 'c_load_dictionary'] pkgpath = py.path.local(__file__).dirpath().join(os.pardir) srcpath = pkgpath.join("src") @@ -35,6 +35,8 @@ ts_memory = 'auto' ts_helper = 'auto' +std_string_name = 'std::basic_string' + eci = ExternalCompilationInfo( separate_module_files=[srcpath.join("reflexcwrapper.cxx")], include_dirs=[incpath] + rootincpath, diff --git a/pypy/module/cppyy/converter.py b/pypy/module/cppyy/converter.py --- a/pypy/module/cppyy/converter.py +++ b/pypy/module/cppyy/converter.py @@ -178,7 +178,7 @@ raise OperationError(space.w_TypeError, space.wrap("raw buffer interface not supported")) ba = rffi.cast(rffi.CCHARP, address) - ba[capi.c_function_arg_typeoffset()] = 'o' + ba[capi.c_function_arg_typeoffset(space)] = 'o' def from_memory(self, space, w_obj, w_pycppclass, offset): # read access, so no copy needed @@ -249,7 +249,7 @@ x = rffi.cast(self.c_ptrtype, address) x[0] = self._unwrap_object(space, w_obj) ba = rffi.cast(rffi.CCHARP, address) - ba[capi.c_function_arg_typeoffset()] = self.typecode + ba[capi.c_function_arg_typeoffset(space)] = self.typecode class VoidConverter(TypeConverter): @@ -352,7 +352,7 @@ arg = space.str_w(w_obj) x[0] = rffi.cast(rffi.LONG, rffi.str2charp(arg)) ba = rffi.cast(rffi.CCHARP, address) - ba[capi.c_function_arg_typeoffset()] = 'o' + ba[capi.c_function_arg_typeoffset(space)] = 'o' def from_memory(self, space, w_obj, w_pycppclass, offset): address = self._get_raw_address(space, w_obj, offset) @@ -379,7 +379,7 @@ x = rffi.cast(rffi.VOIDPP, address) x[0] = self._unwrap_object(space, w_obj) ba = rffi.cast(rffi.CCHARP, address) - ba[capi.c_function_arg_typeoffset()] = 'o' + ba[capi.c_function_arg_typeoffset(space)] = 'o' def convert_argument_libffi(self, space, w_obj, address, call_local): x = rffi.cast(rffi.VOIDPP, address) @@ -399,7 +399,7 @@ except TypeError: r[0] = rffi.cast(rffi.VOIDP, get_rawobject(space, w_obj)) x[0] = rffi.cast(rffi.VOIDP, call_local) - ba[capi.c_function_arg_typeoffset()] = 'a' + ba[capi.c_function_arg_typeoffset(space)] = 'a' def finalize_call(self, space, w_obj, call_local): r = rffi.cast(rffi.VOIDPP, call_local) @@ -425,9 +425,9 @@ def _unwrap_object(self, space, w_obj): from pypy.module.cppyy.interp_cppyy import W_CPPInstance if isinstance(w_obj, W_CPPInstance): - if capi.c_is_subtype(w_obj.cppclass, self.cppclass): From noreply at buildbot.pypy.org Tue Apr 23 00:05:50 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Tue, 23 Apr 2013 00:05:50 +0200 (CEST) Subject: [pypy-commit] pypy py3k: skip these for now, they deadlock windows Message-ID: <20130422220550.0C0D71C0328@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63558:2dc244b54a19 Date: 2013-04-22 15:03 -0700 http://bitbucket.org/pypy/pypy/changeset/2dc244b54a19/ Log: skip these for now, they deadlock windows diff --git a/lib-python/3/test/test_class.py b/lib-python/3/test/test_class.py --- a/lib-python/3/test/test_class.py +++ b/lib-python/3/test/test_class.py @@ -1,5 +1,6 @@ "Test the functionality of Python classes implementing operators." +import sys import unittest from test import support @@ -467,6 +468,9 @@ self.assertRaises(TypeError, hash, C2()) + @unittest.skipIf(support.check_impl_detail(pypy=True) and + sys.platform == 'win32', + "XXX: https://bugs.pypy.org/issue1461") def testSFBug532646(self): # Test for SF bug 532646 diff --git a/lib-python/3/test/test_descr.py b/lib-python/3/test/test_descr.py --- a/lib-python/3/test/test_descr.py +++ b/lib-python/3/test/test_descr.py @@ -3462,6 +3462,9 @@ list.__init__(a, sequence=[0, 1, 2]) self.assertEqual(a, [0, 1, 2]) + @unittest.skipIf(support.check_impl_detail(pypy=True) and + sys.platform == 'win32', + "XXX: https://bugs.pypy.org/issue1461") def test_recursive_call(self): # Testing recursive __call__() by setting to instance of class... class A(object): From noreply at buildbot.pypy.org Tue Apr 23 02:01:36 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Tue, 23 Apr 2013 02:01:36 +0200 (CEST) Subject: [pypy-commit] pypy py3k: apply pickling workarounds from default Message-ID: <20130423000136.66D931C023B@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63559:e5bfefa13f01 Date: 2013-04-22 16:58 -0700 http://bitbucket.org/pypy/pypy/changeset/e5bfefa13f01/ Log: apply pickling workarounds from default diff --git a/lib-python/3/multiprocessing/forking.py b/lib-python/3/multiprocessing/forking.py --- a/lib-python/3/multiprocessing/forking.py +++ b/lib-python/3/multiprocessing/forking.py @@ -79,10 +79,13 @@ ForkingPickler.register(type(_C().f), _reduce_method) -def _reduce_method_descriptor(m): - return getattr, (m.__objclass__, m.__name__) -ForkingPickler.register(type(list.append), _reduce_method_descriptor) -ForkingPickler.register(type(int.__add__), _reduce_method_descriptor) +if type(list.append) is not type(ForkingPickler.save): + # Some python implementations have plain functions even for builtin + # types + def _reduce_method_descriptor(m): + return getattr, (m.__objclass__, m.__name__) + ForkingPickler.register(type(list.append), _reduce_method_descriptor) + ForkingPickler.register(type(int.__add__), _reduce_method_descriptor) try: from functools import partial From noreply at buildbot.pypy.org Tue Apr 23 09:27:30 2013 From: noreply at buildbot.pypy.org (arigo) Date: Tue, 23 Apr 2013 09:27:30 +0200 (CEST) Subject: [pypy-commit] pypy default: (yamt) Accept any exception from 'import _curses', like cffi's VerificationError. Message-ID: <20130423072730.A77721C0014@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63560:b040a647f887 Date: 2013-04-23 09:25 +0200 http://bitbucket.org/pypy/pypy/changeset/b040a647f887/ Log: (yamt) Accept any exception from 'import _curses', like cffi's VerificationError. diff --git a/pypy/module/_minimal_curses/__init__.py b/pypy/module/_minimal_curses/__init__.py --- a/pypy/module/_minimal_curses/__init__.py +++ b/pypy/module/_minimal_curses/__init__.py @@ -1,6 +1,6 @@ try: import _curses -except ImportError: +except Exception: # probably ImportError or cffi's VerificationError try: # when running on top of pypy before it had _curses, settle for minimal # we prefer _curses so any constants added make it into _minimal_curses From noreply at buildbot.pypy.org Tue Apr 23 11:12:52 2013 From: noreply at buildbot.pypy.org (bivab) Date: Tue, 23 Apr 2013 11:12:52 +0200 (CEST) Subject: [pypy-commit] pypy default: import test_exception from x86 Message-ID: <20130423091252.94E861C02DA@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63561:322b9239f9a2 Date: 2013-04-23 04:02 -0500 http://bitbucket.org/pypy/pypy/changeset/322b9239f9a2/ Log: import test_exception from x86 diff --git a/rpython/jit/backend/x86/test/test_exception.py b/rpython/jit/backend/arm/test/test_exception.py copy from rpython/jit/backend/x86/test/test_exception.py copy to rpython/jit/backend/arm/test/test_exception.py --- a/rpython/jit/backend/x86/test/test_exception.py +++ b/rpython/jit/backend/arm/test/test_exception.py @@ -1,9 +1,9 @@ import py -from rpython.jit.backend.x86.test.test_basic import Jit386Mixin +from rpython.jit.backend.arm.test.support import JitARMMixin from rpython.jit.metainterp.test.test_exception import ExceptionTests -class TestExceptions(Jit386Mixin, ExceptionTests): +class TestExceptions(JitARMMixin, ExceptionTests): # for the individual tests see # ====> ../../../metainterp/test/test_exception.py From noreply at buildbot.pypy.org Tue Apr 23 11:12:53 2013 From: noreply at buildbot.pypy.org (bivab) Date: Tue, 23 Apr 2013 11:12:53 +0200 (CEST) Subject: [pypy-commit] pypy default: more register clobbering issues in _store_and_reset_exception Message-ID: <20130423091253.E3DD61C02DA@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63562:a801192368b9 Date: 2013-04-23 04:08 -0500 http://bitbucket.org/pypy/pypy/changeset/a801192368b9/ Log: more register clobbering issues in _store_and_reset_exception diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -109,22 +109,25 @@ assert excvalloc is not r.ip assert exctploc is not r.ip tmpreg = r.lr + mc.gen_load_int(r.ip.value, self.cpu.pos_exc_value()) if excvalloc is not None: # store assert excvalloc.is_reg() - mc.gen_load_int(r.ip.value, self.cpu.pos_exc_value()) self.load_reg(mc, excvalloc, r.ip) if on_frame: # store exc_value in JITFRAME ofs = self.cpu.get_ofs_of_frame_field('jf_guard_exc') assert check_imm_arg(ofs) + # self.load_reg(mc, r.ip, r.ip, helper=tmpreg) + # self.store_reg(mc, r.ip, r.fp, ofs, helper=tmpreg) - mc.gen_load_int(r.ip.value, self.cpu.pos_exc_value()) if exctploc is not None: # store pos_exception in exctploc assert exctploc.is_reg() - mc.gen_load_int(tmpreg.value, self.cpu.pos_exception()) - self.load_reg(mc, exctploc, tmpreg) + mc.gen_load_int(r.ip.value, self.cpu.pos_exception()) + self.load_reg(mc, exctploc, r.ip, helper=tmpreg) + + if on_frame or exctploc is not None: mc.gen_load_int(r.ip.value, self.cpu.pos_exc_value()) # reset exception From noreply at buildbot.pypy.org Tue Apr 23 11:23:56 2013 From: noreply at buildbot.pypy.org (bivab) Date: Tue, 23 Apr 2013 11:23:56 +0200 (CEST) Subject: [pypy-commit] buildbot default: fix build triggered by armhf translation Message-ID: <20130423092356.9731A1C02DA@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r793:66c54fd6df5b Date: 2013-04-23 11:23 +0200 http://bitbucket.org/pypy/buildbot/changeset/66c54fd6df5b/ Log: fix build triggered by armhf translation diff --git a/bot2/pypybuildbot/arm_master.py b/bot2/pypybuildbot/arm_master.py --- a/bot2/pypybuildbot/arm_master.py +++ b/bot2/pypybuildbot/arm_master.py @@ -104,10 +104,12 @@ schedulers = [ Nightly("nighly-arm-0-00", [ + BUILDJITLINUXARM, # on hhu-cross-armel, uses 1 core + BUILDJITLINUXARMHF_RASPBIAN, # on hhu-cross-raspbianhf, uses 1 core + BUILDLINUXARM, # on hhu-cross-armel, uses 1 core - BUILDJITLINUXARM, # on hhu-cross-armel, uses 1 core BUILDLINUXARMHF_RASPBIAN, # on hhu-cross-raspbianhf, uses 1 core - BUILDJITLINUXARMHF_RASPBIAN, # on hhu-cross-raspbianhf, uses 1 core + JITBACKENDONLYLINUXARMEL, # on hhu-imx.53 JITBACKENDONLYLINUXARMHF, # on hhu-raspberry-pi JITBACKENDONLYLINUXARMHF_v7, # on cubieboard-bob @@ -127,7 +129,7 @@ Triggerable("JITLINUXARMHF_RASPBIAN_scheduler", [ JITLINUXARMHF_RASPBIAN, # triggered by BUILDJITLINUXARMHF_RASPBIAN, on hhu-raspberry-pi - JITBACKENDONLYLINUXARMHF_v7, # triggered by BUILDJITLINUXARMHF_RASPBIAN, on cubieboard-bob + JITLINUXARMHF_v7, # triggered by BUILDJITLINUXARMHF_RASPBIAN, on cubieboard-bob ]), ] From noreply at buildbot.pypy.org Tue Apr 23 13:17:41 2013 From: noreply at buildbot.pypy.org (fijal) Date: Tue, 23 Apr 2013 13:17:41 +0200 (CEST) Subject: [pypy-commit] benchmarks default: improve reporting Message-ID: <20130423111741.88F1C1C0014@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r206:842036652c02 Date: 2013-04-23 13:05 +0200 http://bitbucket.org/pypy/benchmarks/changeset/842036652c02/ Log: improve reporting diff --git a/unladen_swallow/perf.py b/unladen_swallow/perf.py --- a/unladen_swallow/perf.py +++ b/unladen_swallow/perf.py @@ -445,7 +445,7 @@ base_python: path to the reference Python binary. changed_python: path to the experimental Python binary. options: optparse.Values instance. - *args, **kwargs: will be passed through to benchmark_function. + *args, **kwargs: will be passed through to benchmark_function. Returns: An object representing differences between the two benchmark runs. @@ -743,7 +743,7 @@ Returns: (stdout, mem_usage), where stdout is the captured stdout as a string; mem_usage is a list of memory usage samples in kilobytes (if - track_memory is False, mem_usage is None). + track_memory is False, mem_usage is None). Raises: RuntimeError: if the command failed. The value of the exception will @@ -758,7 +758,9 @@ future = MemoryUsageFuture(subproc.pid) result, err = subproc.communicate() if subproc.returncode != 0: - raise RuntimeError("Benchmark died: " + err) + print result + raise RuntimeError("Benchmark died (returncode: %d): %s" % + (subproc.returncode, err)) if track_memory: mem_usage = future.GetMemoryUsage() return result, mem_usage @@ -1440,7 +1442,7 @@ BENCH_FUNCS = _FindAllBenchmarks(globals()) # Benchmark groups. The "default" group is what's run if no -b option is -# specified. +# specified. # If you update the default group, be sure to update the module docstring, too. # An "all" group which includes every benchmark perf.py knows about is generated # automatically. @@ -1568,7 +1570,7 @@ " Valid benchmarks are: " + ", ".join(bench_groups.keys() + all_benchmarks))) parser.add_option("--inherit_env", metavar="ENVVARS", type="string", action="callback", - callback=ParseEnvVars, default=[], + callback=ParseEnvVars, default=[], help=("Comma-separated list of environment variable names" " that are inherited from the parent environment" " when running benchmarking subprocesses.")) From noreply at buildbot.pypy.org Tue Apr 23 13:17:42 2013 From: noreply at buildbot.pypy.org (fijal) Date: Tue, 23 Apr 2013 13:17:42 +0200 (CEST) Subject: [pypy-commit] benchmarks default: merge Message-ID: <20130423111742.F346F1C0014@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r207:45bb72a752c5 Date: 2013-04-23 13:17 +0200 http://bitbucket.org/pypy/benchmarks/changeset/45bb72a752c5/ Log: merge diff --git a/unladen_swallow/perf.py b/unladen_swallow/perf.py --- a/unladen_swallow/perf.py +++ b/unladen_swallow/perf.py @@ -445,7 +445,7 @@ base_python: path to the reference Python binary. changed_python: path to the experimental Python binary. options: optparse.Values instance. - *args, **kwargs: will be passed through to benchmark_function. + *args, **kwargs: will be passed through to benchmark_function. Returns: An object representing differences between the two benchmark runs. @@ -743,7 +743,7 @@ Returns: (stdout, mem_usage), where stdout is the captured stdout as a string; mem_usage is a list of memory usage samples in kilobytes (if - track_memory is False, mem_usage is None). + track_memory is False, mem_usage is None). Raises: RuntimeError: if the command failed. The value of the exception will @@ -758,7 +758,9 @@ future = MemoryUsageFuture(subproc.pid) result, err = subproc.communicate() if subproc.returncode != 0: - raise RuntimeError("Benchmark died: " + err) + print result + raise RuntimeError("Benchmark died (returncode: %d): %s" % + (subproc.returncode, err)) if track_memory: mem_usage = future.GetMemoryUsage() return result, mem_usage @@ -1440,7 +1442,7 @@ BENCH_FUNCS = _FindAllBenchmarks(globals()) # Benchmark groups. The "default" group is what's run if no -b option is -# specified. +# specified. # If you update the default group, be sure to update the module docstring, too. # An "all" group which includes every benchmark perf.py knows about is generated # automatically. @@ -1568,7 +1570,7 @@ " Valid benchmarks are: " + ", ".join(bench_groups.keys() + all_benchmarks))) parser.add_option("--inherit_env", metavar="ENVVARS", type="string", action="callback", - callback=ParseEnvVars, default=[], + callback=ParseEnvVars, default=[], help=("Comma-separated list of environment variable names" " that are inherited from the parent environment" " when running benchmarking subprocesses.")) From noreply at buildbot.pypy.org Tue Apr 23 13:22:37 2013 From: noreply at buildbot.pypy.org (fijal) Date: Tue, 23 Apr 2013 13:22:37 +0200 (CEST) Subject: [pypy-commit] benchmarks default: improve reporting even more Message-ID: <20130423112237.95B6A1C023D@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r208:86f449bbae48 Date: 2013-04-23 13:22 +0200 http://bitbucket.org/pypy/benchmarks/changeset/86f449bbae48/ Log: improve reporting even more diff --git a/unladen_swallow/perf.py b/unladen_swallow/perf.py --- a/unladen_swallow/perf.py +++ b/unladen_swallow/perf.py @@ -668,7 +668,12 @@ A string summarizing the difference between the runs, suitable for human consumption. """ - assert len(base_times) == len(changed_times) + if len(base_times) != len(changed_times): + print "Base:" + print base_times + print "Changed:" + print changed_times + raise Exception("length did not match") if options.no_statistics: return RawResult(base_times, changed_times) if len(base_times) == 1: From noreply at buildbot.pypy.org Tue Apr 23 14:29:03 2013 From: noreply at buildbot.pypy.org (bivab) Date: Tue, 23 Apr 2013 14:29:03 +0200 (CEST) Subject: [pypy-commit] buildbot default: Pass the additional and machine specific configurations files to the testrunner for app-level tests Message-ID: <20130423122903.0844C1C0014@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r794:12c1cea0bf64 Date: 2013-04-23 14:25 +0200 http://bitbucket.org/pypy/buildbot/changeset/12c1cea0bf64/ Log: Pass the additional and machine specific configurations files to the testrunner for app-level tests diff --git a/bot2/pypybuildbot/builds.py b/bot2/pypybuildbot/builds.py --- a/bot2/pypybuildbot/builds.py +++ b/bot2/pypybuildbot/builds.py @@ -312,6 +312,8 @@ command=prefix + ["python", "testrunner/runner.py", "--logfile=pytest-A.log", "--config=pypy/pytest-A.cfg", + "--config=pypy/pytest-A.py", + "--config=~/machine-A_cfg.py", "--root=pypy", "--timeout=3600" ] + ["--config=%s" % cfg for cfg in app_tests], logfiles={'pytestLog': 'pytest-A.log'}, From noreply at buildbot.pypy.org Tue Apr 23 14:29:36 2013 From: noreply at buildbot.pypy.org (bivab) Date: Tue, 23 Apr 2013 14:29:36 +0200 (CEST) Subject: [pypy-commit] pypy default: Add custom test collection for app-level tests, mainly to split collected dirs Message-ID: <20130423122936.EFBDF1C0014@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63563:820183b703c1 Date: 2013-04-23 14:24 +0200 http://bitbucket.org/pypy/pypy/changeset/820183b703c1/ Log: Add custom test collection for app-level tests, mainly to split collected dirs and collect the files individually diff --git a/pypy/pytest-A.py b/pypy/pytest-A.py new file mode 100644 --- /dev/null +++ b/pypy/pytest-A.py @@ -0,0 +1,31 @@ +# custom test collection for the app-level testrunner +import platform + +DIRS_SPLIT = { + 'arm': ['interpreter/astcompiler/test', + 'interpreter/pyparser/test', + 'interpreter/test', + 'interpreter/test2', + 'objspace/std/test', + ], +} + + +def get_arch(): + arch = platform.machine().lower() + if arch.startswith('arm'): + return 'arm' + if arch.startswith('x86'): + return 'x86' + return arch + + +def collect_one_testdir(testdirs, reldir, tests): + arch = get_arch() + dirsplit = DIRS_SPLIT.get(arch, []) + for dir in dirsplit: + if reldir.startswith(dir): + testdirs.extend(tests) + break + else: + testdirs.append(reldir) From noreply at buildbot.pypy.org Tue Apr 23 14:39:34 2013 From: noreply at buildbot.pypy.org (arigo) Date: Tue, 23 Apr 2013 14:39:34 +0200 (CEST) Subject: [pypy-commit] pypy stm-gc-2: Fix Message-ID: <20130423123934.4182F1C0014@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: stm-gc-2 Changeset: r63564:c848ebb6e9e1 Date: 2013-04-23 14:13 +0200 http://bitbucket.org/pypy/pypy/changeset/c848ebb6e9e1/ Log: Fix diff --git a/rpython/rlib/rstm.py b/rpython/rlib/rstm.py --- a/rpython/rlib/rstm.py +++ b/rpython/rlib/rstm.py @@ -169,7 +169,7 @@ # ____________________________________________________________ class ThreadLocalReference(object): - _COUNT = 0 + _COUNT = 1 def __init__(self, Cls): "NOT_RPYTHON: must be prebuilt" diff --git a/rpython/translator/stm/threadlocalref.py b/rpython/translator/stm/threadlocalref.py --- a/rpython/translator/stm/threadlocalref.py +++ b/rpython/translator/stm/threadlocalref.py @@ -2,11 +2,6 @@ from rpython.translator.unsimplify import varoftype from rpython.flowspace.model import SpaceOperation, Constant -# -# Note: all this slightly messy code is to have 'stm_threadlocalref_flush' -# which zeroes *all* thread-locals variables accessed with -# stm_threadlocalref_{get,set}. -# def transform_tlref(graphs): ids = set() @@ -41,20 +36,23 @@ for i in range(len(block.operations)-1, -1, -1): op = block.operations[i] if op.opname == 'stm_threadlocalref_set': + id = op.args[0].value + c_num = Constant(ids.index(id), lltype.Signed) v_addr = varoftype(lltype.Ptr(ARRAY)) - ops = getaddr(op.args[0], v_addr) + ops = getaddr(c_num, v_addr) ops.append(SpaceOperation('stm_threadlocalref_llset', [v_addr, op.args[1]], op.result)) block.operations[i:i+1] = ops elif op.opname == 'stm_threadlocalref_get': + id = op.args[0].value + c_num = Constant(ids.index(id), lltype.Signed) v_array = varoftype(lltype.Ptr(ARRAY)) ops = [ SpaceOperation('getfield', [c_threadlocalref, c_fieldname], v_array), - SpaceOperation('getarrayitem', [v_array, - op.args[0]], + SpaceOperation('getarrayitem', [v_array, c_num], op.result)] block.operations[i:i+1] = ops elif op.opname == 'stm_threadlocalref_lladdr': From noreply at buildbot.pypy.org Tue Apr 23 16:02:24 2013 From: noreply at buildbot.pypy.org (fijal) Date: Tue, 23 Apr 2013 16:02:24 +0200 (CEST) Subject: [pypy-commit] pypy vref-copy: this is not going anywhere Message-ID: <20130423140224.3C3541C0014@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: vref-copy Changeset: r63565:fc22917ceb73 Date: 2013-04-23 16:01 +0200 http://bitbucket.org/pypy/pypy/changeset/fc22917ceb73/ Log: this is not going anywhere From noreply at buildbot.pypy.org Tue Apr 23 18:08:20 2013 From: noreply at buildbot.pypy.org (bivab) Date: Tue, 23 Apr 2013 18:08:20 +0200 (CEST) Subject: [pypy-commit] pypy default: Add an alternative method to detect main cpu model and size using different Message-ID: <20130423160820.B7E411C154E@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63566:1891968c05e4 Date: 2013-04-23 18:06 +0200 http://bitbucket.org/pypy/pypy/changeset/1891968c05e4/ Log: Add an alternative method to detect main cpu model and size using different compiler macros, useful for cross-compilation builds. diff --git a/rpython/jit/backend/detect_cpu.py b/rpython/jit/backend/detect_cpu.py --- a/rpython/jit/backend/detect_cpu.py +++ b/rpython/jit/backend/detect_cpu.py @@ -2,12 +2,40 @@ Processor auto-detection """ import sys, os +from rpython.rtyper.tool.rffi_platform import getdefined +from rpython.translator.platform import is_host_build class ProcessorAutodetectError(Exception): pass + +def detect_main_model_and_size_from_platform(): + # based on http://sourceforge.net/p/predef/wiki/Architectures/ + mapping = { + ('x86', '64'): [ + '__amd64__', '__amd64', '__x86_64__', '__x86_64', # AMD64 + '__ia64__', '_IA64', '__IA64__' # Intel Itanium (IA-64) + ], + ('arm', '32'): ['__arm__', '__thumb__'], + ('x86', '32'): ['i386', '__i386', '__i386__', '__i686__',], + ('ppc', '64'): ['__powerpc64__'], + } + for k, v in mapping.iteritems(): + for macro in v: + if not getdefined(macro, ''): + continue + return k + raise ProcessorAutodetectError, "Cannot detect processor using compiler macros" + + +def detect_main_model_from_platform(): + return detect_main_model_and_size_from_platform()[0] + + def autodetect_main_model(): + if not is_host_build(): + return detect_main_model_from_platform() mach = None try: import platform @@ -40,6 +68,8 @@ return mach def autodetect_main_model_and_size(): + if not is_host_build(): + return detect_main_model_and_size_from_platform() model = autodetect_main_model() if sys.maxint == 2**31-1: model += '_32' diff --git a/rpython/jit/backend/test/test_detect_cpu.py b/rpython/jit/backend/test/test_detect_cpu.py --- a/rpython/jit/backend/test/test_detect_cpu.py +++ b/rpython/jit/backend/test/test_detect_cpu.py @@ -26,3 +26,8 @@ else: from rpython.jit.backend.model import AbstractCPU assert issubclass(cpu, AbstractCPU) + + +def test_detect_main_model_and_size_from_platform(): + info = detect_main_model_and_size_from_platform() + assert detect_main_model_and_size_from_platform() == info diff --git a/rpython/translator/platform/__init__.py b/rpython/translator/platform/__init__.py --- a/rpython/translator/platform/__init__.py +++ b/rpython/translator/platform/__init__.py @@ -347,3 +347,6 @@ global host host = platform + +def is_host_build(): + return host == platform diff --git a/rpython/translator/platform/test/test_platform.py b/rpython/translator/platform/test/test_platform.py --- a/rpython/translator/platform/test/test_platform.py +++ b/rpython/translator/platform/test/test_platform.py @@ -172,3 +172,13 @@ assert X() == X() assert Y(3) == Y(3) assert Y(2) != Y(3) + + +def test_is_host_build(): + from rpython.translator import platform + assert platform.host == platform.platform + + assert platform.is_host_build() + platform.set_platform('maemo', None) + assert platform.host != platform.platform + assert not platform.is_host_build() From noreply at buildbot.pypy.org Tue Apr 23 18:14:01 2013 From: noreply at buildbot.pypy.org (bivab) Date: Tue, 23 Apr 2013 18:14:01 +0200 (CEST) Subject: [pypy-commit] pypy default: fix test Message-ID: <20130423161401.8C95C1C023D@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63567:aa774bc17591 Date: 2013-04-23 18:13 +0200 http://bitbucket.org/pypy/pypy/changeset/aa774bc17591/ Log: fix test diff --git a/rpython/jit/backend/detect_cpu.py b/rpython/jit/backend/detect_cpu.py --- a/rpython/jit/backend/detect_cpu.py +++ b/rpython/jit/backend/detect_cpu.py @@ -25,7 +25,7 @@ for macro in v: if not getdefined(macro, ''): continue - return k + return '_'.join(k) raise ProcessorAutodetectError, "Cannot detect processor using compiler macros" diff --git a/rpython/jit/backend/test/test_detect_cpu.py b/rpython/jit/backend/test/test_detect_cpu.py --- a/rpython/jit/backend/test/test_detect_cpu.py +++ b/rpython/jit/backend/test/test_detect_cpu.py @@ -29,5 +29,5 @@ def test_detect_main_model_and_size_from_platform(): - info = detect_main_model_and_size_from_platform() + info = autodetect_main_model_and_size() assert detect_main_model_and_size_from_platform() == info From noreply at buildbot.pypy.org Tue Apr 23 18:14:16 2013 From: noreply at buildbot.pypy.org (timfel) Date: Tue, 23 Apr 2013 18:14:16 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: (lwassermann, timfel) fix nlr when underflowing python c stack Message-ID: <20130423161416.BD5641C023D@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: Changeset: r319:17a80c53451f Date: 2013-04-23 16:12 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/17a80c53451f/ Log: (lwassermann, timfel) fix nlr when underflowing python c stack diff --git a/spyvm/interpreter.py b/spyvm/interpreter.py --- a/spyvm/interpreter.py +++ b/spyvm/interpreter.py @@ -65,13 +65,16 @@ s_new_context = w_active_context.as_context_get_shadow(self.space) while True: assert self.remaining_stack_depth == self.max_stack_depth + # Need to save s_sender, c_loop will nil this on return s_sender = s_new_context.s_sender() try: s_new_context = self.c_loop(s_new_context) except StackOverflow, e: s_new_context = e.s_context except Return, nlr: + s_new_context = s_sender while s_new_context is not nlr.s_target_context: + s_sender = s_new_context.s_sender() s_new_context.mark_returned() s_new_context = s_sender s_new_context.push(nlr.value) From noreply at buildbot.pypy.org Tue Apr 23 18:14:17 2013 From: noreply at buildbot.pypy.org (timfel) Date: Tue, 23 Apr 2013 18:14:17 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: when the idle process relinquishes the processor, fire the timer semaphore Message-ID: <20130423161417.E09BA1C023D@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: Changeset: r320:569c75f21d39 Date: 2013-04-23 16:13 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/569c75f21d39/ Log: when the idle process relinquishes the processor, fire the timer semaphore diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -1332,6 +1332,8 @@ import time time_s = time_mu_s / 1000000.0 time.sleep(time_s) + interp.interrupt_check_counter = 0 + interp.quick_check_for_interrupt(s_frame, dec=0) return w_rcvr @expose_primitive(FORCE_DISPLAY_UPDATE, unwrap_spec=[object]) From noreply at buildbot.pypy.org Tue Apr 23 18:14:18 2013 From: noreply at buildbot.pypy.org (timfel) Date: Tue, 23 Apr 2013 18:14:18 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: (lwassermann, timfel) refactor expose_primitive, split it into an Message-ID: <20130423161418.E544D1C023D@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: Changeset: r321:7a5037c77a3d Date: 2013-04-23 16:14 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/7a5037c77a3d/ Log: (lwassermann, timfel) refactor expose_primitive, split it into an unwrapping+stack-mgmt decorator and a decorator that adds the func to the prim table (so we can re-use the former to implement plugin prims) diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -52,8 +52,6 @@ def expose_primitive(code, unwrap_spec=None, no_result=False, result_is_new_frame=False, clean_stack=True, compiled_method=False): - # some serious magic, don't look - from rpython.rlib.unroll import unrolling_iterable # heuristics to give it a nice name name = None for key, value in globals().iteritems(): @@ -64,13 +62,33 @@ else: name = key + def decorator(func): + assert code not in prim_table + func.func_name = "prim_" + name + + wrapped = wrap_primitive( + unwrap_spec=unwrap_spec, no_result=no_result, + result_is_new_frame=result_is_new_frame, + clean_stack=clean_stack, compiled_method=compiled_method + )(func) + wrapped.func_name = "wrap_prim_" + name + prim_table[code] = wrapped + prim_table_implemented_only.append((code, wrapped)) + return func + return decorator + + +def wrap_primitive(unwrap_spec=None, no_result=False, + result_is_new_frame=False, clean_stack=True, + compiled_method=False): + # some serious magic, don't look + from rpython.rlib.unroll import unrolling_iterable + assert not (no_result and result_is_new_frame) # Because methods always have a receiver, an unwrap_spec of [] is a bug assert unwrap_spec is None or unwrap_spec def decorator(func): - assert code not in prim_table - func.func_name = "prim_" + name if unwrap_spec is None: def wrapped(interp, s_frame, argument_count_m1, s_method=None): if compiled_method: @@ -138,10 +156,7 @@ assert w_result is not None assert isinstance(w_result, model.W_Object) s_frame.push(w_result) - wrapped.func_name = "wrap_prim_" + name - prim_table[code] = wrapped - prim_table_implemented_only.append((code, wrapped)) - return func + return wrapped return decorator # ___________________________________________________________________________ From noreply at buildbot.pypy.org Tue Apr 23 18:14:19 2013 From: noreply at buildbot.pypy.org (timfel) Date: Tue, 23 Apr 2013 18:14:19 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: (lwassermann, timfel) highlight context switches when tracing Message-ID: <20130423161419.E4D9D1C023D@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: Changeset: r322:833ded4effcf Date: 2013-04-23 18:04 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/833ded4effcf/ Log: (lwassermann, timfel) highlight context switches when tracing diff --git a/spyvm/interpreter.py b/spyvm/interpreter.py --- a/spyvm/interpreter.py +++ b/spyvm/interpreter.py @@ -79,6 +79,8 @@ s_new_context = s_sender s_new_context.push(nlr.value) except ProcessSwitch, p: + if self.trace: + print "====== Switch from: %s to: %s ======" % (s_new_context.short_str(0), p.s_new_context.short_str(0)) s_new_context = p.s_new_context def c_loop(self, s_context): From noreply at buildbot.pypy.org Tue Apr 23 18:14:21 2013 From: noreply at buildbot.pypy.org (timfel) Date: Tue, 23 Apr 2013 18:14:21 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: (lwassermann, timfel) use ovfcheck_float_to_int Message-ID: <20130423161421.166171C023D@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: Changeset: r323:49e6a94b64d1 Date: 2013-04-23 18:10 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/49e6a94b64d1/ Log: (lwassermann, timfel) use ovfcheck_float_to_int diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -286,8 +286,10 @@ @expose_primitive(FLOAT_TRUNCATED, unwrap_spec=[float]) def func(interp, s_frame, f): - w_res = interp.space.wrap_int(int(f)) - return w_res + try: + return interp.space.wrap_int(rarithmetic.ovfcheck_float_to_int(f)) + except OverflowError: + raise PrimitiveFailedError @expose_primitive(FLOAT_TIMES_TWO_POWER, unwrap_spec=[float, int]) def func(interp, s_frame, rcvr, arg): From noreply at buildbot.pypy.org Tue Apr 23 18:14:22 2013 From: noreply at buildbot.pypy.org (timfel) Date: Tue, 23 Apr 2013 18:14:22 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: (lwassermann, timfel) refactor run_benchmark to setup a process to run Message-ID: <20130423161422.157F01C023D@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: Changeset: r324:d0c8118a1e75 Date: 2013-04-23 18:11 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/d0c8118a1e75/ Log: (lwassermann, timfel) refactor run_benchmark to setup a process to run the benchmark in. this is closer to what Cog will do when we run a benchmark script from stdin diff --git a/targetimageloadingsmalltalk.py b/targetimageloadingsmalltalk.py --- a/targetimageloadingsmalltalk.py +++ b/targetimageloadingsmalltalk.py @@ -4,21 +4,41 @@ from rpython.rlib.streamio import open_file_as_stream from rpython.rlib import jit -from spyvm import model, interpreter, squeakimage, objspace, wrapper, model, \ - error +from spyvm import model, interpreter, squeakimage, objspace, wrapper,\ + error, shadow from spyvm.tool.analyseimage import create_image def _run_benchmark(interp, number, benchmark): - w_object = interp.space.wrap_int(number) + scheduler = wrapper.scheduler(interp.space) + w_hpp = scheduler.highest_priority_process() + w_benchmark_proc = model.W_PointersObject( + interp.space, + w_hpp.getclass(interp.space), + len(w_hpp._vars) + ) + + # XXX: Copied from interpreter >> perform + w_receiver = interp.space.wrap_int(number) + w_selector = interp.perform(interp.space.wrap_string(benchmark), "asSymbol") + w_method = model.W_CompiledMethod(header=512) + w_method.literalatput0(interp.space, 1, w_selector) + w_method.setbytes([chr(131), chr(0), chr(124)]) #returnTopFromMethod + s_method = w_method.as_compiledmethod_get_shadow(interp.space) + s_frame = shadow.MethodContextShadow.make_context(interp.space, s_method, w_receiver, [], None) + s_frame.push(w_receiver) + # second variable is suspended context + w_benchmark_proc.store(space, 1, s_frame.w_self()) + + # third variable is priority + priority = 40 + w_benchmark_proc.store(space, 2, space.wrap_int(priority)) + + # make process eligible for scheduling + wrapper.ProcessWrapper(interp.space, w_benchmark_proc).put_to_sleep() + t1 = time.time() - try: - w_result = interp.perform(w_object, benchmark) - except interpreter.ReturnFromTopLevel, e: - w_result = e.object - except error.Exit, e: - print e.msg - w_result = None + w_result = _run_image(interp) t2 = time.time() if w_result: if isinstance(w_result, model.W_BytesObject): @@ -35,10 +55,9 @@ assert isinstance(w_ctx, model.W_PointersObject) ap.store_suspended_context(space.w_nil) try: - interp.interpret_with_w_frame(w_ctx) + return interp.interpret_with_w_frame(w_ctx) except error.Exit, e: print e.msg - return 0 space = objspace.ObjSpace() @@ -112,7 +131,8 @@ if benchmark is not None: return _run_benchmark(interp, number, benchmark) else: - return _run_image(interp) + _run_image(interp) + return 0 # _____ Define and setup target ___ From noreply at buildbot.pypy.org Tue Apr 23 18:14:23 2013 From: noreply at buildbot.pypy.org (timfel) Date: Tue, 23 Apr 2013 18:14:23 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: (lwassermann, timfel) start adding some SocketPlugin primitives so we Message-ID: <20130423161423.15E3D1C023D@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: Changeset: r325:771472472998 Date: 2013-04-23 18:13 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/771472472998/ Log: (lwassermann, timfel) start adding some SocketPlugin primitives so we can eventually benchmark Seaside diff --git a/spyvm/plugins/__init__.py b/spyvm/plugins/__init__.py new file mode 100644 diff --git a/spyvm/plugins/plugin.py b/spyvm/plugins/plugin.py new file mode 100644 --- /dev/null +++ b/spyvm/plugins/plugin.py @@ -0,0 +1,38 @@ +from rpython.rlib import jit + +from spyvm import error +from spyvm.primitives import wrap_primitive + + +class Plugin(object): + def __init__(self): + self.prims = {} + self.userdata = {} + + def call(self, name, interp, s_frame, argcount, s_method): + func = self._find_prim(name) + if not func: + raise error.PrimitiveFailedError + else: + return func(interp, s_frame, argcount, s_method) + + @jit.elidable + def _find_prim(self, name): + return self.prims.get(name, None) + + def expose_primitive(self, unwrap_spec=None, no_result=False, + result_is_new_frame=False, clean_stack=True, + compiled_method=False): + def decorator(func): + wrapped = wrap_primitive( + unwrap_spec=unwrap_spec, no_result=no_result, + result_is_new_frame=result_is_new_frame, + clean_stack=clean_stack, compiled_method=compiled_method + )(func) + wrapped.func_name = "wrap_prim_" + func.func_name + self.prims[func.func_name] = wrapped + return func + return decorator + + def _freeze_(self): + return True diff --git a/spyvm/plugins/socket.py b/spyvm/plugins/socket.py new file mode 100644 --- /dev/null +++ b/spyvm/plugins/socket.py @@ -0,0 +1,61 @@ +from rpython.rlib import rsocket + +from spyvm import model, error +from spyvm.plugins.plugin import Plugin + + +SocketPlugin = Plugin() + +def is_squeak_socket(w_socket_handle): + return not isinstance(w_socket_handle, W_SocketHandle) + + + at SocketPlugin.expose_primitive(unwrap_spec=[object, object]) +def primitiveSocketConnectionStatus(interp, s_frame, w_rcvr, w_socket_handle): + """ "Socket Status Values" + InvalidSocket := -1. + Unconnected := 0. + WaitingForConnection := 1. + Connected := 2. + OtherEndClosed := 3. + ThisEndClosed := 4. """ + if is_squeak_socket(w_socket_handle): + return interp.space.wrap_int(-1) + else: + return interp.space.wrap_int(-1) # for now ... + + + at SocketPlugin.expose_primitive(unwrap_spec=[object]) +def primitiveResolverStatus(interp, s_frame, w_rcvr): + """ "Resolver Status Values" + ResolverUninitialized := 0. "network is not initialized" + ResolverReady := 1. "resolver idle, last request succeeded" + ResolverBusy := 2. "lookup in progress" + ResolverError := 3. "resolver idle, last request failed" + """ + if not SocketPlugin.userdata.get("thisNetSession", None): + return interp.space.wrap_int(0) + elif SocketPlugin.userdata.get("lastError", 0) != 0: + return interp.space.wrap_int(3) + else: + return interp.space.wrap_int(1) + + + at SocketPlugin.expose_primitive(unwrap_spec=[object, object]) +def primitiveInitializeNetwork(interp, s_frame, w_rcvr, w_semaphore): + """ + Initialize the network drivers on platforms that need it. + + ... Certainly sir ... + + Note: some platforms (e.g., Mac) only allow + only one name lookup query at a time, so a manager process should + be used to serialize resolver lookup requests + + ... IGNORE ME! ... + """ + return w_rcvr + + +class W_SocketHandle(model.W_WordsObject): + pass diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -815,6 +815,8 @@ @expose_primitive(EXTERNAL_CALL, clean_stack=False, no_result=True, compiled_method=True) def func(interp, s_frame, argcount, s_method): + from spyvm.plugins.socket import SocketPlugin + space = interp.space w_description = s_method.w_self().literalat0(space, 1) if not isinstance(w_description, model.W_PointersObject) or w_description.size() < 2: @@ -828,6 +830,8 @@ if signature == ('BitBltPlugin', 'primitiveCopyBits'): return prim_holder.prim_table[BITBLT_COPY_BITS](interp, s_frame, argcount, s_method) + elif signature[0] == "SocketPlugin": + return SocketPlugin.call(signature[1], interp, s_frame, argcount, s_method) raise PrimitiveFailedError # ___________________________________________________________________________ From noreply at buildbot.pypy.org Tue Apr 23 18:17:34 2013 From: noreply at buildbot.pypy.org (timfel) Date: Tue, 23 Apr 2013 18:17:34 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: (lwassermann, timfel) fix translation Message-ID: <20130423161734.D6DA71C0328@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: Changeset: r326:22de41bedbd6 Date: 2013-04-23 18:17 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/22de41bedbd6/ Log: (lwassermann, timfel) fix translation diff --git a/targetimageloadingsmalltalk.py b/targetimageloadingsmalltalk.py --- a/targetimageloadingsmalltalk.py +++ b/targetimageloadingsmalltalk.py @@ -12,6 +12,7 @@ def _run_benchmark(interp, number, benchmark): scheduler = wrapper.scheduler(interp.space) w_hpp = scheduler.highest_priority_process() + assert isinstance(w_hpp, model.W_PointersObject) w_benchmark_proc = model.W_PointersObject( interp.space, w_hpp.getclass(interp.space), From noreply at buildbot.pypy.org Tue Apr 23 23:34:40 2013 From: noreply at buildbot.pypy.org (wlav) Date: Tue, 23 Apr 2013 23:34:40 +0200 (CEST) Subject: [pypy-commit] pypy default: document new loadable backend and backend specific info Message-ID: <20130423213440.25BA91C31F8@cobra.cs.uni-duesseldorf.de> Author: Wim Lavrijsen Branch: Changeset: r63568:a90daea5f425 Date: 2013-04-23 14:33 -0700 http://bitbucket.org/pypy/pypy/changeset/a90daea5f425/ Log: document new loadable backend and backend specific info diff --git a/pypy/doc/cppyy.rst b/pypy/doc/cppyy.rst --- a/pypy/doc/cppyy.rst +++ b/pypy/doc/cppyy.rst @@ -2,94 +2,128 @@ cppyy: C++ bindings for PyPy ============================ -The cppyy module provides C++ bindings for PyPy by using the reflection -information extracted from C++ header files by means of the -`Reflex package`_. -For this to work, you have to both install Reflex and build PyPy from source, -as the cppyy module is not enabled by default. -Note that the development version of cppyy lives in the reflex-support -branch. -As indicated by this being a branch, support for Reflex is still -experimental. -However, it is functional enough to put it in the hands of those who want -to give it a try. -In the medium term, cppyy will move away from Reflex and instead use -`cling`_ as its backend, which is based on `llvm`_. -Although that will change the logistics on the generation of reflection -information, it will not change the python-side interface. +The cppyy module creates, at run-time, Python-side classes and functions for +C++, by querying a C++ reflection system. +The default system used is `Reflex`_, which extracts the needed information +from C++ header files. +Another current backend is based on `CINT`_, and yet another, more important +one for the medium- to long-term will be based on `cling`_. +The latter sits on top of `llvm`_'s `clang`_, and will therefore allow the use +of C++11. +The work on the cling backend has so far been done only for CPython, but +bringing it to PyPy is a lot less work than developing it in the first place. -.. _`Reflex package`: http://root.cern.ch/drupal/content/reflex +.. _`Reflex`: http://root.cern.ch/drupal/content/reflex +.. _`CINT`: http://root.cern.ch/drupal/content/cint .. _`cling`: http://root.cern.ch/drupal/content/cling .. _`llvm`: http://llvm.org/ +.. _`clang`: http://clang.llvm.org/ + +This document describes the version of cppyy that lives in the main branch of +PyPy. +The development of cppyy happens in the "reflex-support" branch. Motivation ========== -The cppyy module offers two unique features, which result in great -performance as well as better functionality and cross-language integration -than would otherwise be possible. -First, cppyy is written in RPython and therefore open to optimizations by the -JIT up until the actual point of call into C++. -This means that there are no conversions necessary between a garbage collected -and a reference counted environment, as is needed for the use of existing -extension modules written or generated for CPython. -It also means that if variables are already unboxed by the JIT, they can be -passed through directly to C++. -Second, Reflex (and cling far more so) adds dynamic features to C++, thus -greatly reducing impedance mismatches between the two languages. -In fact, Reflex is dynamic enough that you could write the runtime bindings +To provide bindings to another language in CPython, you program to a +generic C-API that exposes many of the interpreter features. +With PyPy, however, there is no such generic C-API, because several of the +interpreter features (e.g. the memory model) are pluggable and therefore +subject to change. +Furthermore, a generic API does not allow any assumptions about the calls +into another language, forcing the JIT to behave conservatively around these +calls and with the objects that cross language boundaries. +In contrast, cppyy does not expose an API, but expects one to be implemented +by a backend. +It makes strong assumptions about the semantics of the API that it uses and +that in turn allows the JIT to make equally strong assumptions. +This is possible, because the expected API is only for providing C++ language +bindings, and does not provide generic programmability. + +The cppyy module further offers two features, which result in improved +performance as well as better functionality and cross-language integration. +First, cppyy itself is written in RPython and therefore open to optimizations +by the JIT up until the actual point of call into C++. +This means for example, that if variables are already unboxed by the JIT, they +can be passed through directly to C++. +Second, a backend such as Reflex (and cling far more so) adds dynamic features +to C++, thus greatly reducing impedance mismatches between the two languages. +For example, Reflex is dynamic enough to allow writing runtime bindings generation in python (as opposed to RPython) and this is used to create very natural "pythonizations" of the bound code. +As another example, cling allows automatic instantiations of templates. + +See this description of the `cppyy architecture`_ for further details. + +.. _`cppyy architecture`: http://morepypy.blogspot.com/2012/06/architecture-of-cppyy.html Installation ============ -For now, the easiest way of getting the latest version of Reflex, is by -installing the ROOT package. -Besides getting the latest version of Reflex, another advantage is that with -the full ROOT package, you can also use your Reflex-bound code on `CPython`_. -`Download`_ a binary or install from `source`_. -Some Linux and Mac systems may have ROOT provided in the list of scientific -software of their packager. -If, however, you prefer a standalone version of Reflex, the best is to get -this `recent snapshot`_, and install like so:: +There are two ways of using cppyy, and the choice depends on how pypy-c was +built: the backend can be builtin, or dynamically loadable. +The former has the disadvantage of requiring pypy-c to be linked with external +C++ libraries (e.g. libReflex.so), but has the advantage of being faster in +some cases. +That advantage will disappear over time, however, with improvements in the +JIT. +Therefore, this document assumes that the dynamically loadable backend is +chosen (it is, by default). +See the `backend documentation`_. - $ tar jxf reflex-2012-05-02.tar.bz2 - $ cd reflex-2012-05-02 - $ build/autogen +.. _`backend documentation`: cppyy_backend.html + +A standalone version of Reflex that also provides the dynamically loadable +backend is available for `download`_. +That version, as well as any other distribution of Reflex (e.g. the one that +comes with `ROOT`_, which may be part of your Linux distribution as part of +the selection of scientific software) will also work for a build with the +builtin backend. + +.. _`download`: http://cern.ch/wlav/reflex-2013-04-23.tar.bz2 +.. _`ROOT`: http://root.cern.ch/ + +Besides Reflex, you probably need a version of `gccxml`_ installed, which is +most easily provided by the packager of your system. +If you read up on gccxml, you will probably notice that it is no longer being +developed and hence will not provide C++11 support. +That's why the medium term plan is to move to cling. +Note that gccxml is only needed to generate reflection libraries. +It is not needed to use them. + +.. _`gccxml`: http://www.gccxml.org + +To install the standalone version of Reflex, after download:: + + $ tar jxf reflex-2013-04-23.tar.bz2 + $ cd reflex-2013-04-23 + $ ./build/autogen $ ./configure $ make && make install -Also, make sure you have a version of `gccxml`_ installed, which is most -easily provided by the packager of your system. -If you read up on gccxml, you'll probably notice that it is no longer being -developed and hence will not provide C++11 support. -That's why the medium term plan is to move to `cling`_. +The usual rules apply: /bin needs to be added to the ``PATH`` and +/lib to the ``LD_LIBRARY_PATH`` environment variable. +For convenience, this document will assume that there is a ``REFLEXHOME`` +variable that points to . +If you downloaded or built the whole of ROOT, ``REFLEXHOME`` should be equal +to ``ROOTSYS``. -.. _`Download`: http://root.cern.ch/drupal/content/downloading-root -.. _`source`: http://root.cern.ch/drupal/content/installing-root-source -.. _`recent snapshot`: http://cern.ch/wlav/reflex-2012-05-02.tar.bz2 -.. _`gccxml`: http://www.gccxml.org +The following is optional, and is only to show how pypy-c can be build +`from source`_, for example to get at the main development branch of cppyy. +The `backend documentation`_ has more details on the backend-specific +prerequisites. -Next, get the `PyPy sources`_, optionally select the reflex-support branch, -and build it. -For the build to succeed, the ``$ROOTSYS`` environment variable must point to -the location of your ROOT (or standalone Reflex) installation, or the -``root-config`` utility must be accessible through ``PATH`` (e.g. by adding -``$ROOTSYS/bin`` to ``PATH``). -In case of the former, include files are expected under ``$ROOTSYS/include`` -and libraries under ``$ROOTSYS/lib``. Then run the translation to build ``pypy-c``:: $ hg clone https://bitbucket.org/pypy/pypy $ cd pypy $ hg up reflex-support # optional - $ cd pypy/goal # This example shows python, but using pypy-c is faster and uses less memory - $ python ../../rpython/bin/rpython.py -O jit --gcrootfinder=shadowstack targetpypystandalone.py --withmod-cppyy + $ python rpython/translator/goal/translate.py --opt=jit pypy/goal/targetpypystandalone --withmod-cppyy This will build a ``pypy-c`` that includes the cppyy module, and through that, Reflex support. @@ -98,12 +132,12 @@ If not, you may want `to obtain a binary distribution`_ to speed up the translation step. -.. _`PyPy sources`: https://bitbucket.org/pypy/pypy/overview +.. _`from source`: https://bitbucket.org/pypy/pypy/overview .. _`to obtain a binary distribution`: http://doc.pypy.org/en/latest/getting-started.html#download-a-pre-built-pypy -Basic example -============= +Basic bindings example +====================== Now test with a trivial example whether all packages are properly installed and functional. @@ -127,7 +161,7 @@ code:: $ genreflex MyClass.h - $ g++ -fPIC -rdynamic -O2 -shared -I$ROOTSYS/include MyClass_rflx.cpp -o libMyClassDict.so -L$ROOTSYS/lib -lReflex + $ g++ -fPIC -rdynamic -O2 -shared -I$REFLEXHOME/include MyClass_rflx.cpp -o libMyClassDict.so -L$REFLEXHOME/lib -lReflex Now you're ready to use the bindings. Since the bindings are designed to look pythonistic, it should be @@ -176,7 +210,7 @@ For example:: $ genreflex MyClass.h --rootmap=libMyClassDict.rootmap --rootmap-lib=libMyClassDict.so - $ g++ -fPIC -rdynamic -O2 -shared -I$ROOTSYS/include MyClass_rflx.cpp -o libMyClassDict.so -L$ROOTSYS/lib -lReflex + $ g++ -fPIC -rdynamic -O2 -shared -I$REFLEXHOME/include MyClass_rflx.cpp -o libMyClassDict.so -L$REFLEXHOME/lib -lReflex where the first option (``--rootmap``) specifies the output file name, and the second option (``--rootmap-lib``) the name of the reflection library where @@ -277,7 +311,7 @@ Now the reflection info can be generated and compiled:: $ genreflex MyAdvanced.h --selection=MyAdvanced.xml - $ g++ -fPIC -rdynamic -O2 -shared -I$ROOTSYS/include MyAdvanced_rflx.cpp -o libAdvExDict.so -L$ROOTSYS/lib -lReflex + $ g++ -fPIC -rdynamic -O2 -shared -I$REFLEXHOME/include MyAdvanced_rflx.cpp -o libAdvExDict.so -L$REFLEXHOME/lib -lReflex and subsequently be used from PyPy:: @@ -336,7 +370,7 @@ bound using:: $ genreflex example.h --deep --rootmap=libexampleDict.rootmap --rootmap-lib=libexampleDict.so - $ g++ -fPIC -rdynamic -O2 -shared -I$ROOTSYS/include example_rflx.cpp -o libexampleDict.so -L$ROOTSYS/lib -lReflex + $ g++ -fPIC -rdynamic -O2 -shared -I$REFLEXHOME/include example_rflx.cpp -o libexampleDict.so -L$REFLEXHOME/lib -lReflex .. _`example code`: cppyy_example.html @@ -595,6 +629,16 @@ All template classes must already exist in the loaded reflection info, they do not work (yet) with the class loader. + For compatibility with other bindings generators, use of square brackets + instead of parenthesis to instantiate templates is supported as well. + +* **templated functions**: Automatically participate in overloading and are + used in the same way as other global functions. + +* **templated methods**: For now, require an explicit selection of the + template parameters. + This will be changed to allow them to participate in overloads as expected. + * **typedefs**: Are simple python references to the actual classes to which they refer. @@ -692,7 +736,7 @@ Run the normal ``genreflex`` and compilation steps:: $ genreflex MyTemplate.h --selection=MyTemplate.xml - $ g++ -fPIC -rdynamic -O2 -shared -I$ROOTSYS/include MyTemplate_rflx.cpp -o libTemplateDict.so -L$ROOTSYS/lib -lReflex + $ g++ -fPIC -rdynamic -O2 -shared -I$REFLEXHOME/include MyTemplate_rflx.cpp -o libTemplateDict.so -L$REFLEXHOME/lib -lReflex Note: this is a dirty corner that clearly could do with some automation, even if the macro already helps. @@ -727,18 +771,18 @@ The fast lane ============= -The following is an experimental feature of cppyy, and that makes it doubly -experimental, so caveat emptor. +The following is an experimental feature of cppyy. +It mostly works, but there are some known issues (e.g. with return-by-value). +Soon it should be the default mode, however. + With a slight modification of Reflex, it can provide function pointers for C++ methods, and hence allow PyPy to call those pointers directly, rather than calling C++ through a Reflex stub. -This results in a rather significant speed-up. -Mind you, the normal stub path is not exactly slow, so for now only use this -out of curiosity or if you really need it. -To install this patch of Reflex, locate the file genreflex-methptrgetter.patch -in pypy/module/cppyy and apply it to the genreflex python scripts found in -``$ROOTSYS/lib``:: +The standalone version of Reflex `provided`_ has been patched, but if you get +Reflex from another source (most likely with a ROOT distribution), locate the +file `genreflex-methptrgetter.patch`_ in pypy/module/cppyy and apply it to +the genreflex python scripts found in ``$ROOTSYS/lib``:: $ cd $ROOTSYS/lib $ patch -p2 < genreflex-methptrgetter.patch @@ -749,8 +793,10 @@ ``-Wno-pmf-conversions`` option to ``g++`` when compiling. The rest works the same way: the fast path will be used transparently (which also means that you can't actually find out whether it is in use, other than -by running a micro-benchmark). +by running a micro-benchmark or a JIT test). +.. _`provided`: http://cern.ch/wlav/reflex-2013-04-23.tar.bz2 +.. _`genreflex-methptrgetter.patch`: https://bitbucket.org/pypy/pypy/src/default/pypy/module/cppyy/genreflex-methptrgetter.patch CPython ======= diff --git a/pypy/doc/cppyy_backend.rst b/pypy/doc/cppyy_backend.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/cppyy_backend.rst @@ -0,0 +1,53 @@ +================== +Backends for cppyy +================== + +The cppyy module needs a backend to provide the C++ reflection information on +which the Python bindings are build. +The backend is called through a C-API, which can be found in the PyPy sources +in: `pypy/module/cppyy/include/capi.h`_. +There are two kinds of API calls: querying about reflection information, which +are used during the creation of Python-side constructs, and making the actual +calls into C++. +The objects passed around are all opaque: cppyy does not make any assumptions +about them, other than that the opaque handles can be copied. +Their definition, however, appears in two places: in the C code (in capi.h), +and on the RPython side (in `capi_types.py`_), so if they are changed, they +need to be changed on both sides. + +.. _`pypy/module/cppyy/include/capi.h`: https://bitbucket.org/pypy/pypy/src/default/pypy/module/cppyy/include/capi.h +.. _`capi_types.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/module/cppyy/capi/capi_types.py + +There are two places where selections in the RPython code affect the choice +(and use) of the backend. +The first is in `pypy/module/cppyy/capi/__init__.py`_:: + + # choose C-API access method: + from pypy.module.cppyy.capi.loadable_capi import * + #from pypy.module.cppyy.capi.builtin_capi import * + +The default is the loadable C-API. +Comment it and uncomment the builtin C-API line, to use the builtin version. + +.. _`pypy/module/cppyy/capi/__init__.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/module/cppyy/capi/__init__.py + +Next, if the builtin C-API is chosen, the specific backend needs to be set as +well (default is Reflex). +This second choice is in `pypy/module/cppyy/capi/builtin_capi.py`_:: + + import reflex_capi as backend + #import cint_capi as backend + +After those choices have been made, built pypy-c as usual. + +.. _`pypy/module/cppyy/capi/builtin_capi.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/module/cppyy/capi/builtin_capi.py + +When building pypy-c from source, keep the following in mind. +If the loadable_capi is chosen, no further prerequisites are needed. +However, for the build of the builtin_capi to succeed, the ``ROOTSYS`` +environment variable must point to the location of your ROOT (or standalone +Reflex in the case of the Reflex backend) installation, or the ``root-config`` +utility must be accessible through ``$PATH`` (e.g. by adding ``$ROOTSYS/bin`` +to ``PATH``). +In case of the former, include files are expected under ``$ROOTSYS/include`` +and libraries under ``$ROOTSYS/lib``. From noreply at buildbot.pypy.org Tue Apr 23 23:34:41 2013 From: noreply at buildbot.pypy.org (wlav) Date: Tue, 23 Apr 2013 23:34:41 +0200 (CEST) Subject: [pypy-commit] pypy default: enable loadable capi by default Message-ID: <20130423213441.766A51C31F8@cobra.cs.uni-duesseldorf.de> Author: Wim Lavrijsen Branch: Changeset: r63569:4c1206a89990 Date: 2013-04-23 14:33 -0700 http://bitbucket.org/pypy/pypy/changeset/4c1206a89990/ Log: enable loadable capi by default diff --git a/pypy/module/cppyy/capi/__init__.py b/pypy/module/cppyy/capi/__init__.py --- a/pypy/module/cppyy/capi/__init__.py +++ b/pypy/module/cppyy/capi/__init__.py @@ -9,8 +9,8 @@ # the selection of the desired backend (default is Reflex). # choose C-API access method: -#from pypy.module.cppyy.capi.loadable_capi import * -from pypy.module.cppyy.capi.builtin_capi import * +from pypy.module.cppyy.capi.loadable_capi import * +#from pypy.module.cppyy.capi.builtin_capi import * from pypy.module.cppyy.capi.capi_types import C_OBJECT,\ C_NULL_TYPE, C_NULL_OBJECT From noreply at buildbot.pypy.org Wed Apr 24 00:03:31 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Wed, 24 Apr 2013 00:03:31 +0200 (CEST) Subject: [pypy-commit] pypy default: fix stat_result's repr on windows Message-ID: <20130423220331.587831C31F9@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: Changeset: r63570:4c31c5cb4b44 Date: 2013-04-23 14:58 -0700 http://bitbucket.org/pypy/pypy/changeset/4c31c5cb4b44/ Log: fix stat_result's repr on windows diff --git a/pypy/module/posix/app_posix.py b/pypy/module/posix/app_posix.py --- a/pypy/module/posix/app_posix.py +++ b/pypy/module/posix/app_posix.py @@ -20,7 +20,7 @@ class stat_result: __metaclass__ = structseqtype - name = "posix.stat_result" + name = osname + ".stat_result" st_mode = structseqfield(0, "protection bits") st_ino = structseqfield(1, "inode") diff --git a/pypy/module/posix/test/test_posix2.py b/pypy/module/posix/test/test_posix2.py --- a/pypy/module/posix/test/test_posix2.py +++ b/pypy/module/posix/test/test_posix2.py @@ -159,6 +159,7 @@ assert st.st_atime == 41 assert st.st_mtime == 42.1 assert st.st_ctime == 43 + assert repr(st).startswith(self.posix.__name__ + '.stat_result') def test_stat_lstat(self): import stat From noreply at buildbot.pypy.org Wed Apr 24 00:03:32 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Wed, 24 Apr 2013 00:03:32 +0200 (CEST) Subject: [pypy-commit] pypy py3k: apparently usemodules may come in as unicode Message-ID: <20130423220332.E91851C31F9@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63571:0c3a1aecb928 Date: 2013-04-23 15:00 -0700 http://bitbucket.org/pypy/pypy/changeset/0c3a1aecb928/ Log: apparently usemodules may come in as unicode diff --git a/pypy/tool/pytest/apptest.py b/pypy/tool/pytest/apptest.py --- a/pypy/tool/pytest/apptest.py +++ b/pypy/tool/pytest/apptest.py @@ -128,7 +128,7 @@ check_usemodules = '' if usemodules: - usemodules = [RENAMED_USEMODULES.get(name, name) + usemodules = [str(RENAMED_USEMODULES.get(name, name)) for name in usemodules] check_usemodules = """\ if not set(%r).issubset(sys.builtin_module_names): From noreply at buildbot.pypy.org Wed Apr 24 00:03:34 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Wed, 24 Apr 2013 00:03:34 +0200 (CEST) Subject: [pypy-commit] pypy py3k: forgot this w/ 7737ba1bb77c Message-ID: <20130423220334.8056A1C31F9@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63572:98b8a8dcc5b9 Date: 2013-04-23 15:01 -0700 http://bitbucket.org/pypy/pypy/changeset/98b8a8dcc5b9/ Log: forgot this w/ 7737ba1bb77c diff --git a/lib-python/3/subprocess.py b/lib-python/3/subprocess.py --- a/lib-python/3/subprocess.py +++ b/lib-python/3/subprocess.py @@ -871,7 +871,7 @@ elif stderr == PIPE: errread, errwrite = _subprocess.CreatePipe(None, 0) elif stderr == STDOUT: - errwrite = c2pwrite + errwrite = c2pwrite.handle # pass id to not close it elif isinstance(stderr, int): errwrite = msvcrt.get_osfhandle(stderr) else: From noreply at buildbot.pypy.org Wed Apr 24 00:31:42 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Wed, 24 Apr 2013 00:31:42 +0200 (CEST) Subject: [pypy-commit] pypy default: avoid _get_osfhandle from crashing on invalid fds Message-ID: <20130423223142.22E871C02DA@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: Changeset: r63573:983d6e1ef146 Date: 2013-04-23 15:28 -0700 http://bitbucket.org/pypy/pypy/changeset/983d6e1ef146/ Log: avoid _get_osfhandle from crashing on invalid fds diff --git a/lib-python/2.7/test/test_fileio.py b/lib-python/2.7/test/test_fileio.py --- a/lib-python/2.7/test/test_fileio.py +++ b/lib-python/2.7/test/test_fileio.py @@ -318,7 +318,6 @@ self.assertRaises(ValueError, _FileIO, -10) self.assertRaises(OSError, _FileIO, make_bad_fd()) if sys.platform == 'win32': - raise unittest.SkipTest('Set _invalid_parameter_handler for low level io') import msvcrt self.assertRaises(IOError, msvcrt.get_osfhandle, make_bad_fd()) diff --git a/lib_pypy/msvcrt.py b/lib_pypy/msvcrt.py --- a/lib_pypy/msvcrt.py +++ b/lib_pypy/msvcrt.py @@ -8,25 +8,37 @@ # PAC: 2010/08 added MS locking for Whoosh import ctypes +import errno from ctypes_support import standard_c_lib as _c from ctypes_support import get_errno -import errno try: open_osfhandle = _c._open_osfhandle except AttributeError: # we are not on windows raise ImportError -try: from __pypy__ import builtinify -except ImportError: builtinify = lambda f: f +try: from __pypy__ import builtinify, validate_fd +except ImportError: builtinify = validate_fd = lambda f: f 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 +_get_osfhandle = _c._get_osfhandle +_get_osfhandle.argtypes = [ctypes.c_int] +_get_osfhandle.restype = ctypes.c_int + + at builtinify +def get_osfhandle(fd): + """"get_osfhandle(fd) -> file handle + + Return the file handle for the file descriptor fd. Raises IOError if + fd is not recognized.""" + try: + validate_fd(fd) + except OSError as e: + raise IOError(*e.args) + return _get_osfhandle(fd) setmode = _c._setmode setmode.argtypes = [ctypes.c_int, ctypes.c_int] From noreply at buildbot.pypy.org Wed Apr 24 00:42:55 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Wed, 24 Apr 2013 00:42:55 +0200 (CEST) Subject: [pypy-commit] pypy py3k: test_concurrent_futures deadlocks windows, skip for now Message-ID: <20130423224255.730161C02DA@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63574:5ccfacfcb761 Date: 2013-04-23 15:40 -0700 http://bitbucket.org/pypy/pypy/changeset/5ccfacfcb761/ Log: test_concurrent_futures deadlocks windows, skip for now diff --git a/lib-python/conftest.py b/lib-python/conftest.py --- a/lib-python/conftest.py +++ b/lib-python/conftest.py @@ -154,7 +154,8 @@ RegrTest('test_compile.py', core=True), RegrTest('test_compileall.py'), RegrTest('test_complex.py', core=True), - RegrTest('test_concurrent_futures.py'), + RegrTest('test_concurrent_futures.py', + skip="XXX: deadlocks" if sys.platform == 'win32' else False), RegrTest('test_contains.py', core=True), RegrTest('test_contextlib.py', usemodules="thread"), RegrTest('test_copy.py', core=True), From noreply at buildbot.pypy.org Wed Apr 24 00:42:57 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Wed, 24 Apr 2013 00:42:57 +0200 (CEST) Subject: [pypy-commit] pypy py3k: merge default Message-ID: <20130423224257.083A81C02DA@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63575:528ec86e4f17 Date: 2013-04-23 15:41 -0700 http://bitbucket.org/pypy/pypy/changeset/528ec86e4f17/ Log: merge default diff --git a/lib-python/2.7/test/test_fileio.py b/lib-python/2.7/test/test_fileio.py --- a/lib-python/2.7/test/test_fileio.py +++ b/lib-python/2.7/test/test_fileio.py @@ -318,7 +318,6 @@ self.assertRaises(ValueError, _FileIO, -10) self.assertRaises(OSError, _FileIO, make_bad_fd()) if sys.platform == 'win32': - raise unittest.SkipTest('Set _invalid_parameter_handler for low level io') import msvcrt self.assertRaises(IOError, msvcrt.get_osfhandle, make_bad_fd()) diff --git a/lib_pypy/msvcrt.py b/lib_pypy/msvcrt.py --- a/lib_pypy/msvcrt.py +++ b/lib_pypy/msvcrt.py @@ -8,25 +8,37 @@ # PAC: 2010/08 added MS locking for Whoosh import ctypes +import errno from ctypes_support import standard_c_lib as _c from ctypes_support import get_errno -import errno try: open_osfhandle = _c._open_osfhandle except AttributeError: # we are not on windows raise ImportError -try: from __pypy__ import builtinify -except ImportError: builtinify = lambda f: f +try: from __pypy__ import builtinify, validate_fd +except ImportError: builtinify = validate_fd = lambda f: f 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 +_get_osfhandle = _c._get_osfhandle +_get_osfhandle.argtypes = [ctypes.c_int] +_get_osfhandle.restype = ctypes.c_int + + at builtinify +def get_osfhandle(fd): + """"get_osfhandle(fd) -> file handle + + Return the file handle for the file descriptor fd. Raises IOError if + fd is not recognized.""" + try: + validate_fd(fd) + except OSError as e: + raise IOError(*e.args) + return _get_osfhandle(fd) setmode = _c._setmode setmode.argtypes = [ctypes.c_int, ctypes.c_int] diff --git a/pypy/doc/cppyy.rst b/pypy/doc/cppyy.rst --- a/pypy/doc/cppyy.rst +++ b/pypy/doc/cppyy.rst @@ -2,94 +2,128 @@ cppyy: C++ bindings for PyPy ============================ -The cppyy module provides C++ bindings for PyPy by using the reflection -information extracted from C++ header files by means of the -`Reflex package`_. -For this to work, you have to both install Reflex and build PyPy from source, -as the cppyy module is not enabled by default. -Note that the development version of cppyy lives in the reflex-support -branch. -As indicated by this being a branch, support for Reflex is still -experimental. -However, it is functional enough to put it in the hands of those who want -to give it a try. -In the medium term, cppyy will move away from Reflex and instead use -`cling`_ as its backend, which is based on `llvm`_. -Although that will change the logistics on the generation of reflection -information, it will not change the python-side interface. +The cppyy module creates, at run-time, Python-side classes and functions for +C++, by querying a C++ reflection system. +The default system used is `Reflex`_, which extracts the needed information +from C++ header files. +Another current backend is based on `CINT`_, and yet another, more important +one for the medium- to long-term will be based on `cling`_. +The latter sits on top of `llvm`_'s `clang`_, and will therefore allow the use +of C++11. +The work on the cling backend has so far been done only for CPython, but +bringing it to PyPy is a lot less work than developing it in the first place. -.. _`Reflex package`: http://root.cern.ch/drupal/content/reflex +.. _`Reflex`: http://root.cern.ch/drupal/content/reflex +.. _`CINT`: http://root.cern.ch/drupal/content/cint .. _`cling`: http://root.cern.ch/drupal/content/cling .. _`llvm`: http://llvm.org/ +.. _`clang`: http://clang.llvm.org/ + +This document describes the version of cppyy that lives in the main branch of +PyPy. +The development of cppyy happens in the "reflex-support" branch. Motivation ========== -The cppyy module offers two unique features, which result in great -performance as well as better functionality and cross-language integration -than would otherwise be possible. -First, cppyy is written in RPython and therefore open to optimizations by the -JIT up until the actual point of call into C++. -This means that there are no conversions necessary between a garbage collected -and a reference counted environment, as is needed for the use of existing -extension modules written or generated for CPython. -It also means that if variables are already unboxed by the JIT, they can be -passed through directly to C++. -Second, Reflex (and cling far more so) adds dynamic features to C++, thus -greatly reducing impedance mismatches between the two languages. -In fact, Reflex is dynamic enough that you could write the runtime bindings +To provide bindings to another language in CPython, you program to a +generic C-API that exposes many of the interpreter features. +With PyPy, however, there is no such generic C-API, because several of the +interpreter features (e.g. the memory model) are pluggable and therefore +subject to change. +Furthermore, a generic API does not allow any assumptions about the calls +into another language, forcing the JIT to behave conservatively around these +calls and with the objects that cross language boundaries. +In contrast, cppyy does not expose an API, but expects one to be implemented +by a backend. +It makes strong assumptions about the semantics of the API that it uses and +that in turn allows the JIT to make equally strong assumptions. +This is possible, because the expected API is only for providing C++ language +bindings, and does not provide generic programmability. + +The cppyy module further offers two features, which result in improved +performance as well as better functionality and cross-language integration. +First, cppyy itself is written in RPython and therefore open to optimizations +by the JIT up until the actual point of call into C++. +This means for example, that if variables are already unboxed by the JIT, they +can be passed through directly to C++. +Second, a backend such as Reflex (and cling far more so) adds dynamic features +to C++, thus greatly reducing impedance mismatches between the two languages. +For example, Reflex is dynamic enough to allow writing runtime bindings generation in python (as opposed to RPython) and this is used to create very natural "pythonizations" of the bound code. +As another example, cling allows automatic instantiations of templates. + +See this description of the `cppyy architecture`_ for further details. + +.. _`cppyy architecture`: http://morepypy.blogspot.com/2012/06/architecture-of-cppyy.html Installation ============ -For now, the easiest way of getting the latest version of Reflex, is by -installing the ROOT package. -Besides getting the latest version of Reflex, another advantage is that with -the full ROOT package, you can also use your Reflex-bound code on `CPython`_. -`Download`_ a binary or install from `source`_. -Some Linux and Mac systems may have ROOT provided in the list of scientific -software of their packager. -If, however, you prefer a standalone version of Reflex, the best is to get -this `recent snapshot`_, and install like so:: +There are two ways of using cppyy, and the choice depends on how pypy-c was +built: the backend can be builtin, or dynamically loadable. +The former has the disadvantage of requiring pypy-c to be linked with external +C++ libraries (e.g. libReflex.so), but has the advantage of being faster in +some cases. +That advantage will disappear over time, however, with improvements in the +JIT. +Therefore, this document assumes that the dynamically loadable backend is +chosen (it is, by default). +See the `backend documentation`_. - $ tar jxf reflex-2012-05-02.tar.bz2 - $ cd reflex-2012-05-02 - $ build/autogen +.. _`backend documentation`: cppyy_backend.html + +A standalone version of Reflex that also provides the dynamically loadable +backend is available for `download`_. +That version, as well as any other distribution of Reflex (e.g. the one that +comes with `ROOT`_, which may be part of your Linux distribution as part of +the selection of scientific software) will also work for a build with the +builtin backend. + +.. _`download`: http://cern.ch/wlav/reflex-2013-04-23.tar.bz2 +.. _`ROOT`: http://root.cern.ch/ + +Besides Reflex, you probably need a version of `gccxml`_ installed, which is +most easily provided by the packager of your system. +If you read up on gccxml, you will probably notice that it is no longer being +developed and hence will not provide C++11 support. +That's why the medium term plan is to move to cling. +Note that gccxml is only needed to generate reflection libraries. +It is not needed to use them. + +.. _`gccxml`: http://www.gccxml.org + +To install the standalone version of Reflex, after download:: + + $ tar jxf reflex-2013-04-23.tar.bz2 + $ cd reflex-2013-04-23 + $ ./build/autogen $ ./configure $ make && make install -Also, make sure you have a version of `gccxml`_ installed, which is most -easily provided by the packager of your system. -If you read up on gccxml, you'll probably notice that it is no longer being -developed and hence will not provide C++11 support. -That's why the medium term plan is to move to `cling`_. +The usual rules apply: /bin needs to be added to the ``PATH`` and +/lib to the ``LD_LIBRARY_PATH`` environment variable. +For convenience, this document will assume that there is a ``REFLEXHOME`` +variable that points to . +If you downloaded or built the whole of ROOT, ``REFLEXHOME`` should be equal +to ``ROOTSYS``. -.. _`Download`: http://root.cern.ch/drupal/content/downloading-root -.. _`source`: http://root.cern.ch/drupal/content/installing-root-source -.. _`recent snapshot`: http://cern.ch/wlav/reflex-2012-05-02.tar.bz2 -.. _`gccxml`: http://www.gccxml.org +The following is optional, and is only to show how pypy-c can be build +`from source`_, for example to get at the main development branch of cppyy. +The `backend documentation`_ has more details on the backend-specific +prerequisites. -Next, get the `PyPy sources`_, optionally select the reflex-support branch, -and build it. -For the build to succeed, the ``$ROOTSYS`` environment variable must point to -the location of your ROOT (or standalone Reflex) installation, or the -``root-config`` utility must be accessible through ``PATH`` (e.g. by adding -``$ROOTSYS/bin`` to ``PATH``). -In case of the former, include files are expected under ``$ROOTSYS/include`` -and libraries under ``$ROOTSYS/lib``. Then run the translation to build ``pypy-c``:: $ hg clone https://bitbucket.org/pypy/pypy $ cd pypy $ hg up reflex-support # optional - $ cd pypy/goal # This example shows python, but using pypy-c is faster and uses less memory - $ python ../../rpython/bin/rpython.py -O jit --gcrootfinder=shadowstack targetpypystandalone.py --withmod-cppyy + $ python rpython/translator/goal/translate.py --opt=jit pypy/goal/targetpypystandalone --withmod-cppyy This will build a ``pypy-c`` that includes the cppyy module, and through that, Reflex support. @@ -98,12 +132,12 @@ If not, you may want `to obtain a binary distribution`_ to speed up the translation step. -.. _`PyPy sources`: https://bitbucket.org/pypy/pypy/overview +.. _`from source`: https://bitbucket.org/pypy/pypy/overview .. _`to obtain a binary distribution`: http://doc.pypy.org/en/latest/getting-started.html#download-a-pre-built-pypy -Basic example -============= +Basic bindings example +====================== Now test with a trivial example whether all packages are properly installed and functional. @@ -127,7 +161,7 @@ code:: $ genreflex MyClass.h - $ g++ -fPIC -rdynamic -O2 -shared -I$ROOTSYS/include MyClass_rflx.cpp -o libMyClassDict.so -L$ROOTSYS/lib -lReflex + $ g++ -fPIC -rdynamic -O2 -shared -I$REFLEXHOME/include MyClass_rflx.cpp -o libMyClassDict.so -L$REFLEXHOME/lib -lReflex Now you're ready to use the bindings. Since the bindings are designed to look pythonistic, it should be @@ -176,7 +210,7 @@ For example:: $ genreflex MyClass.h --rootmap=libMyClassDict.rootmap --rootmap-lib=libMyClassDict.so - $ g++ -fPIC -rdynamic -O2 -shared -I$ROOTSYS/include MyClass_rflx.cpp -o libMyClassDict.so -L$ROOTSYS/lib -lReflex + $ g++ -fPIC -rdynamic -O2 -shared -I$REFLEXHOME/include MyClass_rflx.cpp -o libMyClassDict.so -L$REFLEXHOME/lib -lReflex where the first option (``--rootmap``) specifies the output file name, and the second option (``--rootmap-lib``) the name of the reflection library where @@ -277,7 +311,7 @@ Now the reflection info can be generated and compiled:: $ genreflex MyAdvanced.h --selection=MyAdvanced.xml - $ g++ -fPIC -rdynamic -O2 -shared -I$ROOTSYS/include MyAdvanced_rflx.cpp -o libAdvExDict.so -L$ROOTSYS/lib -lReflex + $ g++ -fPIC -rdynamic -O2 -shared -I$REFLEXHOME/include MyAdvanced_rflx.cpp -o libAdvExDict.so -L$REFLEXHOME/lib -lReflex and subsequently be used from PyPy:: @@ -336,7 +370,7 @@ bound using:: $ genreflex example.h --deep --rootmap=libexampleDict.rootmap --rootmap-lib=libexampleDict.so - $ g++ -fPIC -rdynamic -O2 -shared -I$ROOTSYS/include example_rflx.cpp -o libexampleDict.so -L$ROOTSYS/lib -lReflex + $ g++ -fPIC -rdynamic -O2 -shared -I$REFLEXHOME/include example_rflx.cpp -o libexampleDict.so -L$REFLEXHOME/lib -lReflex .. _`example code`: cppyy_example.html @@ -595,6 +629,16 @@ All template classes must already exist in the loaded reflection info, they do not work (yet) with the class loader. + For compatibility with other bindings generators, use of square brackets + instead of parenthesis to instantiate templates is supported as well. + +* **templated functions**: Automatically participate in overloading and are + used in the same way as other global functions. + +* **templated methods**: For now, require an explicit selection of the + template parameters. + This will be changed to allow them to participate in overloads as expected. + * **typedefs**: Are simple python references to the actual classes to which they refer. @@ -692,7 +736,7 @@ Run the normal ``genreflex`` and compilation steps:: $ genreflex MyTemplate.h --selection=MyTemplate.xml - $ g++ -fPIC -rdynamic -O2 -shared -I$ROOTSYS/include MyTemplate_rflx.cpp -o libTemplateDict.so -L$ROOTSYS/lib -lReflex + $ g++ -fPIC -rdynamic -O2 -shared -I$REFLEXHOME/include MyTemplate_rflx.cpp -o libTemplateDict.so -L$REFLEXHOME/lib -lReflex Note: this is a dirty corner that clearly could do with some automation, even if the macro already helps. @@ -727,18 +771,18 @@ The fast lane ============= -The following is an experimental feature of cppyy, and that makes it doubly -experimental, so caveat emptor. +The following is an experimental feature of cppyy. +It mostly works, but there are some known issues (e.g. with return-by-value). +Soon it should be the default mode, however. + With a slight modification of Reflex, it can provide function pointers for C++ methods, and hence allow PyPy to call those pointers directly, rather than calling C++ through a Reflex stub. -This results in a rather significant speed-up. -Mind you, the normal stub path is not exactly slow, so for now only use this -out of curiosity or if you really need it. -To install this patch of Reflex, locate the file genreflex-methptrgetter.patch -in pypy/module/cppyy and apply it to the genreflex python scripts found in -``$ROOTSYS/lib``:: +The standalone version of Reflex `provided`_ has been patched, but if you get +Reflex from another source (most likely with a ROOT distribution), locate the +file `genreflex-methptrgetter.patch`_ in pypy/module/cppyy and apply it to +the genreflex python scripts found in ``$ROOTSYS/lib``:: $ cd $ROOTSYS/lib $ patch -p2 < genreflex-methptrgetter.patch @@ -749,8 +793,10 @@ ``-Wno-pmf-conversions`` option to ``g++`` when compiling. The rest works the same way: the fast path will be used transparently (which also means that you can't actually find out whether it is in use, other than -by running a micro-benchmark). +by running a micro-benchmark or a JIT test). +.. _`provided`: http://cern.ch/wlav/reflex-2013-04-23.tar.bz2 +.. _`genreflex-methptrgetter.patch`: https://bitbucket.org/pypy/pypy/src/default/pypy/module/cppyy/genreflex-methptrgetter.patch CPython ======= diff --git a/pypy/doc/cppyy_backend.rst b/pypy/doc/cppyy_backend.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/cppyy_backend.rst @@ -0,0 +1,53 @@ +================== +Backends for cppyy +================== + +The cppyy module needs a backend to provide the C++ reflection information on +which the Python bindings are build. +The backend is called through a C-API, which can be found in the PyPy sources +in: `pypy/module/cppyy/include/capi.h`_. +There are two kinds of API calls: querying about reflection information, which +are used during the creation of Python-side constructs, and making the actual +calls into C++. +The objects passed around are all opaque: cppyy does not make any assumptions +about them, other than that the opaque handles can be copied. +Their definition, however, appears in two places: in the C code (in capi.h), +and on the RPython side (in `capi_types.py`_), so if they are changed, they +need to be changed on both sides. + +.. _`pypy/module/cppyy/include/capi.h`: https://bitbucket.org/pypy/pypy/src/default/pypy/module/cppyy/include/capi.h +.. _`capi_types.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/module/cppyy/capi/capi_types.py + +There are two places where selections in the RPython code affect the choice +(and use) of the backend. +The first is in `pypy/module/cppyy/capi/__init__.py`_:: + + # choose C-API access method: + from pypy.module.cppyy.capi.loadable_capi import * + #from pypy.module.cppyy.capi.builtin_capi import * + +The default is the loadable C-API. +Comment it and uncomment the builtin C-API line, to use the builtin version. + +.. _`pypy/module/cppyy/capi/__init__.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/module/cppyy/capi/__init__.py + +Next, if the builtin C-API is chosen, the specific backend needs to be set as +well (default is Reflex). +This second choice is in `pypy/module/cppyy/capi/builtin_capi.py`_:: + + import reflex_capi as backend + #import cint_capi as backend + +After those choices have been made, built pypy-c as usual. + +.. _`pypy/module/cppyy/capi/builtin_capi.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/module/cppyy/capi/builtin_capi.py + +When building pypy-c from source, keep the following in mind. +If the loadable_capi is chosen, no further prerequisites are needed. +However, for the build of the builtin_capi to succeed, the ``ROOTSYS`` +environment variable must point to the location of your ROOT (or standalone +Reflex in the case of the Reflex backend) installation, or the ``root-config`` +utility must be accessible through ``$PATH`` (e.g. by adding ``$ROOTSYS/bin`` +to ``PATH``). +In case of the former, include files are expected under ``$ROOTSYS/include`` +and libraries under ``$ROOTSYS/lib``. diff --git a/pypy/module/_minimal_curses/__init__.py b/pypy/module/_minimal_curses/__init__.py --- a/pypy/module/_minimal_curses/__init__.py +++ b/pypy/module/_minimal_curses/__init__.py @@ -1,6 +1,6 @@ try: import _curses -except ImportError: +except Exception: # probably ImportError or cffi's VerificationError try: # when running on top of pypy before it had _curses, settle for minimal # we prefer _curses so any constants added make it into _minimal_curses diff --git a/pypy/module/cppyy/capi/__init__.py b/pypy/module/cppyy/capi/__init__.py --- a/pypy/module/cppyy/capi/__init__.py +++ b/pypy/module/cppyy/capi/__init__.py @@ -9,8 +9,8 @@ # the selection of the desired backend (default is Reflex). # choose C-API access method: -#from pypy.module.cppyy.capi.loadable_capi import * -from pypy.module.cppyy.capi.builtin_capi import * +from pypy.module.cppyy.capi.loadable_capi import * +#from pypy.module.cppyy.capi.builtin_capi import * from pypy.module.cppyy.capi.capi_types import C_OBJECT,\ C_NULL_TYPE, C_NULL_OBJECT diff --git a/pypy/module/posix/app_posix.py b/pypy/module/posix/app_posix.py --- a/pypy/module/posix/app_posix.py +++ b/pypy/module/posix/app_posix.py @@ -18,7 +18,7 @@ class stat_result(metaclass=structseqtype): - name = "posix.stat_result" + name = osname + ".stat_result" st_mode = structseqfield(0, "protection bits") st_ino = structseqfield(1, "inode") diff --git a/pypy/module/posix/test/test_posix2.py b/pypy/module/posix/test/test_posix2.py --- a/pypy/module/posix/test/test_posix2.py +++ b/pypy/module/posix/test/test_posix2.py @@ -158,6 +158,7 @@ assert st.st_atime == 41 assert st.st_mtime == 42.1 assert st.st_ctime == 43 + assert repr(st).startswith(self.posix.__name__ + '.stat_result') def test_stat_lstat(self): import stat diff --git a/pypy/pytest-A.py b/pypy/pytest-A.py new file mode 100644 --- /dev/null +++ b/pypy/pytest-A.py @@ -0,0 +1,31 @@ +# custom test collection for the app-level testrunner +import platform + +DIRS_SPLIT = { + 'arm': ['interpreter/astcompiler/test', + 'interpreter/pyparser/test', + 'interpreter/test', + 'interpreter/test2', + 'objspace/std/test', + ], +} + + +def get_arch(): + arch = platform.machine().lower() + if arch.startswith('arm'): + return 'arm' + if arch.startswith('x86'): + return 'x86' + return arch + + +def collect_one_testdir(testdirs, reldir, tests): + arch = get_arch() + dirsplit = DIRS_SPLIT.get(arch, []) + for dir in dirsplit: + if reldir.startswith(dir): + testdirs.extend(tests) + break + else: + testdirs.append(reldir) diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -109,22 +109,25 @@ assert excvalloc is not r.ip assert exctploc is not r.ip tmpreg = r.lr + mc.gen_load_int(r.ip.value, self.cpu.pos_exc_value()) if excvalloc is not None: # store assert excvalloc.is_reg() - mc.gen_load_int(r.ip.value, self.cpu.pos_exc_value()) self.load_reg(mc, excvalloc, r.ip) if on_frame: # store exc_value in JITFRAME ofs = self.cpu.get_ofs_of_frame_field('jf_guard_exc') assert check_imm_arg(ofs) + # self.load_reg(mc, r.ip, r.ip, helper=tmpreg) + # self.store_reg(mc, r.ip, r.fp, ofs, helper=tmpreg) - mc.gen_load_int(r.ip.value, self.cpu.pos_exc_value()) if exctploc is not None: # store pos_exception in exctploc assert exctploc.is_reg() - mc.gen_load_int(tmpreg.value, self.cpu.pos_exception()) - self.load_reg(mc, exctploc, tmpreg) + mc.gen_load_int(r.ip.value, self.cpu.pos_exception()) + self.load_reg(mc, exctploc, r.ip, helper=tmpreg) + + if on_frame or exctploc is not None: mc.gen_load_int(r.ip.value, self.cpu.pos_exc_value()) # reset exception diff --git a/rpython/jit/backend/x86/test/test_exception.py b/rpython/jit/backend/arm/test/test_exception.py copy from rpython/jit/backend/x86/test/test_exception.py copy to rpython/jit/backend/arm/test/test_exception.py --- a/rpython/jit/backend/x86/test/test_exception.py +++ b/rpython/jit/backend/arm/test/test_exception.py @@ -1,9 +1,9 @@ import py -from rpython.jit.backend.x86.test.test_basic import Jit386Mixin +from rpython.jit.backend.arm.test.support import JitARMMixin from rpython.jit.metainterp.test.test_exception import ExceptionTests -class TestExceptions(Jit386Mixin, ExceptionTests): +class TestExceptions(JitARMMixin, ExceptionTests): # for the individual tests see # ====> ../../../metainterp/test/test_exception.py diff --git a/rpython/jit/backend/detect_cpu.py b/rpython/jit/backend/detect_cpu.py --- a/rpython/jit/backend/detect_cpu.py +++ b/rpython/jit/backend/detect_cpu.py @@ -2,12 +2,40 @@ Processor auto-detection """ import sys, os +from rpython.rtyper.tool.rffi_platform import getdefined +from rpython.translator.platform import is_host_build class ProcessorAutodetectError(Exception): pass + +def detect_main_model_and_size_from_platform(): + # based on http://sourceforge.net/p/predef/wiki/Architectures/ + mapping = { + ('x86', '64'): [ + '__amd64__', '__amd64', '__x86_64__', '__x86_64', # AMD64 + '__ia64__', '_IA64', '__IA64__' # Intel Itanium (IA-64) + ], + ('arm', '32'): ['__arm__', '__thumb__'], + ('x86', '32'): ['i386', '__i386', '__i386__', '__i686__',], + ('ppc', '64'): ['__powerpc64__'], + } + for k, v in mapping.iteritems(): + for macro in v: + if not getdefined(macro, ''): + continue + return '_'.join(k) + raise ProcessorAutodetectError, "Cannot detect processor using compiler macros" + + +def detect_main_model_from_platform(): + return detect_main_model_and_size_from_platform()[0] + + def autodetect_main_model(): + if not is_host_build(): + return detect_main_model_from_platform() mach = None try: import platform @@ -40,6 +68,8 @@ return mach def autodetect_main_model_and_size(): + if not is_host_build(): + return detect_main_model_and_size_from_platform() model = autodetect_main_model() if sys.maxint == 2**31-1: model += '_32' diff --git a/rpython/jit/backend/test/test_detect_cpu.py b/rpython/jit/backend/test/test_detect_cpu.py --- a/rpython/jit/backend/test/test_detect_cpu.py +++ b/rpython/jit/backend/test/test_detect_cpu.py @@ -26,3 +26,8 @@ else: from rpython.jit.backend.model import AbstractCPU assert issubclass(cpu, AbstractCPU) + + +def test_detect_main_model_and_size_from_platform(): + info = autodetect_main_model_and_size() + assert detect_main_model_and_size_from_platform() == info diff --git a/rpython/translator/platform/__init__.py b/rpython/translator/platform/__init__.py --- a/rpython/translator/platform/__init__.py +++ b/rpython/translator/platform/__init__.py @@ -347,3 +347,6 @@ global host host = platform + +def is_host_build(): + return host == platform diff --git a/rpython/translator/platform/test/test_platform.py b/rpython/translator/platform/test/test_platform.py --- a/rpython/translator/platform/test/test_platform.py +++ b/rpython/translator/platform/test/test_platform.py @@ -172,3 +172,13 @@ assert X() == X() assert Y(3) == Y(3) assert Y(2) != Y(3) + + +def test_is_host_build(): + from rpython.translator import platform + assert platform.host == platform.platform + + assert platform.is_host_build() + platform.set_platform('maemo', None) + assert platform.host != platform.platform + assert not platform.is_host_build() From noreply at buildbot.pypy.org Wed Apr 24 03:22:35 2013 From: noreply at buildbot.pypy.org (wlav) Date: Wed, 24 Apr 2013 03:22:35 +0200 (CEST) Subject: [pypy-commit] pypy default: allow the envar REFLEXHOME in lieu of ROOTSYS Message-ID: <20130424012235.A1D241C31F9@cobra.cs.uni-duesseldorf.de> Author: Wim Lavrijsen Branch: Changeset: r63576:1db95a66c866 Date: 2013-04-23 18:20 -0700 http://bitbucket.org/pypy/pypy/changeset/1db95a66c866/ Log: allow the envar REFLEXHOME in lieu of ROOTSYS diff --git a/pypy/module/cppyy/test/Makefile b/pypy/module/cppyy/test/Makefile --- a/pypy/module/cppyy/test/Makefile +++ b/pypy/module/cppyy/test/Makefile @@ -3,7 +3,11 @@ std_streamsDict.so iotypesDict.so all : $(dicts) -ROOTSYS := ${ROOTSYS} +ifneq (${REFLEXHOME},) + ROOTSYS := ${REFLEXHOME} +else + ROOTSYS := ${ROOTSYS} +endif ifeq ($(ROOTSYS),) genreflex=genreflex From noreply at buildbot.pypy.org Wed Apr 24 03:22:36 2013 From: noreply at buildbot.pypy.org (wlav) Date: Wed, 24 Apr 2013 03:22:36 +0200 (CEST) Subject: [pypy-commit] pypy default: use a more descriptive name (libcppyy_backend) for the loadable library Message-ID: <20130424012236.EF6A21C31F9@cobra.cs.uni-duesseldorf.de> Author: Wim Lavrijsen Branch: Changeset: r63577:f4c195f062d8 Date: 2013-04-23 18:20 -0700 http://bitbucket.org/pypy/pypy/changeset/f4c195f062d8/ Log: use a more descriptive name (libcppyy_backend) for the loadable library diff --git a/pypy/module/cppyy/capi/loadable_capi.py b/pypy/module/cppyy/capi/loadable_capi.py --- a/pypy/module/cppyy/capi/loadable_capi.py +++ b/pypy/module/cppyy/capi/loadable_capi.py @@ -11,7 +11,7 @@ C_METHOD, C_INDEX, C_INDEX_ARRAY, WLAVC_INDEX, C_METHPTRGETTER_PTR -reflection_library = 'rflxlib.so' +reflection_library = 'libcppyy_backend.so' def identify(): return 'loadable_capi' @@ -231,7 +231,7 @@ except Exception: if objectmodel.we_are_translated(): raise OperationError(space.w_ImportError, - space.wrap("missing reflection library rflxlib.so")) + space.wrap("missing reflection library %s" % reflection_library)) return False return True From noreply at buildbot.pypy.org Wed Apr 24 03:22:38 2013 From: noreply at buildbot.pypy.org (wlav) Date: Wed, 24 Apr 2013 03:22:38 +0200 (CEST) Subject: [pypy-commit] pypy default: enable module cppyy Message-ID: <20130424012238.1CA281C31F9@cobra.cs.uni-duesseldorf.de> Author: Wim Lavrijsen Branch: Changeset: r63578:7085c0c5fdf9 Date: 2013-04-23 18:21 -0700 http://bitbucket.org/pypy/pypy/changeset/7085c0c5fdf9/ Log: enable module cppyy diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py --- a/pypy/config/pypyoption.py +++ b/pypy/config/pypyoption.py @@ -35,7 +35,7 @@ "thread", "itertools", "pyexpat", "_ssl", "cpyext", "array", "binascii", "_multiprocessing", '_warnings', "_collections", "_multibytecodec", "micronumpy", "_ffi", - "_continuation", "_cffi_backend", "_csv"] + "_continuation", "_cffi_backend", "_csv", "cppyy"] )) translation_modules = default_modules.copy() @@ -64,6 +64,8 @@ del working_modules["termios"] del working_modules["_minimal_curses"] + del working_modules["cppyy"] # not tested on win32 + # The _locale module is needed by site.py on Windows default_modules["_locale"] = None @@ -75,7 +77,7 @@ del working_modules["_minimal_curses"] del working_modules["termios"] del working_modules["_multiprocessing"] # depends on rctime - + del working_modules["cppyy"] # depends on ctypes module_dependencies = { diff --git a/pypy/tool/pypyjit.py b/pypy/tool/pypyjit.py --- a/pypy/tool/pypyjit.py +++ b/pypy/tool/pypyjit.py @@ -41,7 +41,6 @@ config.objspace.usemodules._lsprof = False # config.objspace.usemodules._ffi = True -#config.objspace.usemodules.cppyy = True config.objspace.usemodules.micronumpy = False # set_pypy_opt_level(config, level='jit') From noreply at buildbot.pypy.org Wed Apr 24 03:23:45 2013 From: noreply at buildbot.pypy.org (wlav) Date: Wed, 24 Apr 2013 03:23:45 +0200 (CEST) Subject: [pypy-commit] pypy reflex-support: merge default into branch Message-ID: <20130424012345.DEDC01C31F9@cobra.cs.uni-duesseldorf.de> Author: Wim Lavrijsen Branch: reflex-support Changeset: r63579:637ebd06c4f9 Date: 2013-04-23 18:23 -0700 http://bitbucket.org/pypy/pypy/changeset/637ebd06c4f9/ Log: merge default into branch diff too long, truncating to 2000 out of 2179 lines diff --git a/Makefile b/Makefile new file mode 100644 --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ + +all: pypy-c + +pypy-c: + @echo "Building PyPy with JIT, it'll take about 40 minutes and 4G of RAM" + @sleep 3 + rpython/bin/rpython -Ojit pypy/goal/targetpypystandalone.py diff --git a/README.rst b/README.rst --- a/README.rst +++ b/README.rst @@ -22,3 +22,16 @@ and send us feedback! the pypy-dev team + +Building +======== + +build with:: + + rpython/bin/rpython -Ojit pypy/goal/targetpypystandalone.py + +This ends up with ``pypy-c`` binary in the main pypy directory. We suggest +to use virtualenv with the resulting pypy-c as the interpreter, you can +find more details about various installation schemes here: + +http://doc.pypy.org/en/latest/getting-started.html#installing-pypy diff --git a/lib-python/2.7/json/decoder.py b/lib-python/2.7/json/decoder.py --- a/lib-python/2.7/json/decoder.py +++ b/lib-python/2.7/json/decoder.py @@ -162,7 +162,7 @@ if nextchar == '}': if object_pairs_hook is not None: result = object_pairs_hook(pairs) - return result, end + return result, end + 1 pairs = {} if object_hook is not None: pairs = object_hook(pairs) diff --git a/lib-python/2.7/json/tests/test_decode.py b/lib-python/2.7/json/tests/test_decode.py --- a/lib-python/2.7/json/tests/test_decode.py +++ b/lib-python/2.7/json/tests/test_decode.py @@ -44,6 +44,7 @@ object_pairs_hook=OrderedDict, object_hook=lambda x: None), OrderedDict(p)) + self.assertEqual(self.loads("{}", object_pairs_hook=list), []) class TestPyDecode(TestDecode, PyTest): pass diff --git a/lib-python/2.7/test/test_descr.py b/lib-python/2.7/test/test_descr.py --- a/lib-python/2.7/test/test_descr.py +++ b/lib-python/2.7/test/test_descr.py @@ -3592,6 +3592,9 @@ list.__init__(a, sequence=[0, 1, 2]) self.assertEqual(a, [0, 1, 2]) + @unittest.skipIf(test_support.check_impl_detail(pypy=True) and + sys.platform == 'win32', + "XXX: https://bugs.pypy.org/issue1461") def test_recursive_call(self): # Testing recursive __call__() by setting to instance of class... class A(object): diff --git a/lib-python/2.7/test/test_fileio.py b/lib-python/2.7/test/test_fileio.py --- a/lib-python/2.7/test/test_fileio.py +++ b/lib-python/2.7/test/test_fileio.py @@ -318,7 +318,6 @@ self.assertRaises(ValueError, _FileIO, -10) self.assertRaises(OSError, _FileIO, make_bad_fd()) if sys.platform == 'win32': - raise unittest.SkipTest('Set _invalid_parameter_handler for low level io') import msvcrt self.assertRaises(IOError, msvcrt.get_osfhandle, make_bad_fd()) diff --git a/lib_pypy/msvcrt.py b/lib_pypy/msvcrt.py --- a/lib_pypy/msvcrt.py +++ b/lib_pypy/msvcrt.py @@ -8,25 +8,37 @@ # PAC: 2010/08 added MS locking for Whoosh import ctypes +import errno from ctypes_support import standard_c_lib as _c from ctypes_support import get_errno -import errno try: open_osfhandle = _c._open_osfhandle except AttributeError: # we are not on windows raise ImportError -try: from __pypy__ import builtinify -except ImportError: builtinify = lambda f: f +try: from __pypy__ import builtinify, validate_fd +except ImportError: builtinify = validate_fd = lambda f: f 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 +_get_osfhandle = _c._get_osfhandle +_get_osfhandle.argtypes = [ctypes.c_int] +_get_osfhandle.restype = ctypes.c_int + + at builtinify +def get_osfhandle(fd): + """"get_osfhandle(fd) -> file handle + + Return the file handle for the file descriptor fd. Raises IOError if + fd is not recognized.""" + try: + validate_fd(fd) + except OSError as e: + raise IOError(*e.args) + return _get_osfhandle(fd) setmode = _c._setmode setmode.argtypes = [ctypes.c_int, ctypes.c_int] diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py --- a/pypy/config/pypyoption.py +++ b/pypy/config/pypyoption.py @@ -35,7 +35,7 @@ "thread", "itertools", "pyexpat", "_ssl", "cpyext", "array", "binascii", "_multiprocessing", '_warnings', "_collections", "_multibytecodec", "micronumpy", "_ffi", - "_continuation", "_cffi_backend", "_csv"] + "_continuation", "_cffi_backend", "_csv", "cppyy"] )) translation_modules = default_modules.copy() @@ -64,6 +64,8 @@ del working_modules["termios"] del working_modules["_minimal_curses"] + del working_modules["cppyy"] # not tested on win32 + # The _locale module is needed by site.py on Windows default_modules["_locale"] = None @@ -75,7 +77,7 @@ del working_modules["_minimal_curses"] del working_modules["termios"] del working_modules["_multiprocessing"] # depends on rctime - + del working_modules["cppyy"] # depends on ctypes module_dependencies = { diff --git a/pypy/doc/config/translation.gcrootfinder.txt b/pypy/doc/config/translation.gcrootfinder.txt --- a/pypy/doc/config/translation.gcrootfinder.txt +++ b/pypy/doc/config/translation.gcrootfinder.txt @@ -9,7 +9,9 @@ - ``--gcrootfinder=asmgcc``: use assembler hackery to find the roots directly from the normal stack. This is a bit faster, but platform specific. It works so far with GCC or MSVC, - on i386 and x86-64. + on i386 and x86-64. It is tested only on Linux (where it is + the default) so other platforms (as well as MSVC) may need + various fixes before they can be used. You may have to force the use of the shadowstack root finder if you are running into troubles or if you insist on translating diff --git a/pypy/doc/cppyy.rst b/pypy/doc/cppyy.rst --- a/pypy/doc/cppyy.rst +++ b/pypy/doc/cppyy.rst @@ -2,94 +2,128 @@ cppyy: C++ bindings for PyPy ============================ -The cppyy module provides C++ bindings for PyPy by using the reflection -information extracted from C++ header files by means of the -`Reflex package`_. -For this to work, you have to both install Reflex and build PyPy from source, -as the cppyy module is not enabled by default. -Note that the development version of cppyy lives in the reflex-support -branch. -As indicated by this being a branch, support for Reflex is still -experimental. -However, it is functional enough to put it in the hands of those who want -to give it a try. -In the medium term, cppyy will move away from Reflex and instead use -`cling`_ as its backend, which is based on `llvm`_. -Although that will change the logistics on the generation of reflection -information, it will not change the python-side interface. +The cppyy module creates, at run-time, Python-side classes and functions for +C++, by querying a C++ reflection system. +The default system used is `Reflex`_, which extracts the needed information +from C++ header files. +Another current backend is based on `CINT`_, and yet another, more important +one for the medium- to long-term will be based on `cling`_. +The latter sits on top of `llvm`_'s `clang`_, and will therefore allow the use +of C++11. +The work on the cling backend has so far been done only for CPython, but +bringing it to PyPy is a lot less work than developing it in the first place. -.. _`Reflex package`: http://root.cern.ch/drupal/content/reflex +.. _`Reflex`: http://root.cern.ch/drupal/content/reflex +.. _`CINT`: http://root.cern.ch/drupal/content/cint .. _`cling`: http://root.cern.ch/drupal/content/cling .. _`llvm`: http://llvm.org/ +.. _`clang`: http://clang.llvm.org/ + +This document describes the version of cppyy that lives in the main branch of +PyPy. +The development of cppyy happens in the "reflex-support" branch. Motivation ========== -The cppyy module offers two unique features, which result in great -performance as well as better functionality and cross-language integration -than would otherwise be possible. -First, cppyy is written in RPython and therefore open to optimizations by the -JIT up until the actual point of call into C++. -This means that there are no conversions necessary between a garbage collected -and a reference counted environment, as is needed for the use of existing -extension modules written or generated for CPython. -It also means that if variables are already unboxed by the JIT, they can be -passed through directly to C++. -Second, Reflex (and cling far more so) adds dynamic features to C++, thus -greatly reducing impedance mismatches between the two languages. -In fact, Reflex is dynamic enough that you could write the runtime bindings +To provide bindings to another language in CPython, you program to a +generic C-API that exposes many of the interpreter features. +With PyPy, however, there is no such generic C-API, because several of the +interpreter features (e.g. the memory model) are pluggable and therefore +subject to change. +Furthermore, a generic API does not allow any assumptions about the calls +into another language, forcing the JIT to behave conservatively around these +calls and with the objects that cross language boundaries. +In contrast, cppyy does not expose an API, but expects one to be implemented +by a backend. +It makes strong assumptions about the semantics of the API that it uses and +that in turn allows the JIT to make equally strong assumptions. +This is possible, because the expected API is only for providing C++ language +bindings, and does not provide generic programmability. + +The cppyy module further offers two features, which result in improved +performance as well as better functionality and cross-language integration. +First, cppyy itself is written in RPython and therefore open to optimizations +by the JIT up until the actual point of call into C++. +This means for example, that if variables are already unboxed by the JIT, they +can be passed through directly to C++. +Second, a backend such as Reflex (and cling far more so) adds dynamic features +to C++, thus greatly reducing impedance mismatches between the two languages. +For example, Reflex is dynamic enough to allow writing runtime bindings generation in python (as opposed to RPython) and this is used to create very natural "pythonizations" of the bound code. +As another example, cling allows automatic instantiations of templates. + +See this description of the `cppyy architecture`_ for further details. + +.. _`cppyy architecture`: http://morepypy.blogspot.com/2012/06/architecture-of-cppyy.html Installation ============ -For now, the easiest way of getting the latest version of Reflex, is by -installing the ROOT package. -Besides getting the latest version of Reflex, another advantage is that with -the full ROOT package, you can also use your Reflex-bound code on `CPython`_. -`Download`_ a binary or install from `source`_. -Some Linux and Mac systems may have ROOT provided in the list of scientific -software of their packager. -If, however, you prefer a standalone version of Reflex, the best is to get -this `recent snapshot`_, and install like so:: +There are two ways of using cppyy, and the choice depends on how pypy-c was +built: the backend can be builtin, or dynamically loadable. +The former has the disadvantage of requiring pypy-c to be linked with external +C++ libraries (e.g. libReflex.so), but has the advantage of being faster in +some cases. +That advantage will disappear over time, however, with improvements in the +JIT. +Therefore, this document assumes that the dynamically loadable backend is +chosen (it is, by default). +See the `backend documentation`_. - $ tar jxf reflex-2012-05-02.tar.bz2 - $ cd reflex-2012-05-02 - $ build/autogen +.. _`backend documentation`: cppyy_backend.html + +A standalone version of Reflex that also provides the dynamically loadable +backend is available for `download`_. +That version, as well as any other distribution of Reflex (e.g. the one that +comes with `ROOT`_, which may be part of your Linux distribution as part of +the selection of scientific software) will also work for a build with the +builtin backend. + +.. _`download`: http://cern.ch/wlav/reflex-2013-04-23.tar.bz2 +.. _`ROOT`: http://root.cern.ch/ + +Besides Reflex, you probably need a version of `gccxml`_ installed, which is +most easily provided by the packager of your system. +If you read up on gccxml, you will probably notice that it is no longer being +developed and hence will not provide C++11 support. +That's why the medium term plan is to move to cling. +Note that gccxml is only needed to generate reflection libraries. +It is not needed to use them. + +.. _`gccxml`: http://www.gccxml.org + +To install the standalone version of Reflex, after download:: + + $ tar jxf reflex-2013-04-23.tar.bz2 + $ cd reflex-2013-04-23 + $ ./build/autogen $ ./configure $ make && make install -Also, make sure you have a version of `gccxml`_ installed, which is most -easily provided by the packager of your system. -If you read up on gccxml, you'll probably notice that it is no longer being -developed and hence will not provide C++11 support. -That's why the medium term plan is to move to `cling`_. +The usual rules apply: /bin needs to be added to the ``PATH`` and +/lib to the ``LD_LIBRARY_PATH`` environment variable. +For convenience, this document will assume that there is a ``REFLEXHOME`` +variable that points to . +If you downloaded or built the whole of ROOT, ``REFLEXHOME`` should be equal +to ``ROOTSYS``. -.. _`Download`: http://root.cern.ch/drupal/content/downloading-root -.. _`source`: http://root.cern.ch/drupal/content/installing-root-source -.. _`recent snapshot`: http://cern.ch/wlav/reflex-2012-05-02.tar.bz2 -.. _`gccxml`: http://www.gccxml.org +The following is optional, and is only to show how pypy-c can be build +`from source`_, for example to get at the main development branch of cppyy. +The `backend documentation`_ has more details on the backend-specific +prerequisites. -Next, get the `PyPy sources`_, optionally select the reflex-support branch, -and build it. -For the build to succeed, the ``$ROOTSYS`` environment variable must point to -the location of your ROOT (or standalone Reflex) installation, or the -``root-config`` utility must be accessible through ``PATH`` (e.g. by adding -``$ROOTSYS/bin`` to ``PATH``). -In case of the former, include files are expected under ``$ROOTSYS/include`` -and libraries under ``$ROOTSYS/lib``. Then run the translation to build ``pypy-c``:: $ hg clone https://bitbucket.org/pypy/pypy $ cd pypy $ hg up reflex-support # optional - $ cd pypy/goal # This example shows python, but using pypy-c is faster and uses less memory - $ python ../../rpython/bin/rpython.py -O jit --gcrootfinder=shadowstack targetpypystandalone.py --withmod-cppyy + $ python rpython/translator/goal/translate.py --opt=jit pypy/goal/targetpypystandalone --withmod-cppyy This will build a ``pypy-c`` that includes the cppyy module, and through that, Reflex support. @@ -98,12 +132,12 @@ If not, you may want `to obtain a binary distribution`_ to speed up the translation step. -.. _`PyPy sources`: https://bitbucket.org/pypy/pypy/overview +.. _`from source`: https://bitbucket.org/pypy/pypy/overview .. _`to obtain a binary distribution`: http://doc.pypy.org/en/latest/getting-started.html#download-a-pre-built-pypy -Basic example -============= +Basic bindings example +====================== Now test with a trivial example whether all packages are properly installed and functional. @@ -127,7 +161,7 @@ code:: $ genreflex MyClass.h - $ g++ -fPIC -rdynamic -O2 -shared -I$ROOTSYS/include MyClass_rflx.cpp -o libMyClassDict.so -L$ROOTSYS/lib -lReflex + $ g++ -fPIC -rdynamic -O2 -shared -I$REFLEXHOME/include MyClass_rflx.cpp -o libMyClassDict.so -L$REFLEXHOME/lib -lReflex Now you're ready to use the bindings. Since the bindings are designed to look pythonistic, it should be @@ -176,7 +210,7 @@ For example:: $ genreflex MyClass.h --rootmap=libMyClassDict.rootmap --rootmap-lib=libMyClassDict.so - $ g++ -fPIC -rdynamic -O2 -shared -I$ROOTSYS/include MyClass_rflx.cpp -o libMyClassDict.so -L$ROOTSYS/lib -lReflex + $ g++ -fPIC -rdynamic -O2 -shared -I$REFLEXHOME/include MyClass_rflx.cpp -o libMyClassDict.so -L$REFLEXHOME/lib -lReflex where the first option (``--rootmap``) specifies the output file name, and the second option (``--rootmap-lib``) the name of the reflection library where @@ -277,7 +311,7 @@ Now the reflection info can be generated and compiled:: $ genreflex MyAdvanced.h --selection=MyAdvanced.xml - $ g++ -fPIC -rdynamic -O2 -shared -I$ROOTSYS/include MyAdvanced_rflx.cpp -o libAdvExDict.so -L$ROOTSYS/lib -lReflex + $ g++ -fPIC -rdynamic -O2 -shared -I$REFLEXHOME/include MyAdvanced_rflx.cpp -o libAdvExDict.so -L$REFLEXHOME/lib -lReflex and subsequently be used from PyPy:: @@ -336,7 +370,7 @@ bound using:: $ genreflex example.h --deep --rootmap=libexampleDict.rootmap --rootmap-lib=libexampleDict.so - $ g++ -fPIC -rdynamic -O2 -shared -I$ROOTSYS/include example_rflx.cpp -o libexampleDict.so -L$ROOTSYS/lib -lReflex + $ g++ -fPIC -rdynamic -O2 -shared -I$REFLEXHOME/include example_rflx.cpp -o libexampleDict.so -L$REFLEXHOME/lib -lReflex .. _`example code`: cppyy_example.html @@ -595,6 +629,16 @@ All template classes must already exist in the loaded reflection info, they do not work (yet) with the class loader. + For compatibility with other bindings generators, use of square brackets + instead of parenthesis to instantiate templates is supported as well. + +* **templated functions**: Automatically participate in overloading and are + used in the same way as other global functions. + +* **templated methods**: For now, require an explicit selection of the + template parameters. + This will be changed to allow them to participate in overloads as expected. + * **typedefs**: Are simple python references to the actual classes to which they refer. @@ -692,7 +736,7 @@ Run the normal ``genreflex`` and compilation steps:: $ genreflex MyTemplate.h --selection=MyTemplate.xml - $ g++ -fPIC -rdynamic -O2 -shared -I$ROOTSYS/include MyTemplate_rflx.cpp -o libTemplateDict.so -L$ROOTSYS/lib -lReflex + $ g++ -fPIC -rdynamic -O2 -shared -I$REFLEXHOME/include MyTemplate_rflx.cpp -o libTemplateDict.so -L$REFLEXHOME/lib -lReflex Note: this is a dirty corner that clearly could do with some automation, even if the macro already helps. @@ -727,18 +771,18 @@ The fast lane ============= -The following is an experimental feature of cppyy, and that makes it doubly -experimental, so caveat emptor. +The following is an experimental feature of cppyy. +It mostly works, but there are some known issues (e.g. with return-by-value). +Soon it should be the default mode, however. + With a slight modification of Reflex, it can provide function pointers for C++ methods, and hence allow PyPy to call those pointers directly, rather than calling C++ through a Reflex stub. -This results in a rather significant speed-up. -Mind you, the normal stub path is not exactly slow, so for now only use this -out of curiosity or if you really need it. -To install this patch of Reflex, locate the file genreflex-methptrgetter.patch -in pypy/module/cppyy and apply it to the genreflex python scripts found in -``$ROOTSYS/lib``:: +The standalone version of Reflex `provided`_ has been patched, but if you get +Reflex from another source (most likely with a ROOT distribution), locate the +file `genreflex-methptrgetter.patch`_ in pypy/module/cppyy and apply it to +the genreflex python scripts found in ``$ROOTSYS/lib``:: $ cd $ROOTSYS/lib $ patch -p2 < genreflex-methptrgetter.patch @@ -749,8 +793,10 @@ ``-Wno-pmf-conversions`` option to ``g++`` when compiling. The rest works the same way: the fast path will be used transparently (which also means that you can't actually find out whether it is in use, other than -by running a micro-benchmark). +by running a micro-benchmark or a JIT test). +.. _`provided`: http://cern.ch/wlav/reflex-2013-04-23.tar.bz2 +.. _`genreflex-methptrgetter.patch`: https://bitbucket.org/pypy/pypy/src/default/pypy/module/cppyy/genreflex-methptrgetter.patch CPython ======= diff --git a/pypy/doc/cppyy_backend.rst b/pypy/doc/cppyy_backend.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/cppyy_backend.rst @@ -0,0 +1,53 @@ +================== +Backends for cppyy +================== + +The cppyy module needs a backend to provide the C++ reflection information on +which the Python bindings are build. +The backend is called through a C-API, which can be found in the PyPy sources +in: `pypy/module/cppyy/include/capi.h`_. +There are two kinds of API calls: querying about reflection information, which +are used during the creation of Python-side constructs, and making the actual +calls into C++. +The objects passed around are all opaque: cppyy does not make any assumptions +about them, other than that the opaque handles can be copied. +Their definition, however, appears in two places: in the C code (in capi.h), +and on the RPython side (in `capi_types.py`_), so if they are changed, they +need to be changed on both sides. + +.. _`pypy/module/cppyy/include/capi.h`: https://bitbucket.org/pypy/pypy/src/default/pypy/module/cppyy/include/capi.h +.. _`capi_types.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/module/cppyy/capi/capi_types.py + +There are two places where selections in the RPython code affect the choice +(and use) of the backend. +The first is in `pypy/module/cppyy/capi/__init__.py`_:: + + # choose C-API access method: + from pypy.module.cppyy.capi.loadable_capi import * + #from pypy.module.cppyy.capi.builtin_capi import * + +The default is the loadable C-API. +Comment it and uncomment the builtin C-API line, to use the builtin version. + +.. _`pypy/module/cppyy/capi/__init__.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/module/cppyy/capi/__init__.py + +Next, if the builtin C-API is chosen, the specific backend needs to be set as +well (default is Reflex). +This second choice is in `pypy/module/cppyy/capi/builtin_capi.py`_:: + + import reflex_capi as backend + #import cint_capi as backend + +After those choices have been made, built pypy-c as usual. + +.. _`pypy/module/cppyy/capi/builtin_capi.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/module/cppyy/capi/builtin_capi.py + +When building pypy-c from source, keep the following in mind. +If the loadable_capi is chosen, no further prerequisites are needed. +However, for the build of the builtin_capi to succeed, the ``ROOTSYS`` +environment variable must point to the location of your ROOT (or standalone +Reflex in the case of the Reflex backend) installation, or the ``root-config`` +utility must be accessible through ``$PATH`` (e.g. by adding ``$ROOTSYS/bin`` +to ``PATH``). +In case of the former, include files are expected under ``$ROOTSYS/include`` +and libraries under ``$ROOTSYS/lib``. diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -57,10 +57,12 @@ Inline the fast path of newarray in the assembler. Disabled on ARM until we fix issues. +.. branch: reflex-support +Allow dynamic loading of a (Reflex) backend that implements the C-API needed +to provide reflection information .. branches we don't care about .. branch: autoreds -.. branch: reflex-support .. branch: kill-faking .. branch: improved_ebnfparse_error .. branch: task-decorator diff --git a/pypy/module/_minimal_curses/__init__.py b/pypy/module/_minimal_curses/__init__.py --- a/pypy/module/_minimal_curses/__init__.py +++ b/pypy/module/_minimal_curses/__init__.py @@ -1,6 +1,6 @@ try: import _curses -except ImportError: +except Exception: # probably ImportError or cffi's VerificationError try: # when running on top of pypy before it had _curses, settle for minimal # we prefer _curses so any constants added make it into _minimal_curses diff --git a/pypy/module/cppyy/capi/__init__.py b/pypy/module/cppyy/capi/__init__.py --- a/pypy/module/cppyy/capi/__init__.py +++ b/pypy/module/cppyy/capi/__init__.py @@ -9,8 +9,8 @@ # the selection of the desired backend (default is Reflex). # choose C-API access method: -#from pypy.module.cppyy.capi.loadable_capi import * -from pypy.module.cppyy.capi.builtin_capi import * +from pypy.module.cppyy.capi.loadable_capi import * +#from pypy.module.cppyy.capi.builtin_capi import * from pypy.module.cppyy.capi.capi_types import C_OBJECT,\ C_NULL_TYPE, C_NULL_OBJECT diff --git a/pypy/module/cppyy/capi/loadable_capi.py b/pypy/module/cppyy/capi/loadable_capi.py --- a/pypy/module/cppyy/capi/loadable_capi.py +++ b/pypy/module/cppyy/capi/loadable_capi.py @@ -11,7 +11,7 @@ C_METHOD, C_INDEX, C_INDEX_ARRAY, WLAVC_INDEX, C_METHPTRGETTER_PTR -reflection_library = 'rflxlib.so' +reflection_library = 'libcppyy_backend.so' def identify(): return 'loadable_capi' @@ -231,7 +231,7 @@ except Exception: if objectmodel.we_are_translated(): raise OperationError(space.w_ImportError, - space.wrap("missing reflection library rflxlib.so")) + space.wrap("missing reflection library %s" % reflection_library)) return False return True diff --git a/pypy/module/cppyy/test/Makefile b/pypy/module/cppyy/test/Makefile --- a/pypy/module/cppyy/test/Makefile +++ b/pypy/module/cppyy/test/Makefile @@ -3,7 +3,11 @@ std_streamsDict.so iotypesDict.so all : $(dicts) -ROOTSYS := ${ROOTSYS} +ifneq (${REFLEXHOME},) + ROOTSYS := ${REFLEXHOME} +else + ROOTSYS := ${ROOTSYS} +endif ifeq ($(ROOTSYS),) genreflex=genreflex diff --git a/pypy/module/posix/app_posix.py b/pypy/module/posix/app_posix.py --- a/pypy/module/posix/app_posix.py +++ b/pypy/module/posix/app_posix.py @@ -20,7 +20,7 @@ class stat_result: __metaclass__ = structseqtype - name = "posix.stat_result" + name = osname + ".stat_result" st_mode = structseqfield(0, "protection bits") st_ino = structseqfield(1, "inode") diff --git a/pypy/module/posix/test/test_posix2.py b/pypy/module/posix/test/test_posix2.py --- a/pypy/module/posix/test/test_posix2.py +++ b/pypy/module/posix/test/test_posix2.py @@ -159,6 +159,7 @@ assert st.st_atime == 41 assert st.st_mtime == 42.1 assert st.st_ctime == 43 + assert repr(st).startswith(self.posix.__name__ + '.stat_result') def test_stat_lstat(self): import stat diff --git a/pypy/module/thread/threadlocals.py b/pypy/module/thread/threadlocals.py --- a/pypy/module/thread/threadlocals.py +++ b/pypy/module/thread/threadlocals.py @@ -52,7 +52,7 @@ def signals_enabled(self): ec = self.getvalue() - return ec._signals_enabled + return ec is not None and ec._signals_enabled def enable_signals(self, space): ec = self.getvalue() @@ -72,10 +72,12 @@ def leave_thread(self, space): "Notification that the current thread is about to stop." from pypy.module.thread.os_local import thread_is_stopping - try: - thread_is_stopping(self.getvalue()) - finally: - self.setvalue(None) + ec = self.getvalue() + if ec is not None: + try: + thread_is_stopping(ec) + finally: + self.setvalue(None) def reinit_threads(self, space): "Called in the child process after a fork()" diff --git a/pypy/pytest-A.py b/pypy/pytest-A.py new file mode 100644 --- /dev/null +++ b/pypy/pytest-A.py @@ -0,0 +1,31 @@ +# custom test collection for the app-level testrunner +import platform + +DIRS_SPLIT = { + 'arm': ['interpreter/astcompiler/test', + 'interpreter/pyparser/test', + 'interpreter/test', + 'interpreter/test2', + 'objspace/std/test', + ], +} + + +def get_arch(): + arch = platform.machine().lower() + if arch.startswith('arm'): + return 'arm' + if arch.startswith('x86'): + return 'x86' + return arch + + +def collect_one_testdir(testdirs, reldir, tests): + arch = get_arch() + dirsplit = DIRS_SPLIT.get(arch, []) + for dir in dirsplit: + if reldir.startswith(dir): + testdirs.extend(tests) + break + else: + testdirs.append(reldir) diff --git a/pypy/tool/pypyjit.py b/pypy/tool/pypyjit.py --- a/pypy/tool/pypyjit.py +++ b/pypy/tool/pypyjit.py @@ -41,7 +41,6 @@ config.objspace.usemodules._lsprof = False # config.objspace.usemodules._ffi = True -#config.objspace.usemodules.cppyy = True config.objspace.usemodules.micronumpy = False # set_pypy_opt_level(config, level='jit') diff --git a/rpython/annotator/model.py b/rpython/annotator/model.py --- a/rpython/annotator/model.py +++ b/rpython/annotator/model.py @@ -527,6 +527,7 @@ s_Int = SomeInteger() s_ImpossibleValue = SomeImpossibleValue() s_Str0 = SomeString(no_nul=True) +s_Unicode0 = SomeUnicodeString(no_nul=True) # ____________________________________________________________ diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -3,6 +3,7 @@ import os from rpython.jit.backend.arm import conditions as c, registers as r +from rpython.jit.backend.arm import shift from rpython.jit.backend.arm.arch import (WORD, DOUBLE_WORD, FUNC_ALIGN, JITFRAME_FIXED_SIZE) from rpython.jit.backend.arm.codebuilder import InstrBuilder, OverwritingBuilder @@ -12,8 +13,9 @@ CoreRegisterManager, check_imm_arg, VFPRegisterManager, operations as regalloc_operations, operations_with_guard as regalloc_operations_with_guard) -from rpython.jit.backend.llsupport import jitframe +from rpython.jit.backend.llsupport import jitframe, rewrite from rpython.jit.backend.llsupport.assembler import DEBUG_COUNTER, debug_bridge, BaseAssembler +from rpython.jit.backend.llsupport.regalloc import get_scale, valid_addressing_size from rpython.jit.backend.llsupport.asmmemmgr import MachineDataBlockWrapper from rpython.jit.backend.model import CompiledLoopToken from rpython.jit.codewriter.effectinfo import EffectInfo @@ -85,7 +87,7 @@ ofs = self.cpu.get_ofs_of_frame_field('jf_guard_exc') # make sure ofs fits into a register assert check_imm_arg(ofs) - mc.LDR_ri(r.r0.value, r.fp.value, imm=ofs) + self.store_reg(mc, r.r0, r.fp, ofs) propagate_exception_descr = rffi.cast(lltype.Signed, cast_instance_to_gcref(self.cpu.propagate_exception_descr)) # put propagate_exception_descr into frame @@ -93,7 +95,7 @@ # make sure ofs fits into a register assert check_imm_arg(ofs) mc.gen_load_int(r.r0.value, propagate_exception_descr) - mc.STR_ri(r.r0.value, r.fp.value, imm=ofs) + self.store_reg(mc, r.r0, r.fp, ofs) mc.MOV_rr(r.r0.value, r.fp.value) self.gen_func_epilog(mc) rawstart = mc.materialize(self.cpu.asmmemmgr, []) @@ -115,12 +117,18 @@ # store exc_value in JITFRAME ofs = self.cpu.get_ofs_of_frame_field('jf_guard_exc') assert check_imm_arg(ofs) - self.store_reg(mc, r.ip, r.fp, ofs) + # + self.load_reg(mc, r.ip, r.ip, helper=tmpreg) + # + self.store_reg(mc, r.ip, r.fp, ofs, helper=tmpreg) if exctploc is not None: # store pos_exception in exctploc assert exctploc.is_reg() mc.gen_load_int(r.ip.value, self.cpu.pos_exception()) - self.load_reg(mc, exctploc, r.ip) + self.load_reg(mc, exctploc, r.ip, helper=tmpreg) + + if on_frame or exctploc is not None: + mc.gen_load_int(r.ip.value, self.cpu.pos_exc_value()) # reset exception mc.gen_load_int(tmpreg.value, 0) @@ -250,27 +258,59 @@ self.wb_slowpath[withcards + 2 * withfloats] = rawstart def _build_malloc_slowpath(self, kind): - if kind != 'fixed': - return 0 + """ While arriving on slowpath, we have a gcpattern on stack 0. + The arguments are passed in r0 and r10, as follows: + + kind == 'fixed': nursery_head in r0 and the size in r1 - r0. + + kind == 'str/unicode': length of the string to allocate in r0. + + kind == 'var': length to allocate in r1, tid in r0, + and itemsize on the stack. + + This function must preserve all registers apart from r0 and r1. + """ + assert kind in ['fixed', 'str', 'unicode', 'var'] mc = InstrBuilder(self.cpu.cpuinfo.arch_version) + # self._push_all_regs_to_jitframe(mc, [r.r0, r.r1], self.cpu.supports_floats) + # + if kind == 'fixed': + addr = self.cpu.gc_ll_descr.get_malloc_slowpath_addr() + elif kind == 'str': + addr = self.cpu.gc_ll_descr.get_malloc_fn_addr('malloc_str') + elif kind == 'unicode': + addr = self.cpu.gc_ll_descr.get_malloc_fn_addr('malloc_unicode') + else: + addr = self.cpu.gc_ll_descr.get_malloc_slowpath_array_addr() + if kind == 'fixed': + # stack layout: [gcmap] + # At this point we know that the values we need to compute the size + # are stored in r0 and r1. + mc.SUB_rr(r.r0.value, r.r1.value, r.r0.value) # compute the size we want + + if hasattr(self.cpu.gc_ll_descr, 'passes_frame'): + mc.MOV_rr(r.r1.value, r.fp.value) + elif kind == 'str' or kind == 'unicode': + # stack layout: [gcmap] + mc.MOV_rr(r.r0.value, r.r1.value) + else: # var + # stack layout: [gcmap][itemsize]... + # tid is in r0 + # length is in r1 + mc.MOV_rr(r.r2.value, r.r1.value) + mc.MOV_rr(r.r1.value, r.r0.value) + mc.POP([r.r0.value]) # load itemsize + # store the gc pattern + mc.POP([r.r4.value]) ofs = self.cpu.get_ofs_of_frame_field('jf_gcmap') - # store the gc pattern - mc.POP([r.r2.value]) - self.store_reg(mc, r.r2, r.fp, ofs) + self.store_reg(mc, r.r4, r.fp, ofs) + # # We need to push two registers here because we are going to make a # call an therefore the stack needs to be 8-byte aligned mc.PUSH([r.ip.value, r.lr.value]) - # At this point we know that the values we need to compute the size - # are stored in r0 and r1. - mc.SUB_rr(r.r0.value, r.r1.value, r.r0.value) # compute the size we want - - if hasattr(self.cpu.gc_ll_descr, 'passes_frame'): - mc.MOV_rr(r.r1.value, r.fp.value) - - addr = self.cpu.gc_ll_descr.get_malloc_slowpath_addr() + # mc.BL(addr) - # # If the slowpath malloc failed, we raise a MemoryError that # always interrupts the current loop, as a "good enough" @@ -289,7 +329,10 @@ self.store_reg(mc, r.ip, r.fp, ofs) # return mc.POP([r.ip.value, r.pc.value]) - return mc.materialize(self.cpu.asmmemmgr, []) + + # + rawstart = mc.materialize(self.cpu.asmmemmgr, []) + return rawstart def _reload_frame_if_necessary(self, mc): gcrootmap = self.cpu.gc_ll_descr.gcrootmap @@ -1168,21 +1211,17 @@ else: raise AssertionError('Trying to pop to an invalid location') - def malloc_cond(self, nursery_free_adr, nursery_top_adr, sizeloc, gcmap): - if sizeloc.is_imm(): # must be correctly aligned - assert sizeloc.value & (WORD-1) == 0 + def malloc_cond(self, nursery_free_adr, nursery_top_adr, size, gcmap): + assert size & (WORD-1) == 0 self.mc.gen_load_int(r.r0.value, nursery_free_adr) self.mc.LDR_ri(r.r0.value, r.r0.value) - if sizeloc.is_imm(): - if check_imm_arg(sizeloc.value): - self.mc.ADD_ri(r.r1.value, r.r0.value, sizeloc.value) - else: - self.mc.gen_load_int(r.r1.value, sizeloc.value) - self.mc.ADD_rr(r.r1.value, r.r0.value, r.r1.value) + if check_imm_arg(size): + self.mc.ADD_ri(r.r1.value, r.r0.value, size) else: - self.mc.ADD_rr(r.r1.value, r.r0.value, sizeloc.value) + self.mc.gen_load_int(r.r1.value, size) + self.mc.ADD_rr(r.r1.value, r.r0.value, r.r1.value) self.mc.gen_load_int(r.ip.value, nursery_top_adr) self.mc.LDR_ri(r.ip.value, r.ip.value) @@ -1203,6 +1242,128 @@ self.mc.gen_load_int(r.ip.value, nursery_free_adr) self.mc.STR_ri(r.r1.value, r.ip.value) + def malloc_cond_varsize_frame(self, nursery_free_adr, nursery_top_adr, + sizeloc, gcmap): + if sizeloc is r.r0: + self.mc.MOV_rr(r.r1.value, r.r0.value) + sizeloc = r.r1 + self.mc.gen_load_int(r.r0.value, nursery_free_adr) + self.mc.LDR_ri(r.r0.value, r.r0.value) + # + self.mc.ADD_rr(r.r1.value, r.r0.value, sizeloc.value) + # + self.mc.gen_load_int(r.ip.value, nursery_top_adr) + self.mc.LDR_ri(r.ip.value, r.ip.value) + + self.mc.CMP_rr(r.r1.value, r.ip.value) + # + self.push_gcmap(self.mc, gcmap, push=True, cond=c.HI) + + self.mc.BL(self.malloc_slowpath, c=c.HI) + + self.mc.gen_load_int(r.ip.value, nursery_free_adr) + self.mc.STR_ri(r.r1.value, r.ip.value) + + def malloc_cond_varsize(self, kind, nursery_free_adr, nursery_top_adr, + lengthloc, itemsize, maxlength, gcmap, + arraydescr): + from rpython.jit.backend.llsupport.descr import ArrayDescr + assert isinstance(arraydescr, ArrayDescr) + + # lengthloc is the length of the array, which we must not modify! + assert lengthloc is not r.r0 and lengthloc is not r.r1 + if lengthloc.is_reg(): + varsizeloc = lengthloc + else: + assert lengthloc.is_stack() + self.regalloc_mov(lengthloc, r.r1) + varsizeloc = r.r1 + # + if check_imm_arg(maxlength): + self.mc.CMP_ri(varsizeloc.value, maxlength) + else: + self.mc.gen_load_int(r.ip.value, maxlength) + self.mc.CMP_rr(varsizeloc.value, r.ip.value) + jmp_adr0 = self.mc.currpos() # jump to (large) + self.mc.BKPT() + # + self.mc.gen_load_int(r.r0.value, nursery_free_adr) + self.mc.LDR_ri(r.r0.value, r.r0.value) + + + if valid_addressing_size(itemsize): + shiftsize = get_scale(itemsize) + else: + shiftsize = self._mul_const_scaled(self.mc, r.lr, varsizeloc, + itemsize) + varsizeloc = r.lr + # now varsizeloc is a register != r0. The size of + # the variable part of the array is (varsizeloc << shiftsize) + assert arraydescr.basesize >= self.gc_minimal_size_in_nursery + constsize = arraydescr.basesize + self.gc_size_of_header + force_realignment = (itemsize % WORD) != 0 + if force_realignment: + constsize += WORD - 1 + self.mc.gen_load_int(r.ip.value, constsize) + # constsize + (varsizeloc << shiftsize) + self.mc.ADD_rr(r.r1.value, r.ip.value, varsizeloc.value, + imm=shiftsize, shifttype=shift.LSL) + self.mc.ADD_rr(r.r1.value, r.r1.value, r.r0.value) + if force_realignment: + self.mc.MVN_ri(r.ip.value, imm=(WORD - 1)) + self.mc.AND_rr(r.r1.value, r.r1.value, r.ip.value) + # now r1 contains the total size in bytes, rounded up to a multiple + # of WORD, plus nursery_free_adr + # + self.mc.gen_load_int(r.ip.value, nursery_top_adr) + self.mc.LDR_ri(r.ip.value, r.ip.value) + + self.mc.CMP_rr(r.r1.value, r.ip.value) + jmp_adr1 = self.mc.currpos() # jump to (after-call) + self.mc.BKPT() + # + # (large) + currpos = self.mc.currpos() + pmc = OverwritingBuilder(self.mc, jmp_adr0, WORD) + pmc.B_offs(currpos, c.GT) + # + # save the gcmap + self.push_gcmap(self.mc, gcmap, push=True) + # + if kind == rewrite.FLAG_ARRAY: + self.mc.gen_load_int(r.r0.value, arraydescr.tid) + self.regalloc_mov(lengthloc, r.r1) + self.regalloc_push(imm(itemsize)) + addr = self.malloc_slowpath_varsize + else: + if kind == rewrite.FLAG_STR: + addr = self.malloc_slowpath_str + else: + assert kind == rewrite.FLAG_UNICODE + addr = self.malloc_slowpath_unicode + self.regalloc_mov(lengthloc, r.r1) + self.mc.BL(addr) + # + jmp_location = self.mc.currpos() # jump to (done) + self.mc.BKPT() + # (after-call) + currpos = self.mc.currpos() + pmc = OverwritingBuilder(self.mc, jmp_adr1, WORD) + pmc.B_offs(currpos, c.LS) + # + # write down the tid, but not if it's the result of the CALL + self.mc.gen_load_int(r.ip.value, arraydescr.tid) + self.mc.STR_ri(r.ip.value, r.r0.value) + + # while we're at it, this line is not needed if we've done the CALL + self.mc.gen_load_int(r.ip.value, nursery_free_adr) + self.mc.STR_ri(r.r1.value, r.ip.value) + # (done) + # skip instructions after call + currpos = self.mc.currpos() + pmc = OverwritingBuilder(self.mc, jmp_location, WORD) + pmc.B_offs(currpos) + def push_gcmap(self, mc, gcmap, push=False, store=False, cond=c.AL): ptr = rffi.cast(lltype.Signed, gcmap) if push: @@ -1220,6 +1381,32 @@ mc.gen_load_int(r.ip.value, 0) self.store_reg(mc, r.ip, r.fp, ofs) + def _mul_const_scaled(self, mc, targetreg, sourcereg, itemsize): + """Produce one operation to do roughly + targetreg = sourcereg * itemsize + except that the targetreg may still need shifting by 0,1,2,3. + """ + if (itemsize & 7) == 0: + shiftsize = 3 + elif (itemsize & 3) == 0: + shiftsize = 2 + elif (itemsize & 1) == 0: + shiftsize = 1 + else: + shiftsize = 0 + itemsize >>= shiftsize + # + if valid_addressing_size(itemsize - 1): + self.mc.ADD_rr(targetreg.value, sourcereg.value, sourcereg.value, + imm=get_scale(itemsize - 1), shifttype=shift.LSL) + elif valid_addressing_size(itemsize): + self.mc.LSL_ri(targetreg.value, sourcereg.value, + get_scale(itemsize)) + else: + mc.gen_load_int(targetreg.value, itemsize) + mc.MUL(targetreg.value, sourcereg.value, targetreg.value) + # + return shiftsize def not_implemented(msg): os.write(2, '[ARM/asm] %s\n' % msg) diff --git a/rpython/jit/backend/arm/detect.py b/rpython/jit/backend/arm/detect.py --- a/rpython/jit/backend/arm/detect.py +++ b/rpython/jit/backend/arm/detect.py @@ -2,6 +2,7 @@ from rpython.translator.tool.cbuild import ExternalCompilationInfo from rpython.rtyper.tool import rffi_platform +from rpython.rlib.clibffi import FFI_DEFAULT_ABI, FFI_SYSV, FFI_VFP from rpython.translator.platform import CompilationError from rpython.rlib.debug import debug_print, debug_start, debug_stop diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -18,7 +18,7 @@ from rpython.jit.backend.arm.helper.regalloc import check_imm_arg from rpython.jit.backend.arm.codebuilder import InstrBuilder, OverwritingBuilder from rpython.jit.backend.arm.jump import remap_frame_layout -from rpython.jit.backend.arm.regalloc import TempInt, TempPtr +from rpython.jit.backend.arm.regalloc import TempBox from rpython.jit.backend.arm.locations import imm from rpython.jit.backend.llsupport import symbolic from rpython.jit.backend.llsupport.gcmap import allocate_gcmap @@ -191,7 +191,7 @@ return fcond def _emit_guard(self, op, arglocs, fcond, save_exc, - is_guard_not_invalidated=False, + is_guard_not_invalidated=False, is_guard_not_forced=False): assert isinstance(save_exc, bool) assert isinstance(fcond, int) @@ -297,7 +297,7 @@ return self._emit_guard(op, locs, fcond, save_exc=False, is_guard_not_invalidated=True) - def emit_op_label(self, op, arglocs, regalloc, fcond): + def emit_op_label(self, op, arglocs, regalloc, fcond): self._check_frame_depth_debug(self.mc) return fcond @@ -1003,57 +1003,33 @@ def _emit_copystrcontent(self, op, regalloc, fcond, is_unicode): # compute the source address args = op.getarglist() - base_loc = regalloc.make_sure_var_in_reg(args[0], args) - ofs_loc = regalloc.make_sure_var_in_reg(args[2], args) + base_loc = regalloc.rm.make_sure_var_in_reg(args[0], args) + ofs_loc = regalloc.rm.make_sure_var_in_reg(args[2], args) assert args[0] is not args[1] # forbidden case of aliasing - regalloc.possibly_free_var(args[0]) - regalloc.free_temp_vars() - if args[3] is not args[2] is not args[4]: # MESS MESS MESS: don't free - regalloc.possibly_free_var(args[2]) # it if ==args[3] or args[4] - regalloc.free_temp_vars() - srcaddr_box = TempPtr() + srcaddr_box = TempBox() forbidden_vars = [args[1], args[3], args[4], srcaddr_box] - srcaddr_loc = regalloc.force_allocate_reg(srcaddr_box, - selected_reg=r.r1) + srcaddr_loc = regalloc.rm.force_allocate_reg(srcaddr_box, forbidden_vars) self._gen_address_inside_string(base_loc, ofs_loc, srcaddr_loc, is_unicode=is_unicode) - # compute the destination address - forbidden_vars = [args[4], args[3], srcaddr_box] - dstaddr_box = TempPtr() - dstaddr_loc = regalloc.force_allocate_reg(dstaddr_box, - selected_reg=r.r0) - forbidden_vars.append(dstaddr_box) - base_loc = regalloc.make_sure_var_in_reg(args[1], forbidden_vars) - ofs_loc = regalloc.make_sure_var_in_reg(args[3], forbidden_vars) - assert base_loc.is_reg() - assert ofs_loc.is_reg() - regalloc.possibly_free_var(args[1]) - if args[3] is not args[4]: # more of the MESS described above - regalloc.possibly_free_var(args[3]) - regalloc.free_temp_vars() + base_loc = regalloc.rm.make_sure_var_in_reg(args[1], forbidden_vars) + ofs_loc = regalloc.rm.make_sure_var_in_reg(args[3], forbidden_vars) + forbidden_vars = [args[4], srcaddr_box] + dstaddr_box = TempBox() + dstaddr_loc = regalloc.rm.force_allocate_reg(dstaddr_box, forbidden_vars) self._gen_address_inside_string(base_loc, ofs_loc, dstaddr_loc, is_unicode=is_unicode) - # compute the length in bytes - forbidden_vars = [srcaddr_box, dstaddr_box] - # XXX basically duplicates regalloc.ensure_value_is_boxed, but we - # need the box here - if isinstance(args[4], Box): - length_box = args[4] - length_loc = regalloc.make_sure_var_in_reg(args[4], - forbidden_vars) - else: - length_box = TempInt() - length_loc = regalloc.force_allocate_reg(length_box, - forbidden_vars, selected_reg=r.r2) - immloc = regalloc.convert_to_imm(args[4]) - self.load(length_loc, immloc) + length_box = args[4] + length_loc = regalloc.loc(length_box) if is_unicode: - bytes_box = TempPtr() - bytes_loc = regalloc.force_allocate_reg(bytes_box, - forbidden_vars, selected_reg=r.r2) + forbidden_vars = [srcaddr_box, dstaddr_box] + bytes_box = TempBox() + bytes_loc = regalloc.rm.force_allocate_reg(bytes_box, forbidden_vars) scale = self._get_unicode_item_scale() + if not length_loc.is_reg(): + self.regalloc_mov(length_loc, bytes_loc) + length_loc = bytes_loc assert length_loc.is_reg() self.mc.MOV_ri(r.ip.value, 1 << scale) self.mc.MUL(bytes_loc.value, r.ip.value, length_loc.value) @@ -1062,12 +1038,11 @@ # call memcpy() regalloc.before_call() self._emit_call(imm(self.memcpy_addr), - [dstaddr_loc, srcaddr_loc, length_loc], - can_collect=False) - - regalloc.possibly_free_var(length_box) - regalloc.possibly_free_var(dstaddr_box) - regalloc.possibly_free_var(srcaddr_box) + [dstaddr_loc, srcaddr_loc, length_loc], + can_collect=False) + regalloc.rm.possibly_free_var(length_box) + regalloc.rm.possibly_free_var(dstaddr_box) + regalloc.rm.possibly_free_var(srcaddr_box) def _gen_address_inside_string(self, baseloc, ofsloc, resloc, is_unicode): if is_unicode: @@ -1079,21 +1054,21 @@ self.cpu.translate_support_code) assert itemsize == 1 scale = 0 - self._gen_address(ofsloc, ofs_items, scale, resloc, baseloc) + self._gen_address(resloc, baseloc, ofsloc, scale, ofs_items) - def _gen_address(self, sizereg, baseofs, scale, result, baseloc=None): - assert sizereg.is_reg() + # result = base_loc + (scaled_loc << scale) + static_offset + def _gen_address(self, result, base_loc, scaled_loc, scale=0, static_offset=0): + assert scaled_loc.is_reg() + assert base_loc.is_reg() + assert check_imm_arg(scale) + assert check_imm_arg(static_offset) if scale > 0: + self.mc.LSL_ri(r.ip.value, scaled_loc.value, scale) scaled_loc = r.ip - self.mc.LSL_ri(r.ip.value, sizereg.value, scale) else: - scaled_loc = sizereg - if baseloc is not None: - assert baseloc.is_reg() - self.mc.ADD_rr(result.value, baseloc.value, scaled_loc.value) - self.mc.ADD_ri(result.value, result.value, baseofs) - else: - self.mc.ADD_ri(result.value, scaled_loc.value, baseofs) + scaled_loc = scaled_loc + self.mc.ADD_rr(result.value, base_loc.value, scaled_loc.value) + self.mc.ADD_ri(result.value, result.value, static_offset) def _get_unicode_item_scale(self): _, itemsize, _ = symbolic.get_array_token(rstr.UNICODE, @@ -1320,6 +1295,7 @@ with saved_registers(self.mc, regs_to_save, vfp_regs_to_save): self._emit_call(imm(self.reacqgil_addr), [], fcond, can_collect=False) + self._reload_frame_if_necessary(self.mc) def _store_force_index(self, guard_op): faildescr = guard_op.getdescr() @@ -1334,23 +1310,6 @@ self._alignment_check() return fcond - def emit_op_call_malloc_nursery(self, op, arglocs, regalloc, fcond): - # registers r0 and r1 are allocated for this call - assert len(arglocs) == 1 - sizeloc = arglocs[0] - gc_ll_descr = self.cpu.gc_ll_descr - gcmap = regalloc.get_gcmap([r.r0, r.r1]) - self.malloc_cond( - gc_ll_descr.get_nursery_free_addr(), - gc_ll_descr.get_nursery_top_addr(), - sizeloc, - gcmap - ) - self._alignment_check() - return fcond - emit_op_call_malloc_nursery_varsize_frame = emit_op_call_malloc_nursery - - def _alignment_check(self): if not self.debug: return @@ -1436,7 +1395,7 @@ self.mc.VCVT_f64_f32(r.vfp_ip.value, arg.value) self.mc.VMOV_rc(res.value, r.ip.value, r.vfp_ip.value) return fcond - + def emit_op_cast_singlefloat_to_float(self, op, arglocs, regalloc, fcond): arg, res = arglocs assert res.is_vfp_reg() diff --git a/rpython/jit/backend/arm/regalloc.py b/rpython/jit/backend/arm/regalloc.py --- a/rpython/jit/backend/arm/regalloc.py +++ b/rpython/jit/backend/arm/regalloc.py @@ -2,7 +2,8 @@ from rpython.rlib import rgc from rpython.rlib.debug import debug_print, debug_start, debug_stop from rpython.jit.backend.llsupport.regalloc import FrameManager, \ - RegisterManager, TempBox, compute_vars_longevity, BaseRegalloc + RegisterManager, TempBox, compute_vars_longevity, BaseRegalloc, \ + get_scale from rpython.jit.backend.arm import registers as r from rpython.jit.backend.arm import locations from rpython.jit.backend.arm.locations import imm, get_fp_offset @@ -1011,20 +1012,72 @@ self.rm.force_allocate_reg(op.result, selected_reg=r.r0) t = TempInt() self.rm.force_allocate_reg(t, selected_reg=r.r1) + + sizeloc = size_box.getint() + gc_ll_descr = self.cpu.gc_ll_descr + gcmap = self.get_gcmap([r.r0, r.r1]) self.possibly_free_var(t) - return [imm(size)] + self.assembler.malloc_cond( + gc_ll_descr.get_nursery_free_addr(), + gc_ll_descr.get_nursery_top_addr(), + sizeloc, + gcmap + ) + self.assembler._alignment_check() def prepare_op_call_malloc_nursery_varsize_frame(self, op, fcond): size_box = op.getarg(0) - assert isinstance(size_box, BoxInt) - + assert isinstance(size_box, BoxInt) # we cannot have a const here! + # sizeloc must be in a register, but we can free it now + # (we take care explicitly of conflicts with r0 or r1) + sizeloc = self.rm.make_sure_var_in_reg(size_box) + self.rm.possibly_free_var(size_box) + # self.rm.force_allocate_reg(op.result, selected_reg=r.r0) + # t = TempInt() self.rm.force_allocate_reg(t, selected_reg=r.r1) - argloc = self.make_sure_var_in_reg(size_box, - forbidden_vars=[op.result, t]) + # + gcmap = self.get_gcmap([r.r0, r.r1]) self.possibly_free_var(t) - return [argloc] + # + gc_ll_descr = self.assembler.cpu.gc_ll_descr + self.assembler.malloc_cond_varsize_frame( + gc_ll_descr.get_nursery_free_addr(), + gc_ll_descr.get_nursery_top_addr(), + sizeloc, + gcmap + ) + self.assembler._alignment_check() + + def prepare_op_call_malloc_nursery_varsize(self, op, fcond): + gc_ll_descr = self.assembler.cpu.gc_ll_descr + if not hasattr(gc_ll_descr, 'max_size_of_young_obj'): + raise Exception("unreachable code") + # for boehm, this function should never be called + arraydescr = op.getdescr() + length_box = op.getarg(2) + assert isinstance(length_box, BoxInt) # we cannot have a const here! + # the result will be in r0 + self.rm.force_allocate_reg(op.result, selected_reg=r.r0) + # we need r1 as a temporary + tmp_box = TempBox() + self.rm.force_allocate_reg(tmp_box, selected_reg=r.r1) + gcmap = self.get_gcmap([r.r0, r.r1]) # allocate the gcmap *before* + self.rm.possibly_free_var(tmp_box) + # length_box always survives: it's typically also present in the + # next operation that will copy it inside the new array. It's + # fine to load it from the stack too, as long as it's != r0, r1. + lengthloc = self.rm.loc(length_box) + self.rm.possibly_free_var(length_box) + # + itemsize = op.getarg(1).getint() + maxlength = (gc_ll_descr.max_size_of_young_obj - WORD * 2) / itemsize + self.assembler.malloc_cond_varsize( + op.getarg(0).getint(), + gc_ll_descr.get_nursery_free_addr(), + gc_ll_descr.get_nursery_top_addr(), + lengthloc, itemsize, maxlength, gcmap, arraydescr) prepare_op_debug_merge_point = void prepare_op_jit_debug = void @@ -1211,13 +1264,6 @@ operations_with_guard = [notimplemented_with_guard] * (rop._LAST + 1) -def get_scale(size): - scale = 0 - while (1 << scale) < size: - scale += 1 - assert (1 << scale) == size - return scale - for key, value in rop.__dict__.items(): key = key.lower() if key.startswith('_'): diff --git a/rpython/jit/backend/arm/runner.py b/rpython/jit/backend/arm/runner.py --- a/rpython/jit/backend/arm/runner.py +++ b/rpython/jit/backend/arm/runner.py @@ -23,6 +23,7 @@ supports_longlong = False # XXX requires an implementation of # read_timestamp that works in user mode supports_singlefloats = not detect_hardfloat() + can_inline_varsize_malloc = True from rpython.jit.backend.arm.arch import JITFRAME_FIXED_SIZE all_reg_indexes = range(len(all_regs)) diff --git a/rpython/jit/backend/x86/test/test_exception.py b/rpython/jit/backend/arm/test/test_exception.py copy from rpython/jit/backend/x86/test/test_exception.py copy to rpython/jit/backend/arm/test/test_exception.py --- a/rpython/jit/backend/x86/test/test_exception.py +++ b/rpython/jit/backend/arm/test/test_exception.py @@ -1,9 +1,9 @@ import py -from rpython.jit.backend.x86.test.test_basic import Jit386Mixin +from rpython.jit.backend.arm.test.support import JitARMMixin from rpython.jit.metainterp.test.test_exception import ExceptionTests -class TestExceptions(Jit386Mixin, ExceptionTests): +class TestExceptions(JitARMMixin, ExceptionTests): # for the individual tests see # ====> ../../../metainterp/test/test_exception.py diff --git a/rpython/jit/backend/detect_cpu.py b/rpython/jit/backend/detect_cpu.py --- a/rpython/jit/backend/detect_cpu.py +++ b/rpython/jit/backend/detect_cpu.py @@ -2,12 +2,40 @@ Processor auto-detection """ import sys, os +from rpython.rtyper.tool.rffi_platform import getdefined +from rpython.translator.platform import is_host_build class ProcessorAutodetectError(Exception): pass + +def detect_main_model_and_size_from_platform(): + # based on http://sourceforge.net/p/predef/wiki/Architectures/ + mapping = { + ('x86', '64'): [ + '__amd64__', '__amd64', '__x86_64__', '__x86_64', # AMD64 + '__ia64__', '_IA64', '__IA64__' # Intel Itanium (IA-64) + ], + ('arm', '32'): ['__arm__', '__thumb__'], + ('x86', '32'): ['i386', '__i386', '__i386__', '__i686__',], + ('ppc', '64'): ['__powerpc64__'], + } + for k, v in mapping.iteritems(): + for macro in v: + if not getdefined(macro, ''): + continue + return '_'.join(k) + raise ProcessorAutodetectError, "Cannot detect processor using compiler macros" + + +def detect_main_model_from_platform(): + return detect_main_model_and_size_from_platform()[0] + + def autodetect_main_model(): + if not is_host_build(): + return detect_main_model_from_platform() mach = None try: import platform @@ -40,6 +68,8 @@ return mach def autodetect_main_model_and_size(): + if not is_host_build(): + return detect_main_model_and_size_from_platform() model = autodetect_main_model() if sys.maxint == 2**31-1: model += '_32' diff --git a/rpython/jit/backend/llsupport/regalloc.py b/rpython/jit/backend/llsupport/regalloc.py --- a/rpython/jit/backend/llsupport/regalloc.py +++ b/rpython/jit/backend/llsupport/regalloc.py @@ -740,6 +740,16 @@ op = Fake(None) return op.is_comparison() or op.is_ovf() +def valid_addressing_size(size): + return size == 1 or size == 2 or size == 4 or size == 8 + +def get_scale(size): + assert valid_addressing_size(size) + if size < 4: + return size - 1 # 1, 2 => 0, 1 + else: + return (size >> 2) + 1 # 4, 8 => 2, 3 + def not_implemented(msg): os.write(2, '[llsupport/regalloc] %s\n' % msg) diff --git a/rpython/jit/backend/test/runner_test.py b/rpython/jit/backend/test/runner_test.py --- a/rpython/jit/backend/test/runner_test.py +++ b/rpython/jit/backend/test/runner_test.py @@ -3943,7 +3943,8 @@ a = lltype.malloc(A, 2, flavor='raw') a[0] = rffi.cast(rffi.SHORT, 666) a[1] = rffi.cast(rffi.SHORT, 777) - a_int = rffi.cast(lltype.Signed, a) + addr = llmemory.cast_ptr_to_adr(a) + a_int = heaptracker.adr2int(addr) print 'a_int:', a_int self.execute_operation(rop.SETARRAYITEM_RAW, [ConstInt(a_int), ConstInt(0), ConstInt(-7654)], diff --git a/rpython/jit/backend/test/test_detect_cpu.py b/rpython/jit/backend/test/test_detect_cpu.py --- a/rpython/jit/backend/test/test_detect_cpu.py +++ b/rpython/jit/backend/test/test_detect_cpu.py @@ -26,3 +26,8 @@ else: from rpython.jit.backend.model import AbstractCPU assert issubclass(cpu, AbstractCPU) + + +def test_detect_main_model_and_size_from_platform(): + info = autodetect_main_model_and_size() + assert detect_main_model_and_size_from_platform() == info diff --git a/rpython/jit/backend/tool/viewcode.py b/rpython/jit/backend/tool/viewcode.py --- a/rpython/jit/backend/tool/viewcode.py +++ b/rpython/jit/backend/tool/viewcode.py @@ -53,8 +53,7 @@ 'x86_32': 'i386', 'x86_64': 'x86-64', 'i386': 'i386', - 'armv6_32': 'arm', - 'armv7_32': 'arm', + 'arm_32': 'arm', } cmd = find_objdump() objdump = ('%(command)s -M %(backend)s -b binary -m %(machine)s ' diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -13,8 +13,9 @@ from rpython.rtyper.annlowlevel import llhelper, cast_instance_to_gcref from rpython.rlib.jit import AsmInfo from rpython.jit.backend.model import CompiledLoopToken -from rpython.jit.backend.x86.regalloc import (RegAlloc, get_ebp_ofs, _get_scale, - gpr_reg_mgr_cls, xmm_reg_mgr_cls, _valid_addressing_size) +from rpython.jit.backend.x86.regalloc import (RegAlloc, get_ebp_ofs, + gpr_reg_mgr_cls, xmm_reg_mgr_cls) +from rpython.jit.backend.llsupport.regalloc import (get_scale, valid_addressing_size) from rpython.jit.backend.x86.arch import (FRAME_FIXED_SIZE, WORD, IS_X86_64, JITFRAME_FIXED_SIZE, IS_X86_32, PASS_ON_MY_FRAME) @@ -1523,7 +1524,7 @@ base_loc, ofs_loc, size_loc, ofs, sign_loc = arglocs assert isinstance(ofs, ImmedLoc) assert isinstance(size_loc, ImmedLoc) - scale = _get_scale(size_loc.value) + scale = get_scale(size_loc.value) src_addr = addr_add(base_loc, ofs_loc, ofs.value, scale) self.load_from_mem(resloc, src_addr, size_loc, sign_loc) @@ -1552,12 +1553,12 @@ shift = 0 itemsize >>= shift # - if _valid_addressing_size(itemsize - 1): + if valid_addressing_size(itemsize - 1): mc.LEA_ra(targetreg, (sourcereg, sourcereg, - _get_scale(itemsize - 1), 0)) - elif _valid_addressing_size(itemsize): + get_scale(itemsize - 1), 0)) + elif valid_addressing_size(itemsize): mc.LEA_ra(targetreg, (rx86.NO_BASE_REGISTER, sourcereg, - _get_scale(itemsize), 0)) + get_scale(itemsize), 0)) else: mc.IMUL_rri(targetreg, sourcereg, itemsize) # @@ -1570,9 +1571,9 @@ if isinstance(index_loc, ImmedLoc): temp_loc = imm(index_loc.value * itemsize) shift = 0 - elif _valid_addressing_size(itemsize): + elif valid_addressing_size(itemsize): temp_loc = index_loc - shift = _get_scale(itemsize) + shift = get_scale(itemsize) else: assert isinstance(index_loc, RegLoc) assert isinstance(temp_loc, RegLoc) @@ -1610,7 +1611,7 @@ base_loc, ofs_loc, value_loc, size_loc, baseofs = arglocs assert isinstance(baseofs, ImmedLoc) assert isinstance(size_loc, ImmedLoc) - scale = _get_scale(size_loc.value) + scale = get_scale(size_loc.value) dest_addr = AddressLoc(base_loc, ofs_loc, scale, baseofs.value) self.save_into_mem(dest_addr, value_loc, size_loc) @@ -2443,8 +2444,8 @@ jmp_adr0 = self.mc.get_relative_pos() self.mc.MOV(eax, heap(nursery_free_adr)) - if _valid_addressing_size(itemsize): - shift = _get_scale(itemsize) + if valid_addressing_size(itemsize): + shift = get_scale(itemsize) else: shift = self._imul_const_scaled(self.mc, edi.value, varsizeloc.value, itemsize) diff --git a/rpython/jit/backend/x86/regalloc.py b/rpython/jit/backend/x86/regalloc.py --- a/rpython/jit/backend/x86/regalloc.py +++ b/rpython/jit/backend/x86/regalloc.py @@ -1380,16 +1380,6 @@ # i.e. the n'th word beyond the fixed frame size. return base_ofs + WORD * (position + JITFRAME_FIXED_SIZE) -def _valid_addressing_size(size): - return size == 1 or size == 2 or size == 4 or size == 8 - -def _get_scale(size): - assert _valid_addressing_size(size) - if size < 4: - return size - 1 # 1, 2 => 0, 1 - else: - return (size >> 2) + 1 # 4, 8 => 2, 3 - def not_implemented(msg): os.write(2, '[x86/regalloc] %s\n' % msg) raise NotImplementedError(msg) diff --git a/rpython/jit/backend/x86/rx86.py b/rpython/jit/backend/x86/rx86.py --- a/rpython/jit/backend/x86/rx86.py +++ b/rpython/jit/backend/x86/rx86.py @@ -682,10 +682,12 @@ def define_modrm_modes(insnname_template, before_modrm, after_modrm=[], regtype='GPR'): def add_insn(code, *modrm): - args = before_modrm + list(modrm) + after_modrm + args = before_modrm + list(modrm) methname = insnname_template.replace('*', code) - if methname.endswith('_rr') or methname.endswith('_xx'): + if (methname.endswith('_rr') or methname.endswith('_xx') + or methname.endswith('_ri')): args.append('\xC0') + args += after_modrm if regtype == 'XMM': insn_func = xmminsn(*args) diff --git a/rpython/jit/backend/x86/test/test_regloc.py b/rpython/jit/backend/x86/test/test_regloc.py --- a/rpython/jit/backend/x86/test/test_regloc.py +++ b/rpython/jit/backend/x86/test/test_regloc.py @@ -1,4 +1,5 @@ import struct, sys +from rpython.jit.backend.x86.rx86 import R from rpython.jit.backend.x86.regloc import * from rpython.jit.backend.x86.test.test_rx86 import CodeBuilder32, CodeBuilder64, assert_encodes_as from rpython.jit.backend.x86.assembler import heap @@ -15,36 +16,49 @@ cb32 = LocationCodeBuilder32 cb64 = LocationCodeBuilder64 +def test_mov_8(): + assert_encodes_as(cb32, "MOV8_ri", (R.cl, 25), '\xB1\x19') + def test_mov_16(): + # only 'MOV16_*r' and 'MOV16_*i' are supported # 32-bit assert_encodes_as(cb32, "MOV16", (ecx, ebx), '\x66\x89\xD9') - assert_encodes_as(cb32, "MOV16", (ecx, ImmedLoc(12345)), '\x66\xB9\x39\x30') - + assert_encodes_as(cb32, "MOV16", + (AddressLoc(ecx, ImmedLoc(16), 0, 0), ebx), + '\x66\x89\x59\x10') # 64-bit assert_encodes_as(cb64, "MOV16", (r8, ebx), '\x66\x41\x89\xD8') # 11 011 000 assert_encodes_as(cb64, "MOV16", (ebx, r8), '\x66\x44\x89\xC3') # 11 000 011 - assert_encodes_as(cb64, "MOV16", (ecx, ebx), '\x66\x40\x89\xD9') - assert_encodes_as(cb64, "MOV16", (ecx, ImmedLoc(12345)), '\x66\xB9\x39\x30') + assert_encodes_as(cb64, "MOV16", (ecx, ebx), '\x66\x89\xD9') # for the next case we don't pick the most efficient encoding, but well - expected = '\x66\x40\xC7\xC1\xC7\xCF' # could be '\x66\xB9\xC7\xCF' + expected = '\x66\xC7\xC1\x39\x30' # could be '\x66\xB9\x39\x30' + assert_encodes_as(cb64, "MOV16", (ecx, ImmedLoc(12345)), expected) + # for the next case we don't pick the most efficient encoding, but well + expected = '\x66\xC7\xC1\xC7\xCF' # could be '\x66\xB9\xC7\xCF' assert_encodes_as(cb64, "MOV16", (ecx, ImmedLoc(-12345)), expected) - assert_encodes_as(cb64, "MOV16", (r9, ImmedLoc(12345)), '\x66\x41\xB9\x39\x30') + # for the next case we don't pick the most efficient encoding, but well + expected = '\x66\x41\xC7\xC1\x39\x30' # could be '\x66\x41\xB9\x39\x30' + assert_encodes_as(cb64, "MOV16", (r9, ImmedLoc(12345)), expected) # for the next case we don't pick the most efficient encoding, but well expected = '\x66\x41\xC7\xC1\xC7\xCF' # could be '\x66\x41\xB9\xC7\xCF' assert_encodes_as(cb64, "MOV16", (r9, ImmedLoc(-12345)), expected) - assert_encodes_as(cb64, "MOV16", (AddressLoc(r13, ImmedLoc(0), 0, 0), ImmedLoc(12345)), '\x66\x41\xC7\x45\x00\x39\x30') + assert_encodes_as(cb64, "MOV16", + (AddressLoc(r13, ImmedLoc(0), 0, 0), ImmedLoc(12345)), + '\x66\x41\xC7\x45\x00\x39\x30') def test_cmp_16(): + # only 'CMP16_mi' is supported # 32-bit - assert_encodes_as(cb32, "CMP16", (ecx, ebx), '\x66\x39\xD9') - assert_encodes_as(cb32, "CMP16", (ecx, ImmedLoc(12345)), '\x66\x81\xF9\x39\x30') - + assert_encodes_as(cb32, "CMP16", + (AddressLoc(ecx, ImmedLoc(0), 0, 0), ImmedLoc(21324)), + '\x66\x81\x39\x4c\x53') + assert_encodes_as(cb32, "CMP16", + (AddressLoc(esi, ImmedLoc(2), 0, 0), ImmedLoc(-12345)), + '\x66\x81\x7e\x02\xc7\xcf') # 64-bit - assert_encodes_as(cb64, "CMP16", (r8, ebx), '\x66\x41\x39\xD8') # 11 011 000 - assert_encodes_as(cb64, "CMP16", (ebx, r8), '\x66\x44\x39\xC3') # 11 000 011 - assert_encodes_as(cb64, "CMP16", (ecx, ebx), '\x66\x40\x39\xD9') - assert_encodes_as(cb64, "CMP16", (ecx, ImmedLoc(12345)), '\x66\x40\x81\xF9\x39\x30') - assert_encodes_as(cb64, "CMP16", (AddressLoc(r13, ImmedLoc(0), 0, 0), ImmedLoc(12345)), '\x66\x41\x81\x7D\x00\x39\x30') + assert_encodes_as(cb64, "CMP16", + (AddressLoc(r13, ImmedLoc(0), 0, 0), ImmedLoc(12345)), + '\x66\x41\x81\x7D\x00\x39\x30') def test_relocation(): from rpython.rtyper.lltypesystem import lltype, rffi diff --git a/rpython/rlib/rwin32.py b/rpython/rlib/rwin32.py --- a/rpython/rlib/rwin32.py +++ b/rpython/rlib/rwin32.py @@ -5,6 +5,7 @@ import os import errno +from rpython.rtyper.module.ll_os_environ import make_env_impls from rpython.rtyper.tool import rffi_platform from rpython.tool.udir import udir from rpython.translator.tool.cbuild import ExternalCompilationInfo @@ -390,3 +391,5 @@ raise lastWindowsError('os_kill failed to terminate process') finally: CloseHandle(handle) + + _wenviron_items, _wgetenv, _wputenv = make_env_impls(win32=True) diff --git a/rpython/rlib/test/test_rwin32.py b/rpython/rlib/test/test_rwin32.py --- a/rpython/rlib/test/test_rwin32.py +++ b/rpython/rlib/test/test_rwin32.py @@ -1,3 +1,4 @@ +# encoding: utf-8 import os, py if os.name != 'nt': py.test.skip('tests for win32 only') @@ -47,3 +48,13 @@ rwin32.CloseHandle(handle) assert proc.wait() == signal.SIGTERM + at py.test.mark.dont_track_allocations('putenv intentionally keeps strings alive') +def test_wenviron(): + name, value = u'PYPY_TEST_日本', u'foobar日本' + rwin32._wputenv(name, value) + assert rwin32._wgetenv(name) == value + env = dict(rwin32._wenviron_items()) + assert env[name] == value + for key, value in env.iteritems(): + assert type(key) is unicode + assert type(value) is unicode diff --git a/rpython/rtyper/module/ll_os.py b/rpython/rtyper/module/ll_os.py --- a/rpython/rtyper/module/ll_os.py +++ b/rpython/rtyper/module/ll_os.py @@ -7,14 +7,15 @@ import os, sys, errno import py -from rpython.rtyper.module.support import OOSupport +from rpython.rtyper.module.support import ( + _WIN32, OOSupport, StringTraits, UnicodeTraits, underscore_on_windows) from rpython.tool.sourcetools import func_renamer from rpython.rlib.rarithmetic import r_longlong from rpython.rtyper.extfunc import ( BaseLazyRegistering, register_external) from rpython.rtyper.extfunc import registering, registering_if, extdef from rpython.annotator.model import ( - SomeInteger, SomeString, SomeTuple, SomeFloat, SomeUnicodeString) + SomeInteger, SomeString, SomeTuple, SomeFloat, s_Str0, s_Unicode0) from rpython.annotator.model import s_ImpossibleValue, s_None, s_Bool from rpython.rtyper.lltypesystem import rffi from rpython.rtyper.lltypesystem import lltype @@ -25,8 +26,8 @@ from rpython.rtyper.lltypesystem.rstr import STR from rpython.rlib.objectmodel import specialize -str0 = SomeString(no_nul=True) -unicode0 = SomeUnicodeString(no_nul=True) +str0 = s_Str0 +unicode0 = s_Unicode0 def monkeypatch_rposix(posixfunc, unicodefunc, signature): func_name = posixfunc.__name__ @@ -66,42 +67,6 @@ # Monkeypatch the function in rpython.rlib.rposix setattr(rposix, func_name, new_func) -class StringTraits: - str = str - str0 = str0 - CHAR = rffi.CHAR - CCHARP = rffi.CCHARP - charp2str = staticmethod(rffi.charp2str) - str2charp = staticmethod(rffi.str2charp) - free_charp = staticmethod(rffi.free_charp) - scoped_alloc_buffer = staticmethod(rffi.scoped_alloc_buffer) - - @staticmethod - def posix_function_name(name): - return underscore_on_windows + name - - @staticmethod - def ll_os_name(name): - return 'll_os.ll_os_' + name - -class UnicodeTraits: - str = unicode - str0 = unicode0 - CHAR = rffi.WCHAR_T - CCHARP = rffi.CWCHARP - charp2str = staticmethod(rffi.wcharp2unicode) - str2charp = staticmethod(rffi.unicode2wcharp) - free_charp = staticmethod(rffi.free_wcharp) - scoped_alloc_buffer = staticmethod(rffi.scoped_alloc_unicodebuffer) - - @staticmethod - def posix_function_name(name): - return underscore_on_windows + 'w' + name - - @staticmethod - def ll_os_name(name): - return 'll_os.ll_os_w' + name - def registering_str_unicode(posixfunc, condition=True): if not condition or posixfunc is None: return registering(None, condition=False) @@ -129,16 +94,6 @@ posix = __import__(os.name) -if sys.platform.startswith('win'): - _WIN32 = True -else: - _WIN32 = False - -if _WIN32: - underscore_on_windows = '_' -else: - underscore_on_windows = '' - includes = [] if not _WIN32: # XXX many of these includes are not portable at all diff --git a/rpython/rtyper/module/ll_os_environ.py b/rpython/rtyper/module/ll_os_environ.py --- a/rpython/rtyper/module/ll_os_environ.py +++ b/rpython/rtyper/module/ll_os_environ.py @@ -4,10 +4,10 @@ from rpython.rtyper.controllerentry import Controller from rpython.rtyper.extfunc import register_external from rpython.rtyper.lltypesystem import rffi, lltype -from rpython.rtyper.module import ll_os -from rpython.rlib import rposix +from rpython.rtyper.module.support import _WIN32, StringTraits, UnicodeTraits +from rpython.translator.tool.cbuild import ExternalCompilationInfo -str0 = ll_os.str0 +str0 = annmodel.s_Str0 # ____________________________________________________________ # @@ -59,85 +59,8 @@ return r_getenv # ____________________________________________________________ -# -# Lower-level interface: dummy placeholders and external registations - -def r_getenv(name): - just_a_placeholder # should return None if name not found - -os_getenv = rffi.llexternal('getenv', [rffi.CCHARP], rffi.CCHARP, - threadsafe=False) - -def getenv_llimpl(name): - with rffi.scoped_str2charp(name) as l_name: - l_result = os_getenv(l_name) - return rffi.charp2str(l_result) if l_result else None - -register_external(r_getenv, [str0], - annmodel.SomeString(can_be_None=True, no_nul=True), - export_name='ll_os.ll_os_getenv', - llimpl=getenv_llimpl) - -# ____________________________________________________________ - -def r_putenv(name, value): - just_a_placeholder - -class EnvKeepalive: - pass -envkeepalive = EnvKeepalive() -envkeepalive.byname = {} - -os_putenv = rffi.llexternal('putenv', [rffi.CCHARP], rffi.INT) - -def putenv_llimpl(name, value): - l_string = rffi.str2charp('%s=%s' % (name, value)) - error = rffi.cast(lltype.Signed, os_putenv(l_string)) - if error: - rffi.free_charp(l_string) - raise OSError(rposix.get_errno(), "os_putenv failed") - # keep 'l_string' alive - we know that the C library needs it - # until the next call to putenv() with the same 'name'. - l_oldstring = envkeepalive.byname.get(name, lltype.nullptr(rffi.CCHARP.TO)) - envkeepalive.byname[name] = l_string - if l_oldstring: - rffi.free_charp(l_oldstring) - -register_external(r_putenv, [str0, str0], annmodel.s_None, - export_name='ll_os.ll_os_putenv', - llimpl=putenv_llimpl) - -# ____________________________________________________________ - -def r_unsetenv(name): - # default implementation for platforms without a real unsetenv() - r_putenv(name, '') - -if hasattr(__import__(os.name), 'unsetenv'): - os_unsetenv = rffi.llexternal('unsetenv', [rffi.CCHARP], rffi.INT) - - def unsetenv_llimpl(name): - with rffi.scoped_str2charp(name) as l_name: - error = rffi.cast(lltype.Signed, os_unsetenv(l_name)) - if error: - raise OSError(rposix.get_errno(), "os_unsetenv failed") - try: - l_oldstring = envkeepalive.byname[name] - except KeyError: - pass - else: - del envkeepalive.byname[name] - rffi.free_charp(l_oldstring) - - register_external(r_unsetenv, [str0], annmodel.s_None, - export_name='ll_os.ll_os_unsetenv', - llimpl=unsetenv_llimpl) - -# ____________________________________________________________ # Access to the 'environ' external variable -from rpython.translator.tool.cbuild import ExternalCompilationInfo - if sys.platform.startswith('darwin'): CCHARPPP = rffi.CArrayPtr(rffi.CCHARPP) _os_NSGetEnviron = rffi.llexternal( @@ -146,16 +69,21 @@ ) def os_get_environ(): return _os_NSGetEnviron()[0] -elif sys.platform.startswith('win'): +elif _WIN32: + eci = ExternalCompilationInfo(includes=['stdlib.h']) + CWCHARPP = lltype.Ptr(lltype.Array(rffi.CWCHARP, hints={'nolength': True})) + os_get_environ, _os_set_environ = rffi.CExternVariable( - rffi.CCHARPP, - '_environ', - ExternalCompilationInfo(includes=['stdlib.h'])) + rffi.CCHARPP, '_environ', eci) + get__wenviron, _set__wenviron = rffi.CExternVariable( + CWCHARPP, '_wenviron', eci, c_type='wchar_t **') else: os_get_environ, _os_set_environ = rffi.CExternVariable( rffi.CCHARPP, 'environ', ExternalCompilationInfo()) # ____________________________________________________________ +# +# Lower-level interface: dummy placeholders and external registations def r_envkeys(): just_a_placeholder @@ -181,18 +109,109 @@ def r_envitems(): just_a_placeholder -def envitems_llimpl(): - environ = os_get_environ() - result = [] - i = 0 - while environ[i]: - name_value = rffi.charp2str(environ[i]) - p = name_value.find('=') - if p >= 0: - result.append((name_value[:p], name_value[p+1:])) - i += 1 - return result +def r_getenv(name): + just_a_placeholder # should return None if name not found + +def r_putenv(name, value): + just_a_placeholder + +os_getenv = rffi.llexternal('getenv', [rffi.CCHARP], rffi.CCHARP, + threadsafe=False) +os_putenv = rffi.llexternal('putenv', [rffi.CCHARP], rffi.INT) +if _WIN32: + _wgetenv = rffi.llexternal('_wgetenv', [rffi.CWCHARP], rffi.CWCHARP, + compilation_info=eci, threadsafe=False) + _wputenv = rffi.llexternal('_wputenv', [rffi.CWCHARP], rffi.INT, + compilation_info=eci) + +class EnvKeepalive: + pass +envkeepalive = EnvKeepalive() +envkeepalive.byname = {} +envkeepalive.bywname = {} + +def make_env_impls(win32=False): + if not win32: + traits = StringTraits() From noreply at buildbot.pypy.org Wed Apr 24 05:19:47 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Wed, 24 Apr 2013 05:19:47 +0200 (CEST) Subject: [pypy-commit] pypy py3k: update the export to fix compiling on windows Message-ID: <20130424031947.A44361C31FA@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63581:c3af9cfd2f5b Date: 2013-04-23 20:19 -0700 http://bitbucket.org/pypy/pypy/changeset/c3af9cfd2f5b/ Log: update the export to fix compiling on windows diff --git a/lib_pypy/_ctypes_test.py b/lib_pypy/_ctypes_test.py --- a/lib_pypy/_ctypes_test.py +++ b/lib_pypy/_ctypes_test.py @@ -31,13 +31,13 @@ library = os.path.join(thisdir, '..', 'include', 'libpypy-c') if not os.path.exists(library + '.lib'): #For a nightly build - library = os.path.join(thisdir, '..', 'include', 'python27') + library = os.path.join(thisdir, '..', 'include', 'python3') if not os.path.exists(library + '.lib'): # For a local translation library = os.path.join(thisdir, '..', 'pypy', 'goal', 'libpypy-c') libraries = [library, 'oleaut32'] extra_ldargs = ['/MANIFEST', # needed for VC10 - '/EXPORT:init_ctypes_test'] + '/EXPORT:PyInit__ctypes_test'] else: libraries = [] extra_ldargs = [] diff --git a/lib_pypy/_testcapi.py b/lib_pypy/_testcapi.py --- a/lib_pypy/_testcapi.py +++ b/lib_pypy/_testcapi.py @@ -31,13 +31,13 @@ library = os.path.join(thisdir, '..', 'include', 'libpypy-c') if not os.path.exists(library + '.lib'): #For a nightly build - library = os.path.join(thisdir, '..', 'include', 'python27') + library = os.path.join(thisdir, '..', 'include', 'python3') if not os.path.exists(library + '.lib'): # For a local translation library = os.path.join(thisdir, '..', 'pypy', 'goal', 'libpypy-c') libraries = [library, 'oleaut32'] extra_ldargs = ['/MANIFEST', # needed for VC10 - '/EXPORT:init_testcapi'] + '/EXPORT:PyInit__testcapi'] else: libraries = [] extra_ldargs = [] From noreply at buildbot.pypy.org Wed Apr 24 05:19:46 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Wed, 24 Apr 2013 05:19:46 +0200 (CEST) Subject: [pypy-commit] pypy py3k: unichr -> chr Message-ID: <20130424031946.5FC511C31F8@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63580:0d482d947e35 Date: 2013-04-23 20:16 -0700 http://bitbucket.org/pypy/pypy/changeset/0d482d947e35/ Log: unichr -> chr diff --git a/pypy/module/__builtin__/operation.py b/pypy/module/__builtin__/operation.py --- a/pypy/module/__builtin__/operation.py +++ b/pypy/module/__builtin__/operation.py @@ -29,7 +29,7 @@ c = UNICHR(code) except ValueError: raise OperationError(space.w_ValueError, - space.wrap("unichr() arg out of range")) + space.wrap("chr() arg out of range")) return space.wrap(c) def len(space, w_obj): From noreply at buildbot.pypy.org Wed Apr 24 05:39:34 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Wed, 24 Apr 2013 05:39:34 +0200 (CEST) Subject: [pypy-commit] pypy py3k: stdlib's test_winreg expects these keyword args Message-ID: <20130424033934.EC04D1C0014@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63582:2158de4626f4 Date: 2013-04-23 20:39 -0700 http://bitbucket.org/pypy/pypy/changeset/2158de4626f4/ Log: stdlib's test_winreg expects these keyword args diff --git a/pypy/module/_winreg/interp_winreg.py b/pypy/module/_winreg/interp_winreg.py --- a/pypy/module/_winreg/interp_winreg.py +++ b/pypy/module/_winreg/interp_winreg.py @@ -471,8 +471,8 @@ raiseWindowsError(space, ret, 'CreateKey') return space.wrap(W_HKEY(rethkey[0])) - at unwrap_spec(subkey=str, res=int, sam=rffi.r_uint) -def CreateKeyEx(space, w_hkey, subkey, res=0, sam=rwinreg.KEY_WRITE): + at unwrap_spec(sub_key=str, reserved=int, access=rffi.r_uint) +def CreateKeyEx(space, w_key, sub_key, reserved=0, access=rwinreg.KEY_WRITE): """key = CreateKey(key, sub_key) - Creates or opens the specified key. key is an already open key, or one of the predefined HKEY_* constants @@ -484,10 +484,10 @@ The return value is the handle of the opened key. If the function fails, an exception is raised.""" - hkey = hkey_w(w_hkey, space) + hkey = hkey_w(w_key, space) with lltype.scoped_alloc(rwinreg.PHKEY.TO, 1) as rethkey: - ret = rwinreg.RegCreateKeyEx(hkey, subkey, res, None, 0, - sam, None, rethkey, + ret = rwinreg.RegCreateKeyEx(hkey, sub_key, reserved, None, 0, + access, None, rethkey, lltype.nullptr(rwin32.LPDWORD.TO)) if ret != 0: raiseWindowsError(space, ret, 'CreateKeyEx') @@ -521,8 +521,8 @@ if ret != 0: raiseWindowsError(space, ret, 'RegDeleteValue') - at unwrap_spec(subkey=str, res=int, sam=rffi.r_uint) -def OpenKey(space, w_hkey, subkey, res=0, sam=rwinreg.KEY_READ): + at unwrap_spec(sub_key=str, reserved=int, access=rffi.r_uint) +def OpenKey(space, w_key, sub_key, reserved=0, access=rwinreg.KEY_READ): """key = OpenKey(key, sub_key, res = 0, sam = KEY_READ) - Opens the specified key. key is an already open key, or any one of the predefined HKEY_* constants. @@ -533,9 +533,9 @@ The result is a new handle to the specified key If the function fails, an EnvironmentError exception is raised.""" - hkey = hkey_w(w_hkey, space) + hkey = hkey_w(w_key, space) with lltype.scoped_alloc(rwinreg.PHKEY.TO, 1) as rethkey: - ret = rwinreg.RegOpenKeyEx(hkey, subkey, res, sam, rethkey) + ret = rwinreg.RegOpenKeyEx(hkey, sub_key, reserved, access, rethkey) if ret != 0: raiseWindowsError(space, ret, 'RegOpenKeyEx') return space.wrap(W_HKEY(rethkey[0])) diff --git a/pypy/module/_winreg/test/test_winreg.py b/pypy/module/_winreg/test/test_winreg.py --- a/pypy/module/_winreg/test/test_winreg.py +++ b/pypy/module/_winreg/test/test_winreg.py @@ -246,3 +246,12 @@ raises(NotImplementedError, DeleteKeyEx, self.root_key, self.test_key_name) + def test_named_arguments(self): + from winreg import KEY_ALL_ACCESS, CreateKeyEx, DeleteKey, OpenKeyEx + with CreateKeyEx(key=self.root_key, sub_key=self.test_key_name, + reserved=0, access=KEY_ALL_ACCESS) as ckey: + assert ckey.handle != 0 + with OpenKeyEx(key=self.root_key, sub_key=self.test_key_name, + reserved=0, access=KEY_ALL_ACCESS) as okey: + assert okey.handle != 0 + DeleteKey(self.root_key, self.test_key_name) From noreply at buildbot.pypy.org Wed Apr 24 06:27:32 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Wed, 24 Apr 2013 06:27:32 +0200 (CEST) Subject: [pypy-commit] pypy py3k: adjust per py3k's lib-python scheme Message-ID: <20130424042732.199091C02DA@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63583:d8cebf136b5f Date: 2013-04-23 21:26 -0700 http://bitbucket.org/pypy/pypy/changeset/d8cebf136b5f/ Log: adjust per py3k's lib-python scheme diff --git a/pypy/tool/release/test/test_package.py b/pypy/tool/release/test/test_package.py --- a/pypy/tool/release/test/test_package.py +++ b/pypy/tool/release/test/test_package.py @@ -26,7 +26,7 @@ builddir = package.package(py.path.local(pypydir).dirpath(), test, rename_pypy_c) prefix = builddir.join(test) - cpyver = '%d.%d' % CPYTHON_VERSION[:2] + cpyver = '%d' % CPYTHON_VERSION[0] assert prefix.join('lib-python', cpyver, 'test').check() assert prefix.join(exe_name_in_archive).check() assert prefix.join('lib_pypy', 'syslog.py').check() From noreply at buildbot.pypy.org Wed Apr 24 08:32:53 2013 From: noreply at buildbot.pypy.org (timfel) Date: Wed, 24 Apr 2013 08:32:53 +0200 (CEST) Subject: [pypy-commit] pypy int-tag-untag-as-operations: merge default Message-ID: <20130424063253.B6AE21C00BD@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: int-tag-untag-as-operations Changeset: r63584:c48b4259a513 Date: 2013-04-24 08:31 +0200 http://bitbucket.org/pypy/pypy/changeset/c48b4259a513/ Log: merge default diff too long, truncating to 2000 out of 10960 lines diff --git a/Makefile b/Makefile new file mode 100644 --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ + +all: pypy-c + +pypy-c: + @echo "Building PyPy with JIT, it'll take about 40 minutes and 4G of RAM" + @sleep 3 + rpython/bin/rpython -Ojit pypy/goal/targetpypystandalone.py diff --git a/README.rst b/README.rst --- a/README.rst +++ b/README.rst @@ -22,3 +22,16 @@ and send us feedback! the pypy-dev team + +Building +======== + +build with:: + + rpython/bin/rpython -Ojit pypy/goal/targetpypystandalone.py + +This ends up with ``pypy-c`` binary in the main pypy directory. We suggest +to use virtualenv with the resulting pypy-c as the interpreter, you can +find more details about various installation schemes here: + +http://doc.pypy.org/en/latest/getting-started.html#installing-pypy diff --git a/lib-python/2.7/json/decoder.py b/lib-python/2.7/json/decoder.py --- a/lib-python/2.7/json/decoder.py +++ b/lib-python/2.7/json/decoder.py @@ -162,7 +162,7 @@ if nextchar == '}': if object_pairs_hook is not None: result = object_pairs_hook(pairs) - return result, end + return result, end + 1 pairs = {} if object_hook is not None: pairs = object_hook(pairs) diff --git a/lib-python/2.7/json/tests/test_decode.py b/lib-python/2.7/json/tests/test_decode.py --- a/lib-python/2.7/json/tests/test_decode.py +++ b/lib-python/2.7/json/tests/test_decode.py @@ -44,6 +44,7 @@ object_pairs_hook=OrderedDict, object_hook=lambda x: None), OrderedDict(p)) + self.assertEqual(self.loads("{}", object_pairs_hook=list), []) class TestPyDecode(TestDecode, PyTest): pass diff --git a/lib-python/2.7/test/test_descr.py b/lib-python/2.7/test/test_descr.py --- a/lib-python/2.7/test/test_descr.py +++ b/lib-python/2.7/test/test_descr.py @@ -3592,6 +3592,9 @@ list.__init__(a, sequence=[0, 1, 2]) self.assertEqual(a, [0, 1, 2]) + @unittest.skipIf(test_support.check_impl_detail(pypy=True) and + sys.platform == 'win32', + "XXX: https://bugs.pypy.org/issue1461") def test_recursive_call(self): # Testing recursive __call__() by setting to instance of class... class A(object): diff --git a/lib-python/2.7/test/test_fileio.py b/lib-python/2.7/test/test_fileio.py --- a/lib-python/2.7/test/test_fileio.py +++ b/lib-python/2.7/test/test_fileio.py @@ -318,7 +318,6 @@ self.assertRaises(ValueError, _FileIO, -10) self.assertRaises(OSError, _FileIO, make_bad_fd()) if sys.platform == 'win32': - raise unittest.SkipTest('Set _invalid_parameter_handler for low level io') import msvcrt self.assertRaises(IOError, msvcrt.get_osfhandle, make_bad_fd()) diff --git a/lib_pypy/msvcrt.py b/lib_pypy/msvcrt.py --- a/lib_pypy/msvcrt.py +++ b/lib_pypy/msvcrt.py @@ -8,25 +8,37 @@ # PAC: 2010/08 added MS locking for Whoosh import ctypes +import errno from ctypes_support import standard_c_lib as _c from ctypes_support import get_errno -import errno try: open_osfhandle = _c._open_osfhandle except AttributeError: # we are not on windows raise ImportError -try: from __pypy__ import builtinify -except ImportError: builtinify = lambda f: f +try: from __pypy__ import builtinify, validate_fd +except ImportError: builtinify = validate_fd = lambda f: f 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 +_get_osfhandle = _c._get_osfhandle +_get_osfhandle.argtypes = [ctypes.c_int] +_get_osfhandle.restype = ctypes.c_int + + at builtinify +def get_osfhandle(fd): + """"get_osfhandle(fd) -> file handle + + Return the file handle for the file descriptor fd. Raises IOError if + fd is not recognized.""" + try: + validate_fd(fd) + except OSError as e: + raise IOError(*e.args) + return _get_osfhandle(fd) setmode = _c._setmode setmode.argtypes = [ctypes.c_int, ctypes.c_int] diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py --- a/pypy/config/pypyoption.py +++ b/pypy/config/pypyoption.py @@ -35,7 +35,7 @@ "thread", "itertools", "pyexpat", "_ssl", "cpyext", "array", "binascii", "_multiprocessing", '_warnings', "_collections", "_multibytecodec", "micronumpy", "_ffi", - "_continuation", "_cffi_backend", "_csv"] + "_continuation", "_cffi_backend", "_csv", "cppyy"] )) translation_modules = default_modules.copy() @@ -64,6 +64,8 @@ del working_modules["termios"] del working_modules["_minimal_curses"] + del working_modules["cppyy"] # not tested on win32 + # The _locale module is needed by site.py on Windows default_modules["_locale"] = None @@ -75,7 +77,7 @@ del working_modules["_minimal_curses"] del working_modules["termios"] del working_modules["_multiprocessing"] # depends on rctime - + del working_modules["cppyy"] # depends on ctypes module_dependencies = { diff --git a/pypy/doc/arm.rst b/pypy/doc/arm.rst --- a/pypy/doc/arm.rst +++ b/pypy/doc/arm.rst @@ -153,7 +153,7 @@ :: - pypy /rpython/bin/rpython -Ojit --platform=arm --gcrootfinder=shadowstack --jit-backend=armv7 targetpypystandalone.py + pypy /rpython/bin/rpython -Ojit --platform=arm --gcrootfinder=shadowstack --jit-backend=arm targetpypystandalone.py The gcrootfinder option is needed to work around `issue 1377`_ and the jit-backend works around `issue 1376`_ diff --git a/pypy/doc/config/translation.gcrootfinder.txt b/pypy/doc/config/translation.gcrootfinder.txt --- a/pypy/doc/config/translation.gcrootfinder.txt +++ b/pypy/doc/config/translation.gcrootfinder.txt @@ -9,7 +9,9 @@ - ``--gcrootfinder=asmgcc``: use assembler hackery to find the roots directly from the normal stack. This is a bit faster, but platform specific. It works so far with GCC or MSVC, - on i386 and x86-64. + on i386 and x86-64. It is tested only on Linux (where it is + the default) so other platforms (as well as MSVC) may need + various fixes before they can be used. You may have to force the use of the shadowstack root finder if you are running into troubles or if you insist on translating diff --git a/pypy/doc/cppyy.rst b/pypy/doc/cppyy.rst --- a/pypy/doc/cppyy.rst +++ b/pypy/doc/cppyy.rst @@ -2,94 +2,128 @@ cppyy: C++ bindings for PyPy ============================ -The cppyy module provides C++ bindings for PyPy by using the reflection -information extracted from C++ header files by means of the -`Reflex package`_. -For this to work, you have to both install Reflex and build PyPy from source, -as the cppyy module is not enabled by default. -Note that the development version of cppyy lives in the reflex-support -branch. -As indicated by this being a branch, support for Reflex is still -experimental. -However, it is functional enough to put it in the hands of those who want -to give it a try. -In the medium term, cppyy will move away from Reflex and instead use -`cling`_ as its backend, which is based on `llvm`_. -Although that will change the logistics on the generation of reflection -information, it will not change the python-side interface. +The cppyy module creates, at run-time, Python-side classes and functions for +C++, by querying a C++ reflection system. +The default system used is `Reflex`_, which extracts the needed information +from C++ header files. +Another current backend is based on `CINT`_, and yet another, more important +one for the medium- to long-term will be based on `cling`_. +The latter sits on top of `llvm`_'s `clang`_, and will therefore allow the use +of C++11. +The work on the cling backend has so far been done only for CPython, but +bringing it to PyPy is a lot less work than developing it in the first place. -.. _`Reflex package`: http://root.cern.ch/drupal/content/reflex +.. _`Reflex`: http://root.cern.ch/drupal/content/reflex +.. _`CINT`: http://root.cern.ch/drupal/content/cint .. _`cling`: http://root.cern.ch/drupal/content/cling .. _`llvm`: http://llvm.org/ +.. _`clang`: http://clang.llvm.org/ + +This document describes the version of cppyy that lives in the main branch of +PyPy. +The development of cppyy happens in the "reflex-support" branch. Motivation ========== -The cppyy module offers two unique features, which result in great -performance as well as better functionality and cross-language integration -than would otherwise be possible. -First, cppyy is written in RPython and therefore open to optimizations by the -JIT up until the actual point of call into C++. -This means that there are no conversions necessary between a garbage collected -and a reference counted environment, as is needed for the use of existing -extension modules written or generated for CPython. -It also means that if variables are already unboxed by the JIT, they can be -passed through directly to C++. -Second, Reflex (and cling far more so) adds dynamic features to C++, thus -greatly reducing impedance mismatches between the two languages. -In fact, Reflex is dynamic enough that you could write the runtime bindings +To provide bindings to another language in CPython, you program to a +generic C-API that exposes many of the interpreter features. +With PyPy, however, there is no such generic C-API, because several of the +interpreter features (e.g. the memory model) are pluggable and therefore +subject to change. +Furthermore, a generic API does not allow any assumptions about the calls +into another language, forcing the JIT to behave conservatively around these +calls and with the objects that cross language boundaries. +In contrast, cppyy does not expose an API, but expects one to be implemented +by a backend. +It makes strong assumptions about the semantics of the API that it uses and +that in turn allows the JIT to make equally strong assumptions. +This is possible, because the expected API is only for providing C++ language +bindings, and does not provide generic programmability. + +The cppyy module further offers two features, which result in improved +performance as well as better functionality and cross-language integration. +First, cppyy itself is written in RPython and therefore open to optimizations +by the JIT up until the actual point of call into C++. +This means for example, that if variables are already unboxed by the JIT, they +can be passed through directly to C++. +Second, a backend such as Reflex (and cling far more so) adds dynamic features +to C++, thus greatly reducing impedance mismatches between the two languages. +For example, Reflex is dynamic enough to allow writing runtime bindings generation in python (as opposed to RPython) and this is used to create very natural "pythonizations" of the bound code. +As another example, cling allows automatic instantiations of templates. + +See this description of the `cppyy architecture`_ for further details. + +.. _`cppyy architecture`: http://morepypy.blogspot.com/2012/06/architecture-of-cppyy.html Installation ============ -For now, the easiest way of getting the latest version of Reflex, is by -installing the ROOT package. -Besides getting the latest version of Reflex, another advantage is that with -the full ROOT package, you can also use your Reflex-bound code on `CPython`_. -`Download`_ a binary or install from `source`_. -Some Linux and Mac systems may have ROOT provided in the list of scientific -software of their packager. -If, however, you prefer a standalone version of Reflex, the best is to get -this `recent snapshot`_, and install like so:: +There are two ways of using cppyy, and the choice depends on how pypy-c was +built: the backend can be builtin, or dynamically loadable. +The former has the disadvantage of requiring pypy-c to be linked with external +C++ libraries (e.g. libReflex.so), but has the advantage of being faster in +some cases. +That advantage will disappear over time, however, with improvements in the +JIT. +Therefore, this document assumes that the dynamically loadable backend is +chosen (it is, by default). +See the `backend documentation`_. - $ tar jxf reflex-2012-05-02.tar.bz2 - $ cd reflex-2012-05-02 - $ build/autogen +.. _`backend documentation`: cppyy_backend.html + +A standalone version of Reflex that also provides the dynamically loadable +backend is available for `download`_. +That version, as well as any other distribution of Reflex (e.g. the one that +comes with `ROOT`_, which may be part of your Linux distribution as part of +the selection of scientific software) will also work for a build with the +builtin backend. + +.. _`download`: http://cern.ch/wlav/reflex-2013-04-23.tar.bz2 +.. _`ROOT`: http://root.cern.ch/ + +Besides Reflex, you probably need a version of `gccxml`_ installed, which is +most easily provided by the packager of your system. +If you read up on gccxml, you will probably notice that it is no longer being +developed and hence will not provide C++11 support. +That's why the medium term plan is to move to cling. +Note that gccxml is only needed to generate reflection libraries. +It is not needed to use them. + +.. _`gccxml`: http://www.gccxml.org + +To install the standalone version of Reflex, after download:: + + $ tar jxf reflex-2013-04-23.tar.bz2 + $ cd reflex-2013-04-23 + $ ./build/autogen $ ./configure $ make && make install -Also, make sure you have a version of `gccxml`_ installed, which is most -easily provided by the packager of your system. -If you read up on gccxml, you'll probably notice that it is no longer being -developed and hence will not provide C++11 support. -That's why the medium term plan is to move to `cling`_. +The usual rules apply: /bin needs to be added to the ``PATH`` and +/lib to the ``LD_LIBRARY_PATH`` environment variable. +For convenience, this document will assume that there is a ``REFLEXHOME`` +variable that points to . +If you downloaded or built the whole of ROOT, ``REFLEXHOME`` should be equal +to ``ROOTSYS``. -.. _`Download`: http://root.cern.ch/drupal/content/downloading-root -.. _`source`: http://root.cern.ch/drupal/content/installing-root-source -.. _`recent snapshot`: http://cern.ch/wlav/reflex-2012-05-02.tar.bz2 -.. _`gccxml`: http://www.gccxml.org +The following is optional, and is only to show how pypy-c can be build +`from source`_, for example to get at the main development branch of cppyy. +The `backend documentation`_ has more details on the backend-specific +prerequisites. -Next, get the `PyPy sources`_, optionally select the reflex-support branch, -and build it. -For the build to succeed, the ``$ROOTSYS`` environment variable must point to -the location of your ROOT (or standalone Reflex) installation, or the -``root-config`` utility must be accessible through ``PATH`` (e.g. by adding -``$ROOTSYS/bin`` to ``PATH``). -In case of the former, include files are expected under ``$ROOTSYS/include`` -and libraries under ``$ROOTSYS/lib``. Then run the translation to build ``pypy-c``:: $ hg clone https://bitbucket.org/pypy/pypy $ cd pypy $ hg up reflex-support # optional - $ cd pypy/goal # This example shows python, but using pypy-c is faster and uses less memory - $ python ../../rpython/bin/rpython.py -O jit --gcrootfinder=shadowstack targetpypystandalone.py --withmod-cppyy + $ python rpython/translator/goal/translate.py --opt=jit pypy/goal/targetpypystandalone --withmod-cppyy This will build a ``pypy-c`` that includes the cppyy module, and through that, Reflex support. @@ -98,12 +132,12 @@ If not, you may want `to obtain a binary distribution`_ to speed up the translation step. -.. _`PyPy sources`: https://bitbucket.org/pypy/pypy/overview +.. _`from source`: https://bitbucket.org/pypy/pypy/overview .. _`to obtain a binary distribution`: http://doc.pypy.org/en/latest/getting-started.html#download-a-pre-built-pypy -Basic example -============= +Basic bindings example +====================== Now test with a trivial example whether all packages are properly installed and functional. @@ -127,7 +161,7 @@ code:: $ genreflex MyClass.h - $ g++ -fPIC -rdynamic -O2 -shared -I$ROOTSYS/include MyClass_rflx.cpp -o libMyClassDict.so -L$ROOTSYS/lib -lReflex + $ g++ -fPIC -rdynamic -O2 -shared -I$REFLEXHOME/include MyClass_rflx.cpp -o libMyClassDict.so -L$REFLEXHOME/lib -lReflex Now you're ready to use the bindings. Since the bindings are designed to look pythonistic, it should be @@ -176,7 +210,7 @@ For example:: $ genreflex MyClass.h --rootmap=libMyClassDict.rootmap --rootmap-lib=libMyClassDict.so - $ g++ -fPIC -rdynamic -O2 -shared -I$ROOTSYS/include MyClass_rflx.cpp -o libMyClassDict.so -L$ROOTSYS/lib -lReflex + $ g++ -fPIC -rdynamic -O2 -shared -I$REFLEXHOME/include MyClass_rflx.cpp -o libMyClassDict.so -L$REFLEXHOME/lib -lReflex where the first option (``--rootmap``) specifies the output file name, and the second option (``--rootmap-lib``) the name of the reflection library where @@ -277,7 +311,7 @@ Now the reflection info can be generated and compiled:: $ genreflex MyAdvanced.h --selection=MyAdvanced.xml - $ g++ -fPIC -rdynamic -O2 -shared -I$ROOTSYS/include MyAdvanced_rflx.cpp -o libAdvExDict.so -L$ROOTSYS/lib -lReflex + $ g++ -fPIC -rdynamic -O2 -shared -I$REFLEXHOME/include MyAdvanced_rflx.cpp -o libAdvExDict.so -L$REFLEXHOME/lib -lReflex and subsequently be used from PyPy:: @@ -336,7 +370,7 @@ bound using:: $ genreflex example.h --deep --rootmap=libexampleDict.rootmap --rootmap-lib=libexampleDict.so - $ g++ -fPIC -rdynamic -O2 -shared -I$ROOTSYS/include example_rflx.cpp -o libexampleDict.so -L$ROOTSYS/lib -lReflex + $ g++ -fPIC -rdynamic -O2 -shared -I$REFLEXHOME/include example_rflx.cpp -o libexampleDict.so -L$REFLEXHOME/lib -lReflex .. _`example code`: cppyy_example.html @@ -595,6 +629,16 @@ All template classes must already exist in the loaded reflection info, they do not work (yet) with the class loader. + For compatibility with other bindings generators, use of square brackets + instead of parenthesis to instantiate templates is supported as well. + +* **templated functions**: Automatically participate in overloading and are + used in the same way as other global functions. + +* **templated methods**: For now, require an explicit selection of the + template parameters. + This will be changed to allow them to participate in overloads as expected. + * **typedefs**: Are simple python references to the actual classes to which they refer. @@ -692,7 +736,7 @@ Run the normal ``genreflex`` and compilation steps:: $ genreflex MyTemplate.h --selection=MyTemplate.xml - $ g++ -fPIC -rdynamic -O2 -shared -I$ROOTSYS/include MyTemplate_rflx.cpp -o libTemplateDict.so -L$ROOTSYS/lib -lReflex + $ g++ -fPIC -rdynamic -O2 -shared -I$REFLEXHOME/include MyTemplate_rflx.cpp -o libTemplateDict.so -L$REFLEXHOME/lib -lReflex Note: this is a dirty corner that clearly could do with some automation, even if the macro already helps. @@ -727,18 +771,18 @@ The fast lane ============= -The following is an experimental feature of cppyy, and that makes it doubly -experimental, so caveat emptor. +The following is an experimental feature of cppyy. +It mostly works, but there are some known issues (e.g. with return-by-value). +Soon it should be the default mode, however. + With a slight modification of Reflex, it can provide function pointers for C++ methods, and hence allow PyPy to call those pointers directly, rather than calling C++ through a Reflex stub. -This results in a rather significant speed-up. -Mind you, the normal stub path is not exactly slow, so for now only use this -out of curiosity or if you really need it. -To install this patch of Reflex, locate the file genreflex-methptrgetter.patch -in pypy/module/cppyy and apply it to the genreflex python scripts found in -``$ROOTSYS/lib``:: +The standalone version of Reflex `provided`_ has been patched, but if you get +Reflex from another source (most likely with a ROOT distribution), locate the +file `genreflex-methptrgetter.patch`_ in pypy/module/cppyy and apply it to +the genreflex python scripts found in ``$ROOTSYS/lib``:: $ cd $ROOTSYS/lib $ patch -p2 < genreflex-methptrgetter.patch @@ -749,8 +793,10 @@ ``-Wno-pmf-conversions`` option to ``g++`` when compiling. The rest works the same way: the fast path will be used transparently (which also means that you can't actually find out whether it is in use, other than -by running a micro-benchmark). +by running a micro-benchmark or a JIT test). +.. _`provided`: http://cern.ch/wlav/reflex-2013-04-23.tar.bz2 +.. _`genreflex-methptrgetter.patch`: https://bitbucket.org/pypy/pypy/src/default/pypy/module/cppyy/genreflex-methptrgetter.patch CPython ======= diff --git a/pypy/doc/cppyy_backend.rst b/pypy/doc/cppyy_backend.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/cppyy_backend.rst @@ -0,0 +1,53 @@ +================== +Backends for cppyy +================== + +The cppyy module needs a backend to provide the C++ reflection information on +which the Python bindings are build. +The backend is called through a C-API, which can be found in the PyPy sources +in: `pypy/module/cppyy/include/capi.h`_. +There are two kinds of API calls: querying about reflection information, which +are used during the creation of Python-side constructs, and making the actual +calls into C++. +The objects passed around are all opaque: cppyy does not make any assumptions +about them, other than that the opaque handles can be copied. +Their definition, however, appears in two places: in the C code (in capi.h), +and on the RPython side (in `capi_types.py`_), so if they are changed, they +need to be changed on both sides. + +.. _`pypy/module/cppyy/include/capi.h`: https://bitbucket.org/pypy/pypy/src/default/pypy/module/cppyy/include/capi.h +.. _`capi_types.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/module/cppyy/capi/capi_types.py + +There are two places where selections in the RPython code affect the choice +(and use) of the backend. +The first is in `pypy/module/cppyy/capi/__init__.py`_:: + + # choose C-API access method: + from pypy.module.cppyy.capi.loadable_capi import * + #from pypy.module.cppyy.capi.builtin_capi import * + +The default is the loadable C-API. +Comment it and uncomment the builtin C-API line, to use the builtin version. + +.. _`pypy/module/cppyy/capi/__init__.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/module/cppyy/capi/__init__.py + +Next, if the builtin C-API is chosen, the specific backend needs to be set as +well (default is Reflex). +This second choice is in `pypy/module/cppyy/capi/builtin_capi.py`_:: + + import reflex_capi as backend + #import cint_capi as backend + +After those choices have been made, built pypy-c as usual. + +.. _`pypy/module/cppyy/capi/builtin_capi.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/module/cppyy/capi/builtin_capi.py + +When building pypy-c from source, keep the following in mind. +If the loadable_capi is chosen, no further prerequisites are needed. +However, for the build of the builtin_capi to succeed, the ``ROOTSYS`` +environment variable must point to the location of your ROOT (or standalone +Reflex in the case of the Reflex backend) installation, or the ``root-config`` +utility must be accessible through ``$PATH`` (e.g. by adding ``$ROOTSYS/bin`` +to ``PATH``). +In case of the former, include files are expected under ``$ROOTSYS/include`` +and libraries under ``$ROOTSYS/lib``. diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -43,19 +43,26 @@ Rudimentary support for bytearray in RPython .. branch: refactor-call_release_gil -Fix a bug which casused cffi to return the wrong result when calling a C +Fix a bug which caused cffi to return the wrong result when calling a C function which calls a Python callback which forces the frames .. branch: virtual-raw-mallocs -JIT optimizations which makes cffi calls even faster, by removing the need to +JIT optimizations which make cffi calls even faster, by removing the need to allocate a temporary buffer where to store the arguments. .. branch: improve-docs-2 Improve documents and straighten out links +.. branch: fast-newarray +Inline the fast path of newarray in the assembler. +Disabled on ARM until we fix issues. + +.. branch: reflex-support +Allow dynamic loading of a (Reflex) backend that implements the C-API needed +to provide reflection information + .. branches we don't care about .. branch: autoreds -.. branch: reflex-support .. branch: kill-faking .. branch: improved_ebnfparse_error .. branch: task-decorator diff --git a/pypy/module/_minimal_curses/__init__.py b/pypy/module/_minimal_curses/__init__.py --- a/pypy/module/_minimal_curses/__init__.py +++ b/pypy/module/_minimal_curses/__init__.py @@ -1,6 +1,6 @@ try: import _curses -except ImportError: +except Exception: # probably ImportError or cffi's VerificationError try: # when running on top of pypy before it had _curses, settle for minimal # we prefer _curses so any constants added make it into _minimal_curses diff --git a/pypy/module/cppyy/__init__.py b/pypy/module/cppyy/__init__.py --- a/pypy/module/cppyy/__init__.py +++ b/pypy/module/cppyy/__init__.py @@ -10,15 +10,17 @@ '_resolve_name' : 'interp_cppyy.resolve_name', '_scope_byname' : 'interp_cppyy.scope_byname', '_template_byname' : 'interp_cppyy.template_byname', + '_std_string_name' : 'interp_cppyy.std_string_name', '_set_class_generator' : 'interp_cppyy.set_class_generator', '_register_class' : 'interp_cppyy.register_class', + '_is_static' : 'interp_cppyy.is_static', 'CPPInstance' : 'interp_cppyy.W_CPPInstance', 'addressof' : 'interp_cppyy.addressof', 'bind_object' : 'interp_cppyy.bind_object', } appleveldefs = { - 'gbl' : 'pythonify.gbl', + '_init_pythonify' : 'pythonify._init_pythonify', 'load_reflection_info' : 'pythonify.load_reflection_info', 'add_pythonization' : 'pythonify.add_pythonization', } @@ -31,3 +33,9 @@ # code generation is not, so give it a chance to run now from pypy.module.cppyy import capi capi.register_pythonizations(space) + + def startup(self, space): + from pypy.module.cppyy import capi + capi.verify_backend(space) # may raise ImportError + + space.call_method(space.wrap(self), '_init_pythonify') diff --git a/pypy/module/cppyy/capi/__init__.py b/pypy/module/cppyy/capi/__init__.py --- a/pypy/module/cppyy/capi/__init__.py +++ b/pypy/module/cppyy/capi/__init__.py @@ -1,37 +1,19 @@ from rpython.rtyper.lltypesystem import rffi, lltype -from rpython.rlib import jit -import reflex_capi as backend -#import cint_capi as backend +# There are two possible ways of accessing the backend through the reflection +# C-API: built it into pypy-c, or load it dynamically. The latter is preferred +# (and is the default) for use with Reflex. B/c of some builtin pythonizations, +# the former is recommended (for now) with CINT. -identify = backend.identify -pythonize = backend.pythonize -register_pythonizations = backend.register_pythonizations +# Note: if builtin_capi is chosen, then inside builtin_capi.py, there is still +# the selection of the desired backend (default is Reflex). -ts_reflect = backend.ts_reflect -ts_call = backend.ts_call -ts_memory = backend.ts_memory -ts_helper = backend.ts_helper +# choose C-API access method: +from pypy.module.cppyy.capi.loadable_capi import * +#from pypy.module.cppyy.capi.builtin_capi import * -_C_OPAQUE_PTR = rffi.LONG -_C_OPAQUE_NULL = lltype.nullptr(rffi.LONGP.TO)# ALT: _C_OPAQUE_PTR.TO - -C_SCOPE = _C_OPAQUE_PTR -C_NULL_SCOPE = rffi.cast(C_SCOPE, _C_OPAQUE_NULL) - -C_TYPE = C_SCOPE -C_NULL_TYPE = C_NULL_SCOPE - -C_OBJECT = _C_OPAQUE_PTR -C_NULL_OBJECT = rffi.cast(C_OBJECT, _C_OPAQUE_NULL) - -C_METHOD = _C_OPAQUE_PTR -C_INDEX = rffi.LONG -C_INDEX_ARRAY = rffi.LONGP -WLAVC_INDEX = rffi.LONG - -C_METHPTRGETTER = lltype.FuncType([C_OBJECT], rffi.VOIDP) -C_METHPTRGETTER_PTR = lltype.Ptr(C_METHPTRGETTER) +from pypy.module.cppyy.capi.capi_types import C_OBJECT,\ + C_NULL_TYPE, C_NULL_OBJECT def direct_ptradd(ptr, offset): offset = rffi.cast(rffi.SIZE_T, offset) @@ -42,457 +24,3 @@ def exchange_address(ptr, cif_descr, index): return rffi.ptradd(ptr, cif_descr.exchange_args[index]) - -c_load_dictionary = backend.c_load_dictionary - -# name to opaque C++ scope representation ------------------------------------ -_c_num_scopes = rffi.llexternal( - "cppyy_num_scopes", - [C_SCOPE], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_num_scopes(cppscope): - return _c_num_scopes(cppscope.handle) -_c_scope_name = rffi.llexternal( - "cppyy_scope_name", - [C_SCOPE, rffi.INT], rffi.CCHARP, - compilation_info = backend.eci) -def c_scope_name(cppscope, iscope): - return charp2str_free(_c_scope_name(cppscope.handle, iscope)) - -_c_resolve_name = rffi.llexternal( - "cppyy_resolve_name", - [rffi.CCHARP], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_resolve_name(name): - return charp2str_free(_c_resolve_name(name)) -c_get_scope_opaque = rffi.llexternal( - "cppyy_get_scope", - [rffi.CCHARP], C_SCOPE, - threadsafe=ts_reflect, - compilation_info=backend.eci) -c_get_template = rffi.llexternal( - "cppyy_get_template", - [rffi.CCHARP], C_TYPE, - threadsafe=ts_reflect, - compilation_info=backend.eci) -_c_actual_class = rffi.llexternal( - "cppyy_actual_class", - [C_TYPE, C_OBJECT], C_TYPE, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_actual_class(cppclass, cppobj): - return _c_actual_class(cppclass.handle, cppobj) - -# memory management ---------------------------------------------------------- -_c_allocate = rffi.llexternal( - "cppyy_allocate", - [C_TYPE], C_OBJECT, - threadsafe=ts_memory, - compilation_info=backend.eci) -def c_allocate(cppclass): - return _c_allocate(cppclass.handle) -_c_deallocate = rffi.llexternal( - "cppyy_deallocate", - [C_TYPE, C_OBJECT], lltype.Void, - threadsafe=ts_memory, - compilation_info=backend.eci) -def c_deallocate(cppclass, cppobject): - _c_deallocate(cppclass.handle, cppobject) -_c_destruct = rffi.llexternal( - "cppyy_destruct", - [C_TYPE, C_OBJECT], lltype.Void, - threadsafe=ts_call, - compilation_info=backend.eci) -def c_destruct(cppclass, cppobject): - _c_destruct(cppclass.handle, cppobject) - -# method/function dispatching ------------------------------------------------ -c_call_v = rffi.llexternal( - "cppyy_call_v", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], lltype.Void, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_b = rffi.llexternal( - "cppyy_call_b", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.UCHAR, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_c = rffi.llexternal( - "cppyy_call_c", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.CHAR, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_h = rffi.llexternal( - "cppyy_call_h", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.SHORT, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_i = rffi.llexternal( - "cppyy_call_i", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.INT, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_l = rffi.llexternal( - "cppyy_call_l", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.LONG, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_ll = rffi.llexternal( - "cppyy_call_ll", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.LONGLONG, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_f = rffi.llexternal( - "cppyy_call_f", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.FLOAT, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_d = rffi.llexternal( - "cppyy_call_d", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.DOUBLE, - threadsafe=ts_call, - compilation_info=backend.eci) - -c_call_r = rffi.llexternal( - "cppyy_call_r", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.VOIDP, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_s = rffi.llexternal( - "cppyy_call_s", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.CCHARP, - threadsafe=ts_call, - compilation_info=backend.eci) - -c_constructor = rffi.llexternal( - "cppyy_constructor", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], lltype.Void, - threadsafe=ts_call, - compilation_info=backend.eci) -_c_call_o = rffi.llexternal( - "cppyy_call_o", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP, C_TYPE], rffi.LONG, - threadsafe=ts_call, - compilation_info=backend.eci) -def c_call_o(method, cppobj, nargs, args, cppclass): - return _c_call_o(method, cppobj, nargs, args, cppclass.handle) - -_c_get_methptr_getter = rffi.llexternal( - "cppyy_get_methptr_getter", - [C_SCOPE, C_INDEX], C_METHPTRGETTER_PTR, - threadsafe=ts_reflect, - compilation_info=backend.eci, - elidable_function=True) -def c_get_methptr_getter(cppscope, index): - return _c_get_methptr_getter(cppscope.handle, index) - -# handling of function argument buffer --------------------------------------- -c_allocate_function_args = rffi.llexternal( - "cppyy_allocate_function_args", - [rffi.SIZE_T], rffi.VOIDP, - threadsafe=ts_memory, - compilation_info=backend.eci) -c_deallocate_function_args = rffi.llexternal( - "cppyy_deallocate_function_args", - [rffi.VOIDP], lltype.Void, - threadsafe=ts_memory, - compilation_info=backend.eci) -c_function_arg_sizeof = rffi.llexternal( - "cppyy_function_arg_sizeof", - [], rffi.SIZE_T, - threadsafe=ts_memory, - compilation_info=backend.eci, - elidable_function=True) -c_function_arg_typeoffset = rffi.llexternal( - "cppyy_function_arg_typeoffset", - [], rffi.SIZE_T, - threadsafe=ts_memory, - compilation_info=backend.eci, - elidable_function=True) - -# scope reflection information ----------------------------------------------- -c_is_namespace = rffi.llexternal( - "cppyy_is_namespace", - [C_SCOPE], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -c_is_enum = rffi.llexternal( - "cppyy_is_enum", - [rffi.CCHARP], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) - -# type/class reflection information ------------------------------------------ -_c_final_name = rffi.llexternal( - "cppyy_final_name", - [C_TYPE], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_final_name(cpptype): - return charp2str_free(_c_final_name(cpptype)) -_c_scoped_final_name = rffi.llexternal( - "cppyy_scoped_final_name", - [C_TYPE], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_scoped_final_name(cpptype): - return charp2str_free(_c_scoped_final_name(cpptype)) -c_has_complex_hierarchy = rffi.llexternal( - "cppyy_has_complex_hierarchy", - [C_TYPE], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -_c_num_bases = rffi.llexternal( - "cppyy_num_bases", - [C_TYPE], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_num_bases(cppclass): - return _c_num_bases(cppclass.handle) -_c_base_name = rffi.llexternal( - "cppyy_base_name", - [C_TYPE, rffi.INT], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_base_name(cppclass, base_index): - return charp2str_free(_c_base_name(cppclass.handle, base_index)) -_c_is_subtype = rffi.llexternal( - "cppyy_is_subtype", - [C_TYPE, C_TYPE], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci, - elidable_function=True) - at jit.elidable_promote() -def c_is_subtype(derived, base): - if derived == base: - return 1 - return _c_is_subtype(derived.handle, base.handle) - -_c_base_offset = rffi.llexternal( - "cppyy_base_offset", - [C_TYPE, C_TYPE, C_OBJECT, rffi.INT], rffi.SIZE_T, - threadsafe=ts_reflect, - compilation_info=backend.eci, - elidable_function=True) - at jit.elidable_promote() -def c_base_offset(derived, base, address, direction): - if derived == base: - return 0 - return _c_base_offset(derived.handle, base.handle, address, direction) - -# method/function reflection information ------------------------------------- -_c_num_methods = rffi.llexternal( - "cppyy_num_methods", - [C_SCOPE], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_num_methods(cppscope): - return _c_num_methods(cppscope.handle) -_c_method_index_at = rffi.llexternal( - "cppyy_method_index_at", - [C_SCOPE, rffi.INT], C_INDEX, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_index_at(cppscope, imethod): - return _c_method_index_at(cppscope.handle, imethod) -_c_method_indices_from_name = rffi.llexternal( - "cppyy_method_indices_from_name", - [C_SCOPE, rffi.CCHARP], C_INDEX_ARRAY, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_indices_from_name(cppscope, name): - indices = _c_method_indices_from_name(cppscope.handle, name) - if not indices: - return [] - py_indices = [] - i = 0 - index = indices[i] - while index != -1: - i += 1 - py_indices.append(index) - index = indices[i] - c_free(rffi.cast(rffi.VOIDP, indices)) # c_free defined below - return py_indices - -_c_method_name = rffi.llexternal( - "cppyy_method_name", - [C_SCOPE, C_INDEX], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_name(cppscope, index): - return charp2str_free(_c_method_name(cppscope.handle, index)) -_c_method_result_type = rffi.llexternal( - "cppyy_method_result_type", - [C_SCOPE, C_INDEX], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_result_type(cppscope, index): - return charp2str_free(_c_method_result_type(cppscope.handle, index)) -_c_method_num_args = rffi.llexternal( - "cppyy_method_num_args", - [C_SCOPE, C_INDEX], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_num_args(cppscope, index): - return _c_method_num_args(cppscope.handle, index) -_c_method_req_args = rffi.llexternal( - "cppyy_method_req_args", - [C_SCOPE, C_INDEX], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_req_args(cppscope, index): - return _c_method_req_args(cppscope.handle, index) -_c_method_arg_type = rffi.llexternal( - "cppyy_method_arg_type", - [C_SCOPE, C_INDEX, rffi.INT], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_arg_type(cppscope, index, arg_index): - return charp2str_free(_c_method_arg_type(cppscope.handle, index, arg_index)) -_c_method_arg_default = rffi.llexternal( - "cppyy_method_arg_default", - [C_SCOPE, C_INDEX, rffi.INT], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_arg_default(cppscope, index, arg_index): - return charp2str_free(_c_method_arg_default(cppscope.handle, index, arg_index)) -_c_method_signature = rffi.llexternal( - "cppyy_method_signature", - [C_SCOPE, C_INDEX], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_signature(cppscope, index): - return charp2str_free(_c_method_signature(cppscope.handle, index)) - -_c_get_method = rffi.llexternal( - "cppyy_get_method", - [C_SCOPE, C_INDEX], C_METHOD, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_get_method(cppscope, index): - return _c_get_method(cppscope.handle, index) -_c_get_global_operator = rffi.llexternal( - "cppyy_get_global_operator", - [C_SCOPE, C_SCOPE, C_SCOPE, rffi.CCHARP], WLAVC_INDEX, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_get_global_operator(nss, lc, rc, op): - if nss is not None: - return _c_get_global_operator(nss.handle, lc.handle, rc.handle, op) - return rffi.cast(WLAVC_INDEX, -1) - -# method properties ---------------------------------------------------------- -_c_is_constructor = rffi.llexternal( - "cppyy_is_constructor", - [C_TYPE, C_INDEX], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_is_constructor(cppclass, index): - return _c_is_constructor(cppclass.handle, index) -_c_is_staticmethod = rffi.llexternal( - "cppyy_is_staticmethod", - [C_TYPE, C_INDEX], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_is_staticmethod(cppclass, index): - return _c_is_staticmethod(cppclass.handle, index) - -# data member reflection information ----------------------------------------- -_c_num_datamembers = rffi.llexternal( - "cppyy_num_datamembers", - [C_SCOPE], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_num_datamembers(cppscope): - return _c_num_datamembers(cppscope.handle) -_c_datamember_name = rffi.llexternal( - "cppyy_datamember_name", - [C_SCOPE, rffi.INT], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_datamember_name(cppscope, datamember_index): - return charp2str_free(_c_datamember_name(cppscope.handle, datamember_index)) -_c_datamember_type = rffi.llexternal( - "cppyy_datamember_type", - [C_SCOPE, rffi.INT], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_datamember_type(cppscope, datamember_index): - return charp2str_free(_c_datamember_type(cppscope.handle, datamember_index)) -_c_datamember_offset = rffi.llexternal( - "cppyy_datamember_offset", - [C_SCOPE, rffi.INT], rffi.SIZE_T, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_datamember_offset(cppscope, datamember_index): - return _c_datamember_offset(cppscope.handle, datamember_index) - -_c_datamember_index = rffi.llexternal( - "cppyy_datamember_index", - [C_SCOPE, rffi.CCHARP], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_datamember_index(cppscope, name): - return _c_datamember_index(cppscope.handle, name) - -# data member properties ----------------------------------------------------- -_c_is_publicdata = rffi.llexternal( - "cppyy_is_publicdata", - [C_SCOPE, rffi.INT], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_is_publicdata(cppscope, datamember_index): - return _c_is_publicdata(cppscope.handle, datamember_index) -_c_is_staticdata = rffi.llexternal( - "cppyy_is_staticdata", - [C_SCOPE, rffi.INT], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_is_staticdata(cppscope, datamember_index): - return _c_is_staticdata(cppscope.handle, datamember_index) - -# misc helpers --------------------------------------------------------------- -c_strtoll = rffi.llexternal( - "cppyy_strtoll", - [rffi.CCHARP], rffi.LONGLONG, - threadsafe=ts_helper, - compilation_info=backend.eci) -c_strtoull = rffi.llexternal( - "cppyy_strtoull", - [rffi.CCHARP], rffi.ULONGLONG, - threadsafe=ts_helper, - compilation_info=backend.eci) -c_free = rffi.llexternal( - "cppyy_free", - [rffi.VOIDP], lltype.Void, - threadsafe=ts_memory, - compilation_info=backend.eci) - -def charp2str_free(charp): - string = rffi.charp2str(charp) - voidp = rffi.cast(rffi.VOIDP, charp) - c_free(voidp) - return string - -c_charp2stdstring = rffi.llexternal( - "cppyy_charp2stdstring", - [rffi.CCHARP], C_OBJECT, - threadsafe=ts_helper, - compilation_info=backend.eci) -c_stdstring2stdstring = rffi.llexternal( - "cppyy_stdstring2stdstring", - [C_OBJECT], C_OBJECT, - threadsafe=ts_helper, - compilation_info=backend.eci) -c_assign2stdstring = rffi.llexternal( - "cppyy_assign2stdstring", - [C_OBJECT, rffi.CCHARP], lltype.Void, - threadsafe=ts_helper, - compilation_info=backend.eci) -c_free_stdstring = rffi.llexternal( - "cppyy_free_stdstring", - [C_OBJECT], lltype.Void, - threadsafe=ts_helper, - compilation_info=backend.eci) diff --git a/pypy/module/cppyy/capi/builtin_capi.py b/pypy/module/cppyy/capi/builtin_capi.py new file mode 100644 --- /dev/null +++ b/pypy/module/cppyy/capi/builtin_capi.py @@ -0,0 +1,561 @@ +from rpython.rtyper.lltypesystem import rffi, lltype +from rpython.rlib import jit + +import reflex_capi as backend +#import cint_capi as backend + +from pypy.module.cppyy.capi.capi_types import C_SCOPE, C_TYPE, C_OBJECT,\ + C_METHOD, C_INDEX, C_INDEX_ARRAY, WLAVC_INDEX,\ + C_METHPTRGETTER, C_METHPTRGETTER_PTR + +identify = backend.identify +pythonize = backend.pythonize +register_pythonizations = backend.register_pythonizations +std_string_name = backend.std_string_name + +ts_reflect = backend.ts_reflect +ts_call = backend.ts_call +ts_memory = backend.ts_memory +ts_helper = backend.ts_helper + +def verify_backend(space): + return True # by definition + +c_load_dictionary = backend.c_load_dictionary + +# name to opaque C++ scope representation ------------------------------------ +_c_num_scopes = rffi.llexternal( + "cppyy_num_scopes", + [C_SCOPE], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_num_scopes(space, cppscope): + return _c_num_scopes(cppscope.handle) +_c_scope_name = rffi.llexternal( + "cppyy_scope_name", + [C_SCOPE, rffi.INT], rffi.CCHARP, + compilation_info = backend.eci) +def c_scope_name(space, cppscope, iscope): + return charp2str_free(space, _c_scope_name(cppscope.handle, iscope)) + +_c_resolve_name = rffi.llexternal( + "cppyy_resolve_name", + [rffi.CCHARP], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_resolve_name(space, name): + return charp2str_free(space, _c_resolve_name(name)) +_c_get_scope_opaque = rffi.llexternal( + "cppyy_get_scope", + [rffi.CCHARP], C_SCOPE, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_get_scope_opaque(space, name): + return _c_get_scope_opaque(name) +_c_get_template = rffi.llexternal( + "cppyy_get_template", + [rffi.CCHARP], C_TYPE, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_get_template(space, name): + return _c_get_template(name) +_c_actual_class = rffi.llexternal( + "cppyy_actual_class", + [C_TYPE, C_OBJECT], C_TYPE, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_actual_class(space, cppclass, cppobj): + return _c_actual_class(cppclass.handle, cppobj) + +# memory management ---------------------------------------------------------- +_c_allocate = rffi.llexternal( + "cppyy_allocate", + [C_TYPE], C_OBJECT, + threadsafe=ts_memory, + compilation_info=backend.eci) +def c_allocate(space, cppclass): + return _c_allocate(cppclass.handle) +_c_deallocate = rffi.llexternal( + "cppyy_deallocate", + [C_TYPE, C_OBJECT], lltype.Void, + threadsafe=ts_memory, + compilation_info=backend.eci) +def c_deallocate(space, cppclass, cppobject): + _c_deallocate(cppclass.handle, cppobject) +_c_destruct = rffi.llexternal( + "cppyy_destruct", + [C_TYPE, C_OBJECT], lltype.Void, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_destruct(space, cppclass, cppobject): + _c_destruct(cppclass.handle, cppobject) + +# method/function dispatching ------------------------------------------------ +_c_call_v = rffi.llexternal( + "cppyy_call_v", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], lltype.Void, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_v(space, cppmethod, cppobject, nargs, args): + _c_call_v(cppmethod, cppobject, nargs, args) +_c_call_b = rffi.llexternal( + "cppyy_call_b", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.UCHAR, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_b(space, cppmethod, cppobject, nargs, args): + return _c_call_b(cppmethod, cppobject, nargs, args) +_c_call_c = rffi.llexternal( + "cppyy_call_c", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.CHAR, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_c(space, cppmethod, cppobject, nargs, args): + return _c_call_c(cppmethod, cppobject, nargs, args) +_c_call_h = rffi.llexternal( + "cppyy_call_h", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.SHORT, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_h(space, cppmethod, cppobject, nargs, args): + return _c_call_h(cppmethod, cppobject, nargs, args) +_c_call_i = rffi.llexternal( + "cppyy_call_i", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.INT, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_i(space, cppmethod, cppobject, nargs, args): + return _c_call_i(cppmethod, cppobject, nargs, args) +_c_call_l = rffi.llexternal( + "cppyy_call_l", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.LONG, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_l(space, cppmethod, cppobject, nargs, args): + return _c_call_l(cppmethod, cppobject, nargs, args) +_c_call_ll = rffi.llexternal( + "cppyy_call_ll", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.LONGLONG, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_ll(space, cppmethod, cppobject, nargs, args): + return _c_call_ll(cppmethod, cppobject, nargs, args) +_c_call_f = rffi.llexternal( + "cppyy_call_f", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.FLOAT, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_f(space, cppmethod, cppobject, nargs, args): + return _c_call_f(cppmethod, cppobject, nargs, args) +_c_call_d = rffi.llexternal( + "cppyy_call_d", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.DOUBLE, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_d(space, cppmethod, cppobject, nargs, args): + return _c_call_d(cppmethod, cppobject, nargs, args) + +_c_call_r = rffi.llexternal( + "cppyy_call_r", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.VOIDP, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_r(space, cppmethod, cppobject, nargs, args): + return _c_call_r(cppmethod, cppobject, nargs, args) +_c_call_s = rffi.llexternal( + "cppyy_call_s", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.CCHARP, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_s(space, cppmethod, cppobject, nargs, args): + return _c_call_s(cppmethod, cppobject, nargs, args) + +_c_constructor = rffi.llexternal( + "cppyy_constructor", + [C_METHOD, C_TYPE, rffi.INT, rffi.VOIDP], C_OBJECT, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_constructor(space, cppmethod, cppobject, nargs, args): + return _c_constructor(cppmethod, cppobject, nargs, args) +_c_call_o = rffi.llexternal( + "cppyy_call_o", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP, C_TYPE], rffi.LONG, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_o(space, method, cppobj, nargs, args, cppclass): + return _c_call_o(method, cppobj, nargs, args, cppclass.handle) + +_c_get_methptr_getter = rffi.llexternal( + "cppyy_get_methptr_getter", + [C_SCOPE, C_INDEX], C_METHPTRGETTER_PTR, + threadsafe=ts_reflect, + compilation_info=backend.eci, + elidable_function=True) +def c_get_methptr_getter(space, cppscope, index): + return _c_get_methptr_getter(cppscope.handle, index) + +# handling of function argument buffer --------------------------------------- +_c_allocate_function_args = rffi.llexternal( + "cppyy_allocate_function_args", + [rffi.SIZE_T], rffi.VOIDP, + threadsafe=ts_memory, + compilation_info=backend.eci) +def c_allocate_function_args(space, size): + return _c_allocate_function_args(size) +_c_deallocate_function_args = rffi.llexternal( + "cppyy_deallocate_function_args", + [rffi.VOIDP], lltype.Void, + threadsafe=ts_memory, + compilation_info=backend.eci) +def c_deallocate_function_args(space, args): + _c_deallocate_function_args(args) +_c_function_arg_sizeof = rffi.llexternal( + "cppyy_function_arg_sizeof", + [], rffi.SIZE_T, + threadsafe=ts_memory, + compilation_info=backend.eci, + elidable_function=True) +def c_function_arg_sizeof(space): + return _c_function_arg_sizeof() +_c_function_arg_typeoffset = rffi.llexternal( + "cppyy_function_arg_typeoffset", + [], rffi.SIZE_T, + threadsafe=ts_memory, + compilation_info=backend.eci, + elidable_function=True) +def c_function_arg_typeoffset(space): + return _c_function_arg_typeoffset() + +# scope reflection information ----------------------------------------------- +_c_is_namespace = rffi.llexternal( + "cppyy_is_namespace", + [C_SCOPE], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_is_namespace(space, scope): + return _c_is_namespace(scope) +_c_is_enum = rffi.llexternal( + "cppyy_is_enum", + [rffi.CCHARP], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_is_enum(space, name): + return _c_is_enum(name) + +# type/class reflection information ------------------------------------------ +_c_final_name = rffi.llexternal( + "cppyy_final_name", + [C_TYPE], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_final_name(space, cpptype): + return charp2str_free(space, _c_final_name(cpptype)) +_c_scoped_final_name = rffi.llexternal( + "cppyy_scoped_final_name", + [C_TYPE], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_scoped_final_name(space, cpptype): + return charp2str_free(space, _c_scoped_final_name(cpptype)) +_c_has_complex_hierarchy = rffi.llexternal( + "cppyy_has_complex_hierarchy", + [C_TYPE], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_has_complex_hierarchy(space, cpptype): + return _c_has_complex_hierarchy(cpptype) +_c_num_bases = rffi.llexternal( + "cppyy_num_bases", + [C_TYPE], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_num_bases(space, cppclass): + return _c_num_bases(cppclass.handle) +_c_base_name = rffi.llexternal( + "cppyy_base_name", + [C_TYPE, rffi.INT], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_base_name(space, cppclass, base_index): + return charp2str_free(space, _c_base_name(cppclass.handle, base_index)) +_c_is_subtype = rffi.llexternal( + "cppyy_is_subtype", + [C_TYPE, C_TYPE], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci, + elidable_function=True) + at jit.elidable_promote('2') +def c_is_subtype(space, derived, base): + if derived == base: + return 1 + return _c_is_subtype(derived.handle, base.handle) + +_c_base_offset = rffi.llexternal( + "cppyy_base_offset", + [C_TYPE, C_TYPE, C_OBJECT, rffi.INT], rffi.SIZE_T, + threadsafe=ts_reflect, + compilation_info=backend.eci, + elidable_function=True) + at jit.elidable_promote('1,2,4') +def c_base_offset(space, derived, base, address, direction): + if derived == base: + return 0 + return _c_base_offset(derived.handle, base.handle, address, direction) +def c_base_offset1(space, derived_h, base, address, direction): + return _c_base_offset(derived_h, base.handle, address, direction) + +# method/function reflection information ------------------------------------- +_c_num_methods = rffi.llexternal( + "cppyy_num_methods", + [C_SCOPE], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_num_methods(space, cppscope): + return _c_num_methods(cppscope.handle) +_c_method_index_at = rffi.llexternal( + "cppyy_method_index_at", + [C_SCOPE, rffi.INT], C_INDEX, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_index_at(space, cppscope, imethod): + return _c_method_index_at(cppscope.handle, imethod) +_c_method_indices_from_name = rffi.llexternal( + "cppyy_method_indices_from_name", + [C_SCOPE, rffi.CCHARP], C_INDEX_ARRAY, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_indices_from_name(space, cppscope, name): + indices = _c_method_indices_from_name(cppscope.handle, name) + if not indices: + return [] + py_indices = [] + i = 0 + index = indices[i] + while index != -1: + i += 1 + py_indices.append(index) + index = indices[i] + c_free(rffi.cast(rffi.VOIDP, indices)) # c_free defined below + return py_indices + +_c_method_name = rffi.llexternal( + "cppyy_method_name", + [C_SCOPE, C_INDEX], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_name(space, cppscope, index): + return charp2str_free(space, _c_method_name(cppscope.handle, index)) +_c_method_result_type = rffi.llexternal( + "cppyy_method_result_type", + [C_SCOPE, C_INDEX], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_result_type(space, cppscope, index): + return charp2str_free(space, _c_method_result_type(cppscope.handle, index)) +_c_method_num_args = rffi.llexternal( + "cppyy_method_num_args", + [C_SCOPE, C_INDEX], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_num_args(space, cppscope, index): + return _c_method_num_args(cppscope.handle, index) +_c_method_req_args = rffi.llexternal( + "cppyy_method_req_args", + [C_SCOPE, C_INDEX], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_req_args(space, cppscope, index): + return _c_method_req_args(cppscope.handle, index) +_c_method_arg_type = rffi.llexternal( + "cppyy_method_arg_type", + [C_SCOPE, C_INDEX, rffi.INT], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_arg_type(space, cppscope, index, arg_index): + return charp2str_free(space, _c_method_arg_type(cppscope.handle, index, arg_index)) +_c_method_arg_default = rffi.llexternal( + "cppyy_method_arg_default", + [C_SCOPE, C_INDEX, rffi.INT], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_arg_default(space, cppscope, index, arg_index): + return charp2str_free(space, _c_method_arg_default(cppscope.handle, index, arg_index)) +_c_method_signature = rffi.llexternal( + "cppyy_method_signature", + [C_SCOPE, C_INDEX], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_signature(space, cppscope, index): + return charp2str_free(space, _c_method_signature(cppscope.handle, index)) + +_c_method_is_template = rffi.llexternal( + "cppyy_method_is_template", + [C_SCOPE, C_INDEX], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_is_template(space, cppscope, index): + return _c_method_is_template(cppscope.handle, index) +_c_method_num_template_args = rffi.llexternal( + "cppyy_method_num_template_args", + [C_SCOPE, C_INDEX], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +_c_method_template_arg_name = rffi.llexternal( + "cppyy_method_template_arg_name", + [C_SCOPE, C_INDEX, C_INDEX], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_template_args(space, cppscope, index): + nargs = _c_method_num_template_args(cppscope.handle, index) + args = [c_resolve_name(space, + charp2str_free(space, _c_method_template_arg_name(cppscope.handle, index, iarg))) + for iarg in range(nargs)] + return args + +_c_get_method = rffi.llexternal( + "cppyy_get_method", + [C_SCOPE, C_INDEX], C_METHOD, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_get_method(space, cppscope, index): + return _c_get_method(cppscope.handle, index) +_c_get_global_operator = rffi.llexternal( + "cppyy_get_global_operator", + [C_SCOPE, C_SCOPE, C_SCOPE, rffi.CCHARP], WLAVC_INDEX, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_get_global_operator(space, nss, lc, rc, op): + if nss is not None: + return _c_get_global_operator(nss.handle, lc.handle, rc.handle, op) + return rffi.cast(WLAVC_INDEX, -1) + +# method properties ---------------------------------------------------------- +_c_is_constructor = rffi.llexternal( + "cppyy_is_constructor", + [C_TYPE, C_INDEX], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_is_constructor(space, cppclass, index): + return _c_is_constructor(cppclass.handle, index) +_c_is_staticmethod = rffi.llexternal( + "cppyy_is_staticmethod", + [C_TYPE, C_INDEX], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_is_staticmethod(space, cppclass, index): + return _c_is_staticmethod(cppclass.handle, index) + +# data member reflection information ----------------------------------------- +_c_num_datamembers = rffi.llexternal( + "cppyy_num_datamembers", + [C_SCOPE], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_num_datamembers(space, cppscope): + return _c_num_datamembers(cppscope.handle) +_c_datamember_name = rffi.llexternal( + "cppyy_datamember_name", + [C_SCOPE, rffi.INT], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_datamember_name(space, cppscope, datamember_index): + return charp2str_free(space, _c_datamember_name(cppscope.handle, datamember_index)) +_c_datamember_type = rffi.llexternal( + "cppyy_datamember_type", + [C_SCOPE, rffi.INT], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_datamember_type(space, cppscope, datamember_index): + return charp2str_free(space, _c_datamember_type(cppscope.handle, datamember_index)) +_c_datamember_offset = rffi.llexternal( + "cppyy_datamember_offset", + [C_SCOPE, rffi.INT], rffi.SIZE_T, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_datamember_offset(space, cppscope, datamember_index): + return _c_datamember_offset(cppscope.handle, datamember_index) + +_c_datamember_index = rffi.llexternal( + "cppyy_datamember_index", + [C_SCOPE, rffi.CCHARP], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_datamember_index(space, cppscope, name): + return _c_datamember_index(cppscope.handle, name) + +# data member properties ----------------------------------------------------- +_c_is_publicdata = rffi.llexternal( + "cppyy_is_publicdata", + [C_SCOPE, rffi.INT], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_is_publicdata(space, cppscope, datamember_index): + return _c_is_publicdata(cppscope.handle, datamember_index) +_c_is_staticdata = rffi.llexternal( + "cppyy_is_staticdata", + [C_SCOPE, rffi.INT], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_is_staticdata(space, cppscope, datamember_index): + return _c_is_staticdata(cppscope.handle, datamember_index) + +# misc helpers --------------------------------------------------------------- +_c_strtoll = rffi.llexternal( + "cppyy_strtoll", + [rffi.CCHARP], rffi.LONGLONG, + threadsafe=ts_helper, + compilation_info=backend.eci) +def c_strtoll(space, svalue): + return _c_strtoll(svalue) +_c_strtoull = rffi.llexternal( + "cppyy_strtoull", + [rffi.CCHARP], rffi.ULONGLONG, + threadsafe=ts_helper, + compilation_info=backend.eci) +def c_strtoull(space, svalue): + return _c_strtoull(svalue) +c_free = rffi.llexternal( + "cppyy_free", + [rffi.VOIDP], lltype.Void, + threadsafe=ts_memory, + compilation_info=backend.eci) + +def charp2str_free(space, charp): + string = rffi.charp2str(charp) + voidp = rffi.cast(rffi.VOIDP, charp) + c_free(voidp) + return string + +_c_charp2stdstring = rffi.llexternal( + "cppyy_charp2stdstring", + [rffi.CCHARP], C_OBJECT, + threadsafe=ts_helper, + compilation_info=backend.eci) +def c_charp2stdstring(space, svalue): + charp = rffi.str2charp(svalue) + result = _c_charp2stdstring(charp) + rffi.free_charp(charp) + return result +_c_stdstring2stdstring = rffi.llexternal( + "cppyy_stdstring2stdstring", + [C_OBJECT], C_OBJECT, + threadsafe=ts_helper, + compilation_info=backend.eci) +def c_stdstring2stdstring(space, cppobject): + return _c_stdstring2stdstring(cppobject) +_c_assign2stdstring = rffi.llexternal( + "cppyy_assign2stdstring", + [C_OBJECT, rffi.CCHARP], lltype.Void, + threadsafe=ts_helper, + compilation_info=backend.eci) +def c_assign2stdstring(space, cppobject, svalue): + charp = rffi.str2charp(svalue) + _c_assign2stdstring(cppobject, charp) + rffi.free_charp(charp) +_c_free_stdstring = rffi.llexternal( + "cppyy_free_stdstring", + [C_OBJECT], lltype.Void, + threadsafe=ts_helper, + compilation_info=backend.eci) +def c_free_stdstring(space, cppobject): + _c_free_stdstring(cppobject) diff --git a/pypy/module/cppyy/capi/capi_types.py b/pypy/module/cppyy/capi/capi_types.py new file mode 100644 --- /dev/null +++ b/pypy/module/cppyy/capi/capi_types.py @@ -0,0 +1,22 @@ +from rpython.rtyper.lltypesystem import rffi, lltype + +# shared ll definitions +_C_OPAQUE_PTR = rffi.LONG +_C_OPAQUE_NULL = lltype.nullptr(rffi.LONGP.TO)# ALT: _C_OPAQUE_PTR.TO + +C_SCOPE = _C_OPAQUE_PTR +C_NULL_SCOPE = rffi.cast(C_SCOPE, _C_OPAQUE_NULL) + +C_TYPE = C_SCOPE +C_NULL_TYPE = C_NULL_SCOPE + +C_OBJECT = _C_OPAQUE_PTR +C_NULL_OBJECT = rffi.cast(C_OBJECT, _C_OPAQUE_NULL) + +C_METHOD = _C_OPAQUE_PTR +C_INDEX = rffi.LONG +C_INDEX_ARRAY = rffi.LONGP +WLAVC_INDEX = rffi.LONG + +C_METHPTRGETTER = lltype.FuncType([C_OBJECT], rffi.VOIDP) +C_METHPTRGETTER_PTR = lltype.Ptr(C_METHPTRGETTER) diff --git a/pypy/module/cppyy/capi/cint_capi.py b/pypy/module/cppyy/capi/cint_capi.py --- a/pypy/module/cppyy/capi/cint_capi.py +++ b/pypy/module/cppyy/capi/cint_capi.py @@ -9,10 +9,8 @@ from rpython.rtyper.lltypesystem import rffi from rpython.rlib import libffi, rdynload -from pypy.module.itertools import interp_itertools - -__all__ = ['identify', 'eci', 'c_load_dictionary'] +__all__ = ['identify', 'std_string_name', 'eci', 'c_load_dictionary'] pkgpath = py.path.local(__file__).dirpath().join(os.pardir) srcpath = pkgpath.join("src") @@ -36,8 +34,10 @@ ts_reflect = False ts_call = False -ts_memory = 'auto' -ts_helper = 'auto' +ts_memory = False +ts_helper = False + +std_string_name = 'string' # force loading in global mode of core libraries, rather than linking with # them as PyPy uses various version of dlopen in various places; note that @@ -120,7 +120,7 @@ classname = space.str_w(args_w[1]) addr_idx = 2 w_address = args_w[addr_idx] - except OperationError: + except (OperationError, TypeError): addr_idx = 1 w_address = args_w[addr_idx] @@ -138,14 +138,14 @@ # call the helper stub to by-pass CINT vbranch = _ttree_Branch(vtree, branchname, klassname, address, bufsize, splitlevel) branch_class = interp_cppyy.scope_byname(space, "TBranch") - w_branch = interp_cppyy.wrap_cppobject( - space, space.w_None, branch_class, vbranch, isref=False, python_owns=False) + w_branch = interp_cppyy.wrap_cppobject(space, vbranch, branch_class) return w_branch - except (OperationError, TypeError, IndexError), e: + except (OperationError, TypeError, IndexError): pass # return control back to the original, unpythonized overload - return tree_class.get_overload("Branch").call(w_self, args_w) + ol = tree_class.get_overload("Branch") + return ol.call(w_self, args_w) def activate_branch(space, w_branch): w_branches = space.call_method(w_branch, "GetListOfBranches") @@ -155,6 +155,12 @@ space.call_method(w_branch, "SetStatus", space.wrap(1)) space.call_method(w_branch, "ResetReadEntry") +c_ttree_GetEntry = rffi.llexternal( + "cppyy_ttree_GetEntry", + [rffi.VOIDP, rffi.LONGLONG], rffi.LONGLONG, + threadsafe=False, + compilation_info=eci) + @unwrap_spec(args_w='args_w') def ttree_getattr(space, w_self, args_w): """Specialized __getattr__ for TTree's that allows switching on/off the @@ -163,28 +169,75 @@ from pypy.module.cppyy import interp_cppyy tree = space.interp_w(interp_cppyy.W_CPPInstance, w_self) + space = tree.space # holds the class cache in State + + # prevent recursion + attr = space.str_w(args_w[0]) + if attr and attr[0] == '_': + raise OperationError(space.w_AttributeError, args_w[0]) + + # try the saved cdata (for builtin types) + try: + w_cdata = space.getattr(w_self, space.wrap('_'+attr)) + from pypy.module._cffi_backend import cdataobj + cdata = space.interp_w(cdataobj.W_CData, w_cdata, can_be_None=False) + return cdata.convert_to_object() + except OperationError: + pass + # setup branch as a data member and enable it for reading - space = tree.space # holds the class cache in State w_branch = space.call_method(w_self, "GetBranch", args_w[0]) + if not space.is_true(w_branch): + raise OperationError(space.w_AttributeError, args_w[0]) + activate_branch(space, w_branch) + + # figure out from where we're reading + entry = space.int_w(space.call_method(w_self, "GetReadEntry")) + if entry == -1: + entry = 0 + + # setup cache structure w_klassname = space.call_method(w_branch, "GetClassName") - klass = interp_cppyy.scope_byname(space, space.str_w(w_klassname)) - w_obj = klass.construct() - #space.call_method(w_branch, "SetStatus", space.wrap(1)) - activate_branch(space, w_branch) - space.call_method(w_branch, "SetObject", w_obj) - space.call_method(w_branch, "GetEntry", space.wrap(0)) - space.setattr(w_self, args_w[0], w_obj) - return w_obj + if space.is_true(w_klassname): + # some instance + klass = interp_cppyy.scope_byname(space, space.str_w(w_klassname)) + w_obj = klass.construct() + space.call_method(w_branch, "SetObject", w_obj) + space.call_method(w_branch, "GetEntry", space.wrap(entry)) + space.setattr(w_self, args_w[0], w_obj) + return w_obj + else: + # builtin data + w_leaf = space.call_method(w_self, "GetLeaf", args_w[0]) + space.call_method(w_branch, "GetEntry", space.wrap(entry)) + + # location + w_address = space.call_method(w_leaf, "GetValuePointer") + buf = space.buffer_w(w_address) + from pypy.module._rawffi import buffer + assert isinstance(buf, buffer.RawFFIBuffer) + address = rffi.cast(rffi.CCHARP, buf.datainstance.ll_buffer) + + # placeholder + w_typename = space.call_method(w_leaf, "GetTypeName" ) + from pypy.module.cppyy import capi + typename = capi.c_resolve_name(space, space.str_w(w_typename)) + if typename == 'bool': typename = '_Bool' + w_address = space.call_method(w_leaf, "GetValuePointer") + from pypy.module._cffi_backend import cdataobj, newtype + cdata = cdataobj.W_CData(space, address, newtype.new_primitive_type(space, typename)) + + # cache result + space.setattr(w_self, space.wrap('_'+attr), space.wrap(cdata)) + return space.getattr(w_self, args_w[0]) class W_TTreeIter(W_Root): def __init__(self, space, w_tree): - from pypy.module.cppyy import interp_cppyy tree = space.interp_w(interp_cppyy.W_CPPInstance, w_tree) - self.tree = tree.get_cppthis(tree.cppclass) + self.vtree = rffi.cast(rffi.VOIDP, tree.get_cppthis(tree.cppclass)) self.w_tree = w_tree - self.getentry = tree.cppclass.get_overload("GetEntry").functions[0] self.current = 0 self.maxentry = space.int_w(space.call_method(w_tree, "GetEntriesFast")) @@ -198,8 +251,8 @@ if self.current == self.maxentry: raise OperationError(self.space.w_StopIteration, self.space.w_None) # TODO: check bytes read? - self.getentry.call(self.tree, [self.space.wrap(self.current)]) - self.current += 1 + c_ttree_GetEntry(self.vtree, self.current) + self.current += 1 return self.w_tree W_TTreeIter.typedef = TypeDef( diff --git a/pypy/module/cppyy/capi/loadable_capi.py b/pypy/module/cppyy/capi/loadable_capi.py new file mode 100644 --- /dev/null +++ b/pypy/module/cppyy/capi/loadable_capi.py @@ -0,0 +1,519 @@ +from rpython.rtyper.lltypesystem import rffi, lltype +from rpython.rlib import jit, jit_libffi, libffi, rdynload, objectmodel +from rpython.rlib.rarithmetic import r_singlefloat +from rpython.tool import leakfinder + +from pypy.interpreter.error import OperationError + +from pypy.module._cffi_backend import ctypefunc, ctypeprim, cdataobj, misc + +from pypy.module.cppyy.capi.capi_types import C_SCOPE, C_TYPE, C_OBJECT,\ + C_METHOD, C_INDEX, C_INDEX_ARRAY, WLAVC_INDEX, C_METHPTRGETTER_PTR + + +reflection_library = 'libcppyy_backend.so' + +def identify(): + return 'loadable_capi' + +# this is not technically correct, but will do for now +std_string_name = 'std::basic_string' + +class _Arg: # poor man's union + _immutable_ = True + def __init__(self, l = 0, s = '', vp = rffi.cast(rffi.VOIDP, 0) ): + self._long = l + self._string = s + self._voidp = vp + +# For the loadable CAPI, the calls start and end in RPython. Therefore, the standard +# _call of W_CTypeFunc, which expects wrapped objects, does not quite work: some +# vars (e.g. void* equivalent) can not be wrapped, and others (such as rfloat) risk +# rounding problems. This W_RCTypeFun then, takes args, instead of args_w. Note that +# rcall() is a new method, so as to not interfere with the base class call and _call +# when rtyping. It is also called directly (see call_capi below). +class W_RCTypeFunc(ctypefunc.W_CTypeFunc): + @jit.unroll_safe + def rcall(self, funcaddr, args): + assert self.cif_descr + self = jit.promote(self) + # no checking of len(args) needed, as calls in this context are not dynamic + + # The following code is functionally similar to W_CTypeFunc._call, but its + # implementation is tailored to the restricted use (include memory handling) + # of the CAPI calls. + space = self.space + cif_descr = self.cif_descr + size = cif_descr.exchange_size + raw_string = rffi.cast(rffi.CCHARP, 0) # only ever have one in the CAPI + buffer = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') + try: + for i in range(len(args)): + data = rffi.ptradd(buffer, cif_descr.exchange_args[i]) + obj = args[i] + argtype = self.fargs[i] + # the following is clumsy, but the data types used as arguments are + # very limited, so it'll do for now + if isinstance(argtype, ctypeprim.W_CTypePrimitiveSigned): + misc.write_raw_signed_data(data, rffi.cast(rffi.LONG, obj._long), argtype.size) + elif isinstance(argtype, ctypeprim.W_CTypePrimitiveUnsigned): + misc.write_raw_unsigned_data(data, rffi.cast(rffi.ULONG, obj._long), argtype.size) + elif obj._voidp != rffi.cast(rffi.VOIDP, 0): + data = rffi.cast(rffi.VOIDPP, data) + data[0] = obj._voidp + else: # only other use is sring + n = len(obj._string) + assert raw_string == rffi.cast(rffi.CCHARP, 0) + raw_string = rffi.str2charp(obj._string) + data = rffi.cast(rffi.CCHARPP, data) + data[0] = raw_string + + jit_libffi.jit_ffi_call(cif_descr, + rffi.cast(rffi.VOIDP, funcaddr), + buffer) + + resultdata = rffi.ptradd(buffer, cif_descr.exchange_result) + # this wrapping is unnecessary, but the assumption is that given the + # immediate unwrapping, the round-trip is removed + w_res = self.ctitem.copy_and_convert_to_object(resultdata) + finally: + if raw_string != rffi.cast(rffi.CCHARP, 0): + rffi.free_charp(raw_string) + lltype.free(buffer, flavor='raw') + return w_res + +class State(object): + def __init__(self, space): + self.library = None + self.capi_calls = {} + + import pypy.module._cffi_backend.newtype as nt + + # TODO: the following need to match up with the globally defined C_XYZ low-level + # types (see capi/__init__.py), but by using strings here, that isn't guaranteed + c_opaque_ptr = nt.new_primitive_type(space, 'long') + + c_scope = c_opaque_ptr + c_type = c_scope + c_object = c_opaque_ptr + c_method = c_opaque_ptr From noreply at buildbot.pypy.org Wed Apr 24 09:45:16 2013 From: noreply at buildbot.pypy.org (bivab) Date: Wed, 24 Apr 2013 09:45:16 +0200 (CEST) Subject: [pypy-commit] pypy default: remove checking for IA-64 macros Message-ID: <20130424074516.2DC281C1006@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63585:d6e7467fc011 Date: 2013-04-24 09:44 +0200 http://bitbucket.org/pypy/pypy/changeset/d6e7467fc011/ Log: remove checking for IA-64 macros diff --git a/rpython/jit/backend/detect_cpu.py b/rpython/jit/backend/detect_cpu.py --- a/rpython/jit/backend/detect_cpu.py +++ b/rpython/jit/backend/detect_cpu.py @@ -15,7 +15,6 @@ mapping = { ('x86', '64'): [ '__amd64__', '__amd64', '__x86_64__', '__x86_64', # AMD64 - '__ia64__', '_IA64', '__IA64__' # Intel Itanium (IA-64) ], ('arm', '32'): ['__arm__', '__thumb__'], ('x86', '32'): ['i386', '__i386', '__i386__', '__i686__',], From noreply at buildbot.pypy.org Wed Apr 24 10:46:04 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 24 Apr 2013 10:46:04 +0200 (CEST) Subject: [pypy-commit] pypy kill-gen-store-back-in: merge default Message-ID: <20130424084604.A3B3C1C02DA@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: kill-gen-store-back-in Changeset: r63586:9cb706dbf6a0 Date: 2013-04-23 16:06 +0200 http://bitbucket.org/pypy/pypy/changeset/9cb706dbf6a0/ Log: merge default diff too long, truncating to 2000 out of 22923 lines diff --git a/.hgignore b/.hgignore --- a/.hgignore +++ b/.hgignore @@ -70,6 +70,7 @@ ^rpython/translator/cli/src/pypylib\.dll$ ^rpython/translator/cli/src/query\.exe$ ^rpython/translator/cli/src/main\.exe$ +^lib_pypy/__pycache__$ ^lib_pypy/ctypes_config_cache/_.+_cache\.py$ ^lib_pypy/ctypes_config_cache/_.+_.+_\.py$ ^rpython/translator/cli/query-descriptions$ diff --git a/Makefile b/Makefile new file mode 100644 --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ + +all: pypy-c + +pypy-c: + @echo "Building PyPy with JIT, it'll take about 40 minutes and 4G of RAM" + @sleep 3 + rpython/bin/rpython -Ojit pypy/goal/targetpypystandalone.py diff --git a/README.rst b/README.rst --- a/README.rst +++ b/README.rst @@ -13,12 +13,25 @@ http://pypy.org/ -The getting-started document will help guide you: +If you want to help developing PyPy, this document might help you: - http://doc.pypy.org/en/latest/getting-started.html + http://doc.pypy.org/ It will also point you to the rest of the documentation which is generated from files in the pypy/doc directory within the source repositories. Enjoy and send us feedback! the pypy-dev team + +Building +======== + +build with:: + + rpython/bin/rpython -Ojit pypy/goal/targetpypystandalone.py + +This ends up with ``pypy-c`` binary in the main pypy directory. We suggest +to use virtualenv with the resulting pypy-c as the interpreter, you can +find more details about various installation schemes here: + +http://doc.pypy.org/en/latest/getting-started.html#installing-pypy diff --git a/lib-python/2.7/json/decoder.py b/lib-python/2.7/json/decoder.py --- a/lib-python/2.7/json/decoder.py +++ b/lib-python/2.7/json/decoder.py @@ -162,7 +162,7 @@ if nextchar == '}': if object_pairs_hook is not None: result = object_pairs_hook(pairs) - return result, end + return result, end + 1 pairs = {} if object_hook is not None: pairs = object_hook(pairs) diff --git a/lib-python/2.7/json/tests/test_decode.py b/lib-python/2.7/json/tests/test_decode.py --- a/lib-python/2.7/json/tests/test_decode.py +++ b/lib-python/2.7/json/tests/test_decode.py @@ -44,6 +44,7 @@ object_pairs_hook=OrderedDict, object_hook=lambda x: None), OrderedDict(p)) + self.assertEqual(self.loads("{}", object_pairs_hook=list), []) class TestPyDecode(TestDecode, PyTest): pass diff --git a/lib-python/2.7/test/test_descr.py b/lib-python/2.7/test/test_descr.py --- a/lib-python/2.7/test/test_descr.py +++ b/lib-python/2.7/test/test_descr.py @@ -3592,6 +3592,9 @@ list.__init__(a, sequence=[0, 1, 2]) self.assertEqual(a, [0, 1, 2]) + @unittest.skipIf(test_support.check_impl_detail(pypy=True) and + sys.platform == 'win32', + "XXX: https://bugs.pypy.org/issue1461") def test_recursive_call(self): # Testing recursive __call__() by setting to instance of class... class A(object): diff --git a/lib-python/conftest.py b/lib-python/conftest.py --- a/lib-python/conftest.py +++ b/lib-python/conftest.py @@ -1,91 +1,89 @@ """ test configuration(s) for running CPython's regression -test suite on top of PyPy +test suite on top of PyPy """ import py import sys import pypy import re -from pypy.interpreter.gateway import ApplevelClass +from pypy.interpreter.gateway import ApplevelClass from pypy.interpreter.error import OperationError -from pypy.interpreter.module import Module as PyPyModule +from pypy.interpreter.module import Module as PyPyModule from pypy.interpreter.main import run_string, run_file -# the following adds command line options as a side effect! -from pypy.conftest import option as pypy_option +# the following adds command line options as a side effect! +from pypy.conftest import option as pypy_option -from pypy.tool.pytest import appsupport +from pypy.tool.pytest import appsupport from pypy.tool.pytest.confpath import pypydir, rpythondir, testdir, testresultdir from rpython.config.parse import parse_info pytest_plugins = "resultlog", rsyncdirs = ['.', '../pypy/'] -# -# Interfacing/Integrating with py.test's collection process +# +# Interfacing/Integrating with py.test's collection process # def pytest_addoption(parser): - group = parser.getgroup("complicance testing options") - group.addoption('-T', '--timeout', action="store", type="string", - default="1000", dest="timeout", - help="fail a test module after the given timeout. " - "specify in seconds or 'NUMmp' aka Mega-Pystones") - group.addoption('--pypy', action="store", type="string", - dest="pypy", help="use given pypy executable to run lib-python tests. " - "This will run the tests directly (i.e. not through py.py)") + group = parser.getgroup("complicance testing options") + group.addoption('-T', '--timeout', action="store", type="string", + default="1000", dest="timeout", + help="fail a test module after the given timeout. " + "specify in seconds or 'NUMmp' aka Mega-Pystones") + group.addoption('--pypy', action="store", type="string", dest="pypy", + help="use given pypy executable to run lib-python tests. " + "This will run the tests directly (i.e. not through py.py)") group.addoption('--filter', action="store", type="string", default=None, - dest="unittest_filter", help="Similar to -k, XXX") + dest="unittest_filter", help="Similar to -k, XXX") -def gettimeout(timeout): +def gettimeout(timeout): from rpython.translator.test import rpystone - if timeout.endswith('mp'): + if timeout.endswith('mp'): megapystone = float(timeout[:-2]) t, stone = pystone.Proc0(10000) - pystonetime = t/stone - seconds = megapystone * 1000000 * pystonetime - return seconds - return float(timeout) + pystonetime = t/stone + seconds = megapystone * 1000000 * pystonetime + return seconds + return float(timeout) # ________________________________________________________________________ # -# classification of all tests files (this is ongoing work) +# classification of all tests files (this is ongoing work) # -class RegrTest: - """ Regression Test Declaration.""" - def __init__(self, basename, core=False, - compiler=None, - usemodules = '', - skip=None): - self.basename = basename +class RegrTest: + """ Regression Test Declaration.""" + def __init__(self, basename, core=False, compiler=None, usemodules='', + skip=None): + self.basename = basename self._usemodules = usemodules.split() + ['signal', 'rctime', 'itertools', '_socket'] - self._compiler = compiler + self._compiler = compiler self.core = core self.skip = skip assert self.getfspath().check(), "%r not found!" % (basename,) def usemodules(self): - return self._usemodules #+ pypy_option.usemodules + return self._usemodules # + pypy_option.usemodules usemodules = property(usemodules) - def compiler(self): - return self._compiler #or pypy_option.compiler + def compiler(self): + return self._compiler # or pypy_option.compiler compiler = property(compiler) - def ismodified(self): + def ismodified(self): #XXX: ask hg return None - def getfspath(self): + def getfspath(self): return testdir.join(self.basename) - def run_file(self, space): + def run_file(self, space): fspath = self.getfspath() assert fspath.check() - modname = fspath.purebasename + modname = fspath.purebasename space.appexec([], '''(): from test import %(modname)s m = %(modname)s @@ -424,7 +422,7 @@ RegrTest('test_textwrap.py'), RegrTest('test_thread.py', usemodules="thread", core=True), RegrTest('test_threaded_import.py', usemodules="thread", core=True), - RegrTest('test_threadedtempfile.py', + RegrTest('test_threadedtempfile.py', usemodules="thread", core=False), RegrTest('test_threading.py', usemodules="thread", core=True), RegrTest('test_threading_local.py', usemodules="thread", core=True), @@ -504,7 +502,7 @@ def pytest_configure(config): config._basename2spec = cache = {} - for x in testmap: + for x in testmap: cache[x.basename] = x def pytest_collect_file(path, parent, __multicall__): @@ -520,33 +518,33 @@ return RunFileExternal(path.basename, parent=parent, regrtest=regrtest) class RunFileExternal(py.test.collect.File): - def __init__(self, name, parent, regrtest): - super(RunFileExternal, self).__init__(name, parent) - self.regrtest = regrtest + def __init__(self, name, parent, regrtest): + super(RunFileExternal, self).__init__(name, parent) + self.regrtest = regrtest self.fspath = regrtest.getfspath() - def collect(self): - if self.regrtest.ismodified(): + def collect(self): + if self.regrtest.ismodified(): name = 'modified' else: name = 'unmodified' - return [ReallyRunFileExternal(name, parent=self)] + return [ReallyRunFileExternal(name, parent=self)] # -# testmethod: +# testmethod: # invoking in a separate process: py.py TESTFILE # import os import time import getpass -class ReallyRunFileExternal(py.test.collect.Item): +class ReallyRunFileExternal(py.test.collect.Item): class ExternalFailure(Exception): """Failure in running subprocess""" - def getinvocation(self, regrtest): - fspath = regrtest.getfspath() - python = sys.executable + def getinvocation(self, regrtest): + fspath = regrtest.getfspath() + python = sys.executable pypy_script = pypydir.join('bin', 'pyinteractive.py') alarm_script = pypydir.join('tool', 'alarm.py') if sys.platform == 'win32': @@ -555,9 +553,9 @@ watchdog_name = 'watchdog.py' watchdog_script = rpythondir.join('tool', watchdog_name) - regr_script = pypydir.join('tool', 'pytest', + regr_script = pypydir.join('tool', 'pytest', 'run-script', 'regrverbose.py') - + regrrun = str(regr_script) option = self.config.option TIMEOUT = gettimeout(option.timeout.lower()) @@ -566,8 +564,7 @@ if not execpath.check(): execpath = py.path.local.sysfind(option.pypy) if not execpath: - raise LookupError("could not find executable %r" % - (option.pypy,)) + raise LookupError("could not find executable %r" % option.pypy) # check modules info = py.process.cmdexec("%s --info" % execpath) @@ -576,34 +573,29 @@ if info.get('objspace.usemodules.%s' % mod) is not True: py.test.skip("%s module not included in %s" % (mod, execpath)) - - cmd = "%s %s %s" %( - execpath, - regrrun, fspath.purebasename) + cmd = "%s %s %s" % (execpath, regrrun, fspath.purebasename) # add watchdog for timing out - cmd = "%s %s %s %s" %( - python, watchdog_script, TIMEOUT, - cmd) + cmd = "%s %s %s %s" % (python, watchdog_script, TIMEOUT, cmd) else: pypy_options = [] pypy_options.extend( ['--withmod-%s' % mod for mod in regrtest.usemodules]) - sopt = " ".join(pypy_options) - cmd = "%s %s %d %s -S %s %s %s -v" %( - python, alarm_script, TIMEOUT, - pypy_script, sopt, + sopt = " ".join(pypy_options) + cmd = "%s %s %d %s -S %s %s %s -v" % ( + python, alarm_script, TIMEOUT, + pypy_script, sopt, regrrun, fspath.purebasename) - return cmd + return cmd - def runtest(self): - """ invoke a subprocess running the test file via PyPy. - record its output into the 'result/user at host' subdirectory. - (we might want to create subdirectories for - each user, because we will probably all produce + def runtest(self): + """ invoke a subprocess running the test file via PyPy. + record its output into the 'result/user at host' subdirectory. + (we might want to create subdirectories for + each user, because we will probably all produce such result runs and they will not be the same - i am afraid. - """ + i am afraid. + """ regrtest = self.parent.regrtest if regrtest.skip: if regrtest.skip is True: @@ -611,8 +603,8 @@ else: msg = regrtest.skip py.test.skip(msg) - (skipped, exit_status, test_stdout, - test_stderr) = self.getresult(regrtest) + (skipped, exit_status, test_stdout, test_stderr) = \ + self.getresult(regrtest) if skipped: py.test.skip(test_stderr.splitlines()[-1]) if exit_status: @@ -624,13 +616,13 @@ out, err = excinfo.value.args return out + err - def getstatusouterr(self, cmd): + def getstatusouterr(self, cmd): tempdir = py.test.ensuretemp(self.fspath.basename) stdout = tempdir.join(self.fspath.basename) + '.out' stderr = tempdir.join(self.fspath.basename) + '.err' if sys.platform == 'win32': - status = os.system("%s >%s 2>%s" %(cmd, stdout, stderr)) - if status>=0: + status = os.system("%s >%s 2>%s" % (cmd, stdout, stderr)) + if status >= 0: status = status else: status = 'abnormal termination 0x%x' % status @@ -644,22 +636,22 @@ stdout.write('') stderr.write('') else: - status = os.system("%s >>%s 2>>%s" %(cmd, stdout, stderr)) + status = os.system("%s >>%s 2>>%s" % (cmd, stdout, stderr)) if os.WIFEXITED(status): status = os.WEXITSTATUS(status) else: status = 'abnormal termination 0x%x' % status return status, stdout.read(mode='rU'), stderr.read(mode='rU') - def getresult(self, regrtest): + def getresult(self, regrtest): cmd = self.getinvocation(regrtest) tempdir = py.test.ensuretemp(self.fspath.basename) oldcwd = tempdir.chdir() exit_status, test_stdout, test_stderr = self.getstatusouterr(cmd) oldcwd.chdir() skipped = False - timedout = test_stderr.rfind(26*"=" + "timedout" + 26*"=") != -1 - if not timedout: + timedout = test_stderr.rfind(26*"=" + "timedout" + 26*"=") != -1 + if not timedout: timedout = test_stderr.rfind("KeyboardInterrupt") != -1 if test_stderr.rfind(26*"=" + "skipped" + 26*"=") != -1: skipped = True @@ -669,12 +661,12 @@ # test in test_zipimport_support.py if re.search(r'\bFAIL\b', test_stdout) or re.search('[^:]ERROR', test_stderr): outcome = 'FAIL' - exit_status = 2 - elif timedout: - outcome = "T/O" - else: + exit_status = 2 + elif timedout: + outcome = "T/O" + else: outcome = "ERR" - + return skipped, exit_status, test_stdout, test_stderr def _keywords(self): @@ -683,4 +675,3 @@ if regrtest.core: lst.append('core') return lst - diff --git a/lib_pypy/_collections.py b/lib_pypy/_collections.py --- a/lib_pypy/_collections.py +++ b/lib_pypy/_collections.py @@ -8,7 +8,6 @@ # Note that PyPy also contains a built-in module '_collections' which will hide # this one if compiled in. -import operator try: from threading import _get_ident as _thread_ident except ImportError: diff --git a/lib_pypy/_ctypes/function.py b/lib_pypy/_ctypes/function.py --- a/lib_pypy/_ctypes/function.py +++ b/lib_pypy/_ctypes/function.py @@ -8,7 +8,6 @@ import _ffi import sys import traceback -import warnings try: from __pypy__ import builtinify except ImportError: builtinify = lambda f: f @@ -315,8 +314,12 @@ return if argtypes is None: - warnings.warn('C function without declared arguments called', - RuntimeWarning, stacklevel=2) + # XXX this warning was originally meaning "it's going to be + # really slow". Now we don't worry that much about slowness + # of ctypes, and it's strange to get warnings for perfectly- + # legal code. + #warnings.warn('C function without declared arguments called', + # RuntimeWarning, stacklevel=2) argtypes = [] if self._com_index: @@ -342,6 +345,7 @@ if not outargs: return result + from ctypes import c_void_p simple_cdata = type(c_void_p()).__bases__[0] outargs = [x.value if type(x).__bases__[0] is simple_cdata else x for x in outargs] diff --git a/lib_pypy/_curses.py b/lib_pypy/_curses.py --- a/lib_pypy/_curses.py +++ b/lib_pypy/_curses.py @@ -359,9 +359,14 @@ if not lib._m_NetBSD: for key in range(lib.KEY_MIN, lib.KEY_MAX): key_n = lib.keyname(key) - if key_n == ffi.NULL or ffi.string(key_n) == "UNKNOWN KEY": + if key_n == ffi.NULL: continue - key_n = ffi.string(key_n).replace('(', '').replace(')', '') + key_n = ffi.string(key_n) + if key_n == b"UNKNOWN KEY": + continue + if not isinstance(key_n, str): # python 3 + key_n = key_n.decode() + key_n = key_n.replace('(', '').replace(')', '') globals()[key_n] = key _setup() diff --git a/lib_pypy/_functools.py b/lib_pypy/_functools.py --- a/lib_pypy/_functools.py +++ b/lib_pypy/_functools.py @@ -20,3 +20,16 @@ if self.keywords is not None: fkeywords = dict(self.keywords, **fkeywords) return self.func(*(self.args + fargs), **fkeywords) + + def __reduce__(self): + d = dict((k, v) for k, v in self.__dict__.iteritems() if k not in + ('func', 'args', 'keywords')) + if len(d) == 0: + d = None + return (type(self), (self.func,), + (self.func, self.args, self.keywords, d)) + + def __setstate__(self, state): + self.func, self.args, self.keywords, d = state + if d is not None: + self.__dict__.update(d) diff --git a/lib_pypy/_pypy_interact.py b/lib_pypy/_pypy_interact.py --- a/lib_pypy/_pypy_interact.py +++ b/lib_pypy/_pypy_interact.py @@ -44,7 +44,7 @@ import code if mainmodule is None: import __main__ as mainmodule - console = code.InteractiveConsole(mainmodule.__dict__) + console = code.InteractiveConsole(mainmodule.__dict__, filename='') # some parts of code.py are copied here because it seems to be impossible # to start an interactive console without printing at least one line # of banner @@ -74,7 +74,6 @@ # ____________________________________________________________ if __name__ == '__main__': # for testing - import os if os.getenv('PYTHONSTARTUP'): execfile(os.getenv('PYTHONSTARTUP')) interactive_console() diff --git a/lib_pypy/_sha512.py b/lib_pypy/_sha512.py --- a/lib_pypy/_sha512.py +++ b/lib_pypy/_sha512.py @@ -30,23 +30,23 @@ def sha_transform(sha_info): W = [] - + d = sha_info['data'] for i in xrange(0,16): W.append( (d[8*i]<<56) + (d[8*i+1]<<48) + (d[8*i+2]<<40) + (d[8*i+3]<<32) + (d[8*i+4]<<24) + (d[8*i+5]<<16) + (d[8*i+6]<<8) + d[8*i+7]) - + for i in xrange(16,80): W.append( (Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]) & 0xffffffffffffffff ) - + ss = sha_info['digest'][:] - + def RND(a,b,c,d,e,f,g,h,i,ki): t0 = (h + Sigma1(e) + Ch(e, f, g) + ki + W[i]) & 0xffffffffffffffff t1 = (Sigma0(a) + Maj(a, b, c)) & 0xffffffffffffffff d = (d + t0) & 0xffffffffffffffff h = (t0 + t1) & 0xffffffffffffffff return d & 0xffffffffffffffff, h & 0xffffffffffffffff - + ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],0,0x428a2f98d728ae22) ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],1,0x7137449123ef65cd) ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],2,0xb5c0fbcfec4d3b2f) @@ -127,8 +127,7 @@ ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],77,0x597f299cfc657e2a) ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],78,0x5fcb6fab3ad6faec) ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],79,0x6c44198c4a475817) - - + dig = [] for i, x in enumerate(sha_info['digest']): dig.append( (x + ss[i]) & 0xffffffffffffffff ) @@ -167,36 +166,35 @@ if clo < sha_info['count_lo']: sha_info['count_hi'] += 1 sha_info['count_lo'] = clo - + sha_info['count_hi'] += (count >> 29) - + if sha_info['local']: i = SHA_BLOCKSIZE - sha_info['local'] if i > count: i = count - + # copy buffer for x in enumerate(buffer[buffer_idx:buffer_idx+i]): sha_info['data'][sha_info['local']+x[0]] = struct.unpack('B', x[1])[0] - + count -= i buffer_idx += i - + sha_info['local'] += i if sha_info['local'] == SHA_BLOCKSIZE: sha_transform(sha_info) sha_info['local'] = 0 else: return - + while count >= SHA_BLOCKSIZE: # copy buffer sha_info['data'] = [struct.unpack('B',c)[0] for c in buffer[buffer_idx:buffer_idx + SHA_BLOCKSIZE]] count -= SHA_BLOCKSIZE buffer_idx += SHA_BLOCKSIZE sha_transform(sha_info) - - + # copy buffer pos = sha_info['local'] sha_info['data'][pos:pos+count] = [struct.unpack('B',c)[0] for c in buffer[buffer_idx:buffer_idx + count]] @@ -216,7 +214,7 @@ sha_info['data'] = [0] * SHA_BLOCKSIZE else: sha_info['data'] = sha_info['data'][:count] + ([0] * (SHA_BLOCKSIZE - count)) - + sha_info['data'][112] = 0; sha_info['data'][113] = 0; sha_info['data'][114] = 0; @@ -225,7 +223,7 @@ sha_info['data'][117] = 0; sha_info['data'][118] = 0; sha_info['data'][119] = 0; - + sha_info['data'][120] = (hi_bit_count >> 24) & 0xff sha_info['data'][121] = (hi_bit_count >> 16) & 0xff sha_info['data'][122] = (hi_bit_count >> 8) & 0xff @@ -234,9 +232,9 @@ sha_info['data'][125] = (lo_bit_count >> 16) & 0xff sha_info['data'][126] = (lo_bit_count >> 8) & 0xff sha_info['data'][127] = (lo_bit_count >> 0) & 0xff - + sha_transform(sha_info) - + dig = [] for i in sha_info['digest']: dig.extend([ ((i>>56) & 0xff), ((i>>48) & 0xff), ((i>>40) & 0xff), ((i>>32) & 0xff), ((i>>24) & 0xff), ((i>>16) & 0xff), ((i>>8) & 0xff), (i & 0xff) ]) @@ -250,13 +248,13 @@ self._sha = sha_init() if s: sha_update(self._sha, getbuf(s)) - + def update(self, s): sha_update(self._sha, getbuf(s)) - + def digest(self): return sha_final(self._sha.copy())[:self._sha['digestsize']] - + def hexdigest(self): return ''.join(['%.2x' % ord(i) for i in self.digest()]) @@ -279,12 +277,14 @@ return new def test(): + import _sha512 + a_str = "just a test string" - + assert _sha512.sha512().hexdigest() == sha512().hexdigest() assert _sha512.sha512(a_str).hexdigest() == sha512(a_str).hexdigest() assert _sha512.sha512(a_str*7).hexdigest() == sha512(a_str*7).hexdigest() - + s = sha512(a_str) s.update(a_str) assert _sha512.sha512(a_str+a_str).hexdigest() == s.hexdigest() diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -29,7 +29,6 @@ import string import sys import weakref -import array from threading import _get_ident as _thread_get_ident try: from __pypy__ import newlist_hint @@ -219,7 +218,7 @@ const char **pzTail /* OUT: Pointer to unused portion of zSql */ ); -void sqlite3_result_blob(sqlite3_context*, const char*, int, void(*)(void*)); +void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); void sqlite3_result_double(sqlite3_context*, double); void sqlite3_result_error(sqlite3_context*, const char*, int); void sqlite3_result_error16(sqlite3_context*, const void*, int); @@ -257,7 +256,13 @@ typedef ... sqlite3; int sqlite3_enable_load_extension(sqlite3 *db, int onoff); """) - unverified_lib = unverified_ffi.dlopen('sqlite3') + libname = 'sqlite3' + if sys.platform == 'win32': + import os + _libname = os.path.join(os.path.dirname(sys.executable), libname) + if os.path.exists(_libname + '.dll'): + libname = _libname + unverified_lib = unverified_ffi.dlopen(libname) return hasattr(unverified_lib, 'sqlite3_enable_load_extension') if _has_load_extension(): @@ -760,9 +765,9 @@ if isinstance(name, unicode): name = name.encode('utf-8') ret = _lib.sqlite3_create_collation(self._db, name, - _lib.SQLITE_UTF8, - _ffi.NULL, - collation_callback) + _lib.SQLITE_UTF8, + _ffi.NULL, + collation_callback) if ret != _lib.SQLITE_OK: raise self._get_exception(ret) @@ -781,9 +786,7 @@ return _lib.SQLITE_DENY self.__func_cache[callback] = authorizer - ret = _lib.sqlite3_set_authorizer(self._db, - authorizer, - _ffi.NULL) + ret = _lib.sqlite3_set_authorizer(self._db, authorizer, _ffi.NULL) if ret != _lib.SQLITE_OK: raise self._get_exception(ret) @@ -799,15 +802,13 @@ @_ffi.callback("int(void*)") def progress_handler(userdata): try: - ret = callable() - return bool(ret) + return bool(callable()) except Exception: # abort query if error occurred return 1 self.__func_cache[callable] = progress_handler - _lib.sqlite3_progress_handler(self._db, nsteps, - progress_handler, - _ffi.NULL) + _lib.sqlite3_progress_handler(self._db, nsteps, progress_handler, + _ffi.NULL) if sys.version_info[0] >= 3: def __get_in_transaction(self): @@ -853,7 +854,7 @@ self._reset = False self.__locked = False self.__closed = False - self.__description = None + self.__lastrowid = None self.__rowcount = -1 con._check_thread() @@ -889,8 +890,8 @@ def __check_reset(self): if self._reset: raise InterfaceError( - "Cursor needed to be reset because of commit/rollback " - "and can no longer be fetched from.") + "Cursor needed to be reset because of commit/rollback " + "and can no longer be fetched from.") def __build_row_cast_map(self): if not self.__connection._detect_types: @@ -959,11 +960,7 @@ elif typ == _lib.SQLITE_BLOB: blob = _lib.sqlite3_column_blob(self.__statement._statement, i) blob_len = _lib.sqlite3_column_bytes(self.__statement._statement, i) - # make a copy of the data into an array, in order to get - # a read-write buffer in the end, and one that own the - # memory for a more predictable length of time than 'blob' - copy = array.array("c", _ffi.buffer(blob, blob_len)) - val = _BLOB_TYPE(copy) + val = _BLOB_TYPE(_ffi.buffer(blob, blob_len)[:]) row.append(val) return tuple(row) @@ -977,41 +974,55 @@ try: if not isinstance(sql, basestring): raise ValueError("operation parameter must be str or unicode") - self.__description = None + try: + del self.__description + except AttributeError: + pass self.__rowcount = -1 self.__statement = self.__connection._statement_cache.get(sql) if self.__connection._isolation_level is not None: - if self.__statement._kind == Statement._DDL: + if self.__statement._type in ("UPDATE", "DELETE", "INSERT", "REPLACE"): + if not self.__connection._in_transaction: + self.__connection._begin() + elif self.__statement._type == "OTHER": if self.__connection._in_transaction: self.__connection.commit() - elif self.__statement._kind == Statement._DML: - if not self.__connection._in_transaction: - self.__connection._begin() - - if multiple and self.__statement._kind != Statement._DML: - raise ProgrammingError("executemany is only for DML statements") + elif self.__statement._type == "SELECT": + if multiple: + raise ProgrammingError("You cannot execute SELECT " + "statements in executemany().") for params in many_params: self.__statement._set_params(params) # Actually execute the SQL statement ret = _lib.sqlite3_step(self.__statement._statement) - if ret not in (_lib.SQLITE_DONE, _lib.SQLITE_ROW): + + if ret == _lib.SQLITE_ROW: + if multiple: + raise ProgrammingError("executemany() can only execute DML statements.") + self.__build_row_cast_map() + self.__next_row = self.__fetch_one_row() + elif ret == _lib.SQLITE_DONE: + if not multiple: + self.__statement._reset() + else: self.__statement._reset() raise self.__connection._get_exception(ret) - if self.__statement._kind == Statement._DML: - self.__statement._reset() - - if ret == _lib.SQLITE_ROW: - self.__build_row_cast_map() - self.__next_row = self.__fetch_one_row() - - if self.__statement._kind == Statement._DML: + if self.__statement._type in ("UPDATE", "DELETE", "INSERT", "REPLACE"): if self.__rowcount == -1: self.__rowcount = 0 self.__rowcount += _lib.sqlite3_changes(self.__connection._db) + + if not multiple and self.__statement._type == "INSERT": + self.__lastrowid = _lib.sqlite3_last_insert_rowid(self.__connection._db) + else: + self.__lastrowid = None + + if multiple: + self.__statement._reset() finally: self.__connection._in_transaction = \ not _lib.sqlite3_get_autocommit(self.__connection._db) @@ -1079,7 +1090,6 @@ try: next_row = self.__next_row except AttributeError: - self.__statement._reset() raise StopIteration del self.__next_row @@ -1087,11 +1097,12 @@ next_row = self.row_factory(self, next_row) ret = _lib.sqlite3_step(self.__statement._statement) - if ret not in (_lib.SQLITE_DONE, _lib.SQLITE_ROW): + if ret == _lib.SQLITE_ROW: + self.__next_row = self.__fetch_one_row() + else: self.__statement._reset() - raise self.__connection._get_exception(ret) - elif ret == _lib.SQLITE_ROW: - self.__next_row = self.__fetch_one_row() + if ret != _lib.SQLITE_DONE: + raise self.__connection._get_exception(ret) return next_row if sys.version_info[0] < 3: @@ -1123,13 +1134,15 @@ rowcount = property(__get_rowcount) def __get_description(self): - if self.__description is None: + try: + return self.__description + except AttributeError: self.__description = self.__statement._get_description() - return self.__description + return self.__description description = property(__get_description) def __get_lastrowid(self): - return _lib.sqlite3_last_insert_rowid(self.__connection._db) + return self.__lastrowid lastrowid = property(__get_lastrowid) def setinputsizes(self, *args): @@ -1140,8 +1153,6 @@ class Statement(object): - _DML, _DQL, _DDL = range(3) - _statement = None def __init__(self, connection, sql): @@ -1152,13 +1163,14 @@ if not isinstance(sql, basestring): raise Warning("SQL is of wrong type. Must be string or unicode.") - first_word = self._statement_kind = sql.lstrip().split(" ")[0].upper() - if first_word in ("INSERT", "UPDATE", "DELETE", "REPLACE"): - self._kind = Statement._DML - elif first_word in ("SELECT", "PRAGMA"): - self._kind = Statement._DQL + + first_word = sql.lstrip().split(" ")[0].upper() + if first_word == "": + self._type = "INVALID" + elif first_word in ("SELECT", "INSERT", "UPDATE", "DELETE", "REPLACE"): + self._type = first_word else: - self._kind = Statement._DDL + self._type = "OTHER" if isinstance(sql, unicode): sql = sql.encode('utf-8') @@ -1171,11 +1183,12 @@ if ret == _lib.SQLITE_OK and not self._statement: # an empty statement, work around that, as it's the least trouble + self._type = "SELECT" c_sql = _ffi.new("char[]", b"select 42") ret = _lib.sqlite3_prepare_v2(self.__con._db, c_sql, -1, statement_star, next_char) self._statement = statement_star[0] - self._kind = Statement._DQL + if ret != _lib.SQLITE_OK: raise self.__con._get_exception(ret) @@ -1286,7 +1299,7 @@ raise ValueError("parameters are of unsupported type") def _get_description(self): - if self._kind == Statement._DML: + if self._type in ("INSERT", "UPDATE", "DELETE", "REPLACE"): return None desc = [] for i in xrange(_lib.sqlite3_column_count(self._statement)): @@ -1391,7 +1404,7 @@ elif typ == _lib.SQLITE_BLOB: blob = _lib.sqlite3_value_blob(params[i]) blob_len = _lib.sqlite3_value_bytes(params[i]) - val = _BLOB_TYPE(_ffi.buffer(blob, blob_len)) + val = _BLOB_TYPE(_ffi.buffer(blob, blob_len)[:]) else: raise NotImplementedError _params.append(val) diff --git a/lib_pypy/dbm.py b/lib_pypy/dbm.py --- a/lib_pypy/dbm.py +++ b/lib_pypy/dbm.py @@ -168,7 +168,7 @@ 'c': os.O_RDWR | os.O_CREAT, 'n': os.O_RDWR | os.O_CREAT | os.O_TRUNC, }[flag] - except KeyError, e: + except KeyError: raise error("arg 2 to open should be 'r', 'w', 'c', or 'n'") a_db = getattr(lib, funcs['open'])(filename, openflag, mode) diff --git a/lib_pypy/greenlet.py b/lib_pypy/greenlet.py --- a/lib_pypy/greenlet.py +++ b/lib_pypy/greenlet.py @@ -1,4 +1,4 @@ -import _continuation, sys +import _continuation __version__ = "0.4.0" diff --git a/lib_pypy/pyrepl/python_reader.py b/lib_pypy/pyrepl/python_reader.py --- a/lib_pypy/pyrepl/python_reader.py +++ b/lib_pypy/pyrepl/python_reader.py @@ -171,11 +171,11 @@ def execute(self, text): try: - # ooh, look at the hack: + # ooh, look at the hack: code = self.compile("# coding:utf8\n"+text.encode('utf-8'), - '', 'single') + '', 'single') except (OverflowError, SyntaxError, ValueError): - self.showsyntaxerror("") + self.showsyntaxerror('') else: self.runcode(code) if sys.stdout and not sys.stdout.closed: diff --git a/lib_pypy/pyrepl/simple_interact.py b/lib_pypy/pyrepl/simple_interact.py --- a/lib_pypy/pyrepl/simple_interact.py +++ b/lib_pypy/pyrepl/simple_interact.py @@ -37,13 +37,13 @@ import code if mainmodule is None: import __main__ as mainmodule - console = code.InteractiveConsole(mainmodule.__dict__) + console = code.InteractiveConsole(mainmodule.__dict__, filename='') def more_lines(unicodetext): # ooh, look at the hack: src = "#coding:utf-8\n"+unicodetext.encode('utf-8') try: - code = console.compile(src, '', 'single') + code = console.compile(src, '', 'single') except (OverflowError, SyntaxError, ValueError): return False else: diff --git a/pypy/doc/arm.rst b/pypy/doc/arm.rst --- a/pypy/doc/arm.rst +++ b/pypy/doc/arm.rst @@ -153,7 +153,7 @@ :: - pypy /rpython/bin/rpython -Ojit --platform=arm --gcrootfinder=shadowstack --jit-backend=armv7 targetpypystandalone.py + pypy /rpython/bin/rpython -Ojit --platform=arm --gcrootfinder=shadowstack --jit-backend=arm targetpypystandalone.py The gcrootfinder option is needed to work around `issue 1377`_ and the jit-backend works around `issue 1376`_ diff --git a/pypy/doc/config/translation.gcrootfinder.txt b/pypy/doc/config/translation.gcrootfinder.txt --- a/pypy/doc/config/translation.gcrootfinder.txt +++ b/pypy/doc/config/translation.gcrootfinder.txt @@ -9,7 +9,9 @@ - ``--gcrootfinder=asmgcc``: use assembler hackery to find the roots directly from the normal stack. This is a bit faster, but platform specific. It works so far with GCC or MSVC, - on i386 and x86-64. + on i386 and x86-64. It is tested only on Linux (where it is + the default) so other platforms (as well as MSVC) may need + various fixes before they can be used. You may have to force the use of the shadowstack root finder if you are running into troubles or if you insist on translating diff --git a/pypy/doc/dir-reference.rst b/pypy/doc/dir-reference.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/dir-reference.rst @@ -0,0 +1,140 @@ +PyPy directory cross-reference +------------------------------ + +Here is a fully referenced alphabetical two-level deep +directory overview of PyPy: + +================================= ============================================ +Directory explanation/links +================================= ============================================ +`pypy/bin/`_ command-line scripts, mainly + `pypy/bin/pyinteractive.py`_ + +`pypy/config/`_ handles the numerous options for building + and running PyPy + +`pypy/doc/`_ text versions of PyPy developer + documentation + +`pypy/doc/config/`_ documentation for the numerous translation + options + +`pypy/doc/discussion/`_ drafts of ideas and documentation + +``doc/*/`` other specific documentation topics or tools + +`pypy/interpreter/`_ `bytecode interpreter`_ and related objects + (frames, functions, modules,...) + +`pypy/interpreter/pyparser/`_ interpreter-level Python source parser + +`pypy/interpreter/astcompiler/`_ interpreter-level bytecode compiler, + via an AST representation + +`pypy/module/`_ contains `mixed modules`_ + implementing core modules with + both application and interpreter level code. + Not all are finished and working. Use + the ``--withmod-xxx`` + or ``--allworkingmodules`` translation + options. + +`pypy/objspace/`_ `object space`_ implementations + +`pypy/objspace/std/`_ the StdObjSpace_ implementing CPython's + objects and types + +`pypy/tool/`_ various utilities and hacks used + from various places + +`pypy/tool/algo/`_ general-purpose algorithmic and mathematic + tools + +`pypy/tool/pytest/`_ support code for our `testing methods`_ + + +`rpython/annotator/`_ `type inferencing code`_ for + `RPython`_ programs + +`rpython/config/`_ handles the numerous options for RPython + + +`rpython/flowspace/`_ the FlowObjSpace_ implementing + `abstract interpretation`_ + +`rpython/rlib/`_ a `"standard library"`_ for RPython_ + programs + +`rpython/rtyper/`_ the `RPython Typer`_ + +`rpython/rtyper/lltypesystem/`_ the `low-level type system`_ for + C-like backends + +`rpython/rtyper/ootypesystem/`_ the `object-oriented type system`_ + for OO backends + +`rpython/memory/`_ the `garbage collector`_ construction + framework + +`rpython/translator/`_ translation_ backends and support code + +`rpython/translator/backendopt/`_ general optimizations that run before a + backend generates code + +`rpython/translator/c/`_ the `GenC backend`_, producing C code + from an + RPython program (generally via the rtyper_) + +`rpython/translator/cli/`_ the `CLI backend`_ for `.NET`_ + (Microsoft CLR or Mono_) + +`pypy/goal/`_ our `main PyPy-translation scripts`_ + live here + +`rpython/translator/jvm/`_ the Java backend + +`rpython/translator/tool/`_ helper tools for translation + +`dotviewer/`_ `graph viewer`_ + +``*/test/`` many directories have a test subdirectory + containing test + modules (see `Testing in PyPy`_) + +``_cache/`` holds cache files from various purposes +================================= ============================================ + +.. _`bytecode interpreter`: interpreter.html +.. _`Testing in PyPy`: coding-guide.html#testing-in-pypy +.. _`mixed modules`: coding-guide.html#mixed-modules +.. _`modules`: coding-guide.html#modules +.. _`basil`: http://people.cs.uchicago.edu/~jriehl/BasilTalk.pdf +.. _`object space`: objspace.html +.. _FlowObjSpace: objspace.html#the-flow-object-space +.. _`transparent proxies`: objspace-proxies.html#tproxy +.. _`Differences between PyPy and CPython`: cpython_differences.html +.. _`What PyPy can do for your objects`: objspace-proxies.html +.. _`Continulets and greenlets`: stackless.html +.. _StdObjSpace: objspace.html#the-standard-object-space +.. _`abstract interpretation`: http://en.wikipedia.org/wiki/Abstract_interpretation +.. _`rpython`: coding-guide.html#rpython +.. _`type inferencing code`: translation.html#the-annotation-pass +.. _`RPython Typer`: translation.html#rpython-typer +.. _`testing methods`: coding-guide.html#testing-in-pypy +.. _`translation`: translation.html +.. _`GenC backend`: translation.html#genc +.. _`CLI backend`: cli-backend.html +.. _`py.py`: getting-started-python.html#the-py.py-interpreter +.. _`translatorshell.py`: getting-started-dev.html#try-out-the-translator +.. _JIT: jit/index.html +.. _`JIT Generation in PyPy`: jit/index.html +.. _`just-in-time compiler generator`: jit/index.html +.. _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 +.. _`main PyPy-translation scripts`: getting-started-python.html#translating-the-pypy-python-interpreter +.. _`.NET`: http://www.microsoft.com/net/ +.. _Mono: http://www.mono-project.com/ +.. _`"standard library"`: rlib.html +.. _`graph viewer`: getting-started-dev.html#try-out-the-translator diff --git a/pypy/doc/getting-started-dev.rst b/pypy/doc/getting-started-dev.rst --- a/pypy/doc/getting-started-dev.rst +++ b/pypy/doc/getting-started-dev.rst @@ -1,13 +1,58 @@ -=============================================================================== -Getting Started with the Translation Toolchain and Development Process -=============================================================================== +============================ +Getting Started with RPython +============================ .. contents:: +RPython is a subset of Python that can be statically compiled. The PyPy +interpreter is written mostly in RPython (with pieces in Python), while +the RPython compiler is written in Python. The hard to understand part +is that Python is a meta-programming language for RPython, that is, +RPython is considered from live objects **after** the imports are done. +This might require more explanation. You start writing RPython from +``entry_point``, a good starting point is +``rpython/translator/goal/targetnopstandalone.py``. This does not do all that +much, but is a start. Now if code analyzed (in this case ``entry_point``) +calls some functions, those calls will be followed. Those followed calls +have to be RPython themselves (and everything they call etc.), however not +entire module files. To show how you can use metaprogramming, we can do +a silly example (note that closures are not RPython):: + + def generator(operation): + if operation == 'add': + def f(a, b): + return a + b + else: + def f(a, b): + return a - b + return f + + add = generator('add') + sub = generator('sub') + + def entry_point(argv): + print add(sub(int(argv[1]), 3) 4) + return 0 + +In this example ``entry_point`` is RPython, ``add`` and ``sub`` are RPython, +however, ``generator`` is not. + +A good introductory level articles are available: + +* Laurence Tratt -- `Fast Enough VMs in Fast Enough Time`_. + +* `How to write interpreters in RPython`_ and `part 2`_ by Andrew Brown. + +.. _`Fast Enough VMs in Fast Enough Time`: http://tratt.net/laurie/tech_articles/articles/fast_enough_vms_in_fast_enough_time + +.. _`How to write interpreters in RPython`: http://morepypy.blogspot.com/2011/04/tutorial-writing-interpreter-with-pypy.html + +.. _`part 2`: http://morepypy.blogspot.com/2011/04/tutorial-part-2-adding-jit.html + .. _`try out the translator`: Trying out the translator -------------------------- +------------------------- The translator is a tool based on the PyPy interpreter which can translate sufficiently static RPython programs into low-level code (in particular it can @@ -28,7 +73,7 @@ >>> t = Translation(snippet.is_perfect_number, [int]) >>> t.view() - + After that, the graph viewer pops up, that lets you interactively inspect the flow graph. To move around, click on something that you want to inspect. To get help about how to use it, press 'H'. To close it again, press 'Q'. @@ -83,10 +128,10 @@ The object returned by ``compile_cli`` or ``compile_jvm`` is a wrapper around the real executable: the parameters are passed as command line arguments, and -the returned value is read from the standard output. +the returned value is read from the standard output. Once you have compiled the snippet, you can also try to launch the -executable directly from the shell. You will find the +executable directly from the shell. You will find the executable in one of the ``/tmp/usession-*`` directories:: # For CLI: diff --git a/pypy/doc/getting-started-python.rst b/pypy/doc/getting-started-python.rst --- a/pypy/doc/getting-started-python.rst +++ b/pypy/doc/getting-started-python.rst @@ -6,7 +6,7 @@ PyPy's Python interpreter is a very compliant Python -interpreter implemented in Python. When translated to C, it passes most of +interpreter implemented in RPython. When compiled, it passes most of `CPythons core language regression tests`_ and comes with many of the extension modules included in the standard library including ``ctypes``. It can run large libraries such as Django_ and Twisted_. There are some small behavioral @@ -147,6 +147,8 @@ Translating using the CLI backend +++++++++++++++++++++++++++++++++ +**Note: the CLI backend is no longer maintained** + To create a standalone .NET executable using the `CLI backend`_:: ./translate.py --backend=cli targetpypystandalone.py diff --git a/pypy/doc/how-to-contribute.rst b/pypy/doc/how-to-contribute.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/how-to-contribute.rst @@ -0,0 +1,78 @@ +How to contribute to PyPy +------------------------- + +This page describes how to contribute to the PyPy project. The first thing +to remember is that PyPy project is very different than most projects out there. +It's also different from a classic compiler project, so academic courses +about compilers often don't apply or lead in the wrong direction. + +Don't just hack +--------------- + +The first and most important rule how not to contribute to PyPy is +"just hacking". This won't work. There are two major reasons why not +-- build times are large and PyPy has very thick layer separation which +make it harder to "just hack a feature". + +Test driven development +----------------------- + +Instead, we practice a lot of test driven development. This is partly because +of very high quality requirements for compilers and partly because there is +simply no other way to get around such complex project, that will keep you sane. +There are probably people out there who are smart enough not to need it, we're +not one of those. You may consider familiarizing yourself with `pytest`_, +since this is a tool we use for tests. +This leads to the next issue: + +Layers +------ + +PyPy has layers. Those layers help us keep the respective parts separated enough +to be worked on independently and make the complexity manageable. This is, +again, just a sanity requirement for such a complex project. For example writing +a new optimization for the JIT usually does **not** involve touching a Python +interpreter at all or the JIT assembler backend or the garbage collector. +Instead it requires writing small tests in +``rpython/jit/metainterp/optimizeopt/test/test_*`` and fixing files there. +After that, you can just compile PyPy and things should just work. + +The short list of layers for further reading. For each of those layers, a good +entry point is a test subdirectory in respective directories. It usually +describes (better or worse) the interfaces between the submodules. For the +``pypy`` subdirectory, most tests are small snippets of python programs that +check for correctness (calls ``AppTestXxx``) that will call the appropriate +part of the interpreter. For the ``rpython`` directory, most tests are small +RPython interpreters that perform certain tasks. To see how they translate +to low-level graphs, run them with ``--view``. To see small interpreters +with a JIT compiler, use ``--viewloops`` option. + +* **python interpreter** - it's the part implemented in the ``pypy/`` directory. + It's implemented in RPython, which is a high level static language with + classes, garbage collection, just-in-time compiler generation and the ability + to call C. A cool part about it is that it can be run untranslated, so all + the tests are runnable without translating PyPy. + + **interpreter** contains the interpreter core + + **objspace** contains implementations of various objects exported to + the Python layer + + **module** directory contains extension modules written in RPython + +* **rpython compiler** that resides in ``rpython/annotator`` and + ``rpython/rtyper`` directories. Consult `introduction to RPython`_ for + further reading + +* **JIT generator** lives in ``rpython/jit`` directory. optimizations live + in ``rpython/jit/metainterp/optimizeopt``, the main JIT in + ``rpython/jit/metainterp`` (runtime part) and + ``rpython/jit/codewriter`` (translation-time part). Backends live in + ``rpython/jit/backend``. + +* **garbage collection** lives in ``rpython/memory`` + +The rest of directories serve specific niche goal and are unlikely a good +entry point. + +.. _`introduction to RPython`: getting-started-dev.rst diff --git a/pypy/doc/index.rst b/pypy/doc/index.rst --- a/pypy/doc/index.rst +++ b/pypy/doc/index.rst @@ -1,15 +1,40 @@ -Welcome to PyPy Development -============================================= +Welcome to PyPy +=============== -The PyPy project aims at producing a flexible and fast Python_ -implementation. The guiding idea is to translate a Python-level -description of the Python language itself to lower level languages. -Rumors have it that the secret goal is being faster-than-C which is -nonsense, isn't it? `more...`_ +The PyPy project aims to produce a flexible and fast Python_ +implementation. This page documents the development of the PyPy +project itself. If you don't know what PyPy is, consult the `PyPy +website`_. If you just want to use PyPy, consult the `download`_ page +and the `getting started with pypy`_ documents. If you want to help +develop PyPy -- keep reading! -Getting into PyPy ... -============================================= +PyPy is written in a language called `RPython`_, which is suitable for +writing dynamic language interpreters (and not much else). RPython is +a subset of Python and is itself written in Python. If you'd like to +learn more about RPython, `Starting with RPython`_ should provide a +reasonable overview. + +**If you would like to contribute to PyPy**, please read `how to +contribute`_ first. PyPy's development style is somewhat different to +that of many other software projects and it often surprises +newcomers. What is **not** necessary is an academic background from +university in writing compilers -- much of it does not apply to PyPy +any way. + +All of the documentation and source code is available under the MIT license, +unless otherwise specified. Consult `LICENSE`_ + +.. _`download`: http://pypy.org/download.html +.. _`getting started with pypy`: getting-started-python.html +.. _`RPython`: coding-guide.html#RPython +.. _`Starting with RPython`: getting-started-dev.html +.. _`how to contribute`: how-to-contribute.html +.. _`PyPy website`: http://pypy.org +.. _`LICENSE`: https://bitbucket.org/pypy/pypy/src/default/LICENSE + +Index of various topics: +======================== * `Getting started`_: how to install and run the PyPy Python interpreter @@ -25,20 +50,30 @@ * `potential project ideas`_: In case you want to get your feet wet... +* `more stuff`_: this is a collection of documentation that's there, but not + particularly organized + Documentation for the PyPy Python Interpreter -=============================================== +============================================= New features of PyPy's Python Interpreter and Translation Framework: * `Differences between PyPy and CPython`_ - * `What PyPy can do for your objects`_ - * `Continulets and greenlets`_ + * `What PyPy can do for your objects`_ - transparent proxy documentation + * `Continulets and greenlets`_ - documentation about stackless features * `JIT Generation in PyPy`_ + * `JIT hooks`_ * `Sandboxing Python code`_ + * `Garbage collection environment variables`_ -Status_ of the project. - +.. _`Differences between PyPy and CPython`: cpython_differences.html +.. _`What PyPy can do for your objects`: objspace-proxies.html +.. _`Continulets and greenlets`: stackless.html +.. _`JIT Generation in PyPy`: jit/index.html +.. _`JIT hooks`: jit-hooks.html +.. _`Sandboxing Python code`: sandbox.html +.. _`Garbage collection environment variables`: gc_info.html Mailing lists, bug tracker, IRC channel ============================================= @@ -79,354 +114,6 @@ .. _`speed.pypy.org`: http://speed.pypy.org .. _`RPython toolchain`: translation.html .. _`potential project ideas`: project-ideas.html - -Project Documentation -===================================== - -PyPy was funded by the EU for several years. See the `web site of the EU -project`_ for more details. - -.. _`web site of the EU project`: http://pypy.org - -architecture_ gives a complete view of PyPy's basic design. - -`coding guide`_ helps you to write code for PyPy (especially also describes -coding in RPython a bit). - -`sprint reports`_ lists reports written at most of our sprints, from -2003 to the present. - -`papers, talks and related projects`_ lists presentations -and related projects as well as our published papers. - -`PyPy video documentation`_ is a page linking to the videos (e.g. of talks and -introductions) that are available. - -`Technical reports`_ is a page that contains links to the -reports that we submitted to the European Union. - -`development methodology`_ describes our sprint-driven approach. - -`LICENSE`_ contains licensing details (basically a straight MIT-license). - -`Glossary`_ of PyPy words to help you align your inner self with -the PyPy universe. - - -Status -=================================== - -PyPy can be used to run Python programs on Linux, OS/X, -Windows, on top of .NET, and on top of Java. -To dig into PyPy it is recommended to try out the current -Mercurial default branch, which is always working or mostly working, -instead of the latest release, which is `2.0 beta1`__. - -.. __: release-2.0.0-beta1.html - -PyPy is mainly developed on Linux and Mac OS X. Windows is supported, -but platform-specific bugs tend to take longer before we notice and fix -them. Linux 64-bit machines are supported (though it may also take some -time before we notice and fix bugs). - -PyPy's own tests `summary`_, daily updated, run through BuildBot infrastructure. -You can also find CPython's compliance tests run with compiled ``pypy-c`` -executables there. - - -Source Code Documentation -=============================================== - -`object spaces`_ discusses the object space interface -and several implementations. - -`bytecode interpreter`_ explains the basic mechanisms -of the bytecode interpreter and virtual machine. - -`interpreter optimizations`_ describes our various strategies for -improving the performance of our interpreter, including alternative -object implementations (for strings, dictionaries and lists) in the -standard object space. - -`translation`_ is a detailed overview of our translation process. The -rtyper_ is the largest component of our translation process. - -`dynamic-language translation`_ is a paper that describes -the translation process, especially the flow object space -and the annotator in detail. (This document is one -of the `EU reports`_.) - -`low-level encapsulation`_ describes how our approach hides -away a lot of low level details. This document is also part -of the `EU reports`_. - -`translation aspects`_ describes how we weave different -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. - -`rlib`_ describes some modules that can be used when implementing programs in -RPython. - -`configuration documentation`_ describes the various configuration options that -allow you to customize PyPy. - -`CLI backend`_ describes the details of the .NET backend. - -`JIT Generation in PyPy`_ describes how we produce the Python Just-in-time Compiler -from our Python interpreter. - - - -.. _`FAQ`: faq.html -.. _Glossary: glossary.html -.. _`PyPy video documentation`: video-index.html -.. _parser: parser.html -.. _`development methodology`: dev_method.html -.. _`sprint reports`: sprint-reports.html -.. _`papers, talks and related projects`: extradoc.html -.. _`object spaces`: objspace.html -.. _`interpreter optimizations`: interpreter-optimizations.html -.. _`translation`: translation.html -.. _`dynamic-language translation`: https://bitbucket.org/pypy/extradoc/raw/tip/eu-report/D05.1_Publish_on_translating_a_very-high-level_description.pdf -.. _`low-level encapsulation`: low-level-encapsulation.html -.. _`translation aspects`: translation-aspects.html -.. _`configuration documentation`: config/ -.. _`coding guide`: coding-guide.html -.. _`architecture`: architecture.html -.. _`getting started`: getting-started.html -.. _`bytecode interpreter`: interpreter.html -.. _`EU reports`: index-report.html -.. _`Technical reports`: index-report.html -.. _`summary`: http://buildbot.pypy.org/summary -.. _`ideas for PyPy related projects`: project-ideas.html -.. _`Nightly builds and benchmarks`: http://tuatara.cs.uni-duesseldorf.de/benchmark.html -.. _`directory reference`: -.. _`rlib`: rlib.html -.. _`Sandboxing Python code`: sandbox.html -.. _`LICENSE`: https://bitbucket.org/pypy/pypy/src/default/LICENSE - -PyPy directory cross-reference ------------------------------- - -Here is a fully referenced alphabetical two-level deep -directory overview of PyPy: - -================================= ============================================ -Directory explanation/links -================================= ============================================ -`pypy/bin/`_ command-line scripts, mainly - `pypy/bin/pyinteractive.py`_ - -`pypy/config/`_ handles the numerous options for building - and running PyPy - -`pypy/doc/`_ text versions of PyPy developer - documentation - -`pypy/doc/config/`_ documentation for the numerous translation - options - -`pypy/doc/discussion/`_ drafts of ideas and documentation - -``doc/*/`` other specific documentation topics or tools - -`pypy/interpreter/`_ `bytecode interpreter`_ and related objects - (frames, functions, modules,...) - -`pypy/interpreter/pyparser/`_ interpreter-level Python source parser - -`pypy/interpreter/astcompiler/`_ interpreter-level bytecode compiler, - via an AST representation - -`pypy/module/`_ contains `mixed modules`_ - implementing core modules with - both application and interpreter level code. - Not all are finished and working. Use - the ``--withmod-xxx`` - or ``--allworkingmodules`` translation - options. - -`pypy/objspace/`_ `object space`_ implementations - -`pypy/objspace/std/`_ the StdObjSpace_ implementing CPython's - objects and types - -`pypy/tool/`_ various utilities and hacks used - from various places - -`pypy/tool/algo/`_ general-purpose algorithmic and mathematic - tools - -`pypy/tool/pytest/`_ support code for our `testing methods`_ - - -`rpython/annotator/`_ `type inferencing code`_ for - `RPython`_ programs - -`rpython/config/`_ handles the numerous options for RPython - - -`rpython/flowspace/`_ the FlowObjSpace_ implementing - `abstract interpretation`_ - -`rpython/rlib/`_ a `"standard library"`_ for RPython_ - programs - -`rpython/rtyper/`_ the `RPython Typer`_ - -`rpython/rtyper/lltypesystem/`_ the `low-level type system`_ for - C-like backends - -`rpython/rtyper/ootypesystem/`_ the `object-oriented type system`_ - for OO backends - -`rpython/memory/`_ the `garbage collector`_ construction - framework - -`rpython/translator/`_ translation_ backends and support code - -`rpython/translator/backendopt/`_ general optimizations that run before a - backend generates code - -`rpython/translator/c/`_ the `GenC backend`_, producing C code - from an - RPython program (generally via the rtyper_) - -`rpython/translator/cli/`_ the `CLI backend`_ for `.NET`_ - (Microsoft CLR or Mono_) - -`pypy/goal/`_ our `main PyPy-translation scripts`_ - live here - -`rpython/translator/jvm/`_ the Java backend - -`rpython/translator/tool/`_ helper tools for translation - -`dotviewer/`_ `graph viewer`_ - -``*/test/`` many directories have a test subdirectory - containing test - modules (see `Testing in PyPy`_) - -``_cache/`` holds cache files from various purposes -================================= ============================================ - -.. _`bytecode interpreter`: interpreter.html -.. _`Testing in PyPy`: coding-guide.html#testing-in-pypy -.. _`mixed modules`: coding-guide.html#mixed-modules -.. _`modules`: coding-guide.html#modules -.. _`basil`: http://people.cs.uchicago.edu/~jriehl/BasilTalk.pdf -.. _`object space`: objspace.html -.. _FlowObjSpace: objspace.html#the-flow-object-space -.. _`transparent proxies`: objspace-proxies.html#tproxy -.. _`Differences between PyPy and CPython`: cpython_differences.html -.. _`What PyPy can do for your objects`: objspace-proxies.html -.. _`Continulets and greenlets`: stackless.html -.. _StdObjSpace: objspace.html#the-standard-object-space -.. _`abstract interpretation`: http://en.wikipedia.org/wiki/Abstract_interpretation -.. _`rpython`: coding-guide.html#rpython -.. _`type inferencing code`: translation.html#the-annotation-pass -.. _`RPython Typer`: translation.html#rpython-typer -.. _`testing methods`: coding-guide.html#testing-in-pypy -.. _`translation`: translation.html -.. _`GenC backend`: translation.html#genc -.. _`CLI backend`: cli-backend.html -.. _`py.py`: getting-started-python.html#the-py.py-interpreter -.. _`translatorshell.py`: getting-started-dev.html#try-out-the-translator -.. _JIT: jit/index.html -.. _`JIT Generation in PyPy`: jit/index.html -.. _`just-in-time compiler generator`: jit/index.html -.. _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 -.. _`main PyPy-translation scripts`: getting-started-python.html#translating-the-pypy-python-interpreter -.. _`.NET`: http://www.microsoft.com/net/ -.. _Mono: http://www.mono-project.com/ -.. _`"standard library"`: rlib.html -.. _`graph viewer`: getting-started-dev.html#try-out-the-translator - - -.. The following documentation is important and reasonably up-to-date: - -.. extradoc: should this be integrated one level up: dcolish? - - -.. toctree:: - :maxdepth: 1 - :hidden: - - getting-started.rst - getting-started-python.rst - getting-started-dev.rst - windows.rst - faq.rst - commandline_ref.rst - architecture.rst - coding-guide.rst - cpython_differences.rst - garbage_collection.rst - gc_info.rst - interpreter.rst - objspace.rst - __pypy__-module.rst - objspace-proxies.rst - config/index.rst - - dev_method.rst - extending.rst - - extradoc.rst - video-index.rst - - glossary.rst - - contributor.rst - - interpreter-optimizations.rst - configuration.rst - parser.rst - rlib.rst - rtyper.rst - rffi.rst - - translation.rst - jit/index.rst - jit/overview.rst - jit/pyjitpl5.rst - - index-of-release-notes.rst - - ctypes-implementation.rst - - how-to-release.rst - - index-report.rst - - stackless.rst - sandbox.rst - - discussions.rst - - cleanup.rst - - sprint-reports.rst - - eventhistory.rst - statistic/index.rst - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`search` -* :ref:`glossary` - +.. _`more stuff`: project-documentation.html .. include:: _ref.txt diff --git a/pypy/doc/needswork.txt b/pypy/doc/needswork.txt deleted file mode 100644 --- a/pypy/doc/needswork.txt +++ /dev/null @@ -1,3 +0,0 @@ -.. warning:: - - This documentation needs work (as discussed during the Gothenburg sprint in 2011) diff --git a/pypy/doc/objspace-proxies.rst b/pypy/doc/objspace-proxies.rst --- a/pypy/doc/objspace-proxies.rst +++ b/pypy/doc/objspace-proxies.rst @@ -5,7 +5,6 @@ .. contents:: - Thanks to the `Object Space`_ architecture, any feature that is based on proxying, extending, changing or otherwise controlling the behavior of all objects in a running program is easy to implement on diff --git a/pypy/doc/project-documentation.rst b/pypy/doc/project-documentation.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/project-documentation.rst @@ -0,0 +1,177 @@ + +Project Documentation +===================================== + +`architecture`_ gives a complete view of PyPy's basic design. + +`coding guide`_ helps you to write code for PyPy (especially also describes +coding in RPython a bit). + +`sprint reports`_ lists reports written at most of our sprints, from +2003 to the present. + +`papers, talks and related projects`_ lists presentations +and related projects as well as our published papers. + +`PyPy video documentation`_ is a page linking to the videos (e.g. of talks and +introductions) that are available. + +`Technical reports`_ is a page that contains links to the +reports that we submitted to the European Union. + +`development methodology`_ describes our sprint-driven approach. + +`LICENSE`_ contains licensing details (basically a straight MIT-license). + +`Glossary`_ of PyPy words to help you align your inner self with +the PyPy universe. + +Source Code Documentation +=============================================== + +`object spaces`_ discusses the object space interface +and several implementations. + +`bytecode interpreter`_ explains the basic mechanisms +of the bytecode interpreter and virtual machine. + +`interpreter optimizations`_ describes our various strategies for +improving the performance of our interpreter, including alternative +object implementations (for strings, dictionaries and lists) in the +standard object space. + +`translation`_ is a detailed overview of our translation process. The +rtyper_ is the largest component of our translation process. + +`dynamic-language translation`_ is a paper that describes +the translation process, especially the flow object space +and the annotator in detail. (This document is one +of the `EU reports`_.) + +`low-level encapsulation`_ describes how our approach hides +away a lot of low level details. This document is also part +of the `EU reports`_. + +`translation aspects`_ describes how we weave different +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. + +`rlib`_ describes some modules that can be used when implementing programs in +RPython. + +`configuration documentation`_ describes the various configuration options that +allow you to customize PyPy. + +`pypy on windows`_ + +`command line reference`_ + +`CLI backend`_ describes the details of the .NET backend. + +`JIT Generation in PyPy`_ describes how we produce the Python Just-in-time Compiler +from our Python interpreter. + +`directory cross-reference`_ + +.. _`garbage collector`: garbage_collection.html +.. _`directory cross-reference`: dir-reference.html +.. _`pypy on windows`: windows.html +.. _`command line reference`: commandline_ref.html +.. _`FAQ`: faq.html +.. _Glossary: glossary.html +.. _`PyPy video documentation`: video-index.html +.. _parser: parser.html +.. _`development methodology`: dev_method.html +.. _`sprint reports`: sprint-reports.html +.. _`papers, talks and related projects`: extradoc.html +.. _`object spaces`: objspace.html +.. _`interpreter optimizations`: interpreter-optimizations.html +.. _`translation`: translation.html +.. _`dynamic-language translation`: https://bitbucket.org/pypy/extradoc/raw/tip/eu-report/D05.1_Publish_on_translating_a_very-high-level_description.pdf +.. _`low-level encapsulation`: low-level-encapsulation.html +.. _`translation aspects`: translation-aspects.html +.. _`configuration documentation`: config/ +.. _`coding guide`: coding-guide.html +.. _`Architecture`: architecture.html +.. _`getting started`: getting-started.html +.. _`bytecode interpreter`: interpreter.html +.. _`EU reports`: index-report.html +.. _`Technical reports`: index-report.html +.. _`summary`: http://buildbot.pypy.org/summary +.. _`ideas for PyPy related projects`: project-ideas.html +.. _`Nightly builds and benchmarks`: http://tuatara.cs.uni-duesseldorf.de/benchmark.html +.. _`directory reference`: +.. _`rlib`: rlib.html +.. _`Sandboxing Python code`: sandbox.html +.. _`LICENSE`: https://bitbucket.org/pypy/pypy/src/default/LICENSE + +.. The following documentation is important and reasonably up-to-date: + +.. extradoc: should this be integrated one level up: dcolish? + +.. toctree:: + :maxdepth: 1 + :hidden: + + interpreter.rst + objspace.rst + __pypy__-module.rst + objspace-proxies.rst + config/index.rst + + dev_method.rst + extending.rst + + extradoc.rst From noreply at buildbot.pypy.org Wed Apr 24 10:46:05 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 24 Apr 2013 10:46:05 +0200 (CEST) Subject: [pypy-commit] pypy default: Refactor code a bit so there is less duplication. Use clang on darwin Message-ID: <20130424084605.DC83E1C02DA@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r63587:ffb4b149feac Date: 2013-04-24 10:45 +0200 http://bitbucket.org/pypy/pypy/changeset/ffb4b149feac/ Log: Refactor code a bit so there is less duplication. Use clang on darwin and *bsd, it seems that GCC there is incredibly buggy (and I DONT WANT TO CARE) diff --git a/rpython/translator/platform/bsd.py b/rpython/translator/platform/bsd.py new file mode 100644 --- /dev/null +++ b/rpython/translator/platform/bsd.py @@ -0,0 +1,31 @@ + +import os +from pypy.translator.platform import posix + +class BSD(posix.BasePosix): + DEFAULT_CC = 'clang' + + so_ext = 'so' + make_cmd = 'gmake' + + standalone_only = [] + shared_only = [] + + def _args_for_shared(self, args): + return ['-shared'] + args + + def _include_dirs_for_libffi(self): + return [os.path.join(os.environ.get("LOCALBASE", "/usr/local"), "include")] + + def _library_dirs_for_libffi(self): + return [os.path.join(os.environ.get("LOCALBASE", "/usr/local"), "lib")] + + def _preprocess_include_dirs(self, include_dirs): + res_incl_dirs = list(include_dirs) + res_incl_dirs.append(os.path.join(os.environ.get("LOCALBASE", "/usr/local"), "include")) + return res_incl_dirs + + def _preprocess_library_dirs(self, library_dirs): + res_lib_dirs = list(library_dirs) + res_lib_dirs.append(os.path.join(os.environ.get("LOCALBASE", "/usr/local"), "lib")) + return res_lib_dirs diff --git a/rpython/translator/platform/darwin.py b/rpython/translator/platform/darwin.py --- a/rpython/translator/platform/darwin.py +++ b/rpython/translator/platform/darwin.py @@ -9,11 +9,7 @@ shared_only = () so_ext = 'dylib' - - # NOTE: With asmgcc GCC 4.2 will fail at runtime due to subtle issues, - # possibly related to GC roots. Using LLVM-GCC or Clang will break the - # build. On Darwin asmgcc is not the default anymore, so it is fine to use - # whatever gcc we find on the system + DEFAULT_CC = 'clang' def _args_for_shared(self, args): return (list(self.shared_only) @@ -26,10 +22,6 @@ def _library_dirs_for_libffi(self): return ['/usr/lib'] - def check___thread(self): - # currently __thread is not supported by Darwin gccs - return False - def _frameworks(self, frameworks): args = [] for f in frameworks: diff --git a/rpython/translator/platform/freebsd.py b/rpython/translator/platform/freebsd.py --- a/rpython/translator/platform/freebsd.py +++ b/rpython/translator/platform/freebsd.py @@ -1,60 +1,14 @@ """Support for FreeBSD.""" import os +from rpython.translator.platform.bsd import BSD -from rpython.translator.platform import posix - -def get_env(key, default): - if key in os.environ: - return os.environ[key] - else: - return default - -def get_env_vector(key, default): - string = get_env(key, default) - # XXX: handle quotes - return string.split() - -class Freebsd(posix.BasePosix): +class Freebsd(BSD): name = "freebsd" - link_flags = ['-pthread'] + get_env_vector('LDFLAGS', '') + link_flags = ['-pthread'] + os.environ.get('LDFLAGS', '').split() cflags = ['-O3', '-pthread', '-fomit-frame-pointer' - ] + get_env_vector('CFLAGS', '') - standalone_only = [] - shared_only = [] - so_ext = 'so' - make_cmd = 'gmake' - - def __init__(self, cc=None): - if cc is None: - cc = get_env("CC", "gcc") - super(Freebsd, self).__init__(cc) - - def _args_for_shared(self, args): - return ['-shared'] + args - - def _preprocess_include_dirs(self, include_dirs): - res_incl_dirs = list(include_dirs) - res_incl_dirs.append(os.path.join(get_env("LOCALBASE", "/usr/local"), "include")) - return res_incl_dirs - - def _preprocess_library_dirs(self, library_dirs): - res_lib_dirs = list(library_dirs) - res_lib_dirs.append(os.path.join(get_env("LOCALBASE", "/usr/local"), "lib")) - return res_lib_dirs - - def _include_dirs_for_libffi(self): - return [os.path.join(get_env("LOCALBASE", "/usr/local"), "include")] - - def _library_dirs_for_libffi(self): - return [os.path.join(get_env("LOCALBASE", "/usr/local"), "lib")] + ] + os.environ.get('CFLAGS', '').split() class Freebsd_64(Freebsd): shared_only = ('-fPIC',) - -class GNUkFreebsd(Freebsd): - extra_libs = ('-lrt',) - -class GNUkFreebsd_64(Freebsd_64): - extra_libs = ('-lrt',) diff --git a/rpython/translator/platform/openbsd.py b/rpython/translator/platform/openbsd.py --- a/rpython/translator/platform/openbsd.py +++ b/rpython/translator/platform/openbsd.py @@ -2,60 +2,17 @@ import os -from rpython.translator.platform import posix +from pypy.translator.platform.bsd import BSD -def get_env(key, default): - if key in os.environ: - return os.environ[key] - else: - return default - -def get_env_vector(key, default): - string = get_env(key, default) - # XXX: handle quotes - return string.split() - -class OpenBSD(posix.BasePosix): +class OpenBSD(BSD): name = "openbsd" - link_flags = get_env_vector("LDFLAGS", '-pthread') - cflags = get_env_vector("CFLAGS", "-O3 -pthread -fomit-frame-pointer -D_BSD_SOURCE") - standalone_only = [] - shared_only = [] - so_ext = 'so' - make_cmd = 'gmake' - - def __init__(self, cc=None): - if cc is None: - cc = get_env("CC", "gcc") - super(OpenBSD, self).__init__(cc) - - def _args_for_shared(self, args): - return ['-shared'] + args - - def _preprocess_include_dirs(self, include_dirs): - res_incl_dirs = list(include_dirs) - res_incl_dirs.append(os.path.join(get_env("LOCALBASE", "/usr/local"), "include")) - return res_incl_dirs - - def _preprocess_library_dirs(self, library_dirs): - res_lib_dirs = list(library_dirs) - res_lib_dirs.append(os.path.join(get_env("LOCALBASE", "/usr/local"), "lib")) - return res_lib_dirs - - def _include_dirs_for_libffi(self): - return [os.path.join(get_env("LOCALBASE", "/usr/local"), "include")] - - def _library_dirs_for_libffi(self): - return [os.path.join(get_env("LOCALBASE", "/usr/local"), "lib")] + link_flags = os.environ.get("LDFLAGS", '-pthread').split() + cflags = os.environ.get("CFLAGS", "-O3 -pthread -fomit-frame-pointer -D_BSD_SOURCE").split() def _libs(self, libraries): libraries=set(libraries + ("intl", "iconv", "compat")) return ['-l%s' % lib for lib in libraries if lib not in ["crypt", "dl", "rt"]] - def check___thread(self): - # currently __thread is not supported by Darwin gccs - return False - class OpenBSD_64(OpenBSD): shared_only = ('-fPIC',) diff --git a/rpython/translator/platform/posix.py b/rpython/translator/platform/posix.py --- a/rpython/translator/platform/posix.py +++ b/rpython/translator/platform/posix.py @@ -13,13 +13,10 @@ relevant_environ = ('CPATH', 'LIBRARY_PATH', 'C_INCLUDE_PATH') + DEFAULT_CC = 'gcc' + def __init__(self, cc=None): - if cc is None: - try: - cc = os.environ['CC'] - except KeyError: - cc = 'gcc' - self.cc = cc + self.cc = cc or os.environ.get('CC', self.DEFAULT_CC) def _libs(self, libraries): return ['-l%s' % lib for lib in libraries] @@ -250,7 +247,7 @@ self.defs = {} self.lines = [] self.makefile_dir = py.path.local(path) - + def pathrel(self, fpath): if fpath.dirpath() == self.makefile_dir: return fpath.basename From noreply at buildbot.pypy.org Wed Apr 24 10:48:05 2013 From: noreply at buildbot.pypy.org (fijal) Date: Wed, 24 Apr 2013 10:48:05 +0200 (CEST) Subject: [pypy-commit] pypy default: fix imports Message-ID: <20130424084805.6EABE1C0014@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r63588:b7fa9f7bda86 Date: 2013-04-24 10:47 +0200 http://bitbucket.org/pypy/pypy/changeset/b7fa9f7bda86/ Log: fix imports diff --git a/rpython/translator/platform/bsd.py b/rpython/translator/platform/bsd.py --- a/rpython/translator/platform/bsd.py +++ b/rpython/translator/platform/bsd.py @@ -1,6 +1,6 @@ import os -from pypy.translator.platform import posix +from rpython.translator.platform import posix class BSD(posix.BasePosix): DEFAULT_CC = 'clang' From noreply at buildbot.pypy.org Wed Apr 24 14:29:00 2013 From: noreply at buildbot.pypy.org (timfel) Date: Wed, 24 Apr 2013 14:29:00 +0200 (CEST) Subject: [pypy-commit] pypy int-tag-untag-as-operations: fix test_random for tag operations Message-ID: <20130424122900.ACFCA1C3334@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: int-tag-untag-as-operations Changeset: r63589:9a46a1846653 Date: 2013-04-24 13:35 +0200 http://bitbucket.org/pypy/pypy/changeset/9a46a1846653/ Log: fix test_random for tag operations diff --git a/rpython/jit/backend/test/test_random.py b/rpython/jit/backend/test/test_random.py --- a/rpython/jit/backend/test/test_random.py +++ b/rpython/jit/backend/test/test_random.py @@ -303,6 +303,17 @@ def produce_into(self, builder, r): self.put(builder, [r.choice(builder.intvars)]) +class UnaryTagOperation(UnaryOperation): + untag_mask = 1 + tag_mask = sys.maxint + def produce_into(self, builder, r): + v = r.choice(builder.intvars) + if (v.value & self.tag_mask) != v.value: + v = builder.do(rop.INT_AND, [v, ConstInt(self.tag_mask)]) + if (v.value | self.untag_mask) != v.value: + v = builder.do(rop.INT_OR, [v, ConstInt(self.untag_mask)]) + self.put(builder, [v]) + class BooleanUnaryOperation(UnaryOperation): def produce_into(self, builder, r): v = builder.get_bool_var(r) @@ -502,11 +513,13 @@ for _op in [rop.INT_NEG, rop.INT_INVERT, - rop.INT_TAG, - rop.INT_UNTAG, ]: OPERATIONS.append(UnaryOperation(_op)) +for _op in [rop.INT_TAG, + rop.INT_UNTAG]: + OPERATIONS.append(UnaryTagOperation(_op)) + OPERATIONS.append(UnaryOperation(rop.INT_IS_TRUE, boolres=True)) OPERATIONS.append(UnaryOperation(rop.INT_IS_ZERO, boolres=True)) OPERATIONS.append(ConstUnaryOperation(rop.SAME_AS, boolres='sometimes')) From noreply at buildbot.pypy.org Wed Apr 24 14:29:01 2013 From: noreply at buildbot.pypy.org (timfel) Date: Wed, 24 Apr 2013 14:29:01 +0200 (CEST) Subject: [pypy-commit] pypy int-tag-untag-as-operations: fix typo Message-ID: <20130424122901.F29D81C3335@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: int-tag-untag-as-operations Changeset: r63590:c3491b1cafbc Date: 2013-04-24 13:35 +0200 http://bitbucket.org/pypy/pypy/changeset/c3491b1cafbc/ Log: fix typo diff --git a/rpython/jit/backend/x86/regalloc.py b/rpython/jit/backend/x86/regalloc.py --- a/rpython/jit/backend/x86/regalloc.py +++ b/rpython/jit/backend/x86/regalloc.py @@ -498,7 +498,7 @@ loc = self.rm.make_sure_var_in_reg(op.getarg(0)) self.rm.possibly_free_vars_for_op(op) res = self.rm.force_allocate_reg(op.result) - self.Perform(op, [loc], res) + self.perform(op, [loc], res) def consider_int_neg(self, op): res = self.rm.force_result_in_reg(op.result, op.getarg(0)) From noreply at buildbot.pypy.org Wed Apr 24 14:29:03 2013 From: noreply at buildbot.pypy.org (timfel) Date: Wed, 24 Apr 2013 14:29:03 +0200 (CEST) Subject: [pypy-commit] pypy int-tag-untag-as-operations: fix test_lloperation.py::test_canfold_opimpl_complete Message-ID: <20130424122903.32AA21C3334@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: int-tag-untag-as-operations Changeset: r63591:b3a63e7e8555 Date: 2013-04-24 14:23 +0200 http://bitbucket.org/pypy/pypy/changeset/b3a63e7e8555/ Log: fix test_lloperation.py::test_canfold_opimpl_complete diff --git a/rpython/rtyper/lltypesystem/opimpl.py b/rpython/rtyper/lltypesystem/opimpl.py --- a/rpython/rtyper/lltypesystem/opimpl.py +++ b/rpython/rtyper/lltypesystem/opimpl.py @@ -185,6 +185,15 @@ assert type(b) is bool return not b +def op_int_untag(a): + assert is_valid_int(a) + assert ((a & 1) == 1, "op_int_untag: not an odd int") + return a >> 1 + +def op_int_tag(a): + assert is_valid_int(a) + return intmask(a << 1) + 1 + def op_int_add(x, y): if not isinstance(x, (int, long, llmemory.AddressOffset)): from rpython.rtyper.lltypesystem import llgroup From noreply at buildbot.pypy.org Wed Apr 24 15:50:30 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Wed, 24 Apr 2013 15:50:30 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: initializing the interrupt key Message-ID: <20130424135030.2BEAA1C0014@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r333:4a27ad95adf4 Date: 2013-04-24 15:49 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/4a27ad95adf4/ Log: initializing the interrupt key diff --git a/spyvm/display.py b/spyvm/display.py --- a/spyvm/display.py +++ b/spyvm/display.py @@ -24,6 +24,7 @@ SDLCursor.has_display = True self.has_surface = False self.mouse_position = [0, 0] + self.interrupt_key = 15 << 8 # pushing all four meta keys, of which we support three... self.button = 0 self.key = 0 From noreply at buildbot.pypy.org Wed Apr 24 16:45:01 2013 From: noreply at buildbot.pypy.org (timfel) Date: Wed, 24 Apr 2013 16:45:01 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk rbigint: commit WIP for largeinteger plugin Message-ID: <20130424144501.921711C1007@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: rbigint Changeset: r334:ec8930f58b8b Date: 2013-04-24 16:44 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/ec8930f58b8b/ Log: commit WIP for largeinteger plugin diff --git a/spyvm/objspace.py b/spyvm/objspace.py --- a/spyvm/objspace.py +++ b/spyvm/objspace.py @@ -227,6 +227,10 @@ def wrap_char(self, c): return self.w_charactertable.fetch(self, ord(c)) + def wrap_rbigint(self, b): + bytes + w_lpi = self.w_LargePositiveInteger.as_class_get_shadow(self).new( + def wrap_bool(self, b): if b: return self.w_true @@ -298,6 +302,26 @@ return [w_array.at0(self, i) for i in range(w_array.size())] + def unwrap_rbigint(self, w_arg): + if isinstance(w_arg, model.W_SmallInteger): + arg = rbigint.fromint(space.unwrap_int(w_arg)) + elif isinstance(w_arg, model.W_LargePositiveInteger1Word): + arg = rbigint.fromint(space.unwrap_uint(w_arg)) + elif isinstance(w_arg, model.W_BytesObject): + # TODO: Check actual classes? + arg = rbigint.frombytes(w_arg.bytes, 'little', False) + if interp.space.getclass(w_arg) is not self.w_LargePositiveInteger: + arg = arg.neg() + else: + raise error.PrimitiveFailedError + return arg + + def unwrap_bool(self, w_arg): + if w_arg not in (self.w_true, self.w_false): + raise PrimitiveFailedError + else: + return w_arg is self.w_true + def get_display(self): w_display = self.objtable['w_display'] if w_display: diff --git a/spyvm/plugins/largeintegers.py b/spyvm/plugins/largeintegers.py new file mode 100644 --- /dev/null +++ b/spyvm/plugins/largeintegers.py @@ -0,0 +1,13 @@ +from rpython.rlib import rbigint + +from spyvm import model, error +from spyvm.plugins.plugin import Plugin + + +SocketPlugin = Plugin() + + + at SocketPlugin.expose_primitive(unwrap_spec=[rbigint, rbigint, bool]) +def primDigitMultiplyNegative(interp, s_frame, rcvr, arg, neg): + result = rcvr.mul(arg) + diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -8,7 +8,7 @@ PrimitiveNotYetWrittenError from spyvm import wrapper -from rpython.rlib import rarithmetic, rfloat, unroll, jit +from rpython.rlib import rarithmetic, rfloat, unroll, jit, rbigint def assert_bounds(n0, minimum, maximum): if not minimum <= n0 < maximum: @@ -134,6 +134,10 @@ args += (interp.space.unwrap_array(w_arg), ) elif spec is char: args += (unwrap_char(w_arg), ) + elif spec is rbigint: + arg += (interp.space.unwrap_rbigint(w_arg), ) + elif spec is bool: + arg += (interp.space.unwrap_bool(w_arg), ) else: raise NotImplementedError( "unknown unwrap_spec %s" % (spec, )) From noreply at buildbot.pypy.org Wed Apr 24 16:54:49 2013 From: noreply at buildbot.pypy.org (cfbolz) Date: Wed, 24 Apr 2013 16:54:49 +0200 (CEST) Subject: [pypy-commit] pypy int-tag-untag-as-operations: transplant 3eb981d2713e from type-specialized-instances Message-ID: <20130424145449.DAC491C1007@cobra.cs.uni-duesseldorf.de> Author: Carl Friedrich Bolz Branch: int-tag-untag-as-operations Changeset: r63592:5af87d057647 Date: 2013-04-24 16:36 +0200 http://bitbucket.org/pypy/pypy/changeset/5af87d057647/ Log: transplant 3eb981d2713e from type-specialized-instances diff --git a/rpython/jit/metainterp/optimizeopt/intbounds.py b/rpython/jit/metainterp/optimizeopt/intbounds.py --- a/rpython/jit/metainterp/optimizeopt/intbounds.py +++ b/rpython/jit/metainterp/optimizeopt/intbounds.py @@ -195,6 +195,7 @@ maxbounds = IntBound((-sys.maxint-1) >> 1, sys.maxint >> 1) v1.intbound.intersect(maxbounds) self.pure(rop.INT_UNTAG, [result], args[0]) + self.pure(rop.INT_TAG, args[:], result) self.emit_operation(op) def optimize_GUARD_OVERFLOW(self, op): diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py --- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py @@ -5540,6 +5540,28 @@ """ self.optimize_loop(ops, expected, preamble) + def test_int_tag_ovf_not_repeated(self): + ops = """ + [i0] + i1 = int_tag_ovf(i0) + guard_no_overflow() [] + i2 = int_tag_ovf(i0) + guard_no_overflow() [] + i5 = int_add(i2, 1) + escape(i5) + jump(i5) + """ + expected = """ + [i0] + i1 = int_tag_ovf(i0) + guard_no_overflow() [] + i5 = int_add(i1, 1) + escape(i5) + jump(i5) + """ + self.optimize_loop(ops, expected) + + def test_mul_ovf(self): ops = """ [i0, i1] From noreply at buildbot.pypy.org Wed Apr 24 16:54:51 2013 From: noreply at buildbot.pypy.org (cfbolz) Date: Wed, 24 Apr 2013 16:54:51 +0200 (CEST) Subject: [pypy-commit] pypy int-tag-untag-as-operations: fix test_rerased in test_ajit Message-ID: <20130424145451.179361C1007@cobra.cs.uni-duesseldorf.de> Author: Carl Friedrich Bolz Branch: int-tag-untag-as-operations Changeset: r63593:033e8618fef1 Date: 2013-04-24 16:54 +0200 http://bitbucket.org/pypy/pypy/changeset/033e8618fef1/ Log: fix test_rerased in test_ajit diff --git a/rpython/jit/backend/llgraph/runner.py b/rpython/jit/backend/llgraph/runner.py --- a/rpython/jit/backend/llgraph/runner.py +++ b/rpython/jit/backend/llgraph/runner.py @@ -802,7 +802,19 @@ else: ovf = False self.overflow_flag = ovf - return z + return z + + def execute_int_tag_ovf(self, _, x): + try: + z = ovfcheck(x << 1) + except OverflowError: + ovf = True + z = 0 + else: + ovf = False + z += 1 + self.overflow_flag = ovf + return z def execute_guard_no_overflow(self, descr): if self.overflow_flag: From noreply at buildbot.pypy.org Wed Apr 24 17:18:27 2013 From: noreply at buildbot.pypy.org (cfbolz) Date: Wed, 24 Apr 2013 17:18:27 +0200 (CEST) Subject: [pypy-commit] pypy int-tag-untag-as-operations: treat ADC like ADD Message-ID: <20130424151827.E788D1C0014@cobra.cs.uni-duesseldorf.de> Author: Carl Friedrich Bolz Branch: int-tag-untag-as-operations Changeset: r63594:0336b725b1ad Date: 2013-04-24 17:17 +0200 http://bitbucket.org/pypy/pypy/changeset/0336b725b1ad/ Log: treat ADC like ADD diff --git a/rpython/jit/backend/x86/test/test_rx86_32_auto_encoding.py b/rpython/jit/backend/x86/test/test_rx86_32_auto_encoding.py --- a/rpython/jit/backend/x86/test/test_rx86_32_auto_encoding.py +++ b/rpython/jit/backend/x86/test/test_rx86_32_auto_encoding.py @@ -281,7 +281,7 @@ return result else: # special cases - if methname in ('ADD_ri', 'AND_ri', 'CMP_ri', 'OR_ri', + if methname in ('ADD_ri', 'ADC_ri', 'AND_ri', 'CMP_ri', 'OR_ri', 'SUB_ri', 'XOR_ri', 'SBB_ri'): if args[0] == rx86.R.eax: return [] # ADD EAX, constant: there is a special encoding From noreply at buildbot.pypy.org Wed Apr 24 18:22:06 2013 From: noreply at buildbot.pypy.org (rguillebert) Date: Wed, 24 Apr 2013 18:22:06 +0200 (CEST) Subject: [pypy-commit] pypy numpy-pickle: Implement ndarray pickling (but no unpickling yet) Message-ID: <20130424162206.7338A1C00BD@cobra.cs.uni-duesseldorf.de> Author: Romain Guillebert Branch: numpy-pickle Changeset: r63595:2a64441f3574 Date: 2013-04-24 18:21 +0200 http://bitbucket.org/pypy/pypy/changeset/2a64441f3574/ Log: Implement ndarray pickling (but no unpickling yet) diff --git a/pypy/module/micronumpy/__init__.py b/pypy/module/micronumpy/__init__.py --- a/pypy/module/micronumpy/__init__.py +++ b/pypy/module/micronumpy/__init__.py @@ -12,6 +12,7 @@ 'zeros': 'interp_numarray.zeros', 'empty': 'interp_numarray.zeros', 'ones': 'interp_numarray.ones', + '_reconstruct' : 'interp_numarray._reconstruct', 'dot': 'interp_arrayops.dot', 'fromstring': 'interp_support.fromstring', 'flatiter': 'interp_flatiter.W_FlatIterator', diff --git a/pypy/module/micronumpy/arrayimpl/concrete.py b/pypy/module/micronumpy/arrayimpl/concrete.py --- a/pypy/module/micronumpy/arrayimpl/concrete.py +++ b/pypy/module/micronumpy/arrayimpl/concrete.py @@ -55,6 +55,9 @@ def get_size(self): return self.size // self.dtype.itemtype.get_element_size() + def get_storage_size(self): + return self.size + def reshape(self, space, orig_array, new_shape): # Since we got to here, prod(new_shape) == self.size new_strides = None @@ -82,7 +85,7 @@ return SliceArray(self.start, strides, backstrides, self.get_shape(), self, orig_array) - def set_real(self, space, orig_array, w_value): + def set_real(self, space, orig_array, w_value): tmp = self.get_real(orig_array) tmp.setslice(space, convert_to_array(space, w_value)) @@ -102,7 +105,7 @@ impl.fill(self.dtype.box(0)) return impl - def set_imag(self, space, orig_array, w_value): + def set_imag(self, space, orig_array, w_value): tmp = self.get_imag(orig_array) tmp.setslice(space, convert_to_array(space, w_value)) diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py --- a/pypy/module/micronumpy/interp_numarray.py +++ b/pypy/module/micronumpy/interp_numarray.py @@ -775,6 +775,26 @@ return space.int(self.descr_getitem(space, space.wrap(0))) raise OperationError(space.w_TypeError, space.wrap("only length-1 arrays can be converted to Python scalars")) + def descr_reduce(self, space): + from rpython.rtyper.lltypesystem import rffi + from rpython.rlib.rstring import StringBuilder + + reconstruct = space.getbuiltinmodule("_numpypy").get("multiarray").get("_reconstruct") + + parameters = space.newtuple([space.gettypefor(W_NDimArray), space.newtuple([space.wrap(0)]), space.wrap("b")]) + + builder = StringBuilder() + builder.append_charpsize(self.implementation.get_storage(), self.implementation.get_storage_size()) + + state = space.newtuple([ + space.wrap(1), # version + self.descr_get_shape(space), + self.get_dtype(), + space.wrap(False), # is_fortran + space.wrap(builder.build()), + ]) + + return space.newtuple([reconstruct, parameters, state]) @unwrap_spec(offset=int) def descr_new_array(space, w_subtype, w_shape, w_dtype=None, w_buffer=None, @@ -807,6 +827,7 @@ W_NDimArray.typedef = TypeDef( "ndarray", + __module__ = "numpypy", __new__ = interp2app(descr_new_array), __len__ = interp2app(W_NDimArray.descr_len), @@ -924,6 +945,7 @@ __pypy_data__ = GetSetProperty(W_NDimArray.fget___pypy_data__, W_NDimArray.fset___pypy_data__, W_NDimArray.fdel___pypy_data__), + __reduce__ = interp2app(W_NDimArray.descr_reduce) ) @unwrap_spec(ndmin=int, copy=bool, subok=bool) @@ -1000,6 +1022,9 @@ arr.fill(one) return space.wrap(arr) +def _reconstruct(space, w_subtype, w_shape, w_dtype): + return descr_new_array(space, w_subtype, w_shape, w_dtype) + W_FlatIterator.typedef = TypeDef( 'flatiter', __iter__ = interp2app(W_FlatIterator.descr_iter), diff --git a/pypy/module/micronumpy/test/test_base.py b/pypy/module/micronumpy/test/test_base.py --- a/pypy/module/micronumpy/test/test_base.py +++ b/pypy/module/micronumpy/test/test_base.py @@ -73,8 +73,8 @@ # Coerce to floats, some of these will eventually be float16, or # whatever our smallest float type is. - assert find_unaryop_result_dtype(space, bool_dtype, promote_to_float=True) is float16_dtype - assert find_unaryop_result_dtype(space, int8_dtype, promote_to_float=True) is float16_dtype + assert find_unaryop_result_dtype(space, bool_dtype, promote_to_float=True) is float16_dtype + assert find_unaryop_result_dtype(space, int8_dtype, promote_to_float=True) is float16_dtype assert find_unaryop_result_dtype(space, uint8_dtype, promote_to_float=True) is float16_dtype assert find_unaryop_result_dtype(space, int16_dtype, promote_to_float=True) is float32_dtype assert find_unaryop_result_dtype(space, uint16_dtype, promote_to_float=True) is float32_dtype diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py --- a/pypy/module/micronumpy/test/test_numarray.py +++ b/pypy/module/micronumpy/test/test_numarray.py @@ -214,6 +214,7 @@ assert get(1, 1) == 3 class AppTestNumArray(BaseNumpyAppTest): + spaceconfig = dict(usemodules=["micronumpy", "struct", "binascii"]) def w_CustomIndexObject(self, index): class CustomIndexObject(object): def __init__(self, index): @@ -1738,6 +1739,17 @@ assert raises(TypeError, "int(array([1, 2]))") assert int(array([1.5])) == 1 + def test__reduce__(self): + from numpypy import array, dtype + from cPickle import loads, dumps + + a = array([1, 2], dtype="int64") + data = a.__reduce__() + + assert data[2][4] == '\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00' + + pickled_data = dumps(a) + assert loads(pickled_data) == a class AppTestMultiDim(BaseNumpyAppTest): def test_init(self): From noreply at buildbot.pypy.org Thu Apr 25 03:04:53 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Thu, 25 Apr 2013 03:04:53 +0200 (CEST) Subject: [pypy-commit] pypy default: utilize the scoped variants Message-ID: <20130425010453.87C431C3250@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: Changeset: r63596:6595b8139545 Date: 2013-04-24 17:57 -0700 http://bitbucket.org/pypy/pypy/changeset/6595b8139545/ Log: utilize the scoped variants diff --git a/rpython/rlib/runicode.py b/rpython/rlib/runicode.py --- a/rpython/rlib/runicode.py +++ b/rpython/rlib/runicode.py @@ -1586,8 +1586,7 @@ # XXX don't know how to test this return False - def str_decode_mbcs(s, size, errors, final=False, - errorhandler=None): + def str_decode_mbcs(s, size, errors, final=False, errorhandler=None): if size == 0: return u"", 0 @@ -1598,8 +1597,7 @@ if not final and is_dbcs_lead_byte(s[size-1]): size -= 1 - dataptr = rffi.get_nonmovingbuffer(s) - try: + with rffi.scoped_nonmovingbuffer(s) as dataptr: # first get the size of the result usize = MultiByteToWideChar(CP_ACP, 0, dataptr, size, @@ -1607,25 +1605,17 @@ if usize == 0: raise rwin32.lastWindowsError() - raw_buf, gc_buf = rffi.alloc_unicodebuffer(usize) - try: + with rffi.scoped_alloc_unicodebuffer(usize) as buf: # do the conversion if MultiByteToWideChar(CP_ACP, 0, - dataptr, size, raw_buf, usize) == 0: + dataptr, size, buf.raw, usize) == 0: raise rwin32.lastWindowsError() + return buf.str(usize), size - return (rffi.unicode_from_buffer(raw_buf, gc_buf, usize, usize), - size) - finally: - rffi.keep_unicodebuffer_alive_until_here(raw_buf, gc_buf) - finally: - rffi.free_nonmovingbuffer(s, dataptr) - - def unicode_encode_mbcs(p, size, errors, errorhandler=None): + def unicode_encode_mbcs(s, size, errors, errorhandler=None): if size == 0: return '' - dataptr = rffi.get_nonmoving_unicodebuffer(p) - try: + with rffi.scoped_nonmoving_unicodebuffer(s) as dataptr: # first get the size of the result mbcssize = WideCharToMultiByte(CP_ACP, 0, dataptr, size, None, 0, @@ -1633,19 +1623,13 @@ if mbcssize == 0: raise rwin32.lastWindowsError() - raw_buf, gc_buf = rffi.alloc_buffer(mbcssize) - try: + with rffi.scoped_alloc_buffer(mbcssize) as buf: # do the conversion if WideCharToMultiByte(CP_ACP, 0, - dataptr, size, raw_buf, mbcssize, + dataptr, size, buf.raw, mbcssize, None, None) == 0: raise rwin32.lastWindowsError() - - return rffi.str_from_buffer(raw_buf, gc_buf, mbcssize, mbcssize) - finally: - rffi.keep_buffer_alive_until_here(raw_buf, gc_buf) - finally: - rffi.free_nonmoving_unicodebuffer(p, dataptr) + return buf.str(mbcssize) # ____________________________________________________________ # Decimal Encoder From noreply at buildbot.pypy.org Thu Apr 25 03:04:54 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Thu, 25 Apr 2013 03:04:54 +0200 (CEST) Subject: [pypy-commit] pypy default: add force_ignore/replace=True (py2 behavior) toggles to the mbcs functions. for Message-ID: <20130425010454.AFC8D1C3250@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: Changeset: r63597:c70e9a0f576f Date: 2013-04-24 17:58 -0700 http://bitbucket.org/pypy/pypy/changeset/c70e9a0f576f/ Log: add force_ignore/replace=True (py2 behavior) toggles to the mbcs functions. for py3k, which will specify =False diff --git a/rpython/rlib/runicode.py b/rpython/rlib/runicode.py --- a/rpython/rlib/runicode.py +++ b/rpython/rlib/runicode.py @@ -1566,6 +1566,7 @@ from rpython.rtyper.lltypesystem import lltype, rffi from rpython.rlib import rwin32 CP_ACP = 0 + BOOLP = lltype.Ptr(lltype.Array(rwin32.BOOL, hints={'nolength': True})) MultiByteToWideChar = rffi.llexternal('MultiByteToWideChar', [rffi.UINT, rwin32.DWORD, @@ -1578,7 +1579,7 @@ [rffi.UINT, rwin32.DWORD, rffi.CWCHARP, rffi.INT, rwin32.LPCSTR, rffi.INT, - rwin32.LPCSTR, rffi.VOIDP], + rwin32.LPCSTR, BOOLP], rffi.INT, calling_conv='win') @@ -1586,12 +1587,31 @@ # XXX don't know how to test this return False - def str_decode_mbcs(s, size, errors, final=False, errorhandler=None): + def _decode_mbcs_error(s, errorhandler): + if rwin32.GetLastError() == rwin32.ERROR_NO_UNICODE_TRANSLATION: + msg = ("No mapping for the Unicode character exists in the target " + "multi-byte code page.") + errorhandler('strict', 'mbcs', msg, s, 0, 0) + else: + raise rwin32.lastWindowsError() + + def str_decode_mbcs(s, size, errors, final=False, errorhandler=None, + force_ignore=True): + if errorhandler is None: + errorhandler = default_unicode_error_decode + + if not force_ignore and errors not in ('strict', 'ignore'): + msg = "mbcs encoding does not support errors='%s'" % errors + errorhandler('strict', 'mbcs', msg, s, 0, 0) + if size == 0: return u"", 0 - if errorhandler is None: - errorhandler = default_unicode_error_decode + if force_ignore or errors == 'ignore': + flags = 0 + else: + # strict + flags = rwin32.MB_ERR_INVALID_CHARS # Skip trailing lead-byte unless 'final' is set if not final and is_dbcs_lead_byte(s[size-1]): @@ -1599,37 +1619,68 @@ with rffi.scoped_nonmovingbuffer(s) as dataptr: # first get the size of the result - usize = MultiByteToWideChar(CP_ACP, 0, + usize = MultiByteToWideChar(CP_ACP, flags, dataptr, size, lltype.nullptr(rffi.CWCHARP.TO), 0) if usize == 0: - raise rwin32.lastWindowsError() + _decode_mbcs_error(s, errorhandler) with rffi.scoped_alloc_unicodebuffer(usize) as buf: # do the conversion - if MultiByteToWideChar(CP_ACP, 0, + if MultiByteToWideChar(CP_ACP, flags, dataptr, size, buf.raw, usize) == 0: - raise rwin32.lastWindowsError() + _decode_mbcs_error(s, errorhandler) return buf.str(usize), size - def unicode_encode_mbcs(s, size, errors, errorhandler=None): + def unicode_encode_mbcs(s, size, errors, errorhandler=None, + force_replace=True): + if errorhandler is None: + errorhandler = default_unicode_error_encode + + if not force_replace and errors not in ('strict', 'replace'): + msg = "mbcs encoding does not support errors='%s'" % errors + errorhandler('strict', 'mbcs', msg, s, 0, 0) + if size == 0: return '' - with rffi.scoped_nonmoving_unicodebuffer(s) as dataptr: - # first get the size of the result - mbcssize = WideCharToMultiByte(CP_ACP, 0, - dataptr, size, None, 0, - None, None) - if mbcssize == 0: - raise rwin32.lastWindowsError() - with rffi.scoped_alloc_buffer(mbcssize) as buf: - # do the conversion - if WideCharToMultiByte(CP_ACP, 0, - dataptr, size, buf.raw, mbcssize, - None, None) == 0: + if force_replace or errors == 'replace': + flags = 0 + used_default_p = lltype.nullptr(BOOLP.TO) + else: + # strict + flags = rwin32.WC_NO_BEST_FIT_CHARS + used_default_p = lltype.malloc(BOOLP.TO, 1, flavor='raw') + used_default_p[0] = rffi.cast(rwin32.BOOL, False) + + try: + with rffi.scoped_nonmoving_unicodebuffer(s) as dataptr: + # first get the size of the result + mbcssize = WideCharToMultiByte(CP_ACP, flags, + dataptr, size, None, 0, + None, used_default_p) + if mbcssize == 0: raise rwin32.lastWindowsError() - return buf.str(mbcssize) + # If we used a default char, then we failed! + if (used_default_p and + rffi.cast(lltype.Bool, used_default_p[0])): + errorhandler('strict', 'mbcs', "invalid character", + s, 0, 0) + + with rffi.scoped_alloc_buffer(mbcssize) as buf: + # do the conversion + if WideCharToMultiByte(CP_ACP, flags, + dataptr, size, buf.raw, mbcssize, + None, used_default_p) == 0: + raise rwin32.lastWindowsError() + if (used_default_p and + rffi.cast(lltype.Bool, used_default_p[0])): + errorhandler('strict', 'mbcs', "invalid character", + s, 0, 0) + return buf.str(mbcssize) + finally: + if used_default_p: + lltype.free(used_default_p, flavor='raw') # ____________________________________________________________ # Decimal Encoder diff --git a/rpython/rlib/rwin32.py b/rpython/rlib/rwin32.py --- a/rpython/rlib/rwin32.py +++ b/rpython/rlib/rwin32.py @@ -91,6 +91,8 @@ PROCESS_VM_OPERATION PROCESS_VM_READ PROCESS_VM_WRITE CTRL_C_EVENT CTRL_BREAK_EVENT + MB_ERR_INVALID_CHARS ERROR_NO_UNICODE_TRANSLATION + WC_NO_BEST_FIT_CHARS """ from rpython.translator.platform import host_factory static_platform = host_factory() diff --git a/rpython/rlib/test/test_runicode.py b/rpython/rlib/test/test_runicode.py --- a/rpython/rlib/test/test_runicode.py +++ b/rpython/rlib/test/test_runicode.py @@ -728,6 +728,30 @@ self.checkencode(u"\N{GREEK CAPITAL LETTER PHI}", "mbcs") # a F self.checkencode(u"\N{GREEK CAPITAL LETTER PSI}", "mbcs") # a ? + def test_mbcs_decode_force_ignore(self): + if sys.platform != 'win32': + py.test.skip("mbcs encoding is win32-specific") + + # XXX: requires a locale w/ a restrictive encoding to test + from rpython.rlib.rlocale import getdefaultlocale + if getdefaultlocale()[1] != 'cp932': + py.test.skip("requires cp932 locale") + + s = '\xff\xf4\x8f\xbf\xbf' + encoder = self.getdecoder('mbcs') + assert encoder(s, len(s), 'strict') == (u'\U0010ffff', 5) + py.test.raises(UnicodeEncodeError, encoder, s, len(s), 'strict', + force_ignore=False) + + def test_mbcs_encode_force_replace(self): + if sys.platform != 'win32': + py.test.skip("mbcs encoding is win32-specific") + u = u'@test_2224_tmp-?L??\udc80' + encoder = self.getencoder('mbcs') + assert encoder(u, len(u), 'strict') == '@test_2224_tmp-?L???' + py.test.raises(UnicodeEncodeError, encoder, u, len(u), 'strict', + force_replace=False) + def test_encode_decimal(self): encoder = self.getencoder('decimal') assert encoder(u' 12, 34 ', 8, None) == ' 12, 34 ' From noreply at buildbot.pypy.org Thu Apr 25 03:04:56 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Thu, 25 Apr 2013 03:04:56 +0200 (CEST) Subject: [pypy-commit] pypy py3k: fix the decode test Message-ID: <20130425010456.2508B1C3250@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63598:a052d8710c2d Date: 2013-04-24 10:49 -0700 http://bitbucket.org/pypy/pypy/changeset/a052d8710c2d/ Log: fix the decode test diff --git a/pypy/module/_codecs/test/test_codecs.py b/pypy/module/_codecs/test/test_codecs.py --- a/pypy/module/_codecs/test/test_codecs.py +++ b/pypy/module/_codecs/test/test_codecs.py @@ -669,4 +669,4 @@ assert 'test'.encode('mbcs') == b'test' assert 'caf\xe9'.encode('mbcs') == b'caf\xe9' assert '\u040a'.encode('mbcs') == b'?' # some cyrillic letter - assert 'cafx\e9'.decode('mbcs') == b'cafx\e9' + assert b'cafx\e9'.decode('mbcs') == 'cafx\e9' From noreply at buildbot.pypy.org Thu Apr 25 03:04:57 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Thu, 25 Apr 2013 03:04:57 +0200 (CEST) Subject: [pypy-commit] pypy py3k: 2to3 Message-ID: <20130425010457.509BF1C3250@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63599:ef1505d5cddd Date: 2013-04-24 10:49 -0700 http://bitbucket.org/pypy/pypy/changeset/ef1505d5cddd/ Log: 2to3 diff --git a/pypy/module/_multiprocessing/test/test_win32.py b/pypy/module/_multiprocessing/test/test_win32.py --- a/pypy/module/_multiprocessing/test/test_win32.py +++ b/pypy/module/_multiprocessing/test/test_win32.py @@ -39,7 +39,7 @@ try: win32.ConnectNamedPipe(readhandle, win32.NULL) - except WindowsError, e: + except WindowsError as e: if e.args[0] != win32.ERROR_PIPE_CONNECTED: raise From noreply at buildbot.pypy.org Thu Apr 25 03:04:58 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Thu, 25 Apr 2013 03:04:58 +0200 (CEST) Subject: [pypy-commit] pypy py3k: merge default Message-ID: <20130425010458.B5A511C3250@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63600:49003927f2cc Date: 2013-04-24 18:03 -0700 http://bitbucket.org/pypy/pypy/changeset/49003927f2cc/ Log: merge default diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py --- a/pypy/config/pypyoption.py +++ b/pypy/config/pypyoption.py @@ -35,8 +35,8 @@ "thread", "itertools", "pyexpat", "_ssl", "cpyext", "array", "binascii", "_multiprocessing", '_warnings', "_collections", "_multibytecodec", "_ffi", - "_continuation", "_csv", "_cffi_backend", # "micronumpy", - "_posixsubprocess", + "_continuation", "_csv", "_cffi_backend", + "_posixsubprocess", # "cppyy", "micronumpy", ] )) @@ -67,6 +67,8 @@ del working_modules["_minimal_curses"] del working_modules["_posixsubprocess"] +# del working_modules["cppyy"] # not tested on win32 + # The _locale module is needed by site.py on Windows default_modules["_locale"] = None @@ -78,7 +80,7 @@ del working_modules["_minimal_curses"] del working_modules["termios"] del working_modules["_multiprocessing"] # depends on rctime - +# del working_modules["cppyy"] # depends on ctypes module_dependencies = { diff --git a/pypy/module/cppyy/capi/loadable_capi.py b/pypy/module/cppyy/capi/loadable_capi.py --- a/pypy/module/cppyy/capi/loadable_capi.py +++ b/pypy/module/cppyy/capi/loadable_capi.py @@ -11,7 +11,7 @@ C_METHOD, C_INDEX, C_INDEX_ARRAY, WLAVC_INDEX, C_METHPTRGETTER_PTR -reflection_library = 'rflxlib.so' +reflection_library = 'libcppyy_backend.so' def identify(): return 'loadable_capi' @@ -231,7 +231,7 @@ except Exception: if objectmodel.we_are_translated(): raise OperationError(space.w_ImportError, - space.wrap("missing reflection library rflxlib.so")) + space.wrap("missing reflection library %s" % reflection_library)) return False return True diff --git a/pypy/module/cppyy/test/Makefile b/pypy/module/cppyy/test/Makefile --- a/pypy/module/cppyy/test/Makefile +++ b/pypy/module/cppyy/test/Makefile @@ -3,7 +3,11 @@ std_streamsDict.so iotypesDict.so all : $(dicts) -ROOTSYS := ${ROOTSYS} +ifneq (${REFLEXHOME},) + ROOTSYS := ${REFLEXHOME} +else + ROOTSYS := ${ROOTSYS} +endif ifeq ($(ROOTSYS),) genreflex=genreflex diff --git a/pypy/tool/pypyjit.py b/pypy/tool/pypyjit.py --- a/pypy/tool/pypyjit.py +++ b/pypy/tool/pypyjit.py @@ -41,7 +41,6 @@ config.objspace.usemodules._lsprof = False # config.objspace.usemodules._ffi = True -#config.objspace.usemodules.cppyy = True config.objspace.usemodules.micronumpy = False # set_pypy_opt_level(config, level='jit') diff --git a/rpython/jit/backend/detect_cpu.py b/rpython/jit/backend/detect_cpu.py --- a/rpython/jit/backend/detect_cpu.py +++ b/rpython/jit/backend/detect_cpu.py @@ -15,7 +15,6 @@ mapping = { ('x86', '64'): [ '__amd64__', '__amd64', '__x86_64__', '__x86_64', # AMD64 - '__ia64__', '_IA64', '__IA64__' # Intel Itanium (IA-64) ], ('arm', '32'): ['__arm__', '__thumb__'], ('x86', '32'): ['i386', '__i386', '__i386__', '__i686__',], diff --git a/rpython/rlib/runicode.py b/rpython/rlib/runicode.py --- a/rpython/rlib/runicode.py +++ b/rpython/rlib/runicode.py @@ -1566,6 +1566,7 @@ from rpython.rtyper.lltypesystem import lltype, rffi from rpython.rlib import rwin32 CP_ACP = 0 + BOOLP = lltype.Ptr(lltype.Array(rwin32.BOOL, hints={'nolength': True})) MultiByteToWideChar = rffi.llexternal('MultiByteToWideChar', [rffi.UINT, rwin32.DWORD, @@ -1578,7 +1579,7 @@ [rffi.UINT, rwin32.DWORD, rffi.CWCHARP, rffi.INT, rwin32.LPCSTR, rffi.INT, - rwin32.LPCSTR, rffi.VOIDP], + rwin32.LPCSTR, BOOLP], rffi.INT, calling_conv='win') @@ -1586,66 +1587,100 @@ # XXX don't know how to test this return False - def str_decode_mbcs(s, size, errors, final=False, - errorhandler=None): + def _decode_mbcs_error(s, errorhandler): + if rwin32.GetLastError() == rwin32.ERROR_NO_UNICODE_TRANSLATION: + msg = ("No mapping for the Unicode character exists in the target " + "multi-byte code page.") + errorhandler('strict', 'mbcs', msg, s, 0, 0) + else: + raise rwin32.lastWindowsError() + + def str_decode_mbcs(s, size, errors, final=False, errorhandler=None, + force_ignore=True): + if errorhandler is None: + errorhandler = default_unicode_error_decode + + if not force_ignore and errors not in ('strict', 'ignore'): + msg = "mbcs encoding does not support errors='%s'" % errors + errorhandler('strict', 'mbcs', msg, s, 0, 0) + if size == 0: return u"", 0 - if errorhandler is None: - errorhandler = default_unicode_error_decode + if force_ignore or errors == 'ignore': + flags = 0 + else: + # strict + flags = rwin32.MB_ERR_INVALID_CHARS # Skip trailing lead-byte unless 'final' is set if not final and is_dbcs_lead_byte(s[size-1]): size -= 1 - dataptr = rffi.get_nonmovingbuffer(s) - try: + with rffi.scoped_nonmovingbuffer(s) as dataptr: # first get the size of the result - usize = MultiByteToWideChar(CP_ACP, 0, + usize = MultiByteToWideChar(CP_ACP, flags, dataptr, size, lltype.nullptr(rffi.CWCHARP.TO), 0) if usize == 0: - raise rwin32.lastWindowsError() + _decode_mbcs_error(s, errorhandler) - raw_buf, gc_buf = rffi.alloc_unicodebuffer(usize) - try: + with rffi.scoped_alloc_unicodebuffer(usize) as buf: # do the conversion - if MultiByteToWideChar(CP_ACP, 0, - dataptr, size, raw_buf, usize) == 0: - raise rwin32.lastWindowsError() + if MultiByteToWideChar(CP_ACP, flags, + dataptr, size, buf.raw, usize) == 0: + _decode_mbcs_error(s, errorhandler) + return buf.str(usize), size - return (rffi.unicode_from_buffer(raw_buf, gc_buf, usize, usize), - size) - finally: - rffi.keep_unicodebuffer_alive_until_here(raw_buf, gc_buf) - finally: - rffi.free_nonmovingbuffer(s, dataptr) + def unicode_encode_mbcs(s, size, errors, errorhandler=None, + force_replace=True): + if errorhandler is None: + errorhandler = default_unicode_error_encode - def unicode_encode_mbcs(p, size, errors, errorhandler=None): + if not force_replace and errors not in ('strict', 'replace'): + msg = "mbcs encoding does not support errors='%s'" % errors + errorhandler('strict', 'mbcs', msg, s, 0, 0) + if size == 0: return '' - dataptr = rffi.get_nonmoving_unicodebuffer(p) + + if force_replace or errors == 'replace': + flags = 0 + used_default_p = lltype.nullptr(BOOLP.TO) + else: + # strict + flags = rwin32.WC_NO_BEST_FIT_CHARS + used_default_p = lltype.malloc(BOOLP.TO, 1, flavor='raw') + used_default_p[0] = rffi.cast(rwin32.BOOL, False) + try: - # first get the size of the result - mbcssize = WideCharToMultiByte(CP_ACP, 0, - dataptr, size, None, 0, - None, None) - if mbcssize == 0: - raise rwin32.lastWindowsError() + with rffi.scoped_nonmoving_unicodebuffer(s) as dataptr: + # first get the size of the result + mbcssize = WideCharToMultiByte(CP_ACP, flags, + dataptr, size, None, 0, + None, used_default_p) + if mbcssize == 0: + raise rwin32.lastWindowsError() + # If we used a default char, then we failed! + if (used_default_p and + rffi.cast(lltype.Bool, used_default_p[0])): + errorhandler('strict', 'mbcs', "invalid character", + s, 0, 0) - raw_buf, gc_buf = rffi.alloc_buffer(mbcssize) - try: - # do the conversion - if WideCharToMultiByte(CP_ACP, 0, - dataptr, size, raw_buf, mbcssize, - None, None) == 0: - raise rwin32.lastWindowsError() - - return rffi.str_from_buffer(raw_buf, gc_buf, mbcssize, mbcssize) - finally: - rffi.keep_buffer_alive_until_here(raw_buf, gc_buf) + with rffi.scoped_alloc_buffer(mbcssize) as buf: + # do the conversion + if WideCharToMultiByte(CP_ACP, flags, + dataptr, size, buf.raw, mbcssize, + None, used_default_p) == 0: + raise rwin32.lastWindowsError() + if (used_default_p and + rffi.cast(lltype.Bool, used_default_p[0])): + errorhandler('strict', 'mbcs', "invalid character", + s, 0, 0) + return buf.str(mbcssize) finally: - rffi.free_nonmoving_unicodebuffer(p, dataptr) + if used_default_p: + lltype.free(used_default_p, flavor='raw') # ____________________________________________________________ # Decimal Encoder diff --git a/rpython/rlib/rwin32.py b/rpython/rlib/rwin32.py --- a/rpython/rlib/rwin32.py +++ b/rpython/rlib/rwin32.py @@ -91,6 +91,8 @@ PROCESS_VM_OPERATION PROCESS_VM_READ PROCESS_VM_WRITE CTRL_C_EVENT CTRL_BREAK_EVENT + MB_ERR_INVALID_CHARS ERROR_NO_UNICODE_TRANSLATION + WC_NO_BEST_FIT_CHARS """ from rpython.translator.platform import host_factory static_platform = host_factory() diff --git a/rpython/rlib/test/test_runicode.py b/rpython/rlib/test/test_runicode.py --- a/rpython/rlib/test/test_runicode.py +++ b/rpython/rlib/test/test_runicode.py @@ -728,6 +728,30 @@ self.checkencode(u"\N{GREEK CAPITAL LETTER PHI}", "mbcs") # a F self.checkencode(u"\N{GREEK CAPITAL LETTER PSI}", "mbcs") # a ? + def test_mbcs_decode_force_ignore(self): + if sys.platform != 'win32': + py.test.skip("mbcs encoding is win32-specific") + + # XXX: requires a locale w/ a restrictive encoding to test + from rpython.rlib.rlocale import getdefaultlocale + if getdefaultlocale()[1] != 'cp932': + py.test.skip("requires cp932 locale") + + s = '\xff\xf4\x8f\xbf\xbf' + encoder = self.getdecoder('mbcs') + assert encoder(s, len(s), 'strict') == (u'\U0010ffff', 5) + py.test.raises(UnicodeEncodeError, encoder, s, len(s), 'strict', + force_ignore=False) + + def test_mbcs_encode_force_replace(self): + if sys.platform != 'win32': + py.test.skip("mbcs encoding is win32-specific") + u = u'@test_2224_tmp-?L??\udc80' + encoder = self.getencoder('mbcs') + assert encoder(u, len(u), 'strict') == '@test_2224_tmp-?L???' + py.test.raises(UnicodeEncodeError, encoder, u, len(u), 'strict', + force_replace=False) + def test_encode_decimal(self): encoder = self.getencoder('decimal') assert encoder(u' 12, 34 ', 8, None) == ' 12, 34 ' diff --git a/rpython/translator/platform/bsd.py b/rpython/translator/platform/bsd.py new file mode 100644 --- /dev/null +++ b/rpython/translator/platform/bsd.py @@ -0,0 +1,31 @@ + +import os +from rpython.translator.platform import posix + +class BSD(posix.BasePosix): + DEFAULT_CC = 'clang' + + so_ext = 'so' + make_cmd = 'gmake' + + standalone_only = [] + shared_only = [] + + def _args_for_shared(self, args): + return ['-shared'] + args + + def _include_dirs_for_libffi(self): + return [os.path.join(os.environ.get("LOCALBASE", "/usr/local"), "include")] + + def _library_dirs_for_libffi(self): + return [os.path.join(os.environ.get("LOCALBASE", "/usr/local"), "lib")] + + def _preprocess_include_dirs(self, include_dirs): + res_incl_dirs = list(include_dirs) + res_incl_dirs.append(os.path.join(os.environ.get("LOCALBASE", "/usr/local"), "include")) + return res_incl_dirs + + def _preprocess_library_dirs(self, library_dirs): + res_lib_dirs = list(library_dirs) + res_lib_dirs.append(os.path.join(os.environ.get("LOCALBASE", "/usr/local"), "lib")) + return res_lib_dirs diff --git a/rpython/translator/platform/darwin.py b/rpython/translator/platform/darwin.py --- a/rpython/translator/platform/darwin.py +++ b/rpython/translator/platform/darwin.py @@ -9,11 +9,7 @@ shared_only = () so_ext = 'dylib' - - # NOTE: With asmgcc GCC 4.2 will fail at runtime due to subtle issues, - # possibly related to GC roots. Using LLVM-GCC or Clang will break the - # build. On Darwin asmgcc is not the default anymore, so it is fine to use - # whatever gcc we find on the system + DEFAULT_CC = 'clang' def _args_for_shared(self, args): return (list(self.shared_only) @@ -26,10 +22,6 @@ def _library_dirs_for_libffi(self): return ['/usr/lib'] - def check___thread(self): - # currently __thread is not supported by Darwin gccs - return False - def _frameworks(self, frameworks): args = [] for f in frameworks: diff --git a/rpython/translator/platform/freebsd.py b/rpython/translator/platform/freebsd.py --- a/rpython/translator/platform/freebsd.py +++ b/rpython/translator/platform/freebsd.py @@ -1,60 +1,14 @@ """Support for FreeBSD.""" import os +from rpython.translator.platform.bsd import BSD -from rpython.translator.platform import posix - -def get_env(key, default): - if key in os.environ: - return os.environ[key] - else: - return default - -def get_env_vector(key, default): - string = get_env(key, default) - # XXX: handle quotes - return string.split() - -class Freebsd(posix.BasePosix): +class Freebsd(BSD): name = "freebsd" - link_flags = ['-pthread'] + get_env_vector('LDFLAGS', '') + link_flags = ['-pthread'] + os.environ.get('LDFLAGS', '').split() cflags = ['-O3', '-pthread', '-fomit-frame-pointer' - ] + get_env_vector('CFLAGS', '') - standalone_only = [] - shared_only = [] - so_ext = 'so' - make_cmd = 'gmake' - - def __init__(self, cc=None): - if cc is None: - cc = get_env("CC", "gcc") - super(Freebsd, self).__init__(cc) - - def _args_for_shared(self, args): - return ['-shared'] + args - - def _preprocess_include_dirs(self, include_dirs): - res_incl_dirs = list(include_dirs) - res_incl_dirs.append(os.path.join(get_env("LOCALBASE", "/usr/local"), "include")) - return res_incl_dirs - - def _preprocess_library_dirs(self, library_dirs): - res_lib_dirs = list(library_dirs) - res_lib_dirs.append(os.path.join(get_env("LOCALBASE", "/usr/local"), "lib")) - return res_lib_dirs - - def _include_dirs_for_libffi(self): - return [os.path.join(get_env("LOCALBASE", "/usr/local"), "include")] - - def _library_dirs_for_libffi(self): - return [os.path.join(get_env("LOCALBASE", "/usr/local"), "lib")] + ] + os.environ.get('CFLAGS', '').split() class Freebsd_64(Freebsd): shared_only = ('-fPIC',) - -class GNUkFreebsd(Freebsd): - extra_libs = ('-lrt',) - -class GNUkFreebsd_64(Freebsd_64): - extra_libs = ('-lrt',) diff --git a/rpython/translator/platform/openbsd.py b/rpython/translator/platform/openbsd.py --- a/rpython/translator/platform/openbsd.py +++ b/rpython/translator/platform/openbsd.py @@ -2,60 +2,17 @@ import os -from rpython.translator.platform import posix +from pypy.translator.platform.bsd import BSD -def get_env(key, default): - if key in os.environ: - return os.environ[key] - else: - return default - -def get_env_vector(key, default): - string = get_env(key, default) - # XXX: handle quotes - return string.split() - -class OpenBSD(posix.BasePosix): +class OpenBSD(BSD): name = "openbsd" - link_flags = get_env_vector("LDFLAGS", '-pthread') - cflags = get_env_vector("CFLAGS", "-O3 -pthread -fomit-frame-pointer -D_BSD_SOURCE") - standalone_only = [] - shared_only = [] - so_ext = 'so' - make_cmd = 'gmake' - - def __init__(self, cc=None): - if cc is None: - cc = get_env("CC", "gcc") - super(OpenBSD, self).__init__(cc) - - def _args_for_shared(self, args): - return ['-shared'] + args - - def _preprocess_include_dirs(self, include_dirs): - res_incl_dirs = list(include_dirs) - res_incl_dirs.append(os.path.join(get_env("LOCALBASE", "/usr/local"), "include")) - return res_incl_dirs - - def _preprocess_library_dirs(self, library_dirs): - res_lib_dirs = list(library_dirs) - res_lib_dirs.append(os.path.join(get_env("LOCALBASE", "/usr/local"), "lib")) - return res_lib_dirs - - def _include_dirs_for_libffi(self): - return [os.path.join(get_env("LOCALBASE", "/usr/local"), "include")] - - def _library_dirs_for_libffi(self): - return [os.path.join(get_env("LOCALBASE", "/usr/local"), "lib")] + link_flags = os.environ.get("LDFLAGS", '-pthread').split() + cflags = os.environ.get("CFLAGS", "-O3 -pthread -fomit-frame-pointer -D_BSD_SOURCE").split() def _libs(self, libraries): libraries=set(libraries + ("intl", "iconv", "compat")) return ['-l%s' % lib for lib in libraries if lib not in ["crypt", "dl", "rt"]] - def check___thread(self): - # currently __thread is not supported by Darwin gccs - return False - class OpenBSD_64(OpenBSD): shared_only = ('-fPIC',) diff --git a/rpython/translator/platform/posix.py b/rpython/translator/platform/posix.py --- a/rpython/translator/platform/posix.py +++ b/rpython/translator/platform/posix.py @@ -13,13 +13,10 @@ relevant_environ = ('CPATH', 'LIBRARY_PATH', 'C_INCLUDE_PATH') + DEFAULT_CC = 'gcc' + def __init__(self, cc=None): - if cc is None: - try: - cc = os.environ['CC'] - except KeyError: - cc = 'gcc' - self.cc = cc + self.cc = cc or os.environ.get('CC', self.DEFAULT_CC) def _libs(self, libraries): return ['-l%s' % lib for lib in libraries] @@ -250,7 +247,7 @@ self.defs = {} self.lines = [] self.makefile_dir = py.path.local(path) - + def pathrel(self, fpath): if fpath.dirpath() == self.makefile_dir: return fpath.basename From noreply at buildbot.pypy.org Thu Apr 25 03:04:59 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Thu, 25 Apr 2013 03:04:59 +0200 (CEST) Subject: [pypy-commit] pypy py3k: cpython issue850997: support some basic error handling in the mbcs codec. the Message-ID: <20130425010459.F1D7D1C3250@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63601:ce157ecca710 Date: 2013-04-24 18:03 -0700 http://bitbucket.org/pypy/pypy/changeset/ce157ecca710/ Log: cpython issue850997: support some basic error handling in the mbcs codec. the encoder now supports strict/replace, decoder strict/ignore diff --git a/pypy/module/_codecs/interp_codecs.py b/pypy/module/_codecs/interp_codecs.py --- a/pypy/module/_codecs/interp_codecs.py +++ b/pypy/module/_codecs/interp_codecs.py @@ -538,8 +538,30 @@ make_decoder_wrapper(decoders) if hasattr(runicode, 'str_decode_mbcs'): - make_encoder_wrapper('mbcs_encode') - make_decoder_wrapper('mbcs_decode') + # mbcs functions are not regular, because we have to pass + # "force_ignore/replace=False" + @unwrap_spec(uni=unicode, errors='str_or_None') + def mbcs_encode(space, uni, errors="strict"): + if errors is None: + errors = 'strict' + state = space.fromcache(CodecState) + result = runicode.unicode_encode_mbcs( + uni, len(uni), errors, state.encode_error_handler, + force_replace=False) + return space.newtuple([space.wrapbytes(result), space.wrap(len(uni))]) + + @unwrap_spec(string='bufferstr', errors='str_or_None', + w_final=WrappedDefault(False)) + def mbcs_decode(space, string, errors="strict", w_final=None): + if errors is None: + errors = 'strict' + final = space.is_true(w_final) + state = space.fromcache(CodecState) + result, consumed = runicode.str_decode_mbcs( + string, len(string), errors, + final, state.decode_error_handler, + force_ignore=False) + return space.newtuple([space.wrap(result), space.wrap(consumed)]) # utf-8 functions are not regular, because we have to pass # "allow_surrogates=False" diff --git a/pypy/module/_codecs/test/test_codecs.py b/pypy/module/_codecs/test/test_codecs.py --- a/pypy/module/_codecs/test/test_codecs.py +++ b/pypy/module/_codecs/test/test_codecs.py @@ -668,5 +668,7 @@ return assert 'test'.encode('mbcs') == b'test' assert 'caf\xe9'.encode('mbcs') == b'caf\xe9' - assert '\u040a'.encode('mbcs') == b'?' # some cyrillic letter + raises(UnicodeEncodeError, '\u040a'.encode, 'mbcs') + raises(UnicodeEncodeError, + "-\u5171\u0141\u2661\u0363\uDC80".encode, 'mbcs') assert b'cafx\e9'.decode('mbcs') == 'cafx\e9' From noreply at buildbot.pypy.org Thu Apr 25 03:14:50 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Thu, 25 Apr 2013 03:14:50 +0200 (CEST) Subject: [pypy-commit] pypy default: rename Message-ID: <20130425011450.7A4731C3309@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: Changeset: r63602:84cc0f5357ed Date: 2013-04-24 18:14 -0700 http://bitbucket.org/pypy/pypy/changeset/84cc0f5357ed/ Log: rename diff --git a/rpython/rlib/test/test_runicode.py b/rpython/rlib/test/test_runicode.py --- a/rpython/rlib/test/test_runicode.py +++ b/rpython/rlib/test/test_runicode.py @@ -738,9 +738,9 @@ py.test.skip("requires cp932 locale") s = '\xff\xf4\x8f\xbf\xbf' - encoder = self.getdecoder('mbcs') - assert encoder(s, len(s), 'strict') == (u'\U0010ffff', 5) - py.test.raises(UnicodeEncodeError, encoder, s, len(s), 'strict', + decoder = self.getdecoder('mbcs') + assert decoder(s, len(s), 'strict') == (u'\U0010ffff', 5) + py.test.raises(UnicodeEncodeError, decoder, s, len(s), 'strict', force_ignore=False) def test_mbcs_encode_force_replace(self): From noreply at buildbot.pypy.org Thu Apr 25 03:56:19 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Thu, 25 Apr 2013 03:56:19 +0200 (CEST) Subject: [pypy-commit] pypy py3k: let TextIO determine the default stdio encodings (via Message-ID: <20130425015619.DC4601C0014@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63603:56b7a8c5a3ba Date: 2013-04-24 18:18 -0700 http://bitbucket.org/pypy/pypy/changeset/56b7a8c5a3ba/ Log: let TextIO determine the default stdio encodings (via locale.getpreferredencoding()). fixes windows specifying 'mbcs' which is now incompatible w/ backslashreplace diff --git a/pypy/interpreter/app_main.py b/pypy/interpreter/app_main.py --- a/pypy/interpreter/app_main.py +++ b/pypy/interpreter/app_main.py @@ -240,9 +240,7 @@ encerr = e try: - if not encoding: - encoding = sys.getfilesystemencoding() - if ':' in encoding: + if encoding and ':' in encoding: encoding, errors = encoding.split(':', 1) else: errors = None From noreply at buildbot.pypy.org Thu Apr 25 07:54:37 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Thu, 25 Apr 2013 07:54:37 +0200 (CEST) Subject: [pypy-commit] pypy py3k: bytes begets bytes Message-ID: <20130425055437.5F4401C0328@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63604:2bea06b34961 Date: 2013-04-24 22:48 -0700 http://bitbucket.org/pypy/pypy/changeset/2bea06b34961/ Log: bytes begets bytes diff --git a/pypy/module/posix/interp_posix.py b/pypy/module/posix/interp_posix.py --- a/pypy/module/posix/interp_posix.py +++ b/pypy/module/posix/interp_posix.py @@ -393,7 +393,7 @@ else: path = space.str0_w(w_path) fullpath = rposix._getfullpathname(path) - w_fullpath = space.wrap(fullpath) + w_fullpath = space.wrapbytes(fullpath) except OSError, e: raise wrap_oserror2(space, e, w_path) else: diff --git a/pypy/module/posix/test/test_posix2.py b/pypy/module/posix/test/test_posix2.py --- a/pypy/module/posix/test/test_posix2.py +++ b/pypy/module/posix/test/test_posix2.py @@ -502,6 +502,7 @@ # just see if it does anything path = sysdrv + 'hubber' assert os.sep in posix._getfullpathname(path) + assert type(posix._getfullpathname(b'C:')) is bytes def test_utime(self): os = self.posix From noreply at buildbot.pypy.org Thu Apr 25 07:54:38 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Thu, 25 Apr 2013 07:54:38 +0200 (CEST) Subject: [pypy-commit] pypy py3k: enable the py3 mbcs defaults w/ fsencode/decode too Message-ID: <20130425055438.9771D1C0848@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63605:f384e71d947f Date: 2013-04-24 22:52 -0700 http://bitbucket.org/pypy/pypy/changeset/f384e71d947f/ Log: enable the py3 mbcs defaults w/ fsencode/decode too diff --git a/pypy/interpreter/unicodehelper.py b/pypy/interpreter/unicodehelper.py --- a/pypy/interpreter/unicodehelper.py +++ b/pypy/interpreter/unicodehelper.py @@ -42,7 +42,8 @@ if _WIN32: bytes = space.bytes_w(w_string) uni = str_decode_mbcs(bytes, len(bytes), 'strict', - errorhandler=decode_error_handler(space))[0] + errorhandler=decode_error_handler(space), + force_ignore=False)[0] elif _MACOSX: bytes = space.bytes_w(w_string) uni = runicode.str_decode_utf_8( @@ -69,7 +70,8 @@ if _WIN32: uni = space.unicode_w(w_uni) bytes = unicode_encode_mbcs(uni, len(uni), 'strict', - errorhandler=encode_error_handler(space)) + errorhandler=encode_error_handler(space), + force_replace=False) elif _MACOSX: uni = space.unicode_w(w_uni) bytes = runicode.unicode_encode_utf_8( From noreply at buildbot.pypy.org Thu Apr 25 07:54:39 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Thu, 25 Apr 2013 07:54:39 +0200 (CEST) Subject: [pypy-commit] pypy py3k: fix io_encoding erroneously a bool Message-ID: <20130425055439.D7F271C0328@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63606:1edbc7eba9cb Date: 2013-04-24 22:53 -0700 http://bitbucket.org/pypy/pypy/changeset/1edbc7eba9cb/ Log: fix io_encoding erroneously a bool diff --git a/pypy/interpreter/app_main.py b/pypy/interpreter/app_main.py --- a/pypy/interpreter/app_main.py +++ b/pypy/interpreter/app_main.py @@ -476,7 +476,7 @@ import os readenv = not ignore_environment - io_encoding = readenv and os.getenv("PYTHONIOENCODING") + io_encoding = os.getenv("PYTHONIOENCODING") if readenv else None initstdio(io_encoding, unbuffered) mainmodule = type(sys)('__main__') From noreply at buildbot.pypy.org Thu Apr 25 12:11:52 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Thu, 25 Apr 2013 12:11:52 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: added print_stack method to ContextPartShadow to alleviate Smalltalk stack identification during debugging Message-ID: <20130425101152.6AE911C0848@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r336:2e86339195d1 Date: 2013-04-25 12:10 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/2e86339195d1/ Log: added print_stack method to ContextPartShadow to alleviate Smalltalk stack identification during debugging diff --git a/spyvm/model.py b/spyvm/model.py --- a/spyvm/model.py +++ b/spyvm/model.py @@ -926,7 +926,7 @@ def get_identifier_string(self): from spyvm import shadow - classname = '' + classname = ' class' if len(self.literals) > 0: w_candidate = self.literals[-1] if isinstance(w_candidate, W_PointersObject): @@ -939,6 +939,9 @@ classname = d_shadow.getname() elif isinstance(shadow, shadow.ClassShadow): classname = c_shadow.getname() + class_cutoff = len(classname) - 6 + if class_cutoff > 0: + classname = classname[0:class_cutoff] return "%s>>#%s" % (classname, self._likely_methodname) diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -586,7 +586,8 @@ raise PrimitiveFailedError # only allow combinationRules 0-41 - if interp.space.unwrap_positive_32bit_int(w_rcvr.fetch(interp.space, 3)) > 41: + combinationRule = interp.space.unwrap_positive_32bit_int(w_rcvr.fetch(interp.space, 3)) + if combinationRule > 41: raise PrimitiveFailedError space = interp.space diff --git a/spyvm/shadow.py b/spyvm/shadow.py --- a/spyvm/shadow.py +++ b/spyvm/shadow.py @@ -702,6 +702,15 @@ def instances_array(self): return self.instances_w + # ______________________________________________________________________ + # Debugging printout + + def print_stack(self): + padding = ret_str = '' + if self.s_sender() is not None: + padding, ret_str = self.s_sender().print_stack() + return padding + ' ', '%s\n%s%s' % (ret_str, padding, self.short_str(0)) + class BlockContextShadow(ContextPartShadow): _attr_ = ['_w_home', '_initialip', '_eargc'] @@ -952,6 +961,13 @@ def short_str(self, argcount): block = '[] of ' if self.is_closure_context() else '' + if argcount == 0: + return '%s%s (rcvr: %s) [pc: %d]' % ( + block, + self.w_method().get_identifier_string(), + self.w_receiver().as_repr_string(), + self.pc() + 1 + ) args = '%d' % argcount for i in range(argcount - 1, -1, -1): args += ': %s' % self.peek(i).as_repr_string() From noreply at buildbot.pypy.org Thu Apr 25 12:11:51 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Thu, 25 Apr 2013 12:11:51 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk rbigint: merge with tip Message-ID: <20130425101151.473291C0328@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: rbigint Changeset: r335:8c1cadf26ba3 Date: 2013-04-24 17:48 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/8c1cadf26ba3/ Log: merge with tip diff --git a/spyvm/display.py b/spyvm/display.py --- a/spyvm/display.py +++ b/spyvm/display.py @@ -24,6 +24,7 @@ SDLCursor.has_display = True self.has_surface = False self.mouse_position = [0, 0] + self.interrupt_key = 15 << 8 # pushing all four meta keys, of which we support three... self.button = 0 self.key = 0 diff --git a/spyvm/fieldtypes.py b/spyvm/fieldtypes.py --- a/spyvm/fieldtypes.py +++ b/spyvm/fieldtypes.py @@ -1,6 +1,7 @@ from spyvm import model, shadow from rpython.rlib import objectmodel, jit, signature +from rpython.rlib.listsort import TimSort class TypeTag(): pass @@ -10,6 +11,13 @@ flt = TypeTag() obj = TypeTag() +# may be used during debugging +# LPI, SInt, flt, obj = 'LPI', 'SInt', 'float', 'object' + +class FieldSort(TimSort): + def lt(self, a, b): + return a[0] < b[0] + maps = {} class VarSizedFieldTypes(): @@ -74,16 +82,24 @@ elif parent is None: return self.descent([change]) else: - new_fieldtype = parent.ascent([change, self.diff]) + if n0 == self.diff[0]: + diff = [change] + else: + diff = [change, self.diff] + + new_fieldtype = parent.ascent(diff) + if not objectmodel.we_are_translated(): - assert new_fieldtype.types == self.types[0:n0] + [changed_type] + self.types[n0+1:] + new_types = list(self.types) + new_types[n0] = changed_type + assert new_fieldtype.types == new_types siblings[change] = new_fieldtype return new_fieldtype def ascent(self, changes): parent = self.parent if parent is None: - sort(changes) + FieldSort(changes).sort() return self.descent(changes) else: change = self.diff @@ -96,11 +112,14 @@ return self change = changes[0] + if change[1] is obj: + return self.descent(changes[1:]) siblings = self.siblings if change in siblings: return siblings[change].descent(changes[1:]) else: new_types = list(self.types) + assert new_types[change[0]] == obj new_types[change[0]] = change[1] new_fieldtype = FieldTypes(new_types, self, change) siblings[change] = new_fieldtype @@ -137,32 +156,3 @@ return typer except AttributeError: return nilTyper - -def sort(an_array): - end = len(an_array) - 1 - sort_quick_inplace(an_array, 0, end) - - -def sort_quick_inplace(an_array, start, end): - assert start >= 0 and end < len(an_array) - - def partition(an_array, start, end): - key = an_array[start][0] - i = start - 1 - j = end + 1 - while True: - i += 1 - j -= 1 - while not an_array[j][0] <= key: - j -= 1 - while not an_array[i][0] >= key: - i += 1 - if j <= i: - return j - else: - an_array[i], an_array[j] = an_array[j], an_array[i] - - if start < end: - mid = partition(an_array, start, end) - sort_quick_inplace(an_array, start, mid) - sort_quick_inplace(an_array, mid + 1, end) diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -1352,14 +1352,14 @@ IDLE_FOR_MICROSECONDS = 230 FORCE_DISPLAY_UPDATE = 231 - at expose_primitive(IDLE_FOR_MICROSECONDS, unwrap_spec=[object, int]) + at expose_primitive(IDLE_FOR_MICROSECONDS, unwrap_spec=[object, int], no_result=True, clean_stack=False) def func(interp, s_frame, w_rcvr, time_mu_s): import time time_s = time_mu_s / 1000000.0 time.sleep(time_s) interp.interrupt_check_counter = 0 + s_frame.pop() interp.quick_check_for_interrupt(s_frame, dec=0) - return w_rcvr @expose_primitive(FORCE_DISPLAY_UPDATE, unwrap_spec=[object]) def func(interp, s_frame, w_rcvr): diff --git a/spyvm/test/test_fieldtypes.py b/spyvm/test/test_fieldtypes.py --- a/spyvm/test/test_fieldtypes.py +++ b/spyvm/test/test_fieldtypes.py @@ -2,7 +2,7 @@ from spyvm import model, fieldtypes from spyvm import objspace -from spyvm.fieldtypes import obj, SInt +from spyvm.fieldtypes import obj, SInt, LPI, flt def test_simple_changes(): a = fieldtypes.FieldTypes.of_length(3) @@ -30,4 +30,16 @@ assert len(a.siblings) == 3 assert len(a.sibling(0, SInt).siblings) == 2 assert len(a.sibling(1, SInt).siblings) == 2 - assert len(a.sibling(2, SInt).siblings) == 1 # link to [o, i, i] not created \ No newline at end of file + assert len(a.sibling(2, SInt).siblings) == 1 # link to [o, i, i] not created + +def test_multiple_changes(): + a = fieldtypes.FieldTypes.of_length(3) + b = a.sibling(0, SInt) + for tag in [LPI, flt]: + assert b.sibling(0, tag).types == [tag, obj, obj] + +def test_obj_replacement(): + a = fieldtypes.FieldTypes.of_length(3) + b = a.sibling(0, SInt).sibling(1, SInt) + c = a.sibling(1, SInt) + assert b.sibling(0, obj) is c From noreply at buildbot.pypy.org Thu Apr 25 12:11:53 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Thu, 25 Apr 2013 12:11:53 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: replacing smalltalk line-end sign by python line-end when printing the results of benchmarks Message-ID: <20130425101153.DCDA11C0F38@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r337:522f25d8b9f1 Date: 2013-04-25 12:11 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/522f25d8b9f1/ Log: replacing smalltalk line-end sign by python line-end when printing the results of benchmarks diff --git a/targetimageloadingsmalltalk.py b/targetimageloadingsmalltalk.py --- a/targetimageloadingsmalltalk.py +++ b/targetimageloadingsmalltalk.py @@ -43,8 +43,7 @@ t2 = time.time() if w_result: if isinstance(w_result, model.W_BytesObject): - print '\n' - print w_result.as_string() + print w_result.as_string().replace('\r', '\n') print "took %s seconds" % (t2 - t1) return 0 return -1 From noreply at buildbot.pypy.org Thu Apr 25 14:11:26 2013 From: noreply at buildbot.pypy.org (timfel) Date: Thu, 25 Apr 2013 14:11:26 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: add benchmark script that posts result to codespeed Message-ID: <20130425121126.2008D1C00BD@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: Changeset: r338:e512f8502c91 Date: 2013-04-25 14:10 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/e512f8502c91/ Log: add benchmark script that posts result to codespeed diff --git a/benchmarks.py b/benchmarks.py new file mode 100644 --- /dev/null +++ b/benchmarks.py @@ -0,0 +1,126 @@ +# -*- coding: utf-8 -*- +import os +import socket +import subprocess +import time +import urllib +import urllib2 + +SqueakImage = "Squeak4.4-12327" + +# You need to enter the real URL and have the server running +CODESPEED_URL = 'http://speed.bithug.org/' + +# Executables (assumed to be in the local directory) +executables = ["targetimageloadingsmalltalk-c"] + +# Arguments (inserted between executable and benchmark) +executable_arguments = ["%s.image" % SqueakImage, "-m"] + +# Benchmarks (run for each executable) +benchmarks = ["tinyBenchmarks"] + +def build_data(executable, benchmark, result): + # Mandatory fields + return { + 'commitid': get_commitid(), + 'branch': 'default', + 'project': 'lang-smalltalk', + 'executable': executable, + 'benchmark': benchmark, + 'environment': socket.gethostname(), + 'result_value': str(result), + } + # Optional fields + # data.update({ + # 'std_dev': 1.11111, # Optional. Default is blank + # 'max': 4001.6, # Optional. Default is blank + # 'min': 3995.1, # Optional. Default is blank + # }) + + +def download_prerequesites(): + clean_workspace() + import gzip, tarfile + image = urllib2.urlopen("http://ftp.squeak.org/4.4/%s.tgz" % SqueakImage).read() + sources = urllib2.urlopen('http://ftp.squeak.org/4.4/SqueakV41.sources.gz').read() + with open("image.tgz", "w") as f: + f.write(image) + with gzip.open("image.tgz") as f: + tar = f.read() + with open("image.tar", "w") as f: + f.write(tar) + with tarfile.open("image.tar") as f: + f.extractall(".") + with open("sources.gz", "w") as f: + f.write(sources) + with gzip.open("sources.gz") as f: + with open("SqueakV41.sources", "w") as s: + s.write(f.read()) + +def clean_workspace(): + for f in ["image.tgz", "image.tar", "sources.gz", + "SqueakV41.sources", + "%s.image" % SqueakImage, "%s.changes" % SqueakImage]: + try: + os.remove(f) + except: + pass + + +def get_commitid(): + try: + pipe = subprocess.Popen( + ["hg", "log", "-l", "1", "--template", "{node}"], + stdout=subprocess.PIPE + ) + if pipe.wait() == 0: + return pipe.stdout.read() + except: + pass + try: + pipe = subprocess.Popen( + ["git", "log", "-1", "--pretty=%H"], + stdout=subprocess.PIPE + ) + if pipe.wait() == 0: + return pipe.stdout.read() + except: + pass + raise Exception("commitid not found. not a git or hg repo") + + +def add(executable, benchmark, result): + print "Saving result %s for executable %s, benchmark %s" % ( + result, executable, benchmark) + data = build_data(executable, benchmark, result) + params = urllib.urlencode(data) + response = "None" + print "Saving result for executable %s, revision %s, benchmark %s" % ( + data['executable'], data['commitid'], data['benchmark']) + try: + f = urllib2.urlopen(CODESPEED_URL + 'result/add/', params) + except urllib2.HTTPError as e: + print str(e) + print e.read() + return + response = f.read() + f.close() + print "Server (%s) response: %s\n" % (CODESPEED_URL, response) + + +def run(): + for executable in executables: + for benchmark in benchmarks: + start = time.time() + pipe = subprocess.Popen( + ["./%s" % executable] + executable_arguments + [benchmark] + ) + pipe.wait() + result = time.time() - start + add(executable, benchmark, result) + + +if __name__ == "__main__": + download_prerequesites() + run() From noreply at buildbot.pypy.org Thu Apr 25 15:04:41 2013 From: noreply at buildbot.pypy.org (timfel) Date: Thu, 25 Apr 2013 15:04:41 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: fix benchmark script on windows Message-ID: <20130425130441.3B3B91C02DA@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: Changeset: r339:7e2eea549f71 Date: 2013-04-25 15:04 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/7e2eea549f71/ Log: fix benchmark script on windows diff --git a/benchmarks.py b/benchmarks.py --- a/benchmarks.py +++ b/benchmarks.py @@ -2,6 +2,7 @@ import os import socket import subprocess +import sys import time import urllib import urllib2 @@ -46,17 +47,20 @@ sources = urllib2.urlopen('http://ftp.squeak.org/4.4/SqueakV41.sources.gz').read() with open("image.tgz", "w") as f: f.write(image) - with gzip.open("image.tgz") as f: - tar = f.read() + f = gzip.open("image.tgz") + tar = f.read() + f.close() with open("image.tar", "w") as f: f.write(tar) - with tarfile.open("image.tar") as f: - f.extractall(".") + f = tarfile.open("image.tar"): + f.extractall(".") + f.close() with open("sources.gz", "w") as f: f.write(sources) - with gzip.open("sources.gz") as f: - with open("SqueakV41.sources", "w") as s: - s.write(f.read()) + f = gzip.open("sources.gz") + with open("SqueakV41.sources", "w") as s: + s.write(f.read()) + f.close() def clean_workspace(): for f in ["image.tgz", "image.tar", "sources.gz", @@ -110,11 +114,12 @@ def run(): + suffix = ".exe" if sys.platform == "win32" else "" for executable in executables: for benchmark in benchmarks: start = time.time() pipe = subprocess.Popen( - ["./%s" % executable] + executable_arguments + [benchmark] + ["./%s%s" % (executable, suffix)] + executable_arguments + [benchmark] ) pipe.wait() result = time.time() - start From noreply at buildbot.pypy.org Thu Apr 25 15:18:19 2013 From: noreply at buildbot.pypy.org (timfel) Date: Thu, 25 Apr 2013 15:18:19 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: typo Message-ID: <20130425131819.7E7C61C00BD@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: Changeset: r340:628f9b219f95 Date: 2013-04-25 15:17 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/628f9b219f95/ Log: typo diff --git a/benchmarks.py b/benchmarks.py --- a/benchmarks.py +++ b/benchmarks.py @@ -52,7 +52,7 @@ f.close() with open("image.tar", "w") as f: f.write(tar) - f = tarfile.open("image.tar"): + f = tarfile.open("image.tar") f.extractall(".") f.close() with open("sources.gz", "w") as f: From noreply at buildbot.pypy.org Thu Apr 25 17:26:44 2013 From: noreply at buildbot.pypy.org (timfel) Date: Thu, 25 Apr 2013 17:26:44 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: (lwassermann, timfel) respect float byteorder Message-ID: <20130425152644.CEB0F1C32C4@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: Changeset: r341:7c77f545ff67 Date: 2013-04-25 15:56 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/7c77f545ff67/ Log: (lwassermann, timfel) respect float byteorder diff --git a/spyvm/model.py b/spyvm/model.py --- a/spyvm/model.py +++ b/spyvm/model.py @@ -335,6 +335,8 @@ def fillin(self, space, g_self): high, low = g_self.get_ruints(required_len=2) + if g_self.reader.version.has_floats_reversed: + low, high = high, low self.fillin_fromwords(space, high, low) def getclass(self, space): From noreply at buildbot.pypy.org Thu Apr 25 17:26:45 2013 From: noreply at buildbot.pypy.org (timfel) Date: Thu, 25 Apr 2013 17:26:45 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: (lwassermann, timfel) fix process creation for benchmark in mini image Message-ID: <20130425152645.D746E1C32C4@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: Changeset: r342:2a275ccd6a6a Date: 2013-04-25 15:57 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/2a275ccd6a6a/ Log: (lwassermann, timfel) fix process creation for benchmark in mini image diff --git a/targetimageloadingsmalltalk.py b/targetimageloadingsmalltalk.py --- a/targetimageloadingsmalltalk.py +++ b/targetimageloadingsmalltalk.py @@ -32,7 +32,7 @@ w_benchmark_proc.store(space, 1, s_frame.w_self()) # third variable is priority - priority = 40 + priority = space.unwrap_int(w_hpp.fetch(space, 2)) / 2 + 1 w_benchmark_proc.store(space, 2, space.wrap_int(priority)) # make process eligible for scheduling From noreply at buildbot.pypy.org Thu Apr 25 17:26:46 2013 From: noreply at buildbot.pypy.org (timfel) Date: Thu, 25 Apr 2013 17:26:46 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: (lwassermann, timfel) add weak pointers objects Message-ID: <20130425152646.EEE8A1C32C4@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: Changeset: r343:fc4dcba32c73 Date: 2013-04-25 16:52 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/fc4dcba32c73/ Log: (lwassermann, timfel) add weak pointers objects diff --git a/spyvm/model.py b/spyvm/model.py --- a/spyvm/model.py +++ b/spyvm/model.py @@ -14,7 +14,7 @@ W_BlockContext and W_MethodContext classes have been replaced by functions that create W_PointersObjects of correct size with attached shadows. """ -import sys +import sys, weakref from spyvm import constants, error from rpython.rlib import rrandom, objectmodel, jit, signature @@ -468,32 +468,23 @@ assert s_class is not None return s_class -class W_PointersObject(W_AbstractObjectWithClassReference): +class W_AbstractPointersObject(W_AbstractObjectWithClassReference): """Common object.""" - _attrs_ = ['_shadow', '_vars', 'fieldtypes'] + _attrs_ = ['_shadow'] _shadow = None # Default value @jit.unroll_safe def __init__(self, space, w_class, size): - from spyvm.fieldtypes import fieldtypes_of_length """Create new object with size = fixed + variable size.""" W_AbstractObjectWithClassReference.__init__(self, space, w_class) - - vars = self._vars = [None] * size - self.fieldtypes = fieldtypes_of_length(self.s_class, size) - - for i in range(size): # do it by hand for the JIT's sake - vars[i] = w_nil self._shadow = None # Default value def fillin(self, space, g_self): from spyvm.fieldtypes import fieldtypes_of - self._vars = g_self.get_pointers() self.s_class = g_self.get_class().as_class_get_penumbra(space) self.hash = g_self.get_hash() self.space = space - self.fieldtypes = fieldtypes_of(self) def at0(self, space, index0): # To test, at0 = in varsize part @@ -508,21 +499,11 @@ return self._shadow.fetch(n0) return self._fetch(n0) - def _fetch(self, n0): - # return self._vars[n0] - fieldtypes = jit.promote(self.fieldtypes) - return fieldtypes.fetch(self, n0) - def store(self, space, n0, w_value): if self.has_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 - fieldtypes = jit.promote(self.fieldtypes) - return fieldtypes.store(self, n0, w_value) - def varsize(self, space): return self.size() - self.instsize(space) @@ -537,13 +518,6 @@ return self._shadow.size() return self._size() - def _size(self): - return len(self._vars) - - def invariant(self): - return (W_AbstractObjectWithClassReference.invariant(self) and - isinstance(self._vars, list)) - def store_shadow(self, shadow): assert self._shadow is None or self._shadow is shadow self._shadow = shadow @@ -617,9 +591,8 @@ return self._shadow is not None def become(self, w_other): - if not isinstance(w_other, W_PointersObject): + if not isinstance(w_other, W_AbstractPointersObject): return False - self._vars, w_other._vars = w_other._vars, self._vars # switching means also switching shadows self._shadow, w_other._shadow = w_other._shadow, self._shadow # shadow links are in both directions -> also update shadows @@ -628,22 +601,106 @@ W_AbstractObjectWithClassReference._become(self, w_other) return True + @jit.elidable + def as_repr_string(self): + return W_AbstractObjectWithClassReference.as_embellished_string(self, + className='W_PointersObject', + additionalInformation='len=%d' % self.size()) + +class W_PointersObject(W_AbstractPointersObject): + _attrs_ = ['_vars', 'fieldtypes'] + + @jit.unroll_safe + def __init__(self, space, w_class, size): + from spyvm.fieldtypes import fieldtypes_of_length + """Create new object with size = fixed + variable size.""" + W_AbstractPointersObject.__init__(self, space, w_class, size) + vars = self._vars = [None] * size + self.fieldtypes = fieldtypes_of_length(self.s_class, size) + for i in range(size): # do it by hand for the JIT's sake + vars[i] = w_nil + + def fillin(self, space, g_self): + W_AbstractPointersObject.fillin(self, space, g_self) + from spyvm.fieldtypes import fieldtypes_of + self._vars = g_self.get_pointers() + self.fieldtypes = fieldtypes_of(self) + + def _fetch(self, n0): + # return self._vars[n0] + fieldtypes = jit.promote(self.fieldtypes) + return fieldtypes.fetch(self, n0) + + def _store(self, n0, w_value): + # self._vars[n0] = w_value + fieldtypes = jit.promote(self.fieldtypes) + return fieldtypes.store(self, n0, w_value) + + def _size(self): + return len(self._vars) + + def invariant(self): + return (W_AbstractObjectWithClassReference.invariant(self) and + isinstance(self._vars, list)) + + 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_AbstractPointersObject.become(self, w_other) + def clone(self, space): w_result = W_PointersObject(self.space, self.getclass(space), len(self._vars)) w_result._vars = [self.fetch(space, i) for i in range(len(self._vars))] return w_result - @jit.elidable - def as_repr_string(self): - return W_AbstractObjectWithClassReference.as_embellished_string(self, - className='W_PointersObject', - additionalInformation='len=%d' % self.size()) - def fieldtype(self): from spyvm.fieldtypes import obj return obj +class W_WeakPointersObject(W_AbstractPointersObject): + _attrs_ = ['_weakvars'] + + @jit.unroll_safe + def __init__(self, space, w_class, size): + W_AbstractPointersObject.__init__(self, space, w_class, size) + self._weakvars = [weakref.ref(w_nil)] * size + + def fillin(self, space, g_self): + raise NotImplementedError("we don't expect weak objects in a fresh image") + + def _fetch(self, n0): + weakobj = self._weakvars[n0] + return weakobj() or w_nil + + def _store(self, n0, w_value): + assert w_value is not None + self._weakvars[n0] = weakref.ref(w_value) + + def _size(self): + return len(self._weakvars) + + def invariant(self): + return (W_AbstractObjectWithClassReference.invariant(self) and + isinstance(self._weakvars, list)) + + def become(self, w_other): + if not isinstance(w_other, W_WeakPointersObject): + return False + self._weakvars, w_other._weakvars = w_other._weakvars, self._weakvars + return W_AbstractPointersObject.become(self, w_other) + + def clone(self, space): + w_result = W_WeakPointersObject(self.space, self.getclass(space), + len(self._weakvars)) + for i, var in enumerate(self._weakvars): + w_obj = var() + if w_obj is None: + w_obj = w_nil + w_result._weakvars[i] = weakref.ref(w_obj) + return w_result + class W_BytesObject(W_AbstractObjectWithClassReference): _attrs_ = ['bytes'] diff --git a/spyvm/shadow.py b/spyvm/shadow.py --- a/spyvm/shadow.py +++ b/spyvm/shadow.py @@ -216,6 +216,9 @@ w_new = model.W_LargePositiveInteger1Word(0, extrasize) else: w_new = model.W_BytesObject(self.space, w_cls, extrasize) + elif self.instance_kind == WEAK_POINTERS: + size = self.instsize() + extrasize + w_new = model.W_WeakPointersObject(self.space, w_cls, size) else: raise NotImplementedError(self.instance_kind) return w_new From noreply at buildbot.pypy.org Thu Apr 25 18:16:12 2013 From: noreply at buildbot.pypy.org (arigo) Date: Thu, 25 Apr 2013 18:16:12 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Generalize rgc.register_finalizer() into an API for any W_Root object. Message-ID: <20130425161612.9C0411C02DA@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63607:f21d31bd52cf Date: 2013-04-25 16:49 +0200 http://bitbucket.org/pypy/pypy/changeset/f21d31bd52cf/ Log: Generalize rgc.register_finalizer() into an API for any W_Root object. diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py --- a/pypy/interpreter/baseobjspace.py +++ b/pypy/interpreter/baseobjspace.py @@ -154,25 +154,38 @@ self.delweakref() lifeline.clear_all_weakrefs() - __already_enqueued_for_destruction = () + def register_finalizer(self): + """Register the fact that this object needs finalization. + Can be called several times on the same object with no ill effect.""" + from rpython.rlib import rgc + rgc.register_finalizer(self._invoke_finalizer) - def enqueue_for_destruction(self, space, callback, descrname): - """Put the object in the destructor queue of the space. - At a later, safe point in time, UserDelAction will call - callback(self). If that raises OperationError, prints it - to stderr with the descrname string. + def _invoke_finalizer(self): + # The call-back from rgc.register_finalizer(), cannot be overridden + self.invoke_finalizer() - Note that 'callback' will usually need to start with: - assert isinstance(self, W_SpecificClass) + def invoke_finalizer(self): + raise NotImplementedError + + def finalizer_perform(self, space, descrname, callback, *args): + """For use in invoke_finalizer(). First check if we're called + from the random execution of a __del__ or from UserDelAction, + and raise _FinalizeLater in the former case. Then invoke + callback(*args). If that raises OperationError, prints it to + stderr with the descrname string. The format is: + + Exception XxxError: "error message" in %s%s ignored + + The first %s is descrname (which should thus end with a space + character), and the second %s is repr(self). """ - # this function always resurect the object, so when - # running on top of CPython we must manually ensure that - # we enqueue it only once - if not we_are_translated(): - if callback in self.__already_enqueued_for_destruction: - return - self.__already_enqueued_for_destruction += (callback,) - space.user_del_action.register_callback(self, callback, descrname) + space.user_del_action.must_be_between_bytecodes() + try: + callback(*args) + except OperationError, e: + e.write_unraisable(space, descrname, self) + e.clear(space) # break up reference cycles + finalizer_perform._annspecialcase_ = 'specialize:arg(3)' # hooks that the mapdict implementations needs: def _get_mapdict_map(self): diff --git a/pypy/interpreter/executioncontext.py b/pypy/interpreter/executioncontext.py --- a/pypy/interpreter/executioncontext.py +++ b/pypy/interpreter/executioncontext.py @@ -435,41 +435,31 @@ class UserDelAction(AsyncAction): - """An action that invokes all pending app-level __del__() method. + """An action that invokes all pending finalizers. This is done as an action instead of immediately when the - interp-level __del__() is invoked, because the latter can occur more + interp-level finalizer is invoked, because the latter can occur more or less anywhere in the middle of code that might not be happy with random app-level code mutating data structures under its feet. """ def __init__(self, space): AsyncAction.__init__(self, space) - self.dying_objects = [] - self.finalizers_lock_count = 0 - self.enabled_at_app_level = True + self.in_user_del_action = False - def register_callback(self, w_obj, callback, descrname): - self.dying_objects.append((w_obj, callback, descrname)) - self.fire() + def must_be_between_bytecodes(self): + if not self.in_user_del_action: + from rpython.rlib import rgc + self.fire() + rgc.finalize_later() def perform(self, executioncontext, frame): - if self.finalizers_lock_count > 0: - return - # Each call to perform() first grabs the self.dying_objects - # and replaces it with an empty list. We do this to try to - # avoid too deep recursions of the kind of __del__ being called - # while in the middle of another __del__ call. - pending = self.dying_objects - self.dying_objects = [] - space = self.space - for i in range(len(pending)): - w_obj, callback, descrname = pending[i] - pending[i] = (None, None, None) + from rpython.rlib import rgc + if not self.in_user_del_action: + self.in_user_del_action = True try: - callback(w_obj) - except OperationError, e: - e.write_unraisable(space, descrname, w_obj) - e.clear(space) # break up reference cycles + rgc.progress_through_finalizer_queue() + finally: + self.in_user_del_action = False class FrameTraceAction(AsyncAction): """An action that calls the local trace functions (w_f_trace).""" diff --git a/pypy/module/__builtin__/interp_classobj.py b/pypy/module/__builtin__/interp_classobj.py --- a/pypy/module/__builtin__/interp_classobj.py +++ b/pypy/module/__builtin__/interp_classobj.py @@ -6,7 +6,7 @@ from pypy.interpreter.typedef import GetSetProperty, descr_get_dict, descr_set_dict from rpython.rlib.objectmodel import compute_identity_hash from rpython.rlib.debug import make_sure_not_resized -from rpython.rlib import rgc, jit +from rpython.rlib import jit def raise_type_err(space, argument, expected, w_obj): @@ -313,7 +313,7 @@ assert isinstance(w_class, W_ClassObject) self.w_class = w_class if self.getattr_from_class(space, '__del__') is not None: - rgc.register_finalizer(self.finalizer) + self.register_finalizer() def user_setup(self, space, w_subtype): self.space = space @@ -385,7 +385,7 @@ self.set_oldstyle_class(space, w_value) return if name == '__del__': - rgc.register_finalizer(self.finalizer) + self.register_finalizer() if w_meth is not None: space.call_function(w_meth, w_name, w_value) else: @@ -688,13 +688,14 @@ space.wrap("instance has no next() method")) return space.call_function(w_func) - def finalizer(self): + def invoke_finalizer(self): space = self.space w_func = self.getdictvalue(space, '__del__') if w_func is None: w_func = self.getattr_from_class(space, '__del__') if w_func is not None: - space.call_function(w_func) + self.finalizer_perform(self.space, "__del__ of ", + space.call_function, w_func) def descr_exit(self, space, w_type, w_value, w_tb): w_func = self.getattr(space, '__exit__', False) diff --git a/rpython/rlib/rgc.py b/rpython/rlib/rgc.py --- a/rpython/rlib/rgc.py +++ b/rpython/rlib/rgc.py @@ -290,7 +290,7 @@ gc_supports_finalize_later = CDefinedIntSymbolic('GC_SUPPORTS_FINALIZE_LATER', default=1) def finalize_later(): - if gc_supports_finalize_later: + if not we_are_translated() or gc_supports_finalize_later: raise _FinalizeLater def register_finalizer(method): From noreply at buildbot.pypy.org Thu Apr 25 18:16:13 2013 From: noreply at buildbot.pypy.org (arigo) Date: Thu, 25 Apr 2013 18:16:13 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Trying to make sure we don't run finalizers after CPython started to Message-ID: <20130425161613.F2C0C1C02DA@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63608:603c7ac3b487 Date: 2013-04-25 17:01 +0200 http://bitbucket.org/pypy/pypy/changeset/603c7ac3b487/ Log: Trying to make sure we don't run finalizers after CPython started to clean up modules and replace global names with None, but kind of failing. diff --git a/rpython/rlib/rgc.py b/rpython/rlib/rgc.py --- a/rpython/rlib/rgc.py +++ b/rpython/rlib/rgc.py @@ -1,6 +1,6 @@ from __future__ import absolute_import -import gc, weakref +import gc, weakref, atexit import types import collections @@ -347,12 +347,16 @@ _finalizer_queue.appendleft((obj, func)) break except Exception, e: - raise AssertionError("progress_through_finalizer_queue(): " + raise FinalizerError("progress_through_finalizer_queue(): " "%s raised %s: %s" % (func, e.__class__.__name__, e)) _finalizer_lock.append(None) +class FinalizerError(Exception): + "NOT_RPYTHON" +atexit.register(_finalizer_queue.clear) + class RegisterFinalizerEntry(ExtRegistryEntry): _about_ = register_finalizer From noreply at buildbot.pypy.org Thu Apr 25 18:16:15 2013 From: noreply at buildbot.pypy.org (arigo) Date: Thu, 25 Apr 2013 18:16:15 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Adapt rmmap. Message-ID: <20130425161615.2ED211C02DA@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63609:63acca3cc396 Date: 2013-04-25 17:03 +0200 http://bitbucket.org/pypy/pypy/changeset/63acca3cc396/ Log: Adapt rmmap. diff --git a/rpython/rlib/rmmap.py b/rpython/rlib/rmmap.py --- a/rpython/rlib/rmmap.py +++ b/rpython/rlib/rmmap.py @@ -1,7 +1,7 @@ from rpython.rtyper.tool import rffi_platform from rpython.rtyper.lltypesystem import rffi, lltype, llmemory -from rpython.rlib import rposix +from rpython.rlib import rgc, rposix from rpython.translator.tool.cbuild import ExternalCompilationInfo from rpython.rlib.nonconst import NonConstant @@ -268,6 +268,7 @@ elif _POSIX: self.fd = -1 self.closed = False + rgc.register_finalizer(self.close) def check_valid(self): if _MS_WINDOWS: @@ -315,9 +316,6 @@ c_munmap_safe(self.getptr(0), self.size) self.setdata(NODATA, 0) - def __del__(self): - self.close() - def unmapview(self): UnmapViewOfFile(self.getptr(0)) From noreply at buildbot.pypy.org Thu Apr 25 18:16:16 2013 From: noreply at buildbot.pypy.org (arigo) Date: Thu, 25 Apr 2013 18:16:16 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Fix sockets Message-ID: <20130425161616.545231C02DA@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63610:10da333786e1 Date: 2013-04-25 17:10 +0200 http://bitbucket.org/pypy/pypy/changeset/10da333786e1/ Log: Fix sockets diff --git a/pypy/module/_socket/interp_socket.py b/pypy/module/_socket/interp_socket.py --- a/pypy/module/_socket/interp_socket.py +++ b/pypy/module/_socket/interp_socket.py @@ -132,9 +132,9 @@ class W_RSocket(Wrappable, RSocket): - def __del__(self): + def invoke_finalizer(self): self.clear_all_weakrefs() - RSocket.__del__(self) + RSocket.invoke_finalizer(self) def accept_w(self, space): """accept() -> (socket object, address info) diff --git a/rpython/rlib/rsocket.py b/rpython/rlib/rsocket.py --- a/rpython/rlib/rsocket.py +++ b/rpython/rlib/rsocket.py @@ -79,6 +79,7 @@ self.addrlen = addrlen def __del__(self): + "Lightweight destructor" if self.addr_p: lltype.free(self.addr_p, flavor='raw') @@ -493,8 +494,15 @@ self.type = type self.proto = proto self.timeout = defaults.timeout - - def __del__(self): + self.register_finalizer() + + def register_finalizer(self): + """This version is overriden in pypy/module/_socket with the + one from W_Root""" + from rpython.rlib import rgc + rgc.register_finalizer(self.invoke_finalizer) + + def invoke_finalizer(self): fd = self.fd if fd != _c.INVALID_SOCKET: self.fd = _c.INVALID_SOCKET From noreply at buildbot.pypy.org Thu Apr 25 18:16:17 2013 From: noreply at buildbot.pypy.org (arigo) Date: Thu, 25 Apr 2013 18:16:17 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Progress: __del__ works again on new-style classes. Message-ID: <20130425161617.901221C02DA@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63611:57387227c7ab Date: 2013-04-25 17:41 +0200 http://bitbucket.org/pypy/pypy/changeset/57387227c7ab/ Log: Progress: __del__ works again on new-style classes. diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py --- a/pypy/interpreter/typedef.py +++ b/pypy/interpreter/typedef.py @@ -237,6 +237,17 @@ self.space = space self.w__class__ = w_subtype self.user_setup_slots(w_subtype.nslots) + if w_subtype.has_del: + self.register_finalizer() + + def invoke_finalizer(self): + space = self.space + w_descr = space.lookup(self, '__del__') + if w_descr is None: + return + self.finalizer_perform(self.space, "__del__ method of ", + space.get_and_call_function, + w_descr, self) def user_setup_slots(self, nslots): assert nslots == 0 diff --git a/pypy/module/__builtin__/interp_classobj.py b/pypy/module/__builtin__/interp_classobj.py --- a/pypy/module/__builtin__/interp_classobj.py +++ b/pypy/module/__builtin__/interp_classobj.py @@ -694,7 +694,7 @@ if w_func is None: w_func = self.getattr_from_class(space, '__del__') if w_func is not None: - self.finalizer_perform(self.space, "__del__ of ", + self.finalizer_perform(self.space, "__del__ method of ", space.call_function, w_func) def descr_exit(self, space, w_type, w_value, w_tb): diff --git a/pypy/module/_socket/interp_socket.py b/pypy/module/_socket/interp_socket.py --- a/pypy/module/_socket/interp_socket.py +++ b/pypy/module/_socket/interp_socket.py @@ -132,9 +132,12 @@ class W_RSocket(Wrappable, RSocket): + def __init__(self, family, type, proto): + RSocket.__init__(self, family, type, proto) + self.register_finalizer() + def invoke_finalizer(self): - self.clear_all_weakrefs() - RSocket.invoke_finalizer(self) + RSocket.invoke_finalizer(self) # destroy the socket fd def accept_w(self, space): """accept() -> (socket object, address info) diff --git a/pypy/objspace/std/model.py b/pypy/objspace/std/model.py --- a/pypy/objspace/std/model.py +++ b/pypy/objspace/std/model.py @@ -344,7 +344,7 @@ "Parent base class for wrapped objects provided by the StdObjSpace." # Note that not all wrapped objects in the interpreter inherit from # W_Object. (They inherit from W_Root.) - __slots__ = () + _attrs_ = () def __repr__(self): name = getattr(self, 'name', '') diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py --- a/pypy/objspace/std/typeobject.py +++ b/pypy/objspace/std/typeobject.py @@ -94,6 +94,7 @@ _immutable_fields_ = ["flag_heaptype", "flag_cpytype", "flag_abstract?", + 'has_del?', 'weakrefable', 'hasdict', 'nslots', @@ -292,10 +293,6 @@ if not w_self.is_heaptype(): msg = "can't set attributes on type object '%s'" raise operationerrfmt(space.w_TypeError, msg, w_self.name) - if name == "__del__" and name not in w_self.dict_w: - msg = ("a __del__ method added to an existing type will not be " - "called") - space.warn(space.wrap(msg), space.w_RuntimeWarning) if space.config.objspace.std.withtypeversion: version_tag = w_self.version_tag() if version_tag is not None: @@ -783,6 +780,7 @@ w_self.dict_w['__module__'] = w_name def compute_mro(w_self): + mro_w = None if w_self.is_heaptype(): space = w_self.space w_metaclass = space.type(w_self) @@ -791,9 +789,11 @@ w_mro_meth = space.get(w_mro_func, w_self) w_mro = space.call_function(w_mro_meth) mro_w = space.fixedview(w_mro) - w_self.mro_w = validate_custom_mro(space, mro_w) - return # done - w_self.mro_w = w_self.compute_default_mro()[:] + mro_w = validate_custom_mro(space, mro_w) + if mro_w is None: + mro_w = w_self.compute_default_mro()[:] + w_self.mro_w = mro_w + w_self.has_del = (w_self.lookup("__del__") is not None) def validate_custom_mro(space, mro_w): # do some checking here. Note that unlike CPython, strange MROs From noreply at buildbot.pypy.org Thu Apr 25 18:16:18 2013 From: noreply at buildbot.pypy.org (arigo) Date: Thu, 25 Apr 2013 18:16:18 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Now attaching a __del__ to a class after its creation works. Message-ID: <20130425161618.B20A31C02DA@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63612:038c24c72b90 Date: 2013-04-25 17:46 +0200 http://bitbucket.org/pypy/pypy/changeset/038c24c72b90/ Log: Now attaching a __del__ to a class after its creation works. diff --git a/pypy/objspace/std/test/test_typeobject.py b/pypy/objspace/std/test/test_typeobject.py --- a/pypy/objspace/std/test/test_typeobject.py +++ b/pypy/objspace/std/test/test_typeobject.py @@ -58,7 +58,7 @@ """) finally: space.warn = prev_warn - assert len(warnings) == 2 + assert len(warnings) == 0 # should not give warnings any longer def test_metaclass_typedef(self): py.test.skip("Not implemented yet") @@ -1062,6 +1062,18 @@ A.__dict__['x'] = 5 assert A.x == 5 + def test_late_del(self): + seen = [] + class A(object): + pass + A.__del__ = lambda self: seen.append(1) + A() + for i in range(5): + if seen: + break + import gc; gc.collect() + assert seen + class AppTestWithMethodCacheCounter: spaceconfig = {"objspace.std.withmethodcachecounter": True} diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py --- a/pypy/objspace/std/typeobject.py +++ b/pypy/objspace/std/typeobject.py @@ -293,6 +293,8 @@ if not w_self.is_heaptype(): msg = "can't set attributes on type object '%s'" raise operationerrfmt(space.w_TypeError, msg, w_self.name) + if name == "__del__": + w_self.has_del = True if space.config.objspace.std.withtypeversion: version_tag = w_self.version_tag() if version_tag is not None: From noreply at buildbot.pypy.org Thu Apr 25 18:49:21 2013 From: noreply at buildbot.pypy.org (arigo) Date: Thu, 25 Apr 2013 18:49:21 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Fixes Message-ID: <20130425164921.5E10C1C01AB@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63613:d8aca814350a Date: 2013-04-25 18:48 +0200 http://bitbucket.org/pypy/pypy/changeset/d8aca814350a/ Log: Fixes diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py --- a/pypy/interpreter/baseobjspace.py +++ b/pypy/interpreter/baseobjspace.py @@ -1622,7 +1622,6 @@ ('get', 'get', 3, ['__get__']), ('set', 'set', 3, ['__set__']), ('delete', 'delete', 2, ['__delete__']), - ('userdel', 'del', 1, ['__del__']), ('buffer', 'buffer', 1, ['__buffer__']), # see buffer.py ] diff --git a/pypy/module/_weakref/interp__weakref.py b/pypy/module/_weakref/interp__weakref.py --- a/pypy/module/_weakref/interp__weakref.py +++ b/pypy/module/_weakref/interp__weakref.py @@ -354,7 +354,7 @@ proxy_typedef_dict = {} callable_proxy_typedef_dict = {} -special_ops = {'repr': True, 'userdel': True, 'hash': True} +special_ops = {'repr': True, 'hash': True} for opname, _, arity, special_methods in ObjSpace.MethodTable: if opname in special_ops or not special_methods: diff --git a/pypy/objspace/descroperation.py b/pypy/objspace/descroperation.py --- a/pypy/objspace/descroperation.py +++ b/pypy/objspace/descroperation.py @@ -466,11 +466,6 @@ raise OperationError(space.w_TypeError, space.wrap("__hash__() should return an int or long")) - def userdel(space, w_obj): - w_del = space.lookup(w_obj, '__del__') - if w_del is not None: - space.get_and_call_function(w_del, w_obj) - def cmp(space, w_v, w_w): if space.is_w(w_v, w_w): diff --git a/pypy/objspace/std/builtinshortcut.py b/pypy/objspace/std/builtinshortcut.py --- a/pypy/objspace/std/builtinshortcut.py +++ b/pypy/objspace/std/builtinshortcut.py @@ -32,7 +32,7 @@ ]) KNOWN_MISSING = ['getattr', # mostly non-builtins or optimized by CALL_METHOD - 'setattr', 'delattr', 'userdel', # mostly for non-builtins + 'setattr', 'delattr', # mostly for non-builtins 'get', 'set', 'delete', # uncommon (except on functions) 'getslice', 'setslice', 'delslice', # see below 'delitem', 'trunc', # rare stuff? diff --git a/pypy/objspace/std/model.py b/pypy/objspace/std/model.py --- a/pypy/objspace/std/model.py +++ b/pypy/objspace/std/model.py @@ -425,7 +425,7 @@ NOT_MULTIMETHODS = dict.fromkeys( ['delattr', 'delete', 'get', 'id', 'inplace_div', 'inplace_floordiv', 'inplace_lshift', 'inplace_mod', 'inplace_pow', 'inplace_rshift', - 'inplace_truediv', 'is_', 'set', 'setattr', 'type', 'userdel', + 'inplace_truediv', 'is_', 'set', 'setattr', 'type', 'isinstance', 'issubtype']) # XXX should we just remove those from the method table or we're happy # with just not having multimethods? diff --git a/rpython/rlib/rstacklet.py b/rpython/rlib/rstacklet.py --- a/rpython/rlib/rstacklet.py +++ b/rpython/rlib/rstacklet.py @@ -1,6 +1,6 @@ import sys from rpython.rlib import _rffi_stacklet as _c -from rpython.rlib import jit +from rpython.rlib import rgc, jit from rpython.rlib.objectmodel import we_are_translated from rpython.rtyper.lltypesystem import lltype, llmemory @@ -55,13 +55,14 @@ class StackletThreadDeleter(object): - # quick hack: the __del__ is on another object, so that + # quick hack: the finalize() is on another object, so that # if the main StackletThread ends up in random circular # references, on pypy deletethread() is only called # when all that circular reference mess is gone. def __init__(self, thrd): self._thrd = thrd - def __del__(self): + rgc.register_finalizer(self.finalize) + def finalize(self): thrd = self._thrd if thrd: self._thrd = lltype.nullptr(_c.thread_handle.TO) From noreply at buildbot.pypy.org Thu Apr 25 18:51:22 2013 From: noreply at buildbot.pypy.org (arigo) Date: Thu, 25 Apr 2013 18:51:22 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Test that "del A.__del__" works. Message-ID: <20130425165122.54A531C01AB@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63614:7e349f0e4d68 Date: 2013-04-25 18:50 +0200 http://bitbucket.org/pypy/pypy/changeset/7e349f0e4d68/ Log: Test that "del A.__del__" works. diff --git a/pypy/objspace/std/test/test_typeobject.py b/pypy/objspace/std/test/test_typeobject.py --- a/pypy/objspace/std/test/test_typeobject.py +++ b/pypy/objspace/std/test/test_typeobject.py @@ -1074,6 +1074,20 @@ import gc; gc.collect() assert seen + def test_remove_del(self): + seen = [] + class A(object): + def __del__(self): + seen.append(1) + a = A() + del A.__del__ + a = 42 + for i in range(5): + if seen: + break + import gc; gc.collect() + assert not seen + class AppTestWithMethodCacheCounter: spaceconfig = {"objspace.std.withmethodcachecounter": True} From noreply at buildbot.pypy.org Thu Apr 25 21:21:47 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Thu, 25 Apr 2013 21:21:47 +0200 (CEST) Subject: [pypy-commit] pypy py3k: another windows deadlock, skip for now Message-ID: <20130425192147.CBD281C0F38@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63616:e20e8b97f1af Date: 2013-04-25 12:19 -0700 http://bitbucket.org/pypy/pypy/changeset/e20e8b97f1af/ Log: another windows deadlock, skip for now diff --git a/lib-python/3/test/json_tests/test_recursion.py b/lib-python/3/test/json_tests/test_recursion.py --- a/lib-python/3/test/json_tests/test_recursion.py +++ b/lib-python/3/test/json_tests/test_recursion.py @@ -1,3 +1,6 @@ +import sys +import unittest +from test import support from test.json_tests import PyTest, CTest @@ -75,6 +78,9 @@ with self.assertRaises(RuntimeError): self.loads('[' * 100000 + '1' + ']' * 100000) + @unittest.skipIf(support.check_impl_detail(pypy=True) and + sys.platform == 'win32', + "XXX: https://bugs.pypy.org/issue1461") def test_highly_nested_objects_encoding(self): # See #12051 l, d = [], {} From noreply at buildbot.pypy.org Thu Apr 25 21:21:46 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Thu, 25 Apr 2013 21:21:46 +0200 (CEST) Subject: [pypy-commit] pypy py3k: py3 inherits an additional frame here from the foo exception's __traceback__ Message-ID: <20130425192146.7939E1C00BD@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63615:6f309fa32ef4 Date: 2013-04-25 12:19 -0700 http://bitbucket.org/pypy/pypy/changeset/6f309fa32ef4/ Log: py3 inherits an additional frame here from the foo exception's __traceback__ diff --git a/pypy/module/_continuation/test/test_stacklet.py b/pypy/module/_continuation/test/test_stacklet.py --- a/pypy/module/_continuation/test/test_stacklet.py +++ b/pypy/module/_continuation/test/test_stacklet.py @@ -595,7 +595,8 @@ assert tb.tb_next.tb_frame.f_code.co_name == 'f1' assert tb.tb_next.tb_next.tb_frame.f_code.co_name == 'main' assert tb.tb_next.tb_next.tb_next.tb_frame.f_code.co_name == 'do_raise' - assert tb.tb_next.tb_next.tb_next.tb_next is None + assert tb.tb_next.tb_next.tb_next.tb_next.tb_frame.f_code.co_name == 'f1' + assert tb.tb_next.tb_next.tb_next.tb_next.tb_next is None def test_throw_to_starting(self): from _continuation import continulet From noreply at buildbot.pypy.org Thu Apr 25 21:37:43 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Thu, 25 Apr 2013 21:37:43 +0200 (CEST) Subject: [pypy-commit] pypy py3k: kill basestring Message-ID: <20130425193743.DF3501C00BD@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63617:edd3db2a1a15 Date: 2013-04-25 12:37 -0700 http://bitbucket.org/pypy/pypy/changeset/edd3db2a1a15/ Log: kill basestring diff --git a/lib_pypy/_ctypes/primitive.py b/lib_pypy/_ctypes/primitive.py --- a/lib_pypy/_ctypes/primitive.py +++ b/lib_pypy/_ctypes/primitive.py @@ -230,8 +230,8 @@ return _rawffi.wcharp2rawunicode(addr, size) def _setvalue(self, value): - if isinstance(value, basestring): - if isinstance(value, str): + if isinstance(value, (str, bytes)): + if isinstance(value, bytes): value = value.decode(ConvMode.encoding, ConvMode.errors) array = _rawffi.Array('u')(len(value)+1, value) From noreply at buildbot.pypy.org Fri Apr 26 03:32:07 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Fri, 26 Apr 2013 03:32:07 +0200 (CEST) Subject: [pypy-commit] pypy default: move some code out of descr_init, cleanup Message-ID: <20130426013207.33C681C3435@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: Changeset: r63618:0bf46697f8e7 Date: 2013-04-25 18:15 -0700 http://bitbucket.org/pypy/pypy/changeset/0bf46697f8e7/ Log: move some code out of descr_init, cleanup diff --git a/pypy/module/_io/interp_textio.py b/pypy/module/_io/interp_textio.py --- a/pypy/module/_io/interp_textio.py +++ b/pypy/module/_io/interp_textio.py @@ -1,16 +1,16 @@ -from pypy.module._io.interp_iobase import W_IOBase -from pypy.interpreter.typedef import ( - TypeDef, GetSetProperty, interp_attrproperty_w, interp_attrproperty, - generic_new_descr) -from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault +import sys + from pypy.interpreter.baseobjspace import W_Root from pypy.interpreter.error import OperationError -from rpython.rlib.rarithmetic import intmask, r_ulonglong, r_uint +from pypy.interpreter.gateway import WrappedDefault, interp2app, unwrap_spec +from pypy.interpreter.typedef import ( + GetSetProperty, TypeDef, generic_new_descr, interp_attrproperty, + interp_attrproperty_w) +from pypy.module._codecs import interp_codecs +from pypy.module._io.interp_iobase import W_IOBase, convert_size +from rpython.rlib.rarithmetic import intmask, r_uint, r_ulonglong from rpython.rlib.rbigint import rbigint from rpython.rlib.rstring import UnicodeBuilder -from pypy.module._codecs import interp_codecs -from pypy.module._io.interp_iobase import convert_size -import sys STATE_ZERO, STATE_OK, STATE_DETACHED = range(3) @@ -270,6 +270,27 @@ errors = GetSetProperty(W_TextIOBase.errors_get_w), ) + +def _determine_encoding(space, encoding): + if encoding is not None: + return space.wrap(encoding) + + try: + w_locale = space.call_method(space.builtin, '__import__', + space.wrap('locale')) + w_encoding = space.call_method(w_locale, 'getpreferredencoding') + except OperationError as e: + # getpreferredencoding() may also raise ImportError + if not e.match(space, space.w_ImportError): + raise + return space.wrap('ascii') + else: + if space.isinstance_w(w_encoding, space.w_str): + return w_encoding + + raise OperationError(space.w_IOError, space.wrap( + "could not determine default encoding")) + class PositionCookie(object): def __init__(self, bigint): self.start_pos = bigint.ulonglongmask() @@ -337,32 +358,8 @@ def descr_init(self, space, w_buffer, encoding=None, w_errors=None, w_newline=None, line_buffering=0): self.state = STATE_ZERO - self.w_buffer = w_buffer - - # Set encoding - self.w_encoding = None - if encoding is None: - try: - w_locale = space.call_method(space.builtin, '__import__', - space.wrap("locale")) - self.w_encoding = space.call_method(w_locale, - "getpreferredencoding") - except OperationError, e: - # getpreferredencoding() may also raise ImportError - if not e.match(space, space.w_ImportError): - raise - self.w_encoding = space.wrap("ascii") - else: - if not space.isinstance_w(self.w_encoding, space.w_str): - self.w_encoding = None - if self.w_encoding: - pass - elif encoding is not None: - self.w_encoding = space.wrap(encoding) - else: - raise OperationError(space.w_IOError, space.wrap( - "could not determine default encoding")) + self.w_encoding = _determine_encoding(space, encoding) if space.is_none(w_errors): w_errors = space.wrap("strict") From noreply at buildbot.pypy.org Fri Apr 26 03:32:08 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Fri, 26 Apr 2013 03:32:08 +0200 (CEST) Subject: [pypy-commit] pypy py3k: merge default Message-ID: <20130426013208.8194A1C3435@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63619:17860a9c42a1 Date: 2013-04-25 18:27 -0700 http://bitbucket.org/pypy/pypy/changeset/17860a9c42a1/ Log: merge default diff --git a/pypy/module/_io/interp_textio.py b/pypy/module/_io/interp_textio.py --- a/pypy/module/_io/interp_textio.py +++ b/pypy/module/_io/interp_textio.py @@ -1,16 +1,16 @@ -from pypy.module._io.interp_iobase import W_IOBase -from pypy.interpreter.typedef import ( - TypeDef, GetSetProperty, interp_attrproperty_w, interp_attrproperty, - generic_new_descr) -from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault +import sys + from pypy.interpreter.baseobjspace import W_Root from pypy.interpreter.error import OperationError -from rpython.rlib.rarithmetic import intmask, r_ulonglong, r_uint +from pypy.interpreter.gateway import WrappedDefault, interp2app, unwrap_spec +from pypy.interpreter.typedef import ( + GetSetProperty, TypeDef, generic_new_descr, interp_attrproperty, + interp_attrproperty_w) +from pypy.module._codecs import interp_codecs +from pypy.module._io.interp_iobase import W_IOBase, convert_size +from rpython.rlib.rarithmetic import intmask, r_uint, r_ulonglong from rpython.rlib.rbigint import rbigint from rpython.rlib.rstring import UnicodeBuilder -from pypy.module._codecs import interp_codecs -from pypy.module._io.interp_iobase import convert_size -import sys STATE_ZERO, STATE_OK, STATE_DETACHED = range(3) @@ -267,6 +267,27 @@ errors = GetSetProperty(W_TextIOBase.errors_get_w), ) + +def _determine_encoding(space, encoding): + if encoding is not None: + return space.wrap(encoding) + + try: + w_locale = space.call_method(space.builtin, '__import__', + space.wrap('locale')) + w_encoding = space.call_method(w_locale, 'getpreferredencoding') + except OperationError as e: + # getpreferredencoding() may also raise ImportError + if not e.match(space, space.w_ImportError): + raise + return space.wrap('ascii') + else: + if space.isinstance_w(w_encoding, space.w_unicode): + return w_encoding + + raise OperationError(space.w_IOError, space.wrap( + "could not determine default encoding")) + class PositionCookie(object): def __init__(self, bigint): self.start_pos = bigint.ulonglongmask() @@ -335,32 +356,8 @@ w_errors=None, w_newline=None, line_buffering=0, write_through=0): self.state = STATE_ZERO - self.w_buffer = w_buffer - - # Set encoding - self.w_encoding = None - if encoding is None: - try: - w_locale = space.call_method(space.builtin, '__import__', - space.wrap("locale")) - self.w_encoding = space.call_method(w_locale, - "getpreferredencoding") - except OperationError, e: - # getpreferredencoding() may also raise ImportError - if not e.match(space, space.w_ImportError): - raise - self.w_encoding = space.wrap("ascii") - else: - if not space.isinstance_w(self.w_encoding, space.w_unicode): - self.w_encoding = None - if self.w_encoding: - pass - elif encoding is not None: - self.w_encoding = space.wrap(encoding) - else: - raise OperationError(space.w_IOError, space.wrap( - "could not determine default encoding")) + self.w_encoding = _determine_encoding(space, encoding) if space.is_none(w_errors): w_errors = space.wrap("strict") diff --git a/rpython/rlib/test/test_runicode.py b/rpython/rlib/test/test_runicode.py --- a/rpython/rlib/test/test_runicode.py +++ b/rpython/rlib/test/test_runicode.py @@ -738,9 +738,9 @@ py.test.skip("requires cp932 locale") s = '\xff\xf4\x8f\xbf\xbf' - encoder = self.getdecoder('mbcs') - assert encoder(s, len(s), 'strict') == (u'\U0010ffff', 5) - py.test.raises(UnicodeEncodeError, encoder, s, len(s), 'strict', + decoder = self.getdecoder('mbcs') + assert decoder(s, len(s), 'strict') == (u'\U0010ffff', 5) + py.test.raises(UnicodeEncodeError, decoder, s, len(s), 'strict', force_ignore=False) def test_mbcs_encode_force_replace(self): From noreply at buildbot.pypy.org Fri Apr 26 03:32:09 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Fri, 26 Apr 2013 03:32:09 +0200 (CEST) Subject: [pypy-commit] pypy py3k: cpython issue12802: win's ERROR_DIRECTORY -> ENOTDIR Message-ID: <20130426013209.AD1B91C3435@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63620:c78ecde0e05e Date: 2013-04-25 18:27 -0700 http://bitbucket.org/pypy/pypy/changeset/c78ecde0e05e/ Log: cpython issue12802: win's ERROR_DIRECTORY -> ENOTDIR diff --git a/pypy/module/exceptions/test/test_exc.py b/pypy/module/exceptions/test/test_exc.py --- a/pypy/module/exceptions/test/test_exc.py +++ b/pypy/module/exceptions/test/test_exc.py @@ -4,6 +4,9 @@ class AppTestExc(object): spaceconfig = dict(usemodules=('exceptions',)) + def setup_class(cls): + cls.w_file = cls.space.wrap(__file__) + def test_baseexc(self): assert str(BaseException()) == '' assert repr(BaseException()) == 'BaseException()' @@ -250,3 +253,15 @@ def test_set_traceback(self): e = Exception() raises(TypeError, "e.__traceback__ = 42") + + def test_errno_ENOTDIR(self): + # CPython issue #12802: "not a directory" errors are ENOTDIR + # even on Windows + import os + import errno + try: + os.listdir(self.file) + except OSError as e: + assert e.errno == errno.ENOTDIR + else: + assert False, "Expected OSError" diff --git a/rpython/rlib/rwin32.py b/rpython/rlib/rwin32.py --- a/rpython/rlib/rwin32.py +++ b/rpython/rlib/rwin32.py @@ -178,8 +178,13 @@ int i; for(i=1; i < 65000; i++) { _dosmaperr(i); - if (errno == EINVAL) - continue; + if (errno == EINVAL) { + /* CPython issue #12802 */ + if (i == ERROR_DIRECTORY) + errno = ENOTDIR; + else + continue; + } printf("%d\t%d\n", i, errno); } return 0; @@ -201,7 +206,7 @@ 132: 13, 145: 41, 158: 13, 161: 2, 164: 11, 167: 13, 183: 17, 188: 8, 189: 8, 190: 8, 191: 8, 192: 8, 193: 8, 194: 8, 195: 8, 196: 8, 197: 8, 198: 8, 199: 8, 200: 8, 201: 8, - 202: 8, 206: 2, 215: 11, 1816: 12, + 202: 8, 206: 2, 215: 11, 267: 20, 1816: 12, } else: output = os.popen(str(exename)) From noreply at buildbot.pypy.org Fri Apr 26 03:32:10 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Fri, 26 Apr 2013 03:32:10 +0200 (CEST) Subject: [pypy-commit] pypy py3k: use the expected keyword arg names Message-ID: <20130426013210.DE3A71C3435@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63621:01e9f6182ee0 Date: 2013-04-25 18:27 -0700 http://bitbucket.org/pypy/pypy/changeset/01e9f6182ee0/ Log: use the expected keyword arg names diff --git a/pypy/module/_winreg/interp_winreg.py b/pypy/module/_winreg/interp_winreg.py --- a/pypy/module/_winreg/interp_winreg.py +++ b/pypy/module/_winreg/interp_winreg.py @@ -714,8 +714,8 @@ raise OperationError(space.w_NotImplementedError, space.wrap( "not implemented on this platform")) - at unwrap_spec(subkey=str) -def DeleteKeyEx(space, w_key, subkey): + at unwrap_spec(sub_key=str, reserved=int, access=rffi.r_uint) +def DeleteKeyEx(space, w_key, sub_key, reserved=0, access=rwinreg.KEY_WOW64_64KEY): """DeleteKeyEx(key, sub_key, sam, res) - Deletes the specified key. key is an already open key, or any one of the predefined HKEY_* constants. From noreply at buildbot.pypy.org Fri Apr 26 03:32:12 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Fri, 26 Apr 2013 03:32:12 +0200 (CEST) Subject: [pypy-commit] pypy py3k: currently on the 3.2.3 stdlib Message-ID: <20130426013212.18C601C3435@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63622:dc885e1d6023 Date: 2013-04-25 18:28 -0700 http://bitbucket.org/pypy/pypy/changeset/dc885e1d6023/ Log: currently on the 3.2.3 stdlib diff --git a/pypy/module/sys/version.py b/pypy/module/sys/version.py --- a/pypy/module/sys/version.py +++ b/pypy/module/sys/version.py @@ -7,7 +7,7 @@ from pypy.interpreter import gateway #XXX # the release serial 42 is not in range(16) -CPYTHON_VERSION = (3, 2, 2, "final", 0) +CPYTHON_VERSION = (3, 2, 3, "final", 0) #XXX # sync CPYTHON_VERSION with patchlevel.h, package.py CPYTHON_API_VERSION = 1013 #XXX # sync with include/modsupport.h From noreply at buildbot.pypy.org Fri Apr 26 04:20:39 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Fri, 26 Apr 2013 04:20:39 +0200 (CEST) Subject: [pypy-commit] pypy py3k: add os.device_encoding Message-ID: <20130426022039.D1E671C0328@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63623:0c9a10156aae Date: 2013-04-25 18:47 -0700 http://bitbucket.org/pypy/pypy/changeset/0c9a10156aae/ Log: add os.device_encoding diff --git a/pypy/module/posix/__init__.py b/pypy/module/posix/__init__.py --- a/pypy/module/posix/__init__.py +++ b/pypy/module/posix/__init__.py @@ -88,6 +88,7 @@ 'kill' : 'interp_posix.kill', 'abort' : 'interp_posix.abort', 'urandom' : 'interp_posix.urandom', + 'device_encoding' : 'interp_posix.device_encoding', } if hasattr(os, 'chown'): diff --git a/pypy/module/posix/interp_posix.py b/pypy/module/posix/interp_posix.py --- a/pypy/module/posix/interp_posix.py +++ b/pypy/module/posix/interp_posix.py @@ -1193,3 +1193,24 @@ return space.wrapbytes(rurandom.urandom(context, n)) except OSError, e: raise wrap_oserror(space, e) + + at unwrap_spec(fd=int) +def device_encoding(space, fd): + """device_encoding(fd) -> str + + Return a string describing the encoding of the device if the output + is a terminal; else return None. + """ + if not (rposix.is_valid_fd(fd) and os.isatty(fd)): + return space.w_None + if _WIN32: + if fd == 0: + return 'cp%d' % rwin32.GetConsoleCP() + if fd in (1, 2): + return 'cp%d' % rwin32.GetConsoleOutputCP() + from rpython.rlib import rlocale + if rlocale.HAVE_LANGINFO: + codeset = rlocale.nl_langinfo(rlocale.CODESET) + if codeset: + return space.wrap(codeset) + return space.w_None diff --git a/pypy/module/posix/test/test_posix2.py b/pypy/module/posix/test/test_posix2.py --- a/pypy/module/posix/test/test_posix2.py +++ b/pypy/module/posix/test/test_posix2.py @@ -931,6 +931,12 @@ assert False, "urandom() always returns the same string" # Or very unlucky + def test_device_encoding(self): + import sys + encoding = self.posix.device_encoding(sys.stdout.fileno()) + # just ensure it returns something reasonable + assert encoding is None or type(encoding) is str + class AppTestEnvironment(object): def setup_class(cls): From noreply at buildbot.pypy.org Fri Apr 26 04:20:41 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Fri, 26 Apr 2013 04:20:41 +0200 (CEST) Subject: [pypy-commit] pypy py3k: simply set the default locale here at startup, so nl_langinfo can be used Message-ID: <20130426022041.1A3721C0328@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63624:4077749cb58a Date: 2013-04-25 19:19 -0700 http://bitbucket.org/pypy/pypy/changeset/4077749cb58a/ Log: simply set the default locale here at startup, so nl_langinfo can be used correctly early on diff --git a/pypy/goal/targetpypystandalone.py b/pypy/goal/targetpypystandalone.py --- a/pypy/goal/targetpypystandalone.py +++ b/pypy/goal/targetpypystandalone.py @@ -7,13 +7,10 @@ from pypy.tool.ann_override import PyPyAnnotatorPolicy from rpython.config.config import to_optparse, make_dict, SUPPRESS_USAGE from rpython.config.config import ConflictConfigError +from rpython.rlib import rlocale from pypy.tool.option import make_objspace from pypy.conftest import pypydir -_WIN32 = sys.platform == 'win32' -if not _WIN32: - from rpython.rlib.rlocale import LC_ALL, setlocale - thisdir = py.path.local(__file__).dirpath() try: @@ -53,14 +50,11 @@ try: try: space.call_function(w_run_toplevel, w_call_startup_gateway) - if not _WIN32: - oldlocale = setlocale(LC_ALL, None) - setlocale(LC_ALL, '') + if rlocale.HAVE_LANGINFO: + rlocale.setlocale(rlocale.LC_ALL, '') w_executable = space.fsdecode(space.wrapbytes(argv[0])) w_argv = space.newlist([space.fsdecode(space.wrapbytes(s)) for s in argv[1:]]) - if not _WIN32: - setlocale(LC_ALL, oldlocale) w_exitcode = space.call_function(w_entry_point, w_executable, w_argv) exitcode = space.int_w(w_exitcode) # try to pull it all in From noreply at buildbot.pypy.org Fri Apr 26 04:20:42 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Fri, 26 Apr 2013 04:20:42 +0200 (CEST) Subject: [pypy-commit] pypy py3k: attempt to get the default encoding from os.device_encoding Message-ID: <20130426022042.5A7DE1C0328@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63625:49a2889ff518 Date: 2013-04-25 19:19 -0700 http://bitbucket.org/pypy/pypy/changeset/49a2889ff518/ Log: attempt to get the default encoding from os.device_encoding diff --git a/pypy/module/_io/interp_textio.py b/pypy/module/_io/interp_textio.py --- a/pypy/module/_io/interp_textio.py +++ b/pypy/module/_io/interp_textio.py @@ -268,10 +268,24 @@ ) -def _determine_encoding(space, encoding): +def _determine_encoding(space, encoding, w_buffer): if encoding is not None: return space.wrap(encoding) + # Try os.device_encoding(fileno) + try: + w_fileno = space.call_method(w_buffer, 'fileno') + except OperationError as e: + from pypy.module._io.interp_io import Cache + if not (e.match(space, space.w_AttributeError) or + e.match(space, space.fromcache(Cache).w_unsupportedoperation)): + raise + else: + w_os = space.call_method(space.builtin, '__import__', space.wrap('os')) + w_encoding = space.call_method(w_os, 'device_encoding', w_fileno) + if space.isinstance_w(w_encoding, space.w_unicode): + return w_encoding + try: w_locale = space.call_method(space.builtin, '__import__', space.wrap('locale')) @@ -357,7 +371,7 @@ write_through=0): self.state = STATE_ZERO self.w_buffer = w_buffer - self.w_encoding = _determine_encoding(space, encoding) + self.w_encoding = _determine_encoding(space, encoding, w_buffer) if space.is_none(w_errors): w_errors = space.wrap("strict") diff --git a/pypy/module/_io/test/test_textio.py b/pypy/module/_io/test/test_textio.py --- a/pypy/module/_io/test/test_textio.py +++ b/pypy/module/_io/test/test_textio.py @@ -431,3 +431,14 @@ _check(dec) dec = _io.IncrementalNewlineDecoder(None, translate=True) _check(dec) + + def test_device_encoding(self): + import os + import sys + encoding = os.device_encoding(sys.stderr.fileno()) + if not encoding: + skip("Requires a result from " + "os.device_encoding(sys.stderr.fileno())") + import _io + f = _io.TextIOWrapper(sys.stderr.buffer) + assert f.encoding == encoding From noreply at buildbot.pypy.org Fri Apr 26 04:30:51 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Fri, 26 Apr 2013 04:30:51 +0200 (CEST) Subject: [pypy-commit] pypy py3k: fix translation Message-ID: <20130426023051.8EBF91C0328@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63626:157809b274f4 Date: 2013-04-25 19:30 -0700 http://bitbucket.org/pypy/pypy/changeset/157809b274f4/ Log: fix translation diff --git a/pypy/module/posix/interp_posix.py b/pypy/module/posix/interp_posix.py --- a/pypy/module/posix/interp_posix.py +++ b/pypy/module/posix/interp_posix.py @@ -1205,9 +1205,9 @@ return space.w_None if _WIN32: if fd == 0: - return 'cp%d' % rwin32.GetConsoleCP() + return space.wrap('cp%d' % rwin32.GetConsoleCP()) if fd in (1, 2): - return 'cp%d' % rwin32.GetConsoleOutputCP() + return space.wrap('cp%d' % rwin32.GetConsoleOutputCP()) from rpython.rlib import rlocale if rlocale.HAVE_LANGINFO: codeset = rlocale.nl_langinfo(rlocale.CODESET) From noreply at buildbot.pypy.org Fri Apr 26 06:23:44 2013 From: noreply at buildbot.pypy.org (alex_gaynor) Date: Fri, 26 Apr 2013 06:23:44 +0200 (CEST) Subject: [pypy-commit] pypy default: Inline into ll_setslice (which is really just an ll_arraycopy). Fixed a bug in the heapcache that it revealed. Message-ID: <20130426042345.010EB1C02DA@cobra.cs.uni-duesseldorf.de> Author: Alex Gaynor Branch: Changeset: r63627:23defdb27411 Date: 2013-04-25 21:22 -0700 http://bitbucket.org/pypy/pypy/changeset/23defdb27411/ Log: Inline into ll_setslice (which is really just an ll_arraycopy). Fixed a bug in the heapcache that it revealed. diff --git a/rpython/jit/codewriter/support.py b/rpython/jit/codewriter/support.py --- a/rpython/jit/codewriter/support.py +++ b/rpython/jit/codewriter/support.py @@ -203,7 +203,6 @@ _ll_2_list_append = rlist.ll_append _ll_2_list_extend = rlist.ll_extend _ll_3_list_insert = rlist.ll_insert_nonneg -_ll_4_list_setslice = rlist.ll_listsetslice _ll_2_list_delslice_startonly = rlist.ll_listdelslice_startonly _ll_3_list_delslice_startstop = rlist.ll_listdelslice_startstop _ll_2_list_inplace_mul = rlist.ll_inplace_mul diff --git a/rpython/jit/metainterp/heapcache.py b/rpython/jit/metainterp/heapcache.py --- a/rpython/jit/metainterp/heapcache.py +++ b/rpython/jit/metainterp/heapcache.py @@ -125,7 +125,7 @@ for descr, cache in self.heap_array_cache.iteritems(): for idx, cache in cache.iteritems(): for frombox in cache.keys(): - if frombox not in self.new_boxes: + if not self.new_boxes.get(frombox, False): del cache[frombox] return else: diff --git a/rpython/jit/metainterp/test/test_list.py b/rpython/jit/metainterp/test/test_list.py --- a/rpython/jit/metainterp/test/test_list.py +++ b/rpython/jit/metainterp/test/test_list.py @@ -128,10 +128,10 @@ res = self.interp_operations(f, [], listops=True) assert res == 10 - def test_arraycopy_bug(self): + def test_arraycopy_bug(self): def f(): l = [1, 2, 3, 4] - l2 = [1, 2, 3, 4] + l2 = [1, 2, 3, 5] l[2] = 13 l2[0:len(l2)] = l[:] return l2[0] + l2[1] + l2[2] + l2[3] diff --git a/rpython/rtyper/rlist.py b/rpython/rtyper/rlist.py --- a/rpython/rtyper/rlist.py +++ b/rpython/rtyper/rlist.py @@ -955,7 +955,7 @@ "setslice cannot resize lists in RPython") # XXX ...but it would be easy enough to support if really needed ll_arraycopy(l2, l1, 0, start, count) -ll_listsetslice.oopspec = 'list.setslice(l1, start, stop, l2)' + # ____________________________________________________________ # From noreply at buildbot.pypy.org Fri Apr 26 06:23:46 2013 From: noreply at buildbot.pypy.org (alex_gaynor) Date: Fri, 26 Apr 2013 06:23:46 +0200 (CEST) Subject: [pypy-commit] pypy default: merged upstream Message-ID: <20130426042346.2FEB71C02DA@cobra.cs.uni-duesseldorf.de> Author: Alex Gaynor Branch: Changeset: r63628:bbf532c23b25 Date: 2013-04-25 21:22 -0700 http://bitbucket.org/pypy/pypy/changeset/bbf532c23b25/ Log: merged upstream diff --git a/pypy/module/_io/interp_textio.py b/pypy/module/_io/interp_textio.py --- a/pypy/module/_io/interp_textio.py +++ b/pypy/module/_io/interp_textio.py @@ -1,16 +1,16 @@ -from pypy.module._io.interp_iobase import W_IOBase -from pypy.interpreter.typedef import ( - TypeDef, GetSetProperty, interp_attrproperty_w, interp_attrproperty, - generic_new_descr) -from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault +import sys + from pypy.interpreter.baseobjspace import W_Root from pypy.interpreter.error import OperationError -from rpython.rlib.rarithmetic import intmask, r_ulonglong, r_uint +from pypy.interpreter.gateway import WrappedDefault, interp2app, unwrap_spec +from pypy.interpreter.typedef import ( + GetSetProperty, TypeDef, generic_new_descr, interp_attrproperty, + interp_attrproperty_w) +from pypy.module._codecs import interp_codecs +from pypy.module._io.interp_iobase import W_IOBase, convert_size +from rpython.rlib.rarithmetic import intmask, r_uint, r_ulonglong from rpython.rlib.rbigint import rbigint from rpython.rlib.rstring import UnicodeBuilder -from pypy.module._codecs import interp_codecs -from pypy.module._io.interp_iobase import convert_size -import sys STATE_ZERO, STATE_OK, STATE_DETACHED = range(3) @@ -270,6 +270,27 @@ errors = GetSetProperty(W_TextIOBase.errors_get_w), ) + +def _determine_encoding(space, encoding): + if encoding is not None: + return space.wrap(encoding) + + try: + w_locale = space.call_method(space.builtin, '__import__', + space.wrap('locale')) + w_encoding = space.call_method(w_locale, 'getpreferredencoding') + except OperationError as e: + # getpreferredencoding() may also raise ImportError + if not e.match(space, space.w_ImportError): + raise + return space.wrap('ascii') + else: + if space.isinstance_w(w_encoding, space.w_str): + return w_encoding + + raise OperationError(space.w_IOError, space.wrap( + "could not determine default encoding")) + class PositionCookie(object): def __init__(self, bigint): self.start_pos = bigint.ulonglongmask() @@ -337,32 +358,8 @@ def descr_init(self, space, w_buffer, encoding=None, w_errors=None, w_newline=None, line_buffering=0): self.state = STATE_ZERO - self.w_buffer = w_buffer - - # Set encoding - self.w_encoding = None - if encoding is None: - try: - w_locale = space.call_method(space.builtin, '__import__', - space.wrap("locale")) - self.w_encoding = space.call_method(w_locale, - "getpreferredencoding") - except OperationError, e: - # getpreferredencoding() may also raise ImportError - if not e.match(space, space.w_ImportError): - raise - self.w_encoding = space.wrap("ascii") - else: - if not space.isinstance_w(self.w_encoding, space.w_str): - self.w_encoding = None - if self.w_encoding: - pass - elif encoding is not None: - self.w_encoding = space.wrap(encoding) - else: - raise OperationError(space.w_IOError, space.wrap( - "could not determine default encoding")) + self.w_encoding = _determine_encoding(space, encoding) if space.is_none(w_errors): w_errors = space.wrap("strict") From noreply at buildbot.pypy.org Fri Apr 26 10:43:24 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 26 Apr 2013 10:43:24 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Weakrefs, some small simplifications. Message-ID: <20130426084324.7A4701C026F@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63629:8cf66f2f61cd Date: 2013-04-26 10:29 +0200 http://bitbucket.org/pypy/pypy/changeset/8cf66f2f61cd/ Log: Weakrefs, some small simplifications. diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py --- a/pypy/interpreter/baseobjspace.py +++ b/pypy/interpreter/baseobjspace.py @@ -165,7 +165,7 @@ self.invoke_finalizer() def invoke_finalizer(self): - raise NotImplementedError + raise NotImplementedError # must be overridden def finalizer_perform(self, space, descrname, callback, *args): """For use in invoke_finalizer(). First check if we're called diff --git a/pypy/module/_weakref/interp__weakref.py b/pypy/module/_weakref/interp__weakref.py --- a/pypy/module/_weakref/interp__weakref.py +++ b/pypy/module/_weakref/interp__weakref.py @@ -3,7 +3,7 @@ from pypy.interpreter.error import OperationError from pypy.interpreter.gateway import interp2app, ObjSpace from pypy.interpreter.typedef import TypeDef -from rpython.rlib import jit +from rpython.rlib import rgc, jit from rpython.rlib.rshrinklist import AbstractShrinkList from rpython.rlib.objectmodel import specialize import weakref @@ -14,7 +14,7 @@ return wref() is not None -class WeakrefLifeline(W_Root): +class WeakrefLifeline(object): cached_weakref = None cached_proxy = None other_refs_weak = None @@ -97,37 +97,12 @@ return w_ref return space.w_None - -class WeakrefLifelineWithCallbacks(WeakrefLifeline): - - def __init__(self, space, oldlifeline=None): - self.space = space - if oldlifeline is not None: - self.cached_weakref = oldlifeline.cached_weakref - self.cached_proxy = oldlifeline.cached_proxy - self.other_refs_weak = oldlifeline.other_refs_weak - - def __del__(self): - """This runs when the interp-level object goes away, and allows - its lifeline to go away. The purpose of this is to activate the - callbacks even if there is no __del__ method on the interp-level - W_Root subclass implementing the object. - """ - if self.other_refs_weak is None: - return - items = self.other_refs_weak.items() - for i in range(len(items)-1, -1, -1): - w_ref = items[i]() - if w_ref is not None and w_ref.w_callable is not None: - w_ref.enqueue_for_destruction(self.space, - W_WeakrefBase.activate_callback, - 'weakref callback of ') - def make_weakref_with_callback(self, w_subtype, w_obj, w_callable): space = self.space w_ref = space.allocate_instance(W_Weakref, w_subtype) W_Weakref.__init__(w_ref, space, w_obj, w_callable) self.append_wref_to(w_ref) + rgc.register_finalizer(self.finalizer) return w_ref def make_proxy_with_callback(self, w_obj, w_callable): @@ -137,8 +112,24 @@ else: w_proxy = W_Proxy(space, w_obj, w_callable) self.append_wref_to(w_proxy) + rgc.register_finalizer(self.finalizer) return w_proxy + def finalizer(self): + """This runs when the interp-level object goes away, and allows + its lifeline to go away. The purpose of this is to activate the + callbacks even if there is no __del__ method on the interp-level + W_Root subclass implementing the object. + """ + assert self.other_refs_weak is not None + items = self.other_refs_weak.items() + for i in range(len(items)-1, -1, -1): + w_ref = items[i]() + if w_ref is not None and w_ref.w_callable is not None: + w_ref.finalizer_perform(self.space, 'weakref callback of ', + self.space.call_function, + w_ref.w_callable, w_ref) + # ____________________________________________________________ class Dummy: @@ -166,10 +157,6 @@ def clear(self): self.w_obj_weak = dead_ref - def activate_callback(w_self): - assert isinstance(w_self, W_WeakrefBase) - w_self.space.call_function(w_self.w_callable, w_self) - def descr__repr__(self, space): w_obj = self.dereference() if w_obj is None: @@ -232,21 +219,13 @@ w_obj.setweakref(space, lifeline) return lifeline -def getlifelinewithcallbacks(space, w_obj): - lifeline = w_obj.getweakref() - if not isinstance(lifeline, WeakrefLifelineWithCallbacks): # or None - oldlifeline = lifeline - lifeline = WeakrefLifelineWithCallbacks(space, oldlifeline) - w_obj.setweakref(space, lifeline) - return lifeline - @jit.dont_look_inside def get_or_make_weakref(space, w_subtype, w_obj): return getlifeline(space, w_obj).get_or_make_weakref(w_subtype, w_obj) @jit.dont_look_inside def make_weakref_with_callback(space, w_subtype, w_obj, w_callable): - lifeline = getlifelinewithcallbacks(space, w_obj) + lifeline = getlifeline(space, w_obj) return lifeline.make_weakref_with_callback(w_subtype, w_obj, w_callable) def descr__new__weakref(space, w_subtype, w_obj, w_callable=None, @@ -319,7 +298,7 @@ @jit.dont_look_inside def make_proxy_with_callback(space, w_obj, w_callable): - lifeline = getlifelinewithcallbacks(space, w_obj) + lifeline = getlifeline(space, w_obj) return lifeline.make_proxy_with_callback(w_obj, w_callable) def proxy(space, w_obj, w_callable=None): diff --git a/pypy/module/_weakref/test/test_weakref.py b/pypy/module/_weakref/test/test_weakref.py --- a/pypy/module/_weakref/test/test_weakref.py +++ b/pypy/module/_weakref/test/test_weakref.py @@ -1,6 +1,9 @@ class AppTestWeakref(object): spaceconfig = dict(usemodules=('_weakref',)) - + + def setup_class(cls): + cls.w_appdirect = cls.space.wrap(cls.runappdirect) + def test_simple(self): import _weakref, gc class A(object): @@ -287,7 +290,11 @@ seen_del = [] class A(object): def __del__(self): - seen_del.append(id(self)) + if self.appdirect: + my_id = id(self) + else: + my_id = aid # might be different when non-translated + seen_del.append(my_id) seen_del.append(w1() is None) seen_del.append(w2() is None) seen_callback = [] From noreply at buildbot.pypy.org Fri Apr 26 10:43:25 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 26 Apr 2013 10:43:25 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Fixes for module/gc. Message-ID: <20130426084325.BE5301C026F@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63630:0c9a73e39d8e Date: 2013-04-26 10:37 +0200 http://bitbucket.org/pypy/pypy/changeset/0c9a73e39d8e/ Log: Fixes for module/gc. diff --git a/pypy/interpreter/executioncontext.py b/pypy/interpreter/executioncontext.py --- a/pypy/interpreter/executioncontext.py +++ b/pypy/interpreter/executioncontext.py @@ -445,16 +445,25 @@ def __init__(self, space): AsyncAction.__init__(self, space) self.in_user_del_action = False + self.finalizers_lock_count = 0 # for use by the gc module + self.enabled_at_app_level = True # for use by the gc module def must_be_between_bytecodes(self): - if not self.in_user_del_action: - from rpython.rlib import rgc + if self.finalizers_lock_count == 0: + if self.in_user_del_action: + # we are between bytecodes and finalizers are not disabled, + # proceed. + return + # finalizers are not disabled but we are not between bytecodes, + # call again later self.fire() - rgc.finalize_later() + # then abort the current execution by raising rgc._FinalizeLater + from rpython.rlib import rgc + rgc.finalize_later() def perform(self, executioncontext, frame): from rpython.rlib import rgc - if not self.in_user_del_action: + if not self.in_user_del_action and self.finalizers_lock_count == 0: self.in_user_del_action = True try: rgc.progress_through_finalizer_queue() From noreply at buildbot.pypy.org Fri Apr 26 10:43:27 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 26 Apr 2013 10:43:27 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Mapdict requires WeakrefLifeline to be a subclass of W_Root. Message-ID: <20130426084327.1254C1C026F@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63631:655de6b677ae Date: 2013-04-26 10:42 +0200 http://bitbucket.org/pypy/pypy/changeset/655de6b677ae/ Log: Mapdict requires WeakrefLifeline to be a subclass of W_Root. diff --git a/pypy/module/_weakref/interp__weakref.py b/pypy/module/_weakref/interp__weakref.py --- a/pypy/module/_weakref/interp__weakref.py +++ b/pypy/module/_weakref/interp__weakref.py @@ -3,7 +3,7 @@ from pypy.interpreter.error import OperationError from pypy.interpreter.gateway import interp2app, ObjSpace from pypy.interpreter.typedef import TypeDef -from rpython.rlib import rgc, jit +from rpython.rlib import jit from rpython.rlib.rshrinklist import AbstractShrinkList from rpython.rlib.objectmodel import specialize import weakref @@ -14,7 +14,7 @@ return wref() is not None -class WeakrefLifeline(object): +class WeakrefLifeline(W_Root): cached_weakref = None cached_proxy = None other_refs_weak = None @@ -50,7 +50,7 @@ self.traverse(WeakrefLifeline._clear_wref) # Note that for no particular reason other than convenience, # weakref callbacks are not invoked eagerly here. They are - # invoked by self.__del__() anyway. + # invoked by self.invoke_finalizer() anyway. def get_or_make_weakref(self, w_subtype, w_obj): space = self.space @@ -102,7 +102,7 @@ w_ref = space.allocate_instance(W_Weakref, w_subtype) W_Weakref.__init__(w_ref, space, w_obj, w_callable) self.append_wref_to(w_ref) - rgc.register_finalizer(self.finalizer) + self.register_finalizer() return w_ref def make_proxy_with_callback(self, w_obj, w_callable): @@ -112,10 +112,10 @@ else: w_proxy = W_Proxy(space, w_obj, w_callable) self.append_wref_to(w_proxy) - rgc.register_finalizer(self.finalizer) + self.register_finalizer() return w_proxy - def finalizer(self): + def invoke_finalizer(self): """This runs when the interp-level object goes away, and allows its lifeline to go away. The purpose of this is to activate the callbacks even if there is no __del__ method on the interp-level From noreply at buildbot.pypy.org Fri Apr 26 10:56:58 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 26 Apr 2013 10:56:58 +0200 (CEST) Subject: [pypy-commit] pypy default: Kill CO_CONTAINSGLOBALS, which was used by celldict.py but no longer is. Message-ID: <20130426085658.421851C31E9@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63632:f48d790fc17b Date: 2013-04-26 10:56 +0200 http://bitbucket.org/pypy/pypy/changeset/f48d790fc17b/ Log: Kill CO_CONTAINSGLOBALS, which was used by celldict.py but no longer is. diff --git a/pypy/interpreter/astcompiler/consts.py b/pypy/interpreter/astcompiler/consts.py --- a/pypy/interpreter/astcompiler/consts.py +++ b/pypy/interpreter/astcompiler/consts.py @@ -15,8 +15,6 @@ CO_FUTURE_WITH_STATEMENT = 0x8000 CO_FUTURE_PRINT_FUNCTION = 0x10000 CO_FUTURE_UNICODE_LITERALS = 0x20000 -CO_CONTAINSGLOBALS = 0x80000 # pypy-specific: need to check that it's not used - # by any other flag PyCF_SOURCE_IS_UTF8 = 0x0100 PyCF_DONT_IMPLY_DEDENT = 0x0200 diff --git a/pypy/interpreter/pycode.py b/pypy/interpreter/pycode.py --- a/pypy/interpreter/pycode.py +++ b/pypy/interpreter/pycode.py @@ -12,7 +12,7 @@ from pypy.interpreter.gateway import unwrap_spec from pypy.interpreter.astcompiler.consts import ( CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS, CO_NESTED, - CO_GENERATOR, CO_CONTAINSGLOBALS) + CO_GENERATOR) from pypy.tool.stdlib_opcode import opcodedesc, HAVE_ARGUMENT from rpython.rlib.rarithmetic import intmask from rpython.rlib.objectmodel import compute_hash @@ -88,8 +88,6 @@ self._initialize() def _initialize(self): - self._init_flags() - if self.co_cellvars: argcount = self.co_argcount assert argcount >= 0 # annotator hint @@ -134,22 +132,6 @@ '__pypy__' not in sys.builtin_module_names): raise Exception("CPython host codes should not be rendered") - def _init_flags(self): - co_code = self.co_code - next_instr = 0 - while next_instr < len(co_code): - opcode = ord(co_code[next_instr]) - next_instr += 1 - if opcode >= HAVE_ARGUMENT: - next_instr += 2 - while opcode == opcodedesc.EXTENDED_ARG.index: - opcode = ord(co_code[next_instr]) - next_instr += 3 - if opcode == opcodedesc.LOAD_GLOBAL.index: - self.co_flags |= CO_CONTAINSGLOBALS - elif opcode == opcodedesc.LOAD_NAME.index: - self.co_flags |= CO_CONTAINSGLOBALS - co_names = property(lambda self: [self.space.unwrap(w_name) for w_name in self.co_names_w]) # for trace def signature(self): diff --git a/pypy/interpreter/test/test_code.py b/pypy/interpreter/test/test_code.py --- a/pypy/interpreter/test/test_code.py +++ b/pypy/interpreter/test/test_code.py @@ -9,7 +9,6 @@ filename = filename[:-1] cls.w_file = cls.space.wrap(filename) - cls.w_CO_CONTAINSGLOBALS = cls.space.wrap(consts.CO_CONTAINSGLOBALS) def test_attributes(self): def f(): pass @@ -183,27 +182,3 @@ # CO_NESTED assert f(4).func_code.co_flags & 0x10 assert f.func_code.co_flags & 0x10 == 0 - # check for CO_CONTAINSGLOBALS - assert not f.func_code.co_flags & self.CO_CONTAINSGLOBALS - - - exec """if 1: - r = range - def f(): - return [l for l in r(100)] - def g(): - return [l for l in [1, 2, 3, 4]] -""" - - # check for CO_CONTAINSGLOBALS - assert f.func_code.co_flags & self.CO_CONTAINSGLOBALS - assert not g.func_code.co_flags & self.CO_CONTAINSGLOBALS - - exec """if 1: - b = 2 - def f(x): - exec "a = 1"; - return a + b + x -""" - # check for CO_CONTAINSGLOBALS - assert f.func_code.co_flags & self.CO_CONTAINSGLOBALS From noreply at buildbot.pypy.org Fri Apr 26 12:11:55 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 26 Apr 2013 12:11:55 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Fix generator. Message-ID: <20130426101155.BD8871C026F@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63634:a242524f2ed4 Date: 2013-04-26 12:11 +0200 http://bitbucket.org/pypy/pypy/changeset/a242524f2ed4/ Log: Fix generator. diff --git a/pypy/interpreter/generator.py b/pypy/interpreter/generator.py --- a/pypy/interpreter/generator.py +++ b/pypy/interpreter/generator.py @@ -13,6 +13,7 @@ self.frame = frame # turned into None when frame_finished_execution self.pycode = frame.pycode self.running = False + self.register_finalizer() def descr__repr__(self, space): code_name = self.pycode.co_name @@ -142,7 +143,7 @@ code_name = self.pycode.co_name return space.wrap(code_name) - def __del__(self): + def invoke_finalizer(self): # Only bother enqueuing self to raise an exception if the frame is # still not finished and finally or except blocks are present. self.clear_all_weakrefs() @@ -150,9 +151,9 @@ block = self.frame.lastblock while block is not None: if not isinstance(block, LoopBlock): - self.enqueue_for_destruction(self.space, - GeneratorIterator.descr_close, - "interrupting generator of ") + self.finalizer_perform(self.space, + "interrupting generator of ", + self.descr_close) break block = block.previous From noreply at buildbot.pypy.org Fri Apr 26 13:49:33 2013 From: noreply at buildbot.pypy.org (mattip) Date: Fri, 26 Apr 2013 13:49:33 +0200 (CEST) Subject: [pypy-commit] pypy win32-fixes3: app_main.py needs __pypy__ for windows console codepage handling Message-ID: <20130426114933.B260E1C3146@cobra.cs.uni-duesseldorf.de> Author: mattip Branch: win32-fixes3 Changeset: r63635:fbe73ecc1d01 Date: 2013-04-20 22:16 +0300 http://bitbucket.org/pypy/pypy/changeset/fbe73ecc1d01/ Log: app_main.py needs __pypy__ for windows console codepage handling diff --git a/pypy/interpreter/test2/test_app_main.py b/pypy/interpreter/test2/test_app_main.py --- a/pypy/interpreter/test2/test_app_main.py +++ b/pypy/interpreter/test2/test_app_main.py @@ -577,6 +577,11 @@ class TestNonInteractive: def run_with_status_code(self, cmdline, senddata='', expect_prompt=False, expect_banner=False, python_flags='', env=None): + if os.name == 'nt': + try: + import __pypy__ + except: + py.test.skip('app_main cannot run on non-pypy for windows') cmdline = '%s %s "%s" %s' % (sys.executable, python_flags, app_main, cmdline) print 'POPEN:', cmdline @@ -705,6 +710,11 @@ assert 'copyright' not in data def test_non_interactive_stdout_fully_buffered(self): + if os.name == 'nt': + try: + import __pypy__ + except: + py.test.skip('app_main cannot run on non-pypy for windows') path = getscript(r""" import sys, time sys.stdout.write('\x00(STDOUT)\n\x00') # stays in buffers @@ -725,6 +735,11 @@ def test_non_interactive_stdout_unbuffered(self, monkeypatch): monkeypatch.setenv('PYTHONUNBUFFERED', '1') + if os.name == 'nt': + try: + import __pypy__ + except: + py.test.skip('app_main cannot run on non-pypy for windows') path = getscript(r""" import sys, time sys.stdout.write('\x00(STDOUT)\n\x00') From noreply at buildbot.pypy.org Fri Apr 26 13:49:35 2013 From: noreply at buildbot.pypy.org (mattip) Date: Fri, 26 Apr 2013 13:49:35 +0200 (CEST) Subject: [pypy-commit] pypy win32-fixes3: wip - respect calling convention in lltypesystem/ll2ctypes Message-ID: <20130426114935.044611C31EA@cobra.cs.uni-duesseldorf.de> Author: mattip Branch: win32-fixes3 Changeset: r63636:b4eed482703d Date: 2013-04-26 14:46 +0300 http://bitbucket.org/pypy/pypy/changeset/b4eed482703d/ Log: wip - respect calling convention in lltypesystem/ll2ctypes diff --git a/rpython/jit/backend/llgraph/runner.py b/rpython/jit/backend/llgraph/runner.py --- a/rpython/jit/backend/llgraph/runner.py +++ b/rpython/jit/backend/llgraph/runner.py @@ -64,14 +64,15 @@ self.args = args class CallDescr(AbstractDescr): - def __init__(self, RESULT, ARGS, extrainfo): + def __init__(self, RESULT, ARGS, extrainfo, abi): self.RESULT = RESULT self.ARGS = ARGS self.extrainfo = extrainfo + self.abi = abi def __repr__(self): - return 'CallDescr(%r, %r, %r)' % (self.RESULT, self.ARGS, - self.extrainfo) + return 'CallDescr(%r, %r, %r %r)' % (self.RESULT, self.ARGS, + self.extrainfo, self.abi) def get_extra_info(self): return self.extrainfo @@ -290,13 +291,14 @@ # ------------------------------------------------------------ def calldescrof(self, FUNC, ARGS, RESULT, effect_info): + abi = 0 key = ('call', getkind(RESULT), tuple([getkind(A) for A in ARGS]), - effect_info) + effect_info, abi) try: return self.descrs[key] except KeyError: - descr = CallDescr(RESULT, ARGS, effect_info) + descr = CallDescr(RESULT, ARGS, effect_info, abi) self.descrs[key] = descr return descr @@ -362,7 +364,7 @@ try: return self.descrs[key] except KeyError: - descr = CallDescr(RESULT, ARGS, extrainfo) + descr = CallDescr(RESULT, ARGS, extrainfo, cif_description.abi) self.descrs[key] = descr return descr @@ -865,7 +867,7 @@ # graph, not to directly execute the python function result = self.cpu.maybe_on_top_of_llinterp(func, call_args, descr.RESULT) else: - FUNC = lltype.FuncType(descr.ARGS, descr.RESULT) + FUNC = lltype.FuncType(descr.ARGS, descr.RESULT, descr.abi) func_to_call = rffi.cast(lltype.Ptr(FUNC), func) result = func_to_call(*call_args) del self.force_guard_op diff --git a/rpython/rlib/clibffi.py b/rpython/rlib/clibffi.py --- a/rpython/rlib/clibffi.py +++ b/rpython/rlib/clibffi.py @@ -503,6 +503,7 @@ def __init__(self, name, argtypes, restype, flags=FUNCFLAG_CDECL): self.name = name + print 'AbstractFuncPtr of',name,'flags',flags,'FUNCFLAG_CDECL',FUNCFLAG_CDECL self.argtypes = argtypes self.restype = restype self.flags = flags diff --git a/rpython/rtyper/lltypesystem/ll2ctypes.py b/rpython/rtyper/lltypesystem/ll2ctypes.py --- a/rpython/rtyper/lltypesystem/ll2ctypes.py +++ b/rpython/rtyper/lltypesystem/ll2ctypes.py @@ -362,12 +362,16 @@ restype = None else: restype = get_ctypes_type(T.TO.RESULT) + if T.TO.CALL_CONV == ctypes._FUNCFLAG_STDCALL: + rettype = ctypes.WINFUNCTYPE + else: + rettype = ctypes.CFUNCTYPE try: kwds = {'use_errno': True} - return ctypes.CFUNCTYPE(restype, *argtypes, **kwds) + return rettype(restype, *argtypes, **kwds) except TypeError: # unexpected 'use_errno' argument, old ctypes version - return ctypes.CFUNCTYPE(restype, *argtypes) + return rettype(restype, *argtypes) elif isinstance(T.TO, lltype.OpaqueType): return ctypes.c_void_p else: diff --git a/rpython/rtyper/lltypesystem/lltype.py b/rpython/rtyper/lltypesystem/lltype.py --- a/rpython/rtyper/lltypesystem/lltype.py +++ b/rpython/rtyper/lltypesystem/lltype.py @@ -540,7 +540,7 @@ class FuncType(ContainerType): _gckind = 'raw' __name__ = 'func' - def __init__(self, args, result): + def __init__(self, args, result, call_conv=0): for arg in args: assert isinstance(arg, LowLevelType) # There are external C functions eating raw structures, not @@ -550,6 +550,7 @@ if isinstance(result, ContainerType): raise TypeError, "function result can only be primitive or pointer" self.RESULT = result + self.CALL_CONV = call_conv def __str__(self): args = ', '.join(map(str, self.ARGS)) From noreply at buildbot.pypy.org Fri Apr 26 13:49:37 2013 From: noreply at buildbot.pypy.org (mattip) Date: Fri, 26 Apr 2013 13:49:37 +0200 (CEST) Subject: [pypy-commit] pypy win32-fixes3: merge default into branch Message-ID: <20130426114937.685BD1C31EC@cobra.cs.uni-duesseldorf.de> Author: mattip Branch: win32-fixes3 Changeset: r63637:3e90a9f82d4c Date: 2013-04-26 14:47 +0300 http://bitbucket.org/pypy/pypy/changeset/3e90a9f82d4c/ Log: merge default into branch diff too long, truncating to 2000 out of 7762 lines diff --git a/lib-python/2.7/test/test_descr.py b/lib-python/2.7/test/test_descr.py --- a/lib-python/2.7/test/test_descr.py +++ b/lib-python/2.7/test/test_descr.py @@ -3592,6 +3592,9 @@ list.__init__(a, sequence=[0, 1, 2]) self.assertEqual(a, [0, 1, 2]) + @unittest.skipIf(test_support.check_impl_detail(pypy=True) and + sys.platform == 'win32', + "XXX: https://bugs.pypy.org/issue1461") def test_recursive_call(self): # Testing recursive __call__() by setting to instance of class... class A(object): diff --git a/lib-python/2.7/test/test_fileio.py b/lib-python/2.7/test/test_fileio.py --- a/lib-python/2.7/test/test_fileio.py +++ b/lib-python/2.7/test/test_fileio.py @@ -318,7 +318,6 @@ self.assertRaises(ValueError, _FileIO, -10) self.assertRaises(OSError, _FileIO, make_bad_fd()) if sys.platform == 'win32': - raise unittest.SkipTest('Set _invalid_parameter_handler for low level io') import msvcrt self.assertRaises(IOError, msvcrt.get_osfhandle, make_bad_fd()) diff --git a/lib_pypy/msvcrt.py b/lib_pypy/msvcrt.py --- a/lib_pypy/msvcrt.py +++ b/lib_pypy/msvcrt.py @@ -8,25 +8,37 @@ # PAC: 2010/08 added MS locking for Whoosh import ctypes +import errno from ctypes_support import standard_c_lib as _c from ctypes_support import get_errno -import errno try: open_osfhandle = _c._open_osfhandle except AttributeError: # we are not on windows raise ImportError -try: from __pypy__ import builtinify -except ImportError: builtinify = lambda f: f +try: from __pypy__ import builtinify, validate_fd +except ImportError: builtinify = validate_fd = lambda f: f 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 +_get_osfhandle = _c._get_osfhandle +_get_osfhandle.argtypes = [ctypes.c_int] +_get_osfhandle.restype = ctypes.c_int + + at builtinify +def get_osfhandle(fd): + """"get_osfhandle(fd) -> file handle + + Return the file handle for the file descriptor fd. Raises IOError if + fd is not recognized.""" + try: + validate_fd(fd) + except OSError as e: + raise IOError(*e.args) + return _get_osfhandle(fd) setmode = _c._setmode setmode.argtypes = [ctypes.c_int, ctypes.c_int] diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py --- a/pypy/config/pypyoption.py +++ b/pypy/config/pypyoption.py @@ -35,7 +35,7 @@ "thread", "itertools", "pyexpat", "_ssl", "cpyext", "array", "binascii", "_multiprocessing", '_warnings', "_collections", "_multibytecodec", "micronumpy", "_ffi", - "_continuation", "_cffi_backend", "_csv"] + "_continuation", "_cffi_backend", "_csv", "cppyy"] )) translation_modules = default_modules.copy() @@ -64,6 +64,8 @@ del working_modules["termios"] del working_modules["_minimal_curses"] + del working_modules["cppyy"] # not tested on win32 + # The _locale module is needed by site.py on Windows default_modules["_locale"] = None @@ -75,7 +77,7 @@ del working_modules["_minimal_curses"] del working_modules["termios"] del working_modules["_multiprocessing"] # depends on rctime - + del working_modules["cppyy"] # depends on ctypes module_dependencies = { diff --git a/pypy/doc/cppyy.rst b/pypy/doc/cppyy.rst --- a/pypy/doc/cppyy.rst +++ b/pypy/doc/cppyy.rst @@ -2,94 +2,128 @@ cppyy: C++ bindings for PyPy ============================ -The cppyy module provides C++ bindings for PyPy by using the reflection -information extracted from C++ header files by means of the -`Reflex package`_. -For this to work, you have to both install Reflex and build PyPy from source, -as the cppyy module is not enabled by default. -Note that the development version of cppyy lives in the reflex-support -branch. -As indicated by this being a branch, support for Reflex is still -experimental. -However, it is functional enough to put it in the hands of those who want -to give it a try. -In the medium term, cppyy will move away from Reflex and instead use -`cling`_ as its backend, which is based on `llvm`_. -Although that will change the logistics on the generation of reflection -information, it will not change the python-side interface. +The cppyy module creates, at run-time, Python-side classes and functions for +C++, by querying a C++ reflection system. +The default system used is `Reflex`_, which extracts the needed information +from C++ header files. +Another current backend is based on `CINT`_, and yet another, more important +one for the medium- to long-term will be based on `cling`_. +The latter sits on top of `llvm`_'s `clang`_, and will therefore allow the use +of C++11. +The work on the cling backend has so far been done only for CPython, but +bringing it to PyPy is a lot less work than developing it in the first place. -.. _`Reflex package`: http://root.cern.ch/drupal/content/reflex +.. _`Reflex`: http://root.cern.ch/drupal/content/reflex +.. _`CINT`: http://root.cern.ch/drupal/content/cint .. _`cling`: http://root.cern.ch/drupal/content/cling .. _`llvm`: http://llvm.org/ +.. _`clang`: http://clang.llvm.org/ + +This document describes the version of cppyy that lives in the main branch of +PyPy. +The development of cppyy happens in the "reflex-support" branch. Motivation ========== -The cppyy module offers two unique features, which result in great -performance as well as better functionality and cross-language integration -than would otherwise be possible. -First, cppyy is written in RPython and therefore open to optimizations by the -JIT up until the actual point of call into C++. -This means that there are no conversions necessary between a garbage collected -and a reference counted environment, as is needed for the use of existing -extension modules written or generated for CPython. -It also means that if variables are already unboxed by the JIT, they can be -passed through directly to C++. -Second, Reflex (and cling far more so) adds dynamic features to C++, thus -greatly reducing impedance mismatches between the two languages. -In fact, Reflex is dynamic enough that you could write the runtime bindings +To provide bindings to another language in CPython, you program to a +generic C-API that exposes many of the interpreter features. +With PyPy, however, there is no such generic C-API, because several of the +interpreter features (e.g. the memory model) are pluggable and therefore +subject to change. +Furthermore, a generic API does not allow any assumptions about the calls +into another language, forcing the JIT to behave conservatively around these +calls and with the objects that cross language boundaries. +In contrast, cppyy does not expose an API, but expects one to be implemented +by a backend. +It makes strong assumptions about the semantics of the API that it uses and +that in turn allows the JIT to make equally strong assumptions. +This is possible, because the expected API is only for providing C++ language +bindings, and does not provide generic programmability. + +The cppyy module further offers two features, which result in improved +performance as well as better functionality and cross-language integration. +First, cppyy itself is written in RPython and therefore open to optimizations +by the JIT up until the actual point of call into C++. +This means for example, that if variables are already unboxed by the JIT, they +can be passed through directly to C++. +Second, a backend such as Reflex (and cling far more so) adds dynamic features +to C++, thus greatly reducing impedance mismatches between the two languages. +For example, Reflex is dynamic enough to allow writing runtime bindings generation in python (as opposed to RPython) and this is used to create very natural "pythonizations" of the bound code. +As another example, cling allows automatic instantiations of templates. + +See this description of the `cppyy architecture`_ for further details. + +.. _`cppyy architecture`: http://morepypy.blogspot.com/2012/06/architecture-of-cppyy.html Installation ============ -For now, the easiest way of getting the latest version of Reflex, is by -installing the ROOT package. -Besides getting the latest version of Reflex, another advantage is that with -the full ROOT package, you can also use your Reflex-bound code on `CPython`_. -`Download`_ a binary or install from `source`_. -Some Linux and Mac systems may have ROOT provided in the list of scientific -software of their packager. -If, however, you prefer a standalone version of Reflex, the best is to get -this `recent snapshot`_, and install like so:: +There are two ways of using cppyy, and the choice depends on how pypy-c was +built: the backend can be builtin, or dynamically loadable. +The former has the disadvantage of requiring pypy-c to be linked with external +C++ libraries (e.g. libReflex.so), but has the advantage of being faster in +some cases. +That advantage will disappear over time, however, with improvements in the +JIT. +Therefore, this document assumes that the dynamically loadable backend is +chosen (it is, by default). +See the `backend documentation`_. - $ tar jxf reflex-2012-05-02.tar.bz2 - $ cd reflex-2012-05-02 - $ build/autogen +.. _`backend documentation`: cppyy_backend.html + +A standalone version of Reflex that also provides the dynamically loadable +backend is available for `download`_. +That version, as well as any other distribution of Reflex (e.g. the one that +comes with `ROOT`_, which may be part of your Linux distribution as part of +the selection of scientific software) will also work for a build with the +builtin backend. + +.. _`download`: http://cern.ch/wlav/reflex-2013-04-23.tar.bz2 +.. _`ROOT`: http://root.cern.ch/ + +Besides Reflex, you probably need a version of `gccxml`_ installed, which is +most easily provided by the packager of your system. +If you read up on gccxml, you will probably notice that it is no longer being +developed and hence will not provide C++11 support. +That's why the medium term plan is to move to cling. +Note that gccxml is only needed to generate reflection libraries. +It is not needed to use them. + +.. _`gccxml`: http://www.gccxml.org + +To install the standalone version of Reflex, after download:: + + $ tar jxf reflex-2013-04-23.tar.bz2 + $ cd reflex-2013-04-23 + $ ./build/autogen $ ./configure $ make && make install -Also, make sure you have a version of `gccxml`_ installed, which is most -easily provided by the packager of your system. -If you read up on gccxml, you'll probably notice that it is no longer being -developed and hence will not provide C++11 support. -That's why the medium term plan is to move to `cling`_. +The usual rules apply: /bin needs to be added to the ``PATH`` and +/lib to the ``LD_LIBRARY_PATH`` environment variable. +For convenience, this document will assume that there is a ``REFLEXHOME`` +variable that points to . +If you downloaded or built the whole of ROOT, ``REFLEXHOME`` should be equal +to ``ROOTSYS``. -.. _`Download`: http://root.cern.ch/drupal/content/downloading-root -.. _`source`: http://root.cern.ch/drupal/content/installing-root-source -.. _`recent snapshot`: http://cern.ch/wlav/reflex-2012-05-02.tar.bz2 -.. _`gccxml`: http://www.gccxml.org +The following is optional, and is only to show how pypy-c can be build +`from source`_, for example to get at the main development branch of cppyy. +The `backend documentation`_ has more details on the backend-specific +prerequisites. -Next, get the `PyPy sources`_, optionally select the reflex-support branch, -and build it. -For the build to succeed, the ``$ROOTSYS`` environment variable must point to -the location of your ROOT (or standalone Reflex) installation, or the -``root-config`` utility must be accessible through ``PATH`` (e.g. by adding -``$ROOTSYS/bin`` to ``PATH``). -In case of the former, include files are expected under ``$ROOTSYS/include`` -and libraries under ``$ROOTSYS/lib``. Then run the translation to build ``pypy-c``:: $ hg clone https://bitbucket.org/pypy/pypy $ cd pypy $ hg up reflex-support # optional - $ cd pypy/goal # This example shows python, but using pypy-c is faster and uses less memory - $ python ../../rpython/bin/rpython.py -O jit --gcrootfinder=shadowstack targetpypystandalone.py --withmod-cppyy + $ python rpython/translator/goal/translate.py --opt=jit pypy/goal/targetpypystandalone --withmod-cppyy This will build a ``pypy-c`` that includes the cppyy module, and through that, Reflex support. @@ -98,12 +132,12 @@ If not, you may want `to obtain a binary distribution`_ to speed up the translation step. -.. _`PyPy sources`: https://bitbucket.org/pypy/pypy/overview +.. _`from source`: https://bitbucket.org/pypy/pypy/overview .. _`to obtain a binary distribution`: http://doc.pypy.org/en/latest/getting-started.html#download-a-pre-built-pypy -Basic example -============= +Basic bindings example +====================== Now test with a trivial example whether all packages are properly installed and functional. @@ -127,7 +161,7 @@ code:: $ genreflex MyClass.h - $ g++ -fPIC -rdynamic -O2 -shared -I$ROOTSYS/include MyClass_rflx.cpp -o libMyClassDict.so -L$ROOTSYS/lib -lReflex + $ g++ -fPIC -rdynamic -O2 -shared -I$REFLEXHOME/include MyClass_rflx.cpp -o libMyClassDict.so -L$REFLEXHOME/lib -lReflex Now you're ready to use the bindings. Since the bindings are designed to look pythonistic, it should be @@ -176,7 +210,7 @@ For example:: $ genreflex MyClass.h --rootmap=libMyClassDict.rootmap --rootmap-lib=libMyClassDict.so - $ g++ -fPIC -rdynamic -O2 -shared -I$ROOTSYS/include MyClass_rflx.cpp -o libMyClassDict.so -L$ROOTSYS/lib -lReflex + $ g++ -fPIC -rdynamic -O2 -shared -I$REFLEXHOME/include MyClass_rflx.cpp -o libMyClassDict.so -L$REFLEXHOME/lib -lReflex where the first option (``--rootmap``) specifies the output file name, and the second option (``--rootmap-lib``) the name of the reflection library where @@ -277,7 +311,7 @@ Now the reflection info can be generated and compiled:: $ genreflex MyAdvanced.h --selection=MyAdvanced.xml - $ g++ -fPIC -rdynamic -O2 -shared -I$ROOTSYS/include MyAdvanced_rflx.cpp -o libAdvExDict.so -L$ROOTSYS/lib -lReflex + $ g++ -fPIC -rdynamic -O2 -shared -I$REFLEXHOME/include MyAdvanced_rflx.cpp -o libAdvExDict.so -L$REFLEXHOME/lib -lReflex and subsequently be used from PyPy:: @@ -336,7 +370,7 @@ bound using:: $ genreflex example.h --deep --rootmap=libexampleDict.rootmap --rootmap-lib=libexampleDict.so - $ g++ -fPIC -rdynamic -O2 -shared -I$ROOTSYS/include example_rflx.cpp -o libexampleDict.so -L$ROOTSYS/lib -lReflex + $ g++ -fPIC -rdynamic -O2 -shared -I$REFLEXHOME/include example_rflx.cpp -o libexampleDict.so -L$REFLEXHOME/lib -lReflex .. _`example code`: cppyy_example.html @@ -595,6 +629,16 @@ All template classes must already exist in the loaded reflection info, they do not work (yet) with the class loader. + For compatibility with other bindings generators, use of square brackets + instead of parenthesis to instantiate templates is supported as well. + +* **templated functions**: Automatically participate in overloading and are + used in the same way as other global functions. + +* **templated methods**: For now, require an explicit selection of the + template parameters. + This will be changed to allow them to participate in overloads as expected. + * **typedefs**: Are simple python references to the actual classes to which they refer. @@ -692,7 +736,7 @@ Run the normal ``genreflex`` and compilation steps:: $ genreflex MyTemplate.h --selection=MyTemplate.xml - $ g++ -fPIC -rdynamic -O2 -shared -I$ROOTSYS/include MyTemplate_rflx.cpp -o libTemplateDict.so -L$ROOTSYS/lib -lReflex + $ g++ -fPIC -rdynamic -O2 -shared -I$REFLEXHOME/include MyTemplate_rflx.cpp -o libTemplateDict.so -L$REFLEXHOME/lib -lReflex Note: this is a dirty corner that clearly could do with some automation, even if the macro already helps. @@ -727,18 +771,18 @@ The fast lane ============= -The following is an experimental feature of cppyy, and that makes it doubly -experimental, so caveat emptor. +The following is an experimental feature of cppyy. +It mostly works, but there are some known issues (e.g. with return-by-value). +Soon it should be the default mode, however. + With a slight modification of Reflex, it can provide function pointers for C++ methods, and hence allow PyPy to call those pointers directly, rather than calling C++ through a Reflex stub. -This results in a rather significant speed-up. -Mind you, the normal stub path is not exactly slow, so for now only use this -out of curiosity or if you really need it. -To install this patch of Reflex, locate the file genreflex-methptrgetter.patch -in pypy/module/cppyy and apply it to the genreflex python scripts found in -``$ROOTSYS/lib``:: +The standalone version of Reflex `provided`_ has been patched, but if you get +Reflex from another source (most likely with a ROOT distribution), locate the +file `genreflex-methptrgetter.patch`_ in pypy/module/cppyy and apply it to +the genreflex python scripts found in ``$ROOTSYS/lib``:: $ cd $ROOTSYS/lib $ patch -p2 < genreflex-methptrgetter.patch @@ -749,8 +793,10 @@ ``-Wno-pmf-conversions`` option to ``g++`` when compiling. The rest works the same way: the fast path will be used transparently (which also means that you can't actually find out whether it is in use, other than -by running a micro-benchmark). +by running a micro-benchmark or a JIT test). +.. _`provided`: http://cern.ch/wlav/reflex-2013-04-23.tar.bz2 +.. _`genreflex-methptrgetter.patch`: https://bitbucket.org/pypy/pypy/src/default/pypy/module/cppyy/genreflex-methptrgetter.patch CPython ======= diff --git a/pypy/doc/cppyy_backend.rst b/pypy/doc/cppyy_backend.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/cppyy_backend.rst @@ -0,0 +1,53 @@ +================== +Backends for cppyy +================== + +The cppyy module needs a backend to provide the C++ reflection information on +which the Python bindings are build. +The backend is called through a C-API, which can be found in the PyPy sources +in: `pypy/module/cppyy/include/capi.h`_. +There are two kinds of API calls: querying about reflection information, which +are used during the creation of Python-side constructs, and making the actual +calls into C++. +The objects passed around are all opaque: cppyy does not make any assumptions +about them, other than that the opaque handles can be copied. +Their definition, however, appears in two places: in the C code (in capi.h), +and on the RPython side (in `capi_types.py`_), so if they are changed, they +need to be changed on both sides. + +.. _`pypy/module/cppyy/include/capi.h`: https://bitbucket.org/pypy/pypy/src/default/pypy/module/cppyy/include/capi.h +.. _`capi_types.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/module/cppyy/capi/capi_types.py + +There are two places where selections in the RPython code affect the choice +(and use) of the backend. +The first is in `pypy/module/cppyy/capi/__init__.py`_:: + + # choose C-API access method: + from pypy.module.cppyy.capi.loadable_capi import * + #from pypy.module.cppyy.capi.builtin_capi import * + +The default is the loadable C-API. +Comment it and uncomment the builtin C-API line, to use the builtin version. + +.. _`pypy/module/cppyy/capi/__init__.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/module/cppyy/capi/__init__.py + +Next, if the builtin C-API is chosen, the specific backend needs to be set as +well (default is Reflex). +This second choice is in `pypy/module/cppyy/capi/builtin_capi.py`_:: + + import reflex_capi as backend + #import cint_capi as backend + +After those choices have been made, built pypy-c as usual. + +.. _`pypy/module/cppyy/capi/builtin_capi.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/module/cppyy/capi/builtin_capi.py + +When building pypy-c from source, keep the following in mind. +If the loadable_capi is chosen, no further prerequisites are needed. +However, for the build of the builtin_capi to succeed, the ``ROOTSYS`` +environment variable must point to the location of your ROOT (or standalone +Reflex in the case of the Reflex backend) installation, or the ``root-config`` +utility must be accessible through ``$PATH`` (e.g. by adding ``$ROOTSYS/bin`` +to ``PATH``). +In case of the former, include files are expected under ``$ROOTSYS/include`` +and libraries under ``$ROOTSYS/lib``. diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -57,10 +57,12 @@ Inline the fast path of newarray in the assembler. Disabled on ARM until we fix issues. +.. branch: reflex-support +Allow dynamic loading of a (Reflex) backend that implements the C-API needed +to provide reflection information .. branches we don't care about .. branch: autoreds -.. branch: reflex-support .. branch: kill-faking .. branch: improved_ebnfparse_error .. branch: task-decorator diff --git a/pypy/interpreter/astcompiler/consts.py b/pypy/interpreter/astcompiler/consts.py --- a/pypy/interpreter/astcompiler/consts.py +++ b/pypy/interpreter/astcompiler/consts.py @@ -15,8 +15,6 @@ CO_FUTURE_WITH_STATEMENT = 0x8000 CO_FUTURE_PRINT_FUNCTION = 0x10000 CO_FUTURE_UNICODE_LITERALS = 0x20000 -CO_CONTAINSGLOBALS = 0x80000 # pypy-specific: need to check that it's not used - # by any other flag PyCF_SOURCE_IS_UTF8 = 0x0100 PyCF_DONT_IMPLY_DEDENT = 0x0200 diff --git a/pypy/interpreter/pycode.py b/pypy/interpreter/pycode.py --- a/pypy/interpreter/pycode.py +++ b/pypy/interpreter/pycode.py @@ -12,7 +12,7 @@ from pypy.interpreter.gateway import unwrap_spec from pypy.interpreter.astcompiler.consts import ( CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS, CO_NESTED, - CO_GENERATOR, CO_CONTAINSGLOBALS) + CO_GENERATOR) from pypy.tool.stdlib_opcode import opcodedesc, HAVE_ARGUMENT from rpython.rlib.rarithmetic import intmask from rpython.rlib.objectmodel import compute_hash @@ -88,8 +88,6 @@ self._initialize() def _initialize(self): - self._init_flags() - if self.co_cellvars: argcount = self.co_argcount assert argcount >= 0 # annotator hint @@ -134,22 +132,6 @@ '__pypy__' not in sys.builtin_module_names): raise Exception("CPython host codes should not be rendered") - def _init_flags(self): - co_code = self.co_code - next_instr = 0 - while next_instr < len(co_code): - opcode = ord(co_code[next_instr]) - next_instr += 1 - if opcode >= HAVE_ARGUMENT: - next_instr += 2 - while opcode == opcodedesc.EXTENDED_ARG.index: - opcode = ord(co_code[next_instr]) - next_instr += 3 - if opcode == opcodedesc.LOAD_GLOBAL.index: - self.co_flags |= CO_CONTAINSGLOBALS - elif opcode == opcodedesc.LOAD_NAME.index: - self.co_flags |= CO_CONTAINSGLOBALS - co_names = property(lambda self: [self.space.unwrap(w_name) for w_name in self.co_names_w]) # for trace def signature(self): diff --git a/pypy/interpreter/test/test_code.py b/pypy/interpreter/test/test_code.py --- a/pypy/interpreter/test/test_code.py +++ b/pypy/interpreter/test/test_code.py @@ -9,7 +9,6 @@ filename = filename[:-1] cls.w_file = cls.space.wrap(filename) - cls.w_CO_CONTAINSGLOBALS = cls.space.wrap(consts.CO_CONTAINSGLOBALS) def test_attributes(self): def f(): pass @@ -183,27 +182,3 @@ # CO_NESTED assert f(4).func_code.co_flags & 0x10 assert f.func_code.co_flags & 0x10 == 0 - # check for CO_CONTAINSGLOBALS - assert not f.func_code.co_flags & self.CO_CONTAINSGLOBALS - - - exec """if 1: - r = range - def f(): - return [l for l in r(100)] - def g(): - return [l for l in [1, 2, 3, 4]] -""" - - # check for CO_CONTAINSGLOBALS - assert f.func_code.co_flags & self.CO_CONTAINSGLOBALS - assert not g.func_code.co_flags & self.CO_CONTAINSGLOBALS - - exec """if 1: - b = 2 - def f(x): - exec "a = 1"; - return a + b + x -""" - # check for CO_CONTAINSGLOBALS - assert f.func_code.co_flags & self.CO_CONTAINSGLOBALS diff --git a/pypy/module/_io/interp_textio.py b/pypy/module/_io/interp_textio.py --- a/pypy/module/_io/interp_textio.py +++ b/pypy/module/_io/interp_textio.py @@ -1,16 +1,16 @@ -from pypy.module._io.interp_iobase import W_IOBase -from pypy.interpreter.typedef import ( - TypeDef, GetSetProperty, interp_attrproperty_w, interp_attrproperty, - generic_new_descr) -from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault +import sys + from pypy.interpreter.baseobjspace import W_Root from pypy.interpreter.error import OperationError -from rpython.rlib.rarithmetic import intmask, r_ulonglong, r_uint +from pypy.interpreter.gateway import WrappedDefault, interp2app, unwrap_spec +from pypy.interpreter.typedef import ( + GetSetProperty, TypeDef, generic_new_descr, interp_attrproperty, + interp_attrproperty_w) +from pypy.module._codecs import interp_codecs +from pypy.module._io.interp_iobase import W_IOBase, convert_size +from rpython.rlib.rarithmetic import intmask, r_uint, r_ulonglong from rpython.rlib.rbigint import rbigint from rpython.rlib.rstring import UnicodeBuilder -from pypy.module._codecs import interp_codecs -from pypy.module._io.interp_iobase import convert_size -import sys STATE_ZERO, STATE_OK, STATE_DETACHED = range(3) @@ -270,6 +270,27 @@ errors = GetSetProperty(W_TextIOBase.errors_get_w), ) + +def _determine_encoding(space, encoding): + if encoding is not None: + return space.wrap(encoding) + + try: + w_locale = space.call_method(space.builtin, '__import__', + space.wrap('locale')) + w_encoding = space.call_method(w_locale, 'getpreferredencoding') + except OperationError as e: + # getpreferredencoding() may also raise ImportError + if not e.match(space, space.w_ImportError): + raise + return space.wrap('ascii') + else: + if space.isinstance_w(w_encoding, space.w_str): + return w_encoding + + raise OperationError(space.w_IOError, space.wrap( + "could not determine default encoding")) + class PositionCookie(object): def __init__(self, bigint): self.start_pos = bigint.ulonglongmask() @@ -337,32 +358,8 @@ def descr_init(self, space, w_buffer, encoding=None, w_errors=None, w_newline=None, line_buffering=0): self.state = STATE_ZERO - self.w_buffer = w_buffer - - # Set encoding - self.w_encoding = None - if encoding is None: - try: - w_locale = space.call_method(space.builtin, '__import__', - space.wrap("locale")) - self.w_encoding = space.call_method(w_locale, - "getpreferredencoding") - except OperationError, e: - # getpreferredencoding() may also raise ImportError - if not e.match(space, space.w_ImportError): - raise - self.w_encoding = space.wrap("ascii") - else: - if not space.isinstance_w(self.w_encoding, space.w_str): - self.w_encoding = None - if self.w_encoding: - pass - elif encoding is not None: - self.w_encoding = space.wrap(encoding) - else: - raise OperationError(space.w_IOError, space.wrap( - "could not determine default encoding")) + self.w_encoding = _determine_encoding(space, encoding) if space.is_none(w_errors): w_errors = space.wrap("strict") diff --git a/pypy/module/_minimal_curses/__init__.py b/pypy/module/_minimal_curses/__init__.py --- a/pypy/module/_minimal_curses/__init__.py +++ b/pypy/module/_minimal_curses/__init__.py @@ -1,6 +1,6 @@ try: import _curses -except ImportError: +except Exception: # probably ImportError or cffi's VerificationError try: # when running on top of pypy before it had _curses, settle for minimal # we prefer _curses so any constants added make it into _minimal_curses diff --git a/pypy/module/cppyy/__init__.py b/pypy/module/cppyy/__init__.py --- a/pypy/module/cppyy/__init__.py +++ b/pypy/module/cppyy/__init__.py @@ -10,15 +10,17 @@ '_resolve_name' : 'interp_cppyy.resolve_name', '_scope_byname' : 'interp_cppyy.scope_byname', '_template_byname' : 'interp_cppyy.template_byname', + '_std_string_name' : 'interp_cppyy.std_string_name', '_set_class_generator' : 'interp_cppyy.set_class_generator', '_register_class' : 'interp_cppyy.register_class', + '_is_static' : 'interp_cppyy.is_static', 'CPPInstance' : 'interp_cppyy.W_CPPInstance', 'addressof' : 'interp_cppyy.addressof', 'bind_object' : 'interp_cppyy.bind_object', } appleveldefs = { - 'gbl' : 'pythonify.gbl', + '_init_pythonify' : 'pythonify._init_pythonify', 'load_reflection_info' : 'pythonify.load_reflection_info', 'add_pythonization' : 'pythonify.add_pythonization', } @@ -31,3 +33,9 @@ # code generation is not, so give it a chance to run now from pypy.module.cppyy import capi capi.register_pythonizations(space) + + def startup(self, space): + from pypy.module.cppyy import capi + capi.verify_backend(space) # may raise ImportError + + space.call_method(space.wrap(self), '_init_pythonify') diff --git a/pypy/module/cppyy/capi/__init__.py b/pypy/module/cppyy/capi/__init__.py --- a/pypy/module/cppyy/capi/__init__.py +++ b/pypy/module/cppyy/capi/__init__.py @@ -1,37 +1,19 @@ from rpython.rtyper.lltypesystem import rffi, lltype -from rpython.rlib import jit -import reflex_capi as backend -#import cint_capi as backend +# There are two possible ways of accessing the backend through the reflection +# C-API: built it into pypy-c, or load it dynamically. The latter is preferred +# (and is the default) for use with Reflex. B/c of some builtin pythonizations, +# the former is recommended (for now) with CINT. -identify = backend.identify -pythonize = backend.pythonize -register_pythonizations = backend.register_pythonizations +# Note: if builtin_capi is chosen, then inside builtin_capi.py, there is still +# the selection of the desired backend (default is Reflex). -ts_reflect = backend.ts_reflect -ts_call = backend.ts_call -ts_memory = backend.ts_memory -ts_helper = backend.ts_helper +# choose C-API access method: +from pypy.module.cppyy.capi.loadable_capi import * +#from pypy.module.cppyy.capi.builtin_capi import * -_C_OPAQUE_PTR = rffi.LONG -_C_OPAQUE_NULL = lltype.nullptr(rffi.LONGP.TO)# ALT: _C_OPAQUE_PTR.TO - -C_SCOPE = _C_OPAQUE_PTR -C_NULL_SCOPE = rffi.cast(C_SCOPE, _C_OPAQUE_NULL) - -C_TYPE = C_SCOPE -C_NULL_TYPE = C_NULL_SCOPE - -C_OBJECT = _C_OPAQUE_PTR -C_NULL_OBJECT = rffi.cast(C_OBJECT, _C_OPAQUE_NULL) - -C_METHOD = _C_OPAQUE_PTR -C_INDEX = rffi.LONG -C_INDEX_ARRAY = rffi.LONGP -WLAVC_INDEX = rffi.LONG - -C_METHPTRGETTER = lltype.FuncType([C_OBJECT], rffi.VOIDP) -C_METHPTRGETTER_PTR = lltype.Ptr(C_METHPTRGETTER) +from pypy.module.cppyy.capi.capi_types import C_OBJECT,\ + C_NULL_TYPE, C_NULL_OBJECT def direct_ptradd(ptr, offset): offset = rffi.cast(rffi.SIZE_T, offset) @@ -42,457 +24,3 @@ def exchange_address(ptr, cif_descr, index): return rffi.ptradd(ptr, cif_descr.exchange_args[index]) - -c_load_dictionary = backend.c_load_dictionary - -# name to opaque C++ scope representation ------------------------------------ -_c_num_scopes = rffi.llexternal( - "cppyy_num_scopes", - [C_SCOPE], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_num_scopes(cppscope): - return _c_num_scopes(cppscope.handle) -_c_scope_name = rffi.llexternal( - "cppyy_scope_name", - [C_SCOPE, rffi.INT], rffi.CCHARP, - compilation_info = backend.eci) -def c_scope_name(cppscope, iscope): - return charp2str_free(_c_scope_name(cppscope.handle, iscope)) - -_c_resolve_name = rffi.llexternal( - "cppyy_resolve_name", - [rffi.CCHARP], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_resolve_name(name): - return charp2str_free(_c_resolve_name(name)) -c_get_scope_opaque = rffi.llexternal( - "cppyy_get_scope", - [rffi.CCHARP], C_SCOPE, - threadsafe=ts_reflect, - compilation_info=backend.eci) -c_get_template = rffi.llexternal( - "cppyy_get_template", - [rffi.CCHARP], C_TYPE, - threadsafe=ts_reflect, - compilation_info=backend.eci) -_c_actual_class = rffi.llexternal( - "cppyy_actual_class", - [C_TYPE, C_OBJECT], C_TYPE, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_actual_class(cppclass, cppobj): - return _c_actual_class(cppclass.handle, cppobj) - -# memory management ---------------------------------------------------------- -_c_allocate = rffi.llexternal( - "cppyy_allocate", - [C_TYPE], C_OBJECT, - threadsafe=ts_memory, - compilation_info=backend.eci) -def c_allocate(cppclass): - return _c_allocate(cppclass.handle) -_c_deallocate = rffi.llexternal( - "cppyy_deallocate", - [C_TYPE, C_OBJECT], lltype.Void, - threadsafe=ts_memory, - compilation_info=backend.eci) -def c_deallocate(cppclass, cppobject): - _c_deallocate(cppclass.handle, cppobject) -_c_destruct = rffi.llexternal( - "cppyy_destruct", - [C_TYPE, C_OBJECT], lltype.Void, - threadsafe=ts_call, - compilation_info=backend.eci) -def c_destruct(cppclass, cppobject): - _c_destruct(cppclass.handle, cppobject) - -# method/function dispatching ------------------------------------------------ -c_call_v = rffi.llexternal( - "cppyy_call_v", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], lltype.Void, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_b = rffi.llexternal( - "cppyy_call_b", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.UCHAR, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_c = rffi.llexternal( - "cppyy_call_c", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.CHAR, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_h = rffi.llexternal( - "cppyy_call_h", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.SHORT, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_i = rffi.llexternal( - "cppyy_call_i", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.INT, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_l = rffi.llexternal( - "cppyy_call_l", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.LONG, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_ll = rffi.llexternal( - "cppyy_call_ll", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.LONGLONG, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_f = rffi.llexternal( - "cppyy_call_f", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.FLOAT, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_d = rffi.llexternal( - "cppyy_call_d", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.DOUBLE, - threadsafe=ts_call, - compilation_info=backend.eci) - -c_call_r = rffi.llexternal( - "cppyy_call_r", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.VOIDP, - threadsafe=ts_call, - compilation_info=backend.eci) -c_call_s = rffi.llexternal( - "cppyy_call_s", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.CCHARP, - threadsafe=ts_call, - compilation_info=backend.eci) - -c_constructor = rffi.llexternal( - "cppyy_constructor", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], lltype.Void, - threadsafe=ts_call, - compilation_info=backend.eci) -_c_call_o = rffi.llexternal( - "cppyy_call_o", - [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP, C_TYPE], rffi.LONG, - threadsafe=ts_call, - compilation_info=backend.eci) -def c_call_o(method, cppobj, nargs, args, cppclass): - return _c_call_o(method, cppobj, nargs, args, cppclass.handle) - -_c_get_methptr_getter = rffi.llexternal( - "cppyy_get_methptr_getter", - [C_SCOPE, C_INDEX], C_METHPTRGETTER_PTR, - threadsafe=ts_reflect, - compilation_info=backend.eci, - elidable_function=True) -def c_get_methptr_getter(cppscope, index): - return _c_get_methptr_getter(cppscope.handle, index) - -# handling of function argument buffer --------------------------------------- -c_allocate_function_args = rffi.llexternal( - "cppyy_allocate_function_args", - [rffi.SIZE_T], rffi.VOIDP, - threadsafe=ts_memory, - compilation_info=backend.eci) -c_deallocate_function_args = rffi.llexternal( - "cppyy_deallocate_function_args", - [rffi.VOIDP], lltype.Void, - threadsafe=ts_memory, - compilation_info=backend.eci) -c_function_arg_sizeof = rffi.llexternal( - "cppyy_function_arg_sizeof", - [], rffi.SIZE_T, - threadsafe=ts_memory, - compilation_info=backend.eci, - elidable_function=True) -c_function_arg_typeoffset = rffi.llexternal( - "cppyy_function_arg_typeoffset", - [], rffi.SIZE_T, - threadsafe=ts_memory, - compilation_info=backend.eci, - elidable_function=True) - -# scope reflection information ----------------------------------------------- -c_is_namespace = rffi.llexternal( - "cppyy_is_namespace", - [C_SCOPE], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -c_is_enum = rffi.llexternal( - "cppyy_is_enum", - [rffi.CCHARP], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) - -# type/class reflection information ------------------------------------------ -_c_final_name = rffi.llexternal( - "cppyy_final_name", - [C_TYPE], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_final_name(cpptype): - return charp2str_free(_c_final_name(cpptype)) -_c_scoped_final_name = rffi.llexternal( - "cppyy_scoped_final_name", - [C_TYPE], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_scoped_final_name(cpptype): - return charp2str_free(_c_scoped_final_name(cpptype)) -c_has_complex_hierarchy = rffi.llexternal( - "cppyy_has_complex_hierarchy", - [C_TYPE], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -_c_num_bases = rffi.llexternal( - "cppyy_num_bases", - [C_TYPE], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_num_bases(cppclass): - return _c_num_bases(cppclass.handle) -_c_base_name = rffi.llexternal( - "cppyy_base_name", - [C_TYPE, rffi.INT], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_base_name(cppclass, base_index): - return charp2str_free(_c_base_name(cppclass.handle, base_index)) -_c_is_subtype = rffi.llexternal( - "cppyy_is_subtype", - [C_TYPE, C_TYPE], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci, - elidable_function=True) - at jit.elidable_promote() -def c_is_subtype(derived, base): - if derived == base: - return 1 - return _c_is_subtype(derived.handle, base.handle) - -_c_base_offset = rffi.llexternal( - "cppyy_base_offset", - [C_TYPE, C_TYPE, C_OBJECT, rffi.INT], rffi.SIZE_T, - threadsafe=ts_reflect, - compilation_info=backend.eci, - elidable_function=True) - at jit.elidable_promote() -def c_base_offset(derived, base, address, direction): - if derived == base: - return 0 - return _c_base_offset(derived.handle, base.handle, address, direction) - -# method/function reflection information ------------------------------------- -_c_num_methods = rffi.llexternal( - "cppyy_num_methods", - [C_SCOPE], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_num_methods(cppscope): - return _c_num_methods(cppscope.handle) -_c_method_index_at = rffi.llexternal( - "cppyy_method_index_at", - [C_SCOPE, rffi.INT], C_INDEX, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_index_at(cppscope, imethod): - return _c_method_index_at(cppscope.handle, imethod) -_c_method_indices_from_name = rffi.llexternal( - "cppyy_method_indices_from_name", - [C_SCOPE, rffi.CCHARP], C_INDEX_ARRAY, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_indices_from_name(cppscope, name): - indices = _c_method_indices_from_name(cppscope.handle, name) - if not indices: - return [] - py_indices = [] - i = 0 - index = indices[i] - while index != -1: - i += 1 - py_indices.append(index) - index = indices[i] - c_free(rffi.cast(rffi.VOIDP, indices)) # c_free defined below - return py_indices - -_c_method_name = rffi.llexternal( - "cppyy_method_name", - [C_SCOPE, C_INDEX], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_name(cppscope, index): - return charp2str_free(_c_method_name(cppscope.handle, index)) -_c_method_result_type = rffi.llexternal( - "cppyy_method_result_type", - [C_SCOPE, C_INDEX], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_result_type(cppscope, index): - return charp2str_free(_c_method_result_type(cppscope.handle, index)) -_c_method_num_args = rffi.llexternal( - "cppyy_method_num_args", - [C_SCOPE, C_INDEX], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_num_args(cppscope, index): - return _c_method_num_args(cppscope.handle, index) -_c_method_req_args = rffi.llexternal( - "cppyy_method_req_args", - [C_SCOPE, C_INDEX], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_req_args(cppscope, index): - return _c_method_req_args(cppscope.handle, index) -_c_method_arg_type = rffi.llexternal( - "cppyy_method_arg_type", - [C_SCOPE, C_INDEX, rffi.INT], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_arg_type(cppscope, index, arg_index): - return charp2str_free(_c_method_arg_type(cppscope.handle, index, arg_index)) -_c_method_arg_default = rffi.llexternal( - "cppyy_method_arg_default", - [C_SCOPE, C_INDEX, rffi.INT], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_arg_default(cppscope, index, arg_index): - return charp2str_free(_c_method_arg_default(cppscope.handle, index, arg_index)) -_c_method_signature = rffi.llexternal( - "cppyy_method_signature", - [C_SCOPE, C_INDEX], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_method_signature(cppscope, index): - return charp2str_free(_c_method_signature(cppscope.handle, index)) - -_c_get_method = rffi.llexternal( - "cppyy_get_method", - [C_SCOPE, C_INDEX], C_METHOD, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_get_method(cppscope, index): - return _c_get_method(cppscope.handle, index) -_c_get_global_operator = rffi.llexternal( - "cppyy_get_global_operator", - [C_SCOPE, C_SCOPE, C_SCOPE, rffi.CCHARP], WLAVC_INDEX, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_get_global_operator(nss, lc, rc, op): - if nss is not None: - return _c_get_global_operator(nss.handle, lc.handle, rc.handle, op) - return rffi.cast(WLAVC_INDEX, -1) - -# method properties ---------------------------------------------------------- -_c_is_constructor = rffi.llexternal( - "cppyy_is_constructor", - [C_TYPE, C_INDEX], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_is_constructor(cppclass, index): - return _c_is_constructor(cppclass.handle, index) -_c_is_staticmethod = rffi.llexternal( - "cppyy_is_staticmethod", - [C_TYPE, C_INDEX], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_is_staticmethod(cppclass, index): - return _c_is_staticmethod(cppclass.handle, index) - -# data member reflection information ----------------------------------------- -_c_num_datamembers = rffi.llexternal( - "cppyy_num_datamembers", - [C_SCOPE], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_num_datamembers(cppscope): - return _c_num_datamembers(cppscope.handle) -_c_datamember_name = rffi.llexternal( - "cppyy_datamember_name", - [C_SCOPE, rffi.INT], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_datamember_name(cppscope, datamember_index): - return charp2str_free(_c_datamember_name(cppscope.handle, datamember_index)) -_c_datamember_type = rffi.llexternal( - "cppyy_datamember_type", - [C_SCOPE, rffi.INT], rffi.CCHARP, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_datamember_type(cppscope, datamember_index): - return charp2str_free(_c_datamember_type(cppscope.handle, datamember_index)) -_c_datamember_offset = rffi.llexternal( - "cppyy_datamember_offset", - [C_SCOPE, rffi.INT], rffi.SIZE_T, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_datamember_offset(cppscope, datamember_index): - return _c_datamember_offset(cppscope.handle, datamember_index) - -_c_datamember_index = rffi.llexternal( - "cppyy_datamember_index", - [C_SCOPE, rffi.CCHARP], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_datamember_index(cppscope, name): - return _c_datamember_index(cppscope.handle, name) - -# data member properties ----------------------------------------------------- -_c_is_publicdata = rffi.llexternal( - "cppyy_is_publicdata", - [C_SCOPE, rffi.INT], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_is_publicdata(cppscope, datamember_index): - return _c_is_publicdata(cppscope.handle, datamember_index) -_c_is_staticdata = rffi.llexternal( - "cppyy_is_staticdata", - [C_SCOPE, rffi.INT], rffi.INT, - threadsafe=ts_reflect, - compilation_info=backend.eci) -def c_is_staticdata(cppscope, datamember_index): - return _c_is_staticdata(cppscope.handle, datamember_index) - -# misc helpers --------------------------------------------------------------- -c_strtoll = rffi.llexternal( - "cppyy_strtoll", - [rffi.CCHARP], rffi.LONGLONG, - threadsafe=ts_helper, - compilation_info=backend.eci) -c_strtoull = rffi.llexternal( - "cppyy_strtoull", - [rffi.CCHARP], rffi.ULONGLONG, - threadsafe=ts_helper, - compilation_info=backend.eci) -c_free = rffi.llexternal( - "cppyy_free", - [rffi.VOIDP], lltype.Void, - threadsafe=ts_memory, - compilation_info=backend.eci) - -def charp2str_free(charp): - string = rffi.charp2str(charp) - voidp = rffi.cast(rffi.VOIDP, charp) - c_free(voidp) - return string - -c_charp2stdstring = rffi.llexternal( - "cppyy_charp2stdstring", - [rffi.CCHARP], C_OBJECT, - threadsafe=ts_helper, - compilation_info=backend.eci) -c_stdstring2stdstring = rffi.llexternal( - "cppyy_stdstring2stdstring", - [C_OBJECT], C_OBJECT, - threadsafe=ts_helper, - compilation_info=backend.eci) -c_assign2stdstring = rffi.llexternal( - "cppyy_assign2stdstring", - [C_OBJECT, rffi.CCHARP], lltype.Void, - threadsafe=ts_helper, - compilation_info=backend.eci) -c_free_stdstring = rffi.llexternal( - "cppyy_free_stdstring", - [C_OBJECT], lltype.Void, - threadsafe=ts_helper, - compilation_info=backend.eci) diff --git a/pypy/module/cppyy/capi/builtin_capi.py b/pypy/module/cppyy/capi/builtin_capi.py new file mode 100644 --- /dev/null +++ b/pypy/module/cppyy/capi/builtin_capi.py @@ -0,0 +1,561 @@ +from rpython.rtyper.lltypesystem import rffi, lltype +from rpython.rlib import jit + +import reflex_capi as backend +#import cint_capi as backend + +from pypy.module.cppyy.capi.capi_types import C_SCOPE, C_TYPE, C_OBJECT,\ + C_METHOD, C_INDEX, C_INDEX_ARRAY, WLAVC_INDEX,\ + C_METHPTRGETTER, C_METHPTRGETTER_PTR + +identify = backend.identify +pythonize = backend.pythonize +register_pythonizations = backend.register_pythonizations +std_string_name = backend.std_string_name + +ts_reflect = backend.ts_reflect +ts_call = backend.ts_call +ts_memory = backend.ts_memory +ts_helper = backend.ts_helper + +def verify_backend(space): + return True # by definition + +c_load_dictionary = backend.c_load_dictionary + +# name to opaque C++ scope representation ------------------------------------ +_c_num_scopes = rffi.llexternal( + "cppyy_num_scopes", + [C_SCOPE], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_num_scopes(space, cppscope): + return _c_num_scopes(cppscope.handle) +_c_scope_name = rffi.llexternal( + "cppyy_scope_name", + [C_SCOPE, rffi.INT], rffi.CCHARP, + compilation_info = backend.eci) +def c_scope_name(space, cppscope, iscope): + return charp2str_free(space, _c_scope_name(cppscope.handle, iscope)) + +_c_resolve_name = rffi.llexternal( + "cppyy_resolve_name", + [rffi.CCHARP], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_resolve_name(space, name): + return charp2str_free(space, _c_resolve_name(name)) +_c_get_scope_opaque = rffi.llexternal( + "cppyy_get_scope", + [rffi.CCHARP], C_SCOPE, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_get_scope_opaque(space, name): + return _c_get_scope_opaque(name) +_c_get_template = rffi.llexternal( + "cppyy_get_template", + [rffi.CCHARP], C_TYPE, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_get_template(space, name): + return _c_get_template(name) +_c_actual_class = rffi.llexternal( + "cppyy_actual_class", + [C_TYPE, C_OBJECT], C_TYPE, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_actual_class(space, cppclass, cppobj): + return _c_actual_class(cppclass.handle, cppobj) + +# memory management ---------------------------------------------------------- +_c_allocate = rffi.llexternal( + "cppyy_allocate", + [C_TYPE], C_OBJECT, + threadsafe=ts_memory, + compilation_info=backend.eci) +def c_allocate(space, cppclass): + return _c_allocate(cppclass.handle) +_c_deallocate = rffi.llexternal( + "cppyy_deallocate", + [C_TYPE, C_OBJECT], lltype.Void, + threadsafe=ts_memory, + compilation_info=backend.eci) +def c_deallocate(space, cppclass, cppobject): + _c_deallocate(cppclass.handle, cppobject) +_c_destruct = rffi.llexternal( + "cppyy_destruct", + [C_TYPE, C_OBJECT], lltype.Void, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_destruct(space, cppclass, cppobject): + _c_destruct(cppclass.handle, cppobject) + +# method/function dispatching ------------------------------------------------ +_c_call_v = rffi.llexternal( + "cppyy_call_v", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], lltype.Void, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_v(space, cppmethod, cppobject, nargs, args): + _c_call_v(cppmethod, cppobject, nargs, args) +_c_call_b = rffi.llexternal( + "cppyy_call_b", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.UCHAR, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_b(space, cppmethod, cppobject, nargs, args): + return _c_call_b(cppmethod, cppobject, nargs, args) +_c_call_c = rffi.llexternal( + "cppyy_call_c", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.CHAR, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_c(space, cppmethod, cppobject, nargs, args): + return _c_call_c(cppmethod, cppobject, nargs, args) +_c_call_h = rffi.llexternal( + "cppyy_call_h", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.SHORT, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_h(space, cppmethod, cppobject, nargs, args): + return _c_call_h(cppmethod, cppobject, nargs, args) +_c_call_i = rffi.llexternal( + "cppyy_call_i", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.INT, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_i(space, cppmethod, cppobject, nargs, args): + return _c_call_i(cppmethod, cppobject, nargs, args) +_c_call_l = rffi.llexternal( + "cppyy_call_l", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.LONG, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_l(space, cppmethod, cppobject, nargs, args): + return _c_call_l(cppmethod, cppobject, nargs, args) +_c_call_ll = rffi.llexternal( + "cppyy_call_ll", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.LONGLONG, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_ll(space, cppmethod, cppobject, nargs, args): + return _c_call_ll(cppmethod, cppobject, nargs, args) +_c_call_f = rffi.llexternal( + "cppyy_call_f", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.FLOAT, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_f(space, cppmethod, cppobject, nargs, args): + return _c_call_f(cppmethod, cppobject, nargs, args) +_c_call_d = rffi.llexternal( + "cppyy_call_d", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.DOUBLE, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_d(space, cppmethod, cppobject, nargs, args): + return _c_call_d(cppmethod, cppobject, nargs, args) + +_c_call_r = rffi.llexternal( + "cppyy_call_r", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.VOIDP, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_r(space, cppmethod, cppobject, nargs, args): + return _c_call_r(cppmethod, cppobject, nargs, args) +_c_call_s = rffi.llexternal( + "cppyy_call_s", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.CCHARP, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_s(space, cppmethod, cppobject, nargs, args): + return _c_call_s(cppmethod, cppobject, nargs, args) + +_c_constructor = rffi.llexternal( + "cppyy_constructor", + [C_METHOD, C_TYPE, rffi.INT, rffi.VOIDP], C_OBJECT, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_constructor(space, cppmethod, cppobject, nargs, args): + return _c_constructor(cppmethod, cppobject, nargs, args) +_c_call_o = rffi.llexternal( + "cppyy_call_o", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP, C_TYPE], rffi.LONG, + threadsafe=ts_call, + compilation_info=backend.eci) +def c_call_o(space, method, cppobj, nargs, args, cppclass): + return _c_call_o(method, cppobj, nargs, args, cppclass.handle) + +_c_get_methptr_getter = rffi.llexternal( + "cppyy_get_methptr_getter", + [C_SCOPE, C_INDEX], C_METHPTRGETTER_PTR, + threadsafe=ts_reflect, + compilation_info=backend.eci, + elidable_function=True) +def c_get_methptr_getter(space, cppscope, index): + return _c_get_methptr_getter(cppscope.handle, index) + +# handling of function argument buffer --------------------------------------- +_c_allocate_function_args = rffi.llexternal( + "cppyy_allocate_function_args", + [rffi.SIZE_T], rffi.VOIDP, + threadsafe=ts_memory, + compilation_info=backend.eci) +def c_allocate_function_args(space, size): + return _c_allocate_function_args(size) +_c_deallocate_function_args = rffi.llexternal( + "cppyy_deallocate_function_args", + [rffi.VOIDP], lltype.Void, + threadsafe=ts_memory, + compilation_info=backend.eci) +def c_deallocate_function_args(space, args): + _c_deallocate_function_args(args) +_c_function_arg_sizeof = rffi.llexternal( + "cppyy_function_arg_sizeof", + [], rffi.SIZE_T, + threadsafe=ts_memory, + compilation_info=backend.eci, + elidable_function=True) +def c_function_arg_sizeof(space): + return _c_function_arg_sizeof() +_c_function_arg_typeoffset = rffi.llexternal( + "cppyy_function_arg_typeoffset", + [], rffi.SIZE_T, + threadsafe=ts_memory, + compilation_info=backend.eci, + elidable_function=True) +def c_function_arg_typeoffset(space): + return _c_function_arg_typeoffset() + +# scope reflection information ----------------------------------------------- +_c_is_namespace = rffi.llexternal( + "cppyy_is_namespace", + [C_SCOPE], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_is_namespace(space, scope): + return _c_is_namespace(scope) +_c_is_enum = rffi.llexternal( + "cppyy_is_enum", + [rffi.CCHARP], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_is_enum(space, name): + return _c_is_enum(name) + +# type/class reflection information ------------------------------------------ +_c_final_name = rffi.llexternal( + "cppyy_final_name", + [C_TYPE], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_final_name(space, cpptype): + return charp2str_free(space, _c_final_name(cpptype)) +_c_scoped_final_name = rffi.llexternal( + "cppyy_scoped_final_name", + [C_TYPE], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_scoped_final_name(space, cpptype): + return charp2str_free(space, _c_scoped_final_name(cpptype)) +_c_has_complex_hierarchy = rffi.llexternal( + "cppyy_has_complex_hierarchy", + [C_TYPE], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_has_complex_hierarchy(space, cpptype): + return _c_has_complex_hierarchy(cpptype) +_c_num_bases = rffi.llexternal( + "cppyy_num_bases", + [C_TYPE], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_num_bases(space, cppclass): + return _c_num_bases(cppclass.handle) +_c_base_name = rffi.llexternal( + "cppyy_base_name", + [C_TYPE, rffi.INT], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_base_name(space, cppclass, base_index): + return charp2str_free(space, _c_base_name(cppclass.handle, base_index)) +_c_is_subtype = rffi.llexternal( + "cppyy_is_subtype", + [C_TYPE, C_TYPE], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci, + elidable_function=True) + at jit.elidable_promote('2') +def c_is_subtype(space, derived, base): + if derived == base: + return 1 + return _c_is_subtype(derived.handle, base.handle) + +_c_base_offset = rffi.llexternal( + "cppyy_base_offset", + [C_TYPE, C_TYPE, C_OBJECT, rffi.INT], rffi.SIZE_T, + threadsafe=ts_reflect, + compilation_info=backend.eci, + elidable_function=True) + at jit.elidable_promote('1,2,4') +def c_base_offset(space, derived, base, address, direction): + if derived == base: + return 0 + return _c_base_offset(derived.handle, base.handle, address, direction) +def c_base_offset1(space, derived_h, base, address, direction): + return _c_base_offset(derived_h, base.handle, address, direction) + +# method/function reflection information ------------------------------------- +_c_num_methods = rffi.llexternal( + "cppyy_num_methods", + [C_SCOPE], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_num_methods(space, cppscope): + return _c_num_methods(cppscope.handle) +_c_method_index_at = rffi.llexternal( + "cppyy_method_index_at", + [C_SCOPE, rffi.INT], C_INDEX, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_index_at(space, cppscope, imethod): + return _c_method_index_at(cppscope.handle, imethod) +_c_method_indices_from_name = rffi.llexternal( + "cppyy_method_indices_from_name", + [C_SCOPE, rffi.CCHARP], C_INDEX_ARRAY, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_indices_from_name(space, cppscope, name): + indices = _c_method_indices_from_name(cppscope.handle, name) + if not indices: + return [] + py_indices = [] + i = 0 + index = indices[i] + while index != -1: + i += 1 + py_indices.append(index) + index = indices[i] + c_free(rffi.cast(rffi.VOIDP, indices)) # c_free defined below + return py_indices + +_c_method_name = rffi.llexternal( + "cppyy_method_name", + [C_SCOPE, C_INDEX], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_name(space, cppscope, index): + return charp2str_free(space, _c_method_name(cppscope.handle, index)) +_c_method_result_type = rffi.llexternal( + "cppyy_method_result_type", + [C_SCOPE, C_INDEX], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_result_type(space, cppscope, index): + return charp2str_free(space, _c_method_result_type(cppscope.handle, index)) +_c_method_num_args = rffi.llexternal( + "cppyy_method_num_args", + [C_SCOPE, C_INDEX], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_num_args(space, cppscope, index): + return _c_method_num_args(cppscope.handle, index) +_c_method_req_args = rffi.llexternal( + "cppyy_method_req_args", + [C_SCOPE, C_INDEX], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_req_args(space, cppscope, index): + return _c_method_req_args(cppscope.handle, index) +_c_method_arg_type = rffi.llexternal( + "cppyy_method_arg_type", + [C_SCOPE, C_INDEX, rffi.INT], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_arg_type(space, cppscope, index, arg_index): + return charp2str_free(space, _c_method_arg_type(cppscope.handle, index, arg_index)) +_c_method_arg_default = rffi.llexternal( + "cppyy_method_arg_default", + [C_SCOPE, C_INDEX, rffi.INT], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_arg_default(space, cppscope, index, arg_index): + return charp2str_free(space, _c_method_arg_default(cppscope.handle, index, arg_index)) +_c_method_signature = rffi.llexternal( + "cppyy_method_signature", + [C_SCOPE, C_INDEX], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_signature(space, cppscope, index): + return charp2str_free(space, _c_method_signature(cppscope.handle, index)) + +_c_method_is_template = rffi.llexternal( + "cppyy_method_is_template", + [C_SCOPE, C_INDEX], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_method_is_template(space, cppscope, index): + return _c_method_is_template(cppscope.handle, index) +_c_method_num_template_args = rffi.llexternal( + "cppyy_method_num_template_args", + [C_SCOPE, C_INDEX], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +_c_method_template_arg_name = rffi.llexternal( + "cppyy_method_template_arg_name", + [C_SCOPE, C_INDEX, C_INDEX], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_template_args(space, cppscope, index): + nargs = _c_method_num_template_args(cppscope.handle, index) + args = [c_resolve_name(space, + charp2str_free(space, _c_method_template_arg_name(cppscope.handle, index, iarg))) + for iarg in range(nargs)] + return args + +_c_get_method = rffi.llexternal( + "cppyy_get_method", + [C_SCOPE, C_INDEX], C_METHOD, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_get_method(space, cppscope, index): + return _c_get_method(cppscope.handle, index) +_c_get_global_operator = rffi.llexternal( + "cppyy_get_global_operator", + [C_SCOPE, C_SCOPE, C_SCOPE, rffi.CCHARP], WLAVC_INDEX, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_get_global_operator(space, nss, lc, rc, op): + if nss is not None: + return _c_get_global_operator(nss.handle, lc.handle, rc.handle, op) + return rffi.cast(WLAVC_INDEX, -1) + +# method properties ---------------------------------------------------------- +_c_is_constructor = rffi.llexternal( + "cppyy_is_constructor", + [C_TYPE, C_INDEX], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_is_constructor(space, cppclass, index): + return _c_is_constructor(cppclass.handle, index) +_c_is_staticmethod = rffi.llexternal( + "cppyy_is_staticmethod", + [C_TYPE, C_INDEX], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_is_staticmethod(space, cppclass, index): + return _c_is_staticmethod(cppclass.handle, index) + +# data member reflection information ----------------------------------------- +_c_num_datamembers = rffi.llexternal( + "cppyy_num_datamembers", + [C_SCOPE], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_num_datamembers(space, cppscope): + return _c_num_datamembers(cppscope.handle) +_c_datamember_name = rffi.llexternal( + "cppyy_datamember_name", + [C_SCOPE, rffi.INT], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_datamember_name(space, cppscope, datamember_index): + return charp2str_free(space, _c_datamember_name(cppscope.handle, datamember_index)) +_c_datamember_type = rffi.llexternal( + "cppyy_datamember_type", + [C_SCOPE, rffi.INT], rffi.CCHARP, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_datamember_type(space, cppscope, datamember_index): + return charp2str_free(space, _c_datamember_type(cppscope.handle, datamember_index)) +_c_datamember_offset = rffi.llexternal( + "cppyy_datamember_offset", + [C_SCOPE, rffi.INT], rffi.SIZE_T, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_datamember_offset(space, cppscope, datamember_index): + return _c_datamember_offset(cppscope.handle, datamember_index) + +_c_datamember_index = rffi.llexternal( + "cppyy_datamember_index", + [C_SCOPE, rffi.CCHARP], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_datamember_index(space, cppscope, name): + return _c_datamember_index(cppscope.handle, name) + +# data member properties ----------------------------------------------------- +_c_is_publicdata = rffi.llexternal( + "cppyy_is_publicdata", + [C_SCOPE, rffi.INT], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_is_publicdata(space, cppscope, datamember_index): + return _c_is_publicdata(cppscope.handle, datamember_index) +_c_is_staticdata = rffi.llexternal( + "cppyy_is_staticdata", + [C_SCOPE, rffi.INT], rffi.INT, + threadsafe=ts_reflect, + compilation_info=backend.eci) +def c_is_staticdata(space, cppscope, datamember_index): + return _c_is_staticdata(cppscope.handle, datamember_index) + +# misc helpers --------------------------------------------------------------- +_c_strtoll = rffi.llexternal( + "cppyy_strtoll", + [rffi.CCHARP], rffi.LONGLONG, + threadsafe=ts_helper, + compilation_info=backend.eci) +def c_strtoll(space, svalue): + return _c_strtoll(svalue) +_c_strtoull = rffi.llexternal( + "cppyy_strtoull", + [rffi.CCHARP], rffi.ULONGLONG, + threadsafe=ts_helper, + compilation_info=backend.eci) +def c_strtoull(space, svalue): + return _c_strtoull(svalue) +c_free = rffi.llexternal( + "cppyy_free", + [rffi.VOIDP], lltype.Void, + threadsafe=ts_memory, + compilation_info=backend.eci) + +def charp2str_free(space, charp): + string = rffi.charp2str(charp) + voidp = rffi.cast(rffi.VOIDP, charp) + c_free(voidp) + return string + +_c_charp2stdstring = rffi.llexternal( + "cppyy_charp2stdstring", + [rffi.CCHARP], C_OBJECT, + threadsafe=ts_helper, + compilation_info=backend.eci) +def c_charp2stdstring(space, svalue): + charp = rffi.str2charp(svalue) + result = _c_charp2stdstring(charp) + rffi.free_charp(charp) + return result +_c_stdstring2stdstring = rffi.llexternal( + "cppyy_stdstring2stdstring", + [C_OBJECT], C_OBJECT, + threadsafe=ts_helper, + compilation_info=backend.eci) +def c_stdstring2stdstring(space, cppobject): + return _c_stdstring2stdstring(cppobject) +_c_assign2stdstring = rffi.llexternal( + "cppyy_assign2stdstring", + [C_OBJECT, rffi.CCHARP], lltype.Void, + threadsafe=ts_helper, + compilation_info=backend.eci) +def c_assign2stdstring(space, cppobject, svalue): + charp = rffi.str2charp(svalue) + _c_assign2stdstring(cppobject, charp) + rffi.free_charp(charp) +_c_free_stdstring = rffi.llexternal( + "cppyy_free_stdstring", + [C_OBJECT], lltype.Void, + threadsafe=ts_helper, + compilation_info=backend.eci) +def c_free_stdstring(space, cppobject): + _c_free_stdstring(cppobject) diff --git a/pypy/module/cppyy/capi/capi_types.py b/pypy/module/cppyy/capi/capi_types.py new file mode 100644 --- /dev/null +++ b/pypy/module/cppyy/capi/capi_types.py @@ -0,0 +1,22 @@ +from rpython.rtyper.lltypesystem import rffi, lltype + +# shared ll definitions +_C_OPAQUE_PTR = rffi.LONG +_C_OPAQUE_NULL = lltype.nullptr(rffi.LONGP.TO)# ALT: _C_OPAQUE_PTR.TO + +C_SCOPE = _C_OPAQUE_PTR +C_NULL_SCOPE = rffi.cast(C_SCOPE, _C_OPAQUE_NULL) + +C_TYPE = C_SCOPE +C_NULL_TYPE = C_NULL_SCOPE + +C_OBJECT = _C_OPAQUE_PTR +C_NULL_OBJECT = rffi.cast(C_OBJECT, _C_OPAQUE_NULL) + +C_METHOD = _C_OPAQUE_PTR +C_INDEX = rffi.LONG +C_INDEX_ARRAY = rffi.LONGP +WLAVC_INDEX = rffi.LONG + +C_METHPTRGETTER = lltype.FuncType([C_OBJECT], rffi.VOIDP) +C_METHPTRGETTER_PTR = lltype.Ptr(C_METHPTRGETTER) diff --git a/pypy/module/cppyy/capi/cint_capi.py b/pypy/module/cppyy/capi/cint_capi.py --- a/pypy/module/cppyy/capi/cint_capi.py +++ b/pypy/module/cppyy/capi/cint_capi.py @@ -9,10 +9,8 @@ from rpython.rtyper.lltypesystem import rffi from rpython.rlib import libffi, rdynload -from pypy.module.itertools import interp_itertools - -__all__ = ['identify', 'eci', 'c_load_dictionary'] +__all__ = ['identify', 'std_string_name', 'eci', 'c_load_dictionary'] pkgpath = py.path.local(__file__).dirpath().join(os.pardir) srcpath = pkgpath.join("src") @@ -36,8 +34,10 @@ ts_reflect = False ts_call = False -ts_memory = 'auto' -ts_helper = 'auto' +ts_memory = False +ts_helper = False + +std_string_name = 'string' # force loading in global mode of core libraries, rather than linking with # them as PyPy uses various version of dlopen in various places; note that @@ -120,7 +120,7 @@ classname = space.str_w(args_w[1]) addr_idx = 2 w_address = args_w[addr_idx] - except OperationError: + except (OperationError, TypeError): addr_idx = 1 w_address = args_w[addr_idx] @@ -138,14 +138,14 @@ # call the helper stub to by-pass CINT vbranch = _ttree_Branch(vtree, branchname, klassname, address, bufsize, splitlevel) branch_class = interp_cppyy.scope_byname(space, "TBranch") - w_branch = interp_cppyy.wrap_cppobject( - space, space.w_None, branch_class, vbranch, isref=False, python_owns=False) + w_branch = interp_cppyy.wrap_cppobject(space, vbranch, branch_class) return w_branch - except (OperationError, TypeError, IndexError), e: + except (OperationError, TypeError, IndexError): pass # return control back to the original, unpythonized overload - return tree_class.get_overload("Branch").call(w_self, args_w) + ol = tree_class.get_overload("Branch") + return ol.call(w_self, args_w) def activate_branch(space, w_branch): w_branches = space.call_method(w_branch, "GetListOfBranches") @@ -155,6 +155,12 @@ space.call_method(w_branch, "SetStatus", space.wrap(1)) space.call_method(w_branch, "ResetReadEntry") +c_ttree_GetEntry = rffi.llexternal( + "cppyy_ttree_GetEntry", + [rffi.VOIDP, rffi.LONGLONG], rffi.LONGLONG, + threadsafe=False, + compilation_info=eci) + @unwrap_spec(args_w='args_w') def ttree_getattr(space, w_self, args_w): """Specialized __getattr__ for TTree's that allows switching on/off the @@ -163,28 +169,75 @@ from pypy.module.cppyy import interp_cppyy tree = space.interp_w(interp_cppyy.W_CPPInstance, w_self) + space = tree.space # holds the class cache in State + + # prevent recursion + attr = space.str_w(args_w[0]) + if attr and attr[0] == '_': + raise OperationError(space.w_AttributeError, args_w[0]) + + # try the saved cdata (for builtin types) + try: + w_cdata = space.getattr(w_self, space.wrap('_'+attr)) + from pypy.module._cffi_backend import cdataobj + cdata = space.interp_w(cdataobj.W_CData, w_cdata, can_be_None=False) + return cdata.convert_to_object() + except OperationError: + pass + # setup branch as a data member and enable it for reading - space = tree.space # holds the class cache in State w_branch = space.call_method(w_self, "GetBranch", args_w[0]) + if not space.is_true(w_branch): + raise OperationError(space.w_AttributeError, args_w[0]) + activate_branch(space, w_branch) + + # figure out from where we're reading + entry = space.int_w(space.call_method(w_self, "GetReadEntry")) + if entry == -1: + entry = 0 + + # setup cache structure w_klassname = space.call_method(w_branch, "GetClassName") - klass = interp_cppyy.scope_byname(space, space.str_w(w_klassname)) - w_obj = klass.construct() - #space.call_method(w_branch, "SetStatus", space.wrap(1)) - activate_branch(space, w_branch) - space.call_method(w_branch, "SetObject", w_obj) - space.call_method(w_branch, "GetEntry", space.wrap(0)) - space.setattr(w_self, args_w[0], w_obj) - return w_obj + if space.is_true(w_klassname): + # some instance + klass = interp_cppyy.scope_byname(space, space.str_w(w_klassname)) + w_obj = klass.construct() + space.call_method(w_branch, "SetObject", w_obj) + space.call_method(w_branch, "GetEntry", space.wrap(entry)) + space.setattr(w_self, args_w[0], w_obj) + return w_obj + else: + # builtin data + w_leaf = space.call_method(w_self, "GetLeaf", args_w[0]) + space.call_method(w_branch, "GetEntry", space.wrap(entry)) + + # location + w_address = space.call_method(w_leaf, "GetValuePointer") + buf = space.buffer_w(w_address) + from pypy.module._rawffi import buffer + assert isinstance(buf, buffer.RawFFIBuffer) + address = rffi.cast(rffi.CCHARP, buf.datainstance.ll_buffer) + + # placeholder + w_typename = space.call_method(w_leaf, "GetTypeName" ) + from pypy.module.cppyy import capi + typename = capi.c_resolve_name(space, space.str_w(w_typename)) + if typename == 'bool': typename = '_Bool' + w_address = space.call_method(w_leaf, "GetValuePointer") + from pypy.module._cffi_backend import cdataobj, newtype + cdata = cdataobj.W_CData(space, address, newtype.new_primitive_type(space, typename)) + + # cache result + space.setattr(w_self, space.wrap('_'+attr), space.wrap(cdata)) + return space.getattr(w_self, args_w[0]) class W_TTreeIter(W_Root): def __init__(self, space, w_tree): - from pypy.module.cppyy import interp_cppyy tree = space.interp_w(interp_cppyy.W_CPPInstance, w_tree) - self.tree = tree.get_cppthis(tree.cppclass) + self.vtree = rffi.cast(rffi.VOIDP, tree.get_cppthis(tree.cppclass)) self.w_tree = w_tree - self.getentry = tree.cppclass.get_overload("GetEntry").functions[0] self.current = 0 self.maxentry = space.int_w(space.call_method(w_tree, "GetEntriesFast")) @@ -198,8 +251,8 @@ if self.current == self.maxentry: raise OperationError(self.space.w_StopIteration, self.space.w_None) # TODO: check bytes read? - self.getentry.call(self.tree, [self.space.wrap(self.current)]) - self.current += 1 + c_ttree_GetEntry(self.vtree, self.current) + self.current += 1 return self.w_tree W_TTreeIter.typedef = TypeDef( diff --git a/pypy/module/cppyy/capi/loadable_capi.py b/pypy/module/cppyy/capi/loadable_capi.py new file mode 100644 --- /dev/null +++ b/pypy/module/cppyy/capi/loadable_capi.py @@ -0,0 +1,519 @@ +from rpython.rtyper.lltypesystem import rffi, lltype +from rpython.rlib import jit, jit_libffi, libffi, rdynload, objectmodel +from rpython.rlib.rarithmetic import r_singlefloat +from rpython.tool import leakfinder + +from pypy.interpreter.error import OperationError + +from pypy.module._cffi_backend import ctypefunc, ctypeprim, cdataobj, misc + +from pypy.module.cppyy.capi.capi_types import C_SCOPE, C_TYPE, C_OBJECT,\ From noreply at buildbot.pypy.org Fri Apr 26 14:24:14 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 26 Apr 2013 14:24:14 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Fix Message-ID: <20130426122414.BD8D41C31E9@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63638:00e1300152fb Date: 2013-04-26 14:22 +0200 http://bitbucket.org/pypy/pypy/changeset/00e1300152fb/ Log: Fix diff --git a/pypy/interpreter/test/test_typedef.py b/pypy/interpreter/test/test_typedef.py --- a/pypy/interpreter/test/test_typedef.py +++ b/pypy/interpreter/test/test_typedef.py @@ -177,15 +177,17 @@ class W_Level1(W_Root): def __init__(self, space1): assert space1 is space - def __del__(self): + self.register_finalizer() + def invoke_finalizer(self): space.call_method(w_seen, 'append', space.wrap(1)) class W_Level2(W_Root): def __init__(self, space1): assert space1 is space - def __del__(self): - self.enqueue_for_destruction(space, W_Level2.destructormeth, - 'FOO ') - def destructormeth(self): + self.register_finalizer() + def invoke_finalizer(self): + self.finalizer_perform(space, 'FOO', self.destructormeth, 42) + def destructormeth(self, forty_two): + assert forty_two == 42 space.call_method(w_seen, 'append', space.wrap(2)) W_Level1.typedef = typedef.TypeDef( 'level1', diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py --- a/pypy/interpreter/typedef.py +++ b/pypy/interpreter/typedef.py @@ -223,6 +223,10 @@ if "user" in features: # generic feature needed by all subcls + super_invoke_finalizer = supercls.invoke_finalizer.im_func + if super_invoke_finalizer == W_Root.invoke_finalizer.im_func: + super_invoke_finalizer = lambda self: None + class Proto(object): user_overridden_class = True @@ -243,11 +247,11 @@ def invoke_finalizer(self): space = self.space w_descr = space.lookup(self, '__del__') - if w_descr is None: - return - self.finalizer_perform(self.space, "__del__ method of ", - space.get_and_call_function, - w_descr, self) + if w_descr is not None: + self.finalizer_perform(self.space, "__del__ method of ", + space.get_and_call_function, + w_descr, self) + super_invoke_finalizer(self) def user_setup_slots(self, nslots): assert nslots == 0 From noreply at buildbot.pypy.org Fri Apr 26 14:24:16 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 26 Apr 2013 14:24:16 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Fix _io. Message-ID: <20130426122416.0BA961C31E9@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63639:8ea45acf31ec Date: 2013-04-26 14:22 +0200 http://bitbucket.org/pypy/pypy/changeset/8ea45acf31ec/ Log: Fix _io. diff --git a/pypy/module/_io/interp_iobase.py b/pypy/module/_io/interp_iobase.py --- a/pypy/module/_io/interp_iobase.py +++ b/pypy/module/_io/interp_iobase.py @@ -48,6 +48,7 @@ self.__IOBase_closed = False self.streamholder = None # needed by AutoFlusher get_autoflushher(space).add(self) + self.register_finalizer() def getdict(self, space): return self.w_dict @@ -60,13 +61,8 @@ return True return False - def __del__(self): + def invoke_finalizer(self): self.clear_all_weakrefs() - self.enqueue_for_destruction(self.space, W_IOBase.destructor, - 'internal __del__ of ') - - def destructor(self): - assert isinstance(self, W_IOBase) space = self.space w_closed = space.findattr(self, space.wrap('closed')) try: From noreply at buildbot.pypy.org Fri Apr 26 14:24:17 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 26 Apr 2013 14:24:17 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Fix _file. Message-ID: <20130426122417.4BE041C31E9@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63640:a051b8ab585f Date: 2013-04-26 14:23 +0200 http://bitbucket.org/pypy/pypy/changeset/a051b8ab585f/ Log: Fix _file. diff --git a/pypy/module/_file/interp_file.py b/pypy/module/_file/interp_file.py --- a/pypy/module/_file/interp_file.py +++ b/pypy/module/_file/interp_file.py @@ -2,7 +2,7 @@ import os import stat import errno -from rpython.rlib import streamio, rgc +from rpython.rlib import streamio from rpython.rlib.rarithmetic import r_longlong from rpython.rlib.rstring import StringBuilder from pypy.module._file.interp_stream import W_AbstractStream, StreamErrors @@ -38,9 +38,9 @@ def __init__(self, space): self.space = space - rgc.register_finalizer(self.finalizer) + self.register_finalizer() - def finalizer(self): + def invoke_finalizer(self): try: self.direct_close() except StreamErrors, e: From noreply at buildbot.pypy.org Fri Apr 26 14:31:08 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 26 Apr 2013 14:31:08 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Fix test Message-ID: <20130426123108.D279F1C3240@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63641:5ed5bd6f9688 Date: 2013-04-26 14:30 +0200 http://bitbucket.org/pypy/pypy/changeset/5ed5bd6f9688/ Log: Fix test diff --git a/pypy/interpreter/test/test_typedef.py b/pypy/interpreter/test/test_typedef.py --- a/pypy/interpreter/test/test_typedef.py +++ b/pypy/interpreter/test/test_typedef.py @@ -102,11 +102,8 @@ assert len(checks) == 3 space.appexec([], """(): - seen = [] class X(list): __slots__ = %r - def %s(self): - seen.append(1) x = X() import __pypy__ irepr = __pypy__.internal_repr(x) @@ -114,9 +111,7 @@ %s %s %s - %s - """ % (slots, methodname, checks[0], checks[1], - checks[2], checks[3])) + """ % (slots, checks[0], checks[1], checks[2])) subclasses = {} for key, subcls in typedef._subclass_cache.items(): if key[0] is not space.config: From noreply at buildbot.pypy.org Fri Apr 26 15:07:21 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 26 Apr 2013 15:07:21 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: haaaack to stop complaining at interpreter exit Message-ID: <20130426130721.5151D1C31EA@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63642:9aba857627db Date: 2013-04-26 15:04 +0200 http://bitbucket.org/pypy/pypy/changeset/9aba857627db/ Log: haaaack to stop complaining at interpreter exit diff --git a/rpython/rlib/rgc.py b/rpython/rlib/rgc.py --- a/rpython/rlib/rgc.py +++ b/rpython/rlib/rgc.py @@ -277,8 +277,14 @@ _finalizer_lock = [None] class _UntranslatedFinalizingObject(object): + import sys call_finalizer = None def __del__(self): + # haaaaaaaaaaaaaaack + try: + self.sys._getframe(1) + except ValueError: # 'call stack is not deep enough' + return # ignore, very likely called when shutting down g = object.__new__(self.original_class) g.__dict__ = self.dict _finalizer_queue.append((g, self.func)) From noreply at buildbot.pypy.org Fri Apr 26 15:07:22 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 26 Apr 2013 15:07:22 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Fixes Message-ID: <20130426130722.E4D011C31EA@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63643:a3d8ce2dac6d Date: 2013-04-26 15:09 +0200 http://bitbucket.org/pypy/pypy/changeset/a3d8ce2dac6d/ Log: Fixes diff --git a/rpython/memory/gctypelayout.py b/rpython/memory/gctypelayout.py --- a/rpython/memory/gctypelayout.py +++ b/rpython/memory/gctypelayout.py @@ -232,7 +232,8 @@ infobits |= T_HAS_DESTRUCTOR elif kind == "custom_trace": infobits |= T_HAS_CUSTOM_TRACE - info.extra = extra + else: + assert 0, kind # if not TYPE._is_varsize(): info.fixedsize = llarena.round_up_for_allocation( diff --git a/rpython/memory/test/test_minimark_gc.py b/rpython/memory/test/test_minimark_gc.py --- a/rpython/memory/test/test_minimark_gc.py +++ b/rpython/memory/test/test_minimark_gc.py @@ -1,4 +1,6 @@ from rpython.rlib.rarithmetic import LONG_BIT +from rpython.rlib import rgc +from rpython.rtyper.lltypesystem.lloperation import llop from rpython.memory.test.test_semispace_gc import TestSemiSpaceGC From noreply at buildbot.pypy.org Fri Apr 26 15:19:05 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 26 Apr 2013 15:19:05 +0200 (CEST) Subject: [pypy-commit] pypy default: Waah. Don't do "import TestXxx" classes in other tests: these Message-ID: <20130426131905.2B7DD1C02DA@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63644:b781ef8b70af Date: 2013-04-26 15:15 +0200 http://bitbucket.org/pypy/pypy/changeset/b781ef8b70af/ Log: Waah. Don't do "import TestXxx" classes in other tests: these imported test classes will be run again. diff --git a/rpython/memory/test/test_generational_gc.py b/rpython/memory/test/test_generational_gc.py --- a/rpython/memory/test/test_generational_gc.py +++ b/rpython/memory/test/test_generational_gc.py @@ -1,4 +1,4 @@ -from rpython.memory.test.test_semispace_gc import TestSemiSpaceGC +from rpython.memory.test import test_semispace_gc -class TestGenerationalGC(TestSemiSpaceGC): +class TestGenerationalGC(test_semispace_gc.TestSemiSpaceGC): from rpython.memory.gc.generation import GenerationGC as GCClass diff --git a/rpython/memory/test/test_growingsemispace_gc.py b/rpython/memory/test/test_growingsemispace_gc.py --- a/rpython/memory/test/test_growingsemispace_gc.py +++ b/rpython/memory/test/test_growingsemispace_gc.py @@ -1,8 +1,8 @@ from rpython.rlib.rarithmetic import LONG_BIT -from rpython.memory.test.test_semispace_gc import TestSemiSpaceGC +from rpython.memory.test import test_semispace_gc WORD = LONG_BIT // 8 -class TestGrowingSemiSpaceGC(TestSemiSpaceGC): +class TestGrowingSemiSpaceGC(test_semispace_gc.TestSemiSpaceGC): GC_PARAMS = {'space_size': 16*WORD} diff --git a/rpython/memory/test/test_hybrid_gc.py b/rpython/memory/test/test_hybrid_gc.py --- a/rpython/memory/test/test_hybrid_gc.py +++ b/rpython/memory/test/test_hybrid_gc.py @@ -3,10 +3,10 @@ from rpython.rtyper.lltypesystem import lltype from rpython.rtyper.lltypesystem.lloperation import llop -from rpython.memory.test.test_generational_gc import TestGenerationalGC +from rpython.memory.test import test_generational_gc -class TestHybridGC(TestGenerationalGC): +class TestHybridGC(test_generational_gc.TestGenerationalGC): from rpython.memory.gc.hybrid import HybridGC as GCClass GC_CAN_MALLOC_NONMOVABLE = True GC_CAN_SHRINK_BIG_ARRAY = False diff --git a/rpython/memory/test/test_minimark_gc.py b/rpython/memory/test/test_minimark_gc.py --- a/rpython/memory/test/test_minimark_gc.py +++ b/rpython/memory/test/test_minimark_gc.py @@ -1,10 +1,10 @@ from rpython.rlib.rarithmetic import LONG_BIT -from rpython.memory.test.test_semispace_gc import TestSemiSpaceGC +from rpython.memory.test import test_semispace_gc WORD = LONG_BIT // 8 -class TestMiniMarkGC(TestSemiSpaceGC): +class TestMiniMarkGC(test_semispace_gc.TestSemiSpaceGC): from rpython.memory.gc.minimark import MiniMarkGC as GCClass GC_CAN_SHRINK_BIG_ARRAY = False GC_CAN_MALLOC_NONMOVABLE = True diff --git a/rpython/memory/test/test_minimark_gc_cardmarking.py b/rpython/memory/test/test_minimark_gc_cardmarking.py --- a/rpython/memory/test/test_minimark_gc_cardmarking.py +++ b/rpython/memory/test/test_minimark_gc_cardmarking.py @@ -1,4 +1,4 @@ -from rpython.memory.test.test_minimark_gc import TestMiniMarkGC +from rpython.memory.test import test_minimark_gc -class TestMiniMarkGCCardMarking(TestMiniMarkGC): +class TestMiniMarkGCCardMarking(test_minimark_gc.TestMiniMarkGC): GC_PARAMS = {'card_page_indices': 4} From noreply at buildbot.pypy.org Fri Apr 26 15:19:56 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 26 Apr 2013 15:19:56 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: hg merge default Message-ID: <20130426131956.DFB5D1C02DA@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63645:49fa8123b5eb Date: 2013-04-26 15:19 +0200 http://bitbucket.org/pypy/pypy/changeset/49fa8123b5eb/ Log: hg merge default diff --git a/rpython/memory/test/test_generational_gc.py b/rpython/memory/test/test_generational_gc.py --- a/rpython/memory/test/test_generational_gc.py +++ b/rpython/memory/test/test_generational_gc.py @@ -1,4 +1,4 @@ -from rpython.memory.test.test_semispace_gc import TestSemiSpaceGC +from rpython.memory.test import test_semispace_gc -class TestGenerationalGC(TestSemiSpaceGC): +class TestGenerationalGC(test_semispace_gc.TestSemiSpaceGC): from rpython.memory.gc.generation import GenerationGC as GCClass diff --git a/rpython/memory/test/test_growingsemispace_gc.py b/rpython/memory/test/test_growingsemispace_gc.py --- a/rpython/memory/test/test_growingsemispace_gc.py +++ b/rpython/memory/test/test_growingsemispace_gc.py @@ -1,8 +1,8 @@ from rpython.rlib.rarithmetic import LONG_BIT -from rpython.memory.test.test_semispace_gc import TestSemiSpaceGC +from rpython.memory.test import test_semispace_gc WORD = LONG_BIT // 8 -class TestGrowingSemiSpaceGC(TestSemiSpaceGC): +class TestGrowingSemiSpaceGC(test_semispace_gc.TestSemiSpaceGC): GC_PARAMS = {'space_size': 16*WORD} diff --git a/rpython/memory/test/test_hybrid_gc.py b/rpython/memory/test/test_hybrid_gc.py --- a/rpython/memory/test/test_hybrid_gc.py +++ b/rpython/memory/test/test_hybrid_gc.py @@ -4,10 +4,10 @@ from rpython.rtyper.lltypesystem import lltype from rpython.rtyper.lltypesystem.lloperation import llop -from rpython.memory.test.test_generational_gc import TestGenerationalGC +from rpython.memory.test import test_generational_gc -class TestHybridGC(TestGenerationalGC): +class TestHybridGC(test_generational_gc.TestGenerationalGC): from rpython.memory.gc.hybrid import HybridGC as GCClass GC_CAN_MALLOC_NONMOVABLE = True GC_CAN_SHRINK_BIG_ARRAY = False diff --git a/rpython/memory/test/test_minimark_gc.py b/rpython/memory/test/test_minimark_gc.py --- a/rpython/memory/test/test_minimark_gc.py +++ b/rpython/memory/test/test_minimark_gc.py @@ -2,11 +2,11 @@ from rpython.rlib import rgc from rpython.rtyper.lltypesystem.lloperation import llop -from rpython.memory.test.test_semispace_gc import TestSemiSpaceGC +from rpython.memory.test import test_semispace_gc WORD = LONG_BIT // 8 -class TestMiniMarkGC(TestSemiSpaceGC): +class TestMiniMarkGC(test_semispace_gc.TestSemiSpaceGC): from rpython.memory.gc.minimark import MiniMarkGC as GCClass GC_CAN_SHRINK_BIG_ARRAY = False GC_CAN_MALLOC_NONMOVABLE = True diff --git a/rpython/memory/test/test_minimark_gc_cardmarking.py b/rpython/memory/test/test_minimark_gc_cardmarking.py --- a/rpython/memory/test/test_minimark_gc_cardmarking.py +++ b/rpython/memory/test/test_minimark_gc_cardmarking.py @@ -1,6 +1,6 @@ -from rpython.memory.test.test_minimark_gc import TestMiniMarkGC +from rpython.memory.test import test_minimark_gc -class TestMiniMarkGCCardMarking(TestMiniMarkGC): +class TestMiniMarkGCCardMarking(test_minimark_gc.TestMiniMarkGC): GC_PARAMS = {'card_page_indices': 4} def test_finalizer_with_card_marks_array(self): From noreply at buildbot.pypy.org Fri Apr 26 15:22:20 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 26 Apr 2013 15:22:20 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Some more missing imports Message-ID: <20130426132220.C408E1C104D@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63646:36544ab4ee2b Date: 2013-04-26 15:24 +0200 http://bitbucket.org/pypy/pypy/changeset/36544ab4ee2b/ Log: Some more missing imports diff --git a/rpython/memory/test/test_minimark_gc.py b/rpython/memory/test/test_minimark_gc.py --- a/rpython/memory/test/test_minimark_gc.py +++ b/rpython/memory/test/test_minimark_gc.py @@ -1,5 +1,6 @@ from rpython.rlib.rarithmetic import LONG_BIT from rpython.rlib import rgc +from rpython.rtyper.lltypesystem import lltype from rpython.rtyper.lltypesystem.lloperation import llop from rpython.memory.test import test_semispace_gc diff --git a/rpython/memory/test/test_minimark_gc_cardmarking.py b/rpython/memory/test/test_minimark_gc_cardmarking.py --- a/rpython/memory/test/test_minimark_gc_cardmarking.py +++ b/rpython/memory/test/test_minimark_gc_cardmarking.py @@ -1,3 +1,7 @@ +from rpython.rtyper.lltypesystem import lltype +from rpython.rtyper.lltypesystem.lloperation import llop +from rpython.memory.gc.minimark import WORD + from rpython.memory.test import test_minimark_gc class TestMiniMarkGCCardMarking(test_minimark_gc.TestMiniMarkGC): @@ -31,7 +35,7 @@ assert res == 2 -class TestMiniMarkGCLargeNursery(TestMiniMarkGC): +class TestMiniMarkGCLargeNursery(test_minimark_gc.TestMiniMarkGC): GC_PARAMS = {'nursery_size': 16384*WORD} def setup_class(cls): py.test.skip("takes a lot of extra time to run") From noreply at buildbot.pypy.org Fri Apr 26 15:26:48 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 26 Apr 2013 15:26:48 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: More missing imports. Message-ID: <20130426132648.790FF1C104D@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63647:e045a0597601 Date: 2013-04-26 15:28 +0200 http://bitbucket.org/pypy/pypy/changeset/e045a0597601/ Log: More missing imports. diff --git a/rpython/memory/test/test_minimark_gc.py b/rpython/memory/test/test_minimark_gc.py --- a/rpython/memory/test/test_minimark_gc.py +++ b/rpython/memory/test/test_minimark_gc.py @@ -1,3 +1,4 @@ +import py from rpython.rlib.rarithmetic import LONG_BIT from rpython.rlib import rgc from rpython.rtyper.lltypesystem import lltype @@ -74,3 +75,11 @@ return n * 100 + b.num_finalized res = self.interpret(f, []) assert res == 1 + + +class TestMiniMarkGCLargeNursery(TestMiniMarkGC): + GC_PARAMS = {'nursery_size': 16384*WORD} + def setup_class(cls): + py.test.skip("takes a lot of extra time to run") + def teardown_class(cls): + pass diff --git a/rpython/memory/test/test_minimark_gc_cardmarking.py b/rpython/memory/test/test_minimark_gc_cardmarking.py --- a/rpython/memory/test/test_minimark_gc_cardmarking.py +++ b/rpython/memory/test/test_minimark_gc_cardmarking.py @@ -1,5 +1,7 @@ from rpython.rtyper.lltypesystem import lltype from rpython.rtyper.lltypesystem.lloperation import llop +from rpython.rlib import rgc +from rpython.rlib.objectmodel import keepalive_until_here from rpython.memory.gc.minimark import WORD from rpython.memory.test import test_minimark_gc @@ -33,11 +35,3 @@ return b.num_finalized res = self.interpret(f, [2]) assert res == 2 - - -class TestMiniMarkGCLargeNursery(test_minimark_gc.TestMiniMarkGC): - GC_PARAMS = {'nursery_size': 16384*WORD} - def setup_class(cls): - py.test.skip("takes a lot of extra time to run") - def teardown_class(cls): - pass From noreply at buildbot.pypy.org Fri Apr 26 15:30:27 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 26 Apr 2013 15:30:27 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Fix Message-ID: <20130426133027.95A171C31E9@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63648:f71b0fe069f3 Date: 2013-04-26 15:32 +0200 http://bitbucket.org/pypy/pypy/changeset/f71b0fe069f3/ Log: Fix diff --git a/rpython/translator/c/gc.py b/rpython/translator/c/gc.py --- a/rpython/translator/c/gc.py +++ b/rpython/translator/c/gc.py @@ -315,17 +315,16 @@ if rtti is not None and hasattr(rtti._obj, 'destructor_funcptr'): gctransf = self.db.gctransformer TYPE = structdefnode.STRUCT - fptrs = gctransf.special_funcptr_for_type(TYPE) + kind, fptr = gctransf.special_funcptr_for_type(TYPE) # make sure this is seen by the database early, i.e. before # finish_helpers() on the gctransformer destrptr = rtti._obj.destructor_funcptr self.db.get(destrptr) - # the following, on the other hand, will only discover ll_finalizer + # the following, on the other hand, will only find ll_destructor # helpers. The get() sees and records a delayed pointer. It is # still important to see it so that it can be followed as soon as # the mixlevelannotator resolves it. - for fptr in fptrs.values(): - self.db.get(fptr) + self.db.get(fptr) def array_setup(self, arraydefnode): pass From noreply at buildbot.pypy.org Fri Apr 26 15:48:13 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 26 Apr 2013 15:48:13 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Another __del__ Message-ID: <20130426134813.3D13E1C00BD@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63649:a046776e4e7d Date: 2013-04-26 15:50 +0200 http://bitbucket.org/pypy/pypy/changeset/a046776e4e7d/ Log: Another __del__ diff --git a/pypy/module/_io/interp_bufferedio.py b/pypy/module/_io/interp_bufferedio.py --- a/pypy/module/_io/interp_bufferedio.py +++ b/pypy/module/_io/interp_bufferedio.py @@ -957,9 +957,9 @@ self.w_writer = None raise - def __del__(self): + def invoke_finalizer(self): self.clear_all_weakrefs() - # Don't call the base __del__: do not close the files! + # Don't call the base invoke_finalizer(): do not close the files! # forward to reader for method in ['read', 'peek', 'read1', 'readinto', 'readable']: From noreply at buildbot.pypy.org Fri Apr 26 15:52:56 2013 From: noreply at buildbot.pypy.org (fijal) Date: Fri, 26 Apr 2013 15:52:56 +0200 (CEST) Subject: [pypy-commit] pypy kill-gen-store-back-in: in-progress Message-ID: <20130426135256.390221C026F@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: kill-gen-store-back-in Changeset: r63650:462cd771b59a Date: 2013-04-26 15:52 +0200 http://bitbucket.org/pypy/pypy/changeset/462cd771b59a/ Log: in-progress diff --git a/rpython/jit/metainterp/pyjitpl.py b/rpython/jit/metainterp/pyjitpl.py --- a/rpython/jit/metainterp/pyjitpl.py +++ b/rpython/jit/metainterp/pyjitpl.py @@ -1209,7 +1209,7 @@ CIF_DESCRIPTION_P) kind, descr, itemsize = get_arg_descr(self.metainterp.cpu, cif_description.rtype) - + if kind != 'v': ofs = cif_description.exchange_result assert ofs % itemsize == 0 # alignment check (result) @@ -1694,6 +1694,11 @@ def finishframe(self, resultbox): # handle a non-exceptional return from the current frame self.last_exc_value_box = None + if len(self.framestack) == 1: + # we should call store_token_in_vable here and not in + # compile_done_with_this_frame, so we have the frame to implement + # guard not forced + self.store_token_in_vable() self.popframe() if self.framestack: if resultbox is not None: @@ -2229,7 +2234,6 @@ def compile_done_with_this_frame(self, exitbox): # temporarily put a JUMP to a pseudo-loop - self.store_token_in_vable() sd = self.staticdata result_type = self.jitdriver_sd.result_type if result_type == history.VOID: @@ -2264,6 +2268,8 @@ # in case the force_token has not been recorded, record it here # to make sure we know the virtualizable can be broken. However, the # contents of the virtualizable should be generally correct + assert len(self.framestack) == 1 + self.framestack[0].generate_guard(rop.GUARD_NOT_FORCED, None) self.history.record(rop.FORCE_TOKEN, [], force_token_box) self.history.record(rop.SETFIELD_GC, [vbox, force_token_box], None, descr=vinfo.vable_token_descr) From noreply at buildbot.pypy.org Fri Apr 26 16:36:46 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 26 Apr 2013 16:36:46 +0200 (CEST) Subject: [pypy-commit] pypy default: Bah. Fix the name of these class variables Message-ID: <20130426143646.CE73C1C3240@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63651:e8c9b21805dc Date: 2013-04-26 16:35 +0200 http://bitbucket.org/pypy/pypy/changeset/e8c9b21805dc/ Log: Bah. Fix the name of these class variables diff --git a/rpython/jit/backend/test/runner_test.py b/rpython/jit/backend/test/runner_test.py --- a/rpython/jit/backend/test/runner_test.py +++ b/rpython/jit/backend/test/runner_test.py @@ -41,8 +41,8 @@ class Runner(object): - add_loop_instruction = ['overload for a specific cpu'] - bridge_loop_instruction = ['overload for a specific cpu'] + add_loop_instructions = ['overload for a specific cpu'] + bridge_loop_instructions = ['overload for a specific cpu'] def execute_operation(self, opname, valueboxes, result_type, descr=None): inputargs, operations = self._get_single_operation_list(opname, From noreply at buildbot.pypy.org Fri Apr 26 17:23:44 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 26 Apr 2013 17:23:44 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Fix _ffi. Message-ID: <20130426152344.03E9F1C104D@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63652:998d735a69e5 Date: 2013-04-26 17:17 +0200 http://bitbucket.org/pypy/pypy/changeset/998d735a69e5/ Log: Fix _ffi. diff --git a/pypy/module/_ffi/interp_struct.py b/pypy/module/_ffi/interp_struct.py --- a/pypy/module/_ffi/interp_struct.py +++ b/pypy/module/_ffi/interp_struct.py @@ -2,7 +2,6 @@ from rpython.rlib import clibffi from rpython.rlib import libffi from rpython.rlib import jit -from rpython.rlib.rgc import must_be_light_finalizer from rpython.rlib.rarithmetic import r_uint, r_ulonglong, intmask from pypy.interpreter.baseobjspace import W_Root from pypy.interpreter.typedef import TypeDef, interp_attrproperty @@ -46,7 +45,6 @@ def __init__(self, ffistruct): self.ffistruct = ffistruct - @must_be_light_finalizer def __del__(self): if self.ffistruct: lltype.free(self.ffistruct, flavor='raw', track_allocation=True) @@ -169,7 +167,6 @@ else: self.rawmem = rawmem - @must_be_light_finalizer def __del__(self): if self.autofree and self.rawmem: lltype.free(self.rawmem, flavor='raw') From noreply at buildbot.pypy.org Fri Apr 26 18:14:32 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 26 Apr 2013 18:14:32 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Fix cppyy. Message-ID: <20130426161432.718281C104D@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63653:6d24af5081d1 Date: 2013-04-26 17:32 +0200 http://bitbucket.org/pypy/pypy/changeset/6d24af5081d1/ Log: Fix cppyy. diff --git a/pypy/module/cppyy/interp_cppyy.py b/pypy/module/cppyy/interp_cppyy.py --- a/pypy/module/cppyy/interp_cppyy.py +++ b/pypy/module/cppyy/interp_cppyy.py @@ -969,6 +969,8 @@ assert not isref or not python_owns self.isref = isref self.python_owns = python_owns + if python_owns: + self.register_finalizer() def _nullcheck(self): if not self._rawobject or (self.isref and not self.get_rawobject()): @@ -982,6 +984,8 @@ @unwrap_spec(value=bool) def fset_python_owns(self, space, value): self.python_owns = space.is_true(value) + if self.python_owns: + self.register_finalizer() def get_cppthis(self, calling_scope): return self.cppclass.get_cppthis(self, calling_scope) @@ -1071,16 +1075,15 @@ (self.cppclass.name, rffi.cast(rffi.ULONG, self.get_rawobject()))) def destruct(self): - assert isinstance(self, W_CPPInstance) if self._rawobject and not self.isref: memory_regulator.unregister(self) capi.c_destruct(self.space, self.cppclass, self._rawobject) self._rawobject = capi.C_NULL_OBJECT - def __del__(self): + def invoke_finalizer(self): if self.python_owns: - self.enqueue_for_destruction(self.space, W_CPPInstance.destruct, - '__del__() method of ') + self.finalizer_perform(self.space, '__del__() method of ', + self.destruct) W_CPPInstance.typedef = TypeDef( 'CPPInstance', From noreply at buildbot.pypy.org Fri Apr 26 18:14:33 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 26 Apr 2013 18:14:33 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Fix _ssl. Message-ID: <20130426161433.B1E4A1C104D@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63654:30c2cfc0af97 Date: 2013-04-26 17:40 +0200 http://bitbucket.org/pypy/pypy/changeset/30c2cfc0af97/ Log: Fix _ssl. diff --git a/pypy/module/_ssl/interp_ssl.py b/pypy/module/_ssl/interp_ssl.py --- a/pypy/module/_ssl/interp_ssl.py +++ b/pypy/module/_ssl/interp_ssl.py @@ -132,6 +132,7 @@ self._issuer = lltype.malloc(rffi.CCHARP.TO, X509_NAME_MAXLEN, flavor='raw') self._issuer[0] = '\0' self.shutdown_seen_zero = False + self.register_finalizer() def server(self): return self.space.wrap(rffi.charp2str(self._server)) @@ -139,12 +140,7 @@ def issuer(self): return self.space.wrap(rffi.charp2str(self._issuer)) - def __del__(self): - self.enqueue_for_destruction(self.space, SSLObject.destructor, - '__del__() method of ') - - def destructor(self): - assert isinstance(self, SSLObject) + def invoke_finalizer(self): if self.peer_cert: libssl_X509_free(self.peer_cert) if self.ssl: From noreply at buildbot.pypy.org Fri Apr 26 18:14:34 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 26 Apr 2013 18:14:34 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Fix _io to call close() between bytecodes too. A hack for tests. Message-ID: <20130426161434.EC4CF1C104D@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63655:7acc15347cae Date: 2013-04-26 18:14 +0200 http://bitbucket.org/pypy/pypy/changeset/7acc15347cae/ Log: Fix _io to call close() between bytecodes too. A hack for tests. diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py --- a/pypy/interpreter/baseobjspace.py +++ b/pypy/interpreter/baseobjspace.py @@ -165,6 +165,13 @@ def _invoke_finalizer(self): # The call-back from rgc.register_finalizer(), cannot be overridden + if not we_are_translated(): + # haaaaaack in case this object is from an older test, to + # prevent it from blocking the future calls of finalizers... + from rpython.rlib import rgc + for x, y in rgc._finalizer_queue: + if getattr(x, 'space', None) not in (self, None): + return # there is a pending object with another space self.invoke_finalizer() def invoke_finalizer(self): diff --git a/pypy/module/_io/interp_iobase.py b/pypy/module/_io/interp_iobase.py --- a/pypy/module/_io/interp_iobase.py +++ b/pypy/module/_io/interp_iobase.py @@ -63,6 +63,10 @@ def invoke_finalizer(self): self.clear_all_weakrefs() + self.finalizer_perform(self.space, 'close() method of ', + self._finalizer_close) + + def _finalizer_close(self): space = self.space w_closed = space.findattr(self, space.wrap('closed')) try: From noreply at buildbot.pypy.org Fri Apr 26 18:25:14 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 26 Apr 2013 18:25:14 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Document this design decision. Message-ID: <20130426162514.6C6581C3146@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63656:d9167e6bc4a8 Date: 2013-04-26 18:27 +0200 http://bitbucket.org/pypy/pypy/changeset/d9167e6bc4a8/ Log: Document this design decision. diff --git a/pypy/module/cppyy/interp_cppyy.py b/pypy/module/cppyy/interp_cppyy.py --- a/pypy/module/cppyy/interp_cppyy.py +++ b/pypy/module/cppyy/interp_cppyy.py @@ -1082,6 +1082,9 @@ def invoke_finalizer(self): if self.python_owns: + # Use finalizer_perform() as the safe solution. We could also + # call destruct() directly, but this could have bad effects in + # case the C++ destructor invokes more Python code. self.finalizer_perform(self.space, '__del__() method of ', self.destruct) From noreply at buildbot.pypy.org Fri Apr 26 19:03:42 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 26 Apr 2013 19:03:42 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Port again the changes from default to enable both a destructor and a Message-ID: <20130426170342.2A8CE1C104D@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63657:01e4d6fbc769 Date: 2013-04-26 19:03 +0200 http://bitbucket.org/pypy/pypy/changeset/01e4d6fbc769/ Log: Port again the changes from default to enable both a destructor and a customtrace. Used in gctransform/shadowstack.py. diff --git a/rpython/memory/gc/minimark.py b/rpython/memory/gc/minimark.py --- a/rpython/memory/gc/minimark.py +++ b/rpython/memory/gc/minimark.py @@ -1949,7 +1949,7 @@ if not self.is_forwarded(obj): destructor = self.getdestructor(self.get_type_id(obj)) ll_assert(bool(destructor), "destructor missing") - destructor(obj, NULL) + destructor(obj) else: obj = self.get_forwarding_address(obj) self.old_objects_with_destructors.append(obj) @@ -1967,8 +1967,8 @@ else: # dying destructor = self.getdestructor(self.get_type_id(obj)) - ll_assert(bool(destructor), "no light finalizer found") - destructor(obj, NULL) + ll_assert(bool(destructor), "[2] destructor missing") + destructor(obj) self.old_objects_with_destructors.delete() self.old_objects_with_destructors = new_objects diff --git a/rpython/memory/gctransform/framework.py b/rpython/memory/gctransform/framework.py --- a/rpython/memory/gctransform/framework.py +++ b/rpython/memory/gctransform/framework.py @@ -666,9 +666,8 @@ c_type_id = rmodel.inputconst(TYPE_ID, type_id) info = self.layoutbuilder.get_info(type_id) c_size = rmodel.inputconst(lltype.Signed, info.fixedsize) - kind_and_fptr = self.special_funcptr_for_type(TYPE) - has_destructor = (kind_and_fptr is not None and - kind_and_fptr[0] == "destructor") + fptrs = self.special_funcptr_for_type(TYPE) + has_destructor = "destructor" in fptrs c_has_destructor = rmodel.inputconst(lltype.Bool, has_destructor) if not op.opname.endswith('_varsize') and not flags.get('varsize'): @@ -1241,15 +1240,16 @@ destrptr = rtti._obj.destructor_funcptr DESTR_ARG = lltype.typeOf(destrptr).TO.ARGS[0] typename = TYPE.__name__ - def ll_destructor(addr, ignored): + def ll_destructor(addr): v = llmemory.cast_adr_to_ptr(addr, DESTR_ARG) ll_call_destructor(destrptr, v, typename) - return llmemory.NULL fptr = self.transformer.annotate_finalizer(ll_destructor, - [llmemory.Address, llmemory.Address], llmemory.Address) - g = destrptr._obj.graph - # XXX should catch and ignore DelayedPointer here? - DestructorAnalyzer(self.translator).check_destructor(g) + [llmemory.Address], lltype.Void) + try: + g = destrptr._obj.graph + DestructorAnalyzer(self.translator).check_destructor(g) + except lltype.DelayedPointer: + pass # XXX bah, too bad return fptr def make_custom_trace_funcptr_for_type(self, TYPE): diff --git a/rpython/memory/gctypelayout.py b/rpython/memory/gctypelayout.py --- a/rpython/memory/gctypelayout.py +++ b/rpython/memory/gctypelayout.py @@ -23,16 +23,20 @@ # A custom tracer (CT), enumerates the addresses that contain GCREFs. # It is called with the object as first argument, and the previous # returned address (or NULL the first time) as the second argument. - DESTRUCTOR_OR_CT_FUNC = lltype.FuncType([llmemory.Address, - llmemory.Address], - llmemory.Address) - DESTRUCTOR_OR_CT = lltype.Ptr(DESTRUCTOR_OR_CT_FUNC) - FINALIZER = lltype.Ptr(lltype.FuncType([llmemory.Address], lltype.Void)) + DESTRUCTOR_FUNC = lltype.FuncType([llmemory.Address], lltype.Void) + CUSTOMTRACER_FUNC = lltype.FuncType([llmemory.Address, llmemory.Address], + llmemory.Address) + DESTRUCTOR = lltype.Ptr(DESTRUCTOR_FUNC) + FINALIZER = DESTRUCTOR + CUSTOMTRACER = lltype.Ptr(CUSTOMTRACER_FUNC) + EXTRA = lltype.Struct("type_info_extra", + ('destructor', DESTRUCTOR), + ('customtracer', CUSTOMTRACER)) # structure describing the layout of a typeid TYPE_INFO = lltype.Struct("type_info", ("infobits", lltype.Signed), # combination of the T_xxx consts - ("destructor_or_customtrace", DESTRUCTOR_OR_CT), + ("extra", lltype.Ptr(EXTRA)), ("fixedsize", lltype.Signed), ("ofstoptrs", lltype.Ptr(OFFSETS_TO_GC_PTR)), hints={'immutable': True}, @@ -82,9 +86,9 @@ def q_getdestructor(self, typeid): typeinfo = self.get(typeid) if typeinfo.infobits & T_HAS_DESTRUCTOR: - return typeinfo.destructor_or_customtrace + return typeinfo.extra.destructor else: - return lltype.nullptr(GCData.DESTRUCTOR_OR_CT_FUNC) + return lltype.nullptr(GCData.DESTRUCTOR_FUNC) def q_offsets_to_gc_pointers(self, typeid): return self.get(typeid).ofstoptrs @@ -126,7 +130,7 @@ ll_assert(self.q_has_custom_trace(typeid), "T_HAS_CUSTOM_TRACE missing") typeinfo = self.get(typeid) - return typeinfo.destructor_or_customtrace + return typeinfo.extra.customtracer def q_fast_path_tracing(self, typeid): # return True if none of the flags T_HAS_GCPTR_IN_VARSIZE, @@ -224,16 +228,17 @@ infobits = index info.ofstoptrs = builder.offsets2table(offsets, TYPE) # - kind_and_fptr = builder.special_funcptr_for_type(TYPE) - if kind_and_fptr is not None: - kind, fptr = kind_and_fptr - info.destructor_or_customtrace = fptr - if kind == "destructor": + fptrs = builder.special_funcptr_for_type(TYPE) + if fptrs: + extra = lltype.malloc(GCData.EXTRA, zero=True, immortal=True, + flavor='raw') + if "destructor" in fptrs: + extra.destructor = fptrs["destructor"] infobits |= T_HAS_DESTRUCTOR - elif kind == "custom_trace": + if "custom_trace" in fptrs: + extra.customtracer = fptrs["custom_trace"] infobits |= T_HAS_CUSTOM_TRACE - else: - assert 0, kind + info.extra = extra # if not TYPE._is_varsize(): info.fixedsize = llarena.round_up_for_allocation( @@ -407,13 +412,11 @@ fptr2 = self.make_custom_trace_funcptr_for_type(TYPE) result = {} if fptr1: - kind_and_fptr = "destructor", fptr1 - elif fptr2: - kind_and_fptr = "custom_trace", fptr2 - else: - kind_and_fptr = None - self._special_funcptrs[TYPE] = kind_and_fptr - return kind_and_fptr + result["destructor"] = fptr1 + if fptr2: + result["custom_trace"] = fptr2 + self._special_funcptrs[TYPE] = result + return result def make_destructor_funcptr_for_type(self, TYPE): # must be overridden for proper finalizer support diff --git a/rpython/memory/gcwrapper.py b/rpython/memory/gcwrapper.py --- a/rpython/memory/gcwrapper.py +++ b/rpython/memory/gcwrapper.py @@ -220,16 +220,14 @@ t = self.llinterp.typer.annotator.translator DestructorAnalyzer(t).check_destructor(destrgraph) - def ll_destructor(addr, dummy): - assert dummy == llmemory.NULL + def ll_destructor(addr): try: v = llmemory.cast_adr_to_ptr(addr, DESTR_ARG) self.llinterp.eval_graph(destrgraph, [v], recursive=True) except llinterp.LLException: raise RuntimeError( "a destructor raised an exception, shouldn't happen") - return llmemory.NULL - return llhelper(gctypelayout.GCData.DESTRUCTOR_OR_CT, ll_destructor) + return llhelper(gctypelayout.GCData.DESTRUCTOR, ll_destructor) def make_custom_trace_funcptr_for_type(self, TYPE): from rpython.memory.gctransform.support import get_rtti From noreply at buildbot.pypy.org Fri Apr 26 19:08:25 2013 From: noreply at buildbot.pypy.org (bivab) Date: Fri, 26 Apr 2013 19:08:25 +0200 (CEST) Subject: [pypy-commit] pypy default: one word was missing here Message-ID: <20130426170825.DB23F1C31EA@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63658:7958b8a04501 Date: 2013-04-26 19:07 +0200 http://bitbucket.org/pypy/pypy/changeset/7958b8a04501/ Log: one word was missing here diff --git a/rpython/jit/backend/arm/codebuilder.py b/rpython/jit/backend/arm/codebuilder.py --- a/rpython/jit/backend/arm/codebuilder.py +++ b/rpython/jit/backend/arm/codebuilder.py @@ -335,7 +335,7 @@ # XXX remove and setup aligning in llsupport def materialize(self, asmmemmgr, allblocks, gcrootmap=None): - size = self.get_relative_pos() + size = self.get_relative_pos() + WORD malloced = asmmemmgr.malloc(size, size + 7) allblocks.append(malloced) rawstart = malloced[0] From noreply at buildbot.pypy.org Fri Apr 26 19:41:53 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 26 Apr 2013 19:41:53 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Fix Message-ID: <20130426174153.9717E1C026F@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63659:85c537a8f596 Date: 2013-04-26 19:44 +0200 http://bitbucket.org/pypy/pypy/changeset/85c537a8f596/ Log: Fix diff --git a/rpython/translator/c/gc.py b/rpython/translator/c/gc.py --- a/rpython/translator/c/gc.py +++ b/rpython/translator/c/gc.py @@ -315,7 +315,7 @@ if rtti is not None and hasattr(rtti._obj, 'destructor_funcptr'): gctransf = self.db.gctransformer TYPE = structdefnode.STRUCT - kind, fptr = gctransf.special_funcptr_for_type(TYPE) + fptrs = gctransf.special_funcptr_for_type(TYPE) # make sure this is seen by the database early, i.e. before # finish_helpers() on the gctransformer destrptr = rtti._obj.destructor_funcptr @@ -324,7 +324,8 @@ # helpers. The get() sees and records a delayed pointer. It is # still important to see it so that it can be followed as soon as # the mixlevelannotator resolves it. - self.db.get(fptr) + for fptr in fptrs.values(): + self.db.get(fptr) def array_setup(self, arraydefnode): pass From noreply at buildbot.pypy.org Fri Apr 26 20:37:10 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 26 Apr 2013 20:37:10 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Bah, fix this logic Message-ID: <20130426183710.E2B181C32CA@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63660:16b4c14f5a8f Date: 2013-04-26 20:34 +0200 http://bitbucket.org/pypy/pypy/changeset/16b4c14f5a8f/ Log: Bah, fix this logic diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py --- a/pypy/interpreter/baseobjspace.py +++ b/pypy/interpreter/baseobjspace.py @@ -165,12 +165,15 @@ def _invoke_finalizer(self): # The call-back from rgc.register_finalizer(), cannot be overridden - if not we_are_translated(): + if not we_are_translated() and hasattr(self, 'space'): # haaaaaack in case this object is from an older test, to # prevent it from blocking the future calls of finalizers... from rpython.rlib import rgc for x, y in rgc._finalizer_queue: - if getattr(x, 'space', None) not in (self, None): + if getattr(x, 'space', None) not in (self.space, None): + print '-+- skipping finalizer for %r:' % (self,) + print ' self.space = %r' % (id(self.space),) + print ' later_obj.space = %r' % (id(x.space),) return # there is a pending object with another space self.invoke_finalizer() From noreply at buildbot.pypy.org Fri Apr 26 20:37:12 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 26 Apr 2013 20:37:12 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Fix cpyext. Message-ID: <20130426183712.11B4C1C32CA@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63661:f1553ff74b5e Date: 2013-04-26 20:35 +0200 http://bitbucket.org/pypy/pypy/changeset/f1553ff74b5e/ Log: Fix cpyext. diff --git a/pypy/module/cpyext/pystate.py b/pypy/module/cpyext/pystate.py --- a/pypy/module/cpyext/pystate.py +++ b/pypy/module/cpyext/pystate.py @@ -2,7 +2,7 @@ cpython_api, generic_cpy_call, CANNOT_FAIL, CConfig, cpython_struct) from pypy.module.cpyext.pyobject import PyObject, Py_DecRef, make_ref, from_ref from rpython.rtyper.lltypesystem import rffi, lltype -from rpython.rlib import rthread +from rpython.rlib import rthread, rgc from pypy.module.thread import os_thread PyInterpreterStateStruct = lltype.ForwardReference() @@ -60,7 +60,8 @@ self.memory = lltype.malloc(T, flavor=flavor) else: self.memory = lltype.nullptr(T) - def __del__(self): + rgc.register_finalizer(self.finalizer) + def finalizer(self): if self.memory: if dealloc and self.space: dealloc(self.memory, self.space) diff --git a/pypy/module/cpyext/test/test_getargs.py b/pypy/module/cpyext/test/test_getargs.py --- a/pypy/module/cpyext/test/test_getargs.py +++ b/pypy/module/cpyext/test/test_getargs.py @@ -156,11 +156,12 @@ freed = [] class freestring(str): def __del__(self): - freed.append('x') + freed.append(str(self)) raises(TypeError, pybuffer, freestring("string"), freestring("other string"), 42) import gc; gc.collect() - assert freed == ['x', 'x'] + assert len(freed) == 2 + assert set(freed) == set(['string', 'other string']) def test_pyarg_parse_charbuf_and_length(self): diff --git a/pypy/objspace/std/stringobject.py b/pypy/objspace/std/stringobject.py --- a/pypy/objspace/std/stringobject.py +++ b/pypy/objspace/std/stringobject.py @@ -22,7 +22,7 @@ from pypy.objspace.std.formatting import mod_format class W_AbstractStringObject(W_Object): - __slots__ = () + _attrs_ = () def is_w(self, space, w_other): if not isinstance(w_other, W_AbstractStringObject): From noreply at buildbot.pypy.org Fri Apr 26 22:03:25 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 26 Apr 2013 22:03:25 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Fix _winreg (untested). Message-ID: <20130426200325.CDF091C31EC@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63662:672b7f7ecfd9 Date: 2013-04-26 21:13 +0200 http://bitbucket.org/pypy/pypy/changeset/672b7f7ecfd9/ Log: Fix _winreg (untested). diff --git a/pypy/module/_winreg/interp_winreg.py b/pypy/module/_winreg/interp_winreg.py --- a/pypy/module/_winreg/interp_winreg.py +++ b/pypy/module/_winreg/interp_winreg.py @@ -14,11 +14,13 @@ space.wrap(message)])) class W_HKEY(W_Root): - def __init__(self, hkey): + def __init__(self, space, hkey): + self.space = space self.hkey = hkey + self.register_finalizer() - def descr_del(self, space): - self.Close(space) + def invoke_finalizer(self): + self.Close(self.space) def as_int(self): return rffi.cast(rffi.SIZE_T, self.hkey) @@ -64,7 +66,7 @@ @unwrap_spec(key=int) def new_HKEY(space, w_subtype, key): hkey = rffi.cast(rwinreg.HKEY, key) - return space.wrap(W_HKEY(hkey)) + return space.wrap(W_HKEY(space, hkey)) descr_HKEY_new = interp2app(new_HKEY) W_HKEY.typedef = TypeDef( @@ -91,7 +93,6 @@ __int__ - Converting a handle to an integer returns the Win32 handle. __cmp__ - Handle objects are compared using the handle value.""", __new__ = descr_HKEY_new, - __del__ = interp2app(W_HKEY.descr_del), __repr__ = interp2app(W_HKEY.descr_repr), __int__ = interp2app(W_HKEY.descr_int), __nonzero__ = interp2app(W_HKEY.descr_nonzero), @@ -469,7 +470,7 @@ ret = rwinreg.RegCreateKey(hkey, subkey, rethkey) if ret != 0: raiseWindowsError(space, ret, 'CreateKey') - return space.wrap(W_HKEY(rethkey[0])) + return space.wrap(W_HKEY(space, rethkey[0])) @unwrap_spec(subkey=str, res=int, sam=rffi.r_uint) def CreateKeyEx(space, w_hkey, subkey, res=0, sam=rwinreg.KEY_WRITE): @@ -491,7 +492,7 @@ lltype.nullptr(rwin32.LPDWORD.TO)) if ret != 0: raiseWindowsError(space, ret, 'CreateKeyEx') - return space.wrap(W_HKEY(rethkey[0])) + return space.wrap(W_HKEY(space, rethkey[0])) @unwrap_spec(subkey=str) def DeleteKey(space, w_hkey, subkey): @@ -538,7 +539,7 @@ ret = rwinreg.RegOpenKeyEx(hkey, subkey, res, sam, rethkey) if ret != 0: raiseWindowsError(space, ret, 'RegOpenKeyEx') - return space.wrap(W_HKEY(rethkey[0])) + return space.wrap(W_HKEY(space, rethkey[0])) @unwrap_spec(index=int) def EnumValue(space, w_hkey, index): @@ -682,7 +683,7 @@ ret = rwinreg.RegConnectRegistry(machine, hkey, rethkey) if ret != 0: raiseWindowsError(space, ret, 'RegConnectRegistry') - return space.wrap(W_HKEY(rethkey[0])) + return space.wrap(W_HKEY(space, rethkey[0])) @unwrap_spec(source=unicode) def ExpandEnvironmentStrings(space, source): From noreply at buildbot.pypy.org Fri Apr 26 22:03:27 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 26 Apr 2013 22:03:27 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Fix cpyext/pyobject.py. Add an operation to destructor.py. Message-ID: <20130426200327.17CA61C31EC@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63663:dad9e6bc4c95 Date: 2013-04-26 21:13 +0200 http://bitbucket.org/pypy/pypy/changeset/dad9e6bc4c95/ Log: Fix cpyext/pyobject.py. Add an operation to destructor.py. diff --git a/pypy/module/cpyext/pyobject.py b/pypy/module/cpyext/pyobject.py --- a/pypy/module/cpyext/pyobject.py +++ b/pypy/module/cpyext/pyobject.py @@ -10,6 +10,7 @@ from pypy.objspace.std.objectobject import W_ObjectObject from rpython.rlib.objectmodel import specialize, we_are_translated from rpython.rlib.rweakref import RWeakKeyDictionary +from rpython.rlib import rgc from rpython.rtyper.annlowlevel import llhelper #________________________________________________________ @@ -392,8 +393,9 @@ def __init__(self, space, pyo): self.pyo = pyo self.space = space + rgc.register_finalizer(self.finalizer) - def __del__(self): + def finalizer(self): if self.pyo: assert self.pyo.c_ob_refcnt == 0 _Py_Dealloc(self.space, self.pyo) diff --git a/rpython/translator/backendopt/destructor.py b/rpython/translator/backendopt/destructor.py --- a/rpython/translator/backendopt/destructor.py +++ b/rpython/translator/backendopt/destructor.py @@ -14,7 +14,8 @@ * anything that escapes self * anything that can allocate """ - ok_operations = ['ptr_nonzero', 'ptr_eq', 'ptr_ne', 'free', 'same_as', + ok_operations = ['ptr_nonzero', 'ptr_iszero', 'ptr_eq', 'ptr_ne', + 'free', 'same_as', 'direct_ptradd', 'force_cast', 'track_alloc_stop', 'raw_free'] From noreply at buildbot.pypy.org Fri Apr 26 22:03:28 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 26 Apr 2013 22:03:28 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Fix _multiprocessing. Message-ID: <20130426200328.4CD131C31EC@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63664:da192ff89252 Date: 2013-04-26 22:01 +0200 http://bitbucket.org/pypy/pypy/changeset/da192ff89252/ Log: Fix _multiprocessing. diff --git a/pypy/module/_multiprocessing/interp_connection.py b/pypy/module/_multiprocessing/interp_connection.py --- a/pypy/module/_multiprocessing/interp_connection.py +++ b/pypy/module/_multiprocessing/interp_connection.py @@ -33,8 +33,9 @@ self.flags = flags self.buffer = lltype.malloc(rffi.CCHARP.TO, self.BUFFER_SIZE, flavor='raw') + self.register_finalizer() - def __del__(self): + def invoke_finalizer(self): lltype.free(self.buffer, flavor='raw') try: self.do_close() diff --git a/pypy/module/_multiprocessing/interp_semaphore.py b/pypy/module/_multiprocessing/interp_semaphore.py --- a/pypy/module/_multiprocessing/interp_semaphore.py +++ b/pypy/module/_multiprocessing/interp_semaphore.py @@ -422,6 +422,7 @@ self.kind = kind self.count = 0 self.maxvalue = maxvalue + self.register_finalizer() def kind_get(self, space): return space.newint(self.kind) @@ -505,7 +506,7 @@ def exit(self, space, __args__): self.release(space) - def __del__(self): + def invoke_finalizer(self): delete_semaphore(self.handle) @unwrap_spec(kind=int, value=int, maxvalue=int) From noreply at buildbot.pypy.org Fri Apr 26 22:08:40 2013 From: noreply at buildbot.pypy.org (amauryfa) Date: Fri, 26 Apr 2013 22:08:40 +0200 (CEST) Subject: [pypy-commit] pypy default: Fix tests when run with -A: CPython folds constants differently. Message-ID: <20130426200840.359281C31EC@cobra.cs.uni-duesseldorf.de> Author: Amaury Forgeot d'Arc Branch: Changeset: r63665:d47342f86927 Date: 2013-04-26 22:07 +0200 http://bitbucket.org/pypy/pypy/changeset/d47342f86927/ Log: Fix tests when run with -A: CPython folds constants differently. In particular, unused values are not removed from co_consts. diff --git a/pypy/interpreter/test/test_compiler.py b/pypy/interpreter/test/test_compiler.py --- a/pypy/interpreter/test/test_compiler.py +++ b/pypy/interpreter/test/test_compiler.py @@ -765,6 +765,9 @@ class AppTestOptimizer: + def setup_class(cls): + cls.w_runappdirect = cls.space.wrap(cls.runappdirect) + def test_remove_ending(self): source = """def f(): return 3 @@ -785,7 +788,8 @@ def test_none_constant(self): import opcode co = compile("def f(): return None", "", "exec").co_consts[0] - assert "None" not in co.co_names + if not self.runappdirect: # This is a pypy optimization + assert "None" not in co.co_names co = co.co_code op = ord(co[0]) + (ord(co[1]) << 8) assert op == opcode.opmap["LOAD_CONST"] @@ -800,29 +804,48 @@ def code(source): return compile(source, "", "exec") co = code("x = 10//4") - assert len(co.co_consts) == 2 - assert co.co_consts[0] == 2 + if self.runappdirect: + assert 2 in co.co_consts + else: + # PyPy is more precise + assert len(co.co_consts) == 2 + assert co.co_consts[0] == 2 co = code("x = 10/4") assert len(co.co_consts) == 3 assert co.co_consts[:2] == (10, 4) co = code("from __future__ import division\nx = 10/4") - assert co.co_consts[2] == 2.5 + if self.runappdirect: + assert 2.5 in co.co_consts + else: + assert co.co_consts[2] == 2.5 def test_tuple_folding(self): co = compile("x = (1, 2, 3)", "", "exec") - assert co.co_consts == ((1, 2, 3), None) + if not self.runappdirect: + # PyPy is more precise + assert co.co_consts == ((1, 2, 3), None) + else: + assert (1, 2, 3) in co.co_consts + assert None in co.co_consts co = compile("x = ()", "", "exec") - assert co.co_consts == ((), None) + assert set(co.co_consts) == set(((), None)) def test_unary_folding(self): + def check_const(co, value): + assert value in co.co_consts + if not self.runappdirect: + # This is a pypy optimization + assert co.co_consts[0] == value co = compile("x = -(3)", "", "exec") - assert co.co_consts[0] == -3 + check_const(co, -3) co = compile("x = ~3", "", "exec") - assert co.co_consts[0] == ~3 + check_const(co, ~3) co = compile("x = +(-3)", "", "exec") - assert co.co_consts[0] == -3 + check_const(co, -3) co = compile("x = not None", "", "exec") - assert co.co_consts[0] is True + if not self.runappdirect: + # CPython does not have this optimization + assert co.co_consts == (True, None) def test_folding_of_binops_on_constants(self): def disassemble(func): From noreply at buildbot.pypy.org Fri Apr 26 22:28:15 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Fri, 26 Apr 2013 22:28:15 +0200 (CEST) Subject: [pypy-commit] pypy py3k: these skips appear to work now, w/ some minor py3 adjustments Message-ID: <20130426202815.E8E1E1C31EC@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63666:5ad20662d450 Date: 2013-04-26 13:26 -0700 http://bitbucket.org/pypy/pypy/changeset/5ad20662d450/ Log: these skips appear to work now, w/ some minor py3 adjustments diff --git a/pypy/module/_ffi/test/test_funcptr.py b/pypy/module/_ffi/test/test_funcptr.py --- a/pypy/module/_ffi/test/test_funcptr.py +++ b/pypy/module/_ffi/test/test_funcptr.py @@ -113,7 +113,6 @@ return x+y; } """ - py3k_skip('missing support for longs') import sys from _ffi import CDLL, types libfoo = CDLL(self.libfoo_name) @@ -195,17 +194,16 @@ return len; } """ - py3k_skip('missing support for unicode') from _ffi import CDLL, types import _rawffi libfoo = CDLL(self.libfoo_name) mystrlen = libfoo.getfunc('mystrlen', [types.char_p], types.slong) # # first, try automatic conversion from a string - assert mystrlen('foobar') == 6 + assert mystrlen(b'foobar') == 6 # then, try to pass an explicit pointer CharArray = _rawffi.Array('c') - mystr = CharArray(7, 'foobar') + mystr = CharArray(7, b'foobar') assert mystrlen(mystr.buffer) == 6 mystr.free() mystrlen.free_temp_buffers() @@ -246,16 +244,15 @@ return s; } """ - py3k_skip('missing support for unicode') from _ffi import CDLL, types import _rawffi libfoo = CDLL(self.libfoo_name) do_nothing = libfoo.getfunc('do_nothing', [types.char_p], types.char_p) CharArray = _rawffi.Array('c') # - ptr = do_nothing('foobar') + ptr = do_nothing(b'foobar') array = CharArray.fromaddress(ptr, 7) - assert list(array) == list('foobar\00') + assert bytes(array) == b'foobar\00' do_nothing.free_temp_buffers() def test_typed_pointer_args(self): @@ -295,7 +292,6 @@ return x+y; } """ - py3k_skip('missing support for longs') import sys from _ffi import CDLL, types libfoo = CDLL(self.libfoo_name) @@ -438,7 +434,6 @@ return x+y; } """ - py3k_skip('missing support for ulonglong') from _ffi import CDLL, types maxint64 = 9223372036854775807 # maxint64+1 does not fit into a # longlong, but it does into a diff --git a/pypy/module/_multiprocessing/test/test_memory.py b/pypy/module/_multiprocessing/test/test_memory.py --- a/pypy/module/_multiprocessing/test/test_memory.py +++ b/pypy/module/_multiprocessing/test/test_memory.py @@ -8,7 +8,6 @@ raises(TypeError, _multiprocessing.address_of_buffer, "a") def test_mmap_address(self): - py3k_skip('ctypes not working yet') import mmap import _multiprocessing @@ -19,7 +18,7 @@ sizeof_double = _ctypes.sizeof(c_double) buf = mmap.mmap(-1, 300) - buf[0:300] = '\0' * 300 + buf[0:300] = b'\0' * 300 # Get the address of shared memory address, length = _multiprocessing.address_of_buffer(buf) @@ -27,11 +26,11 @@ # build a ctypes object from it var = c_double.from_address(address) - assert buf[0:sizeof_double] == '\0' * sizeof_double + assert buf[0:sizeof_double] == b'\0' * sizeof_double assert var.value == 0 # check that both objects share the same memory var.value = 123.456 - assert buf[0:sizeof_double] != '\0' * sizeof_double - buf[0:sizeof_double] = '\0' * sizeof_double + assert buf[0:sizeof_double] != b'\0' * sizeof_double + buf[0:sizeof_double] = b'\0' * sizeof_double assert var.value == 0 diff --git a/pypy/module/_rawffi/test/test__rawffi.py b/pypy/module/_rawffi/test/test__rawffi.py --- a/pypy/module/_rawffi/test/test__rawffi.py +++ b/pypy/module/_rawffi/test/test__rawffi.py @@ -557,7 +557,6 @@ raises(ValueError, "_rawffi.Array('xx')") def test_longs_ulongs(self): - py3k_skip('fails on 32bit') import _rawffi lib = _rawffi.CDLL(self.lib_name) some_huge_value = lib.ptr('some_huge_value', [], 'q') @@ -610,7 +609,6 @@ cb.free() def test_another_callback(self): - py3k_skip('fails on 32bit') import _rawffi lib = _rawffi.CDLL(self.lib_name) runcallback = lib.ptr('runcallback', ['P'], 'q') @@ -776,7 +774,6 @@ a.free() def test_truncate(self): - py3k_skip('int vs long') import _rawffi, struct a = _rawffi.Array('b')(1) a[0] = -5 From noreply at buildbot.pypy.org Fri Apr 26 22:33:36 2013 From: noreply at buildbot.pypy.org (amauryfa) Date: Fri, 26 Apr 2013 22:33:36 +0200 (CEST) Subject: [pypy-commit] pypy py3k: hg merge default Message-ID: <20130426203336.E1C2E1C31EC@cobra.cs.uni-duesseldorf.de> Author: Amaury Forgeot d'Arc Branch: py3k Changeset: r63667:e6b80345d013 Date: 2013-04-26 22:26 +0200 http://bitbucket.org/pypy/pypy/changeset/e6b80345d013/ Log: hg merge default diff --git a/pypy/interpreter/astcompiler/consts.py b/pypy/interpreter/astcompiler/consts.py --- a/pypy/interpreter/astcompiler/consts.py +++ b/pypy/interpreter/astcompiler/consts.py @@ -16,8 +16,6 @@ CO_FUTURE_PRINT_FUNCTION = 0x10000 CO_FUTURE_UNICODE_LITERALS = 0x20000 CO_FUTURE_BARRY_AS_BDFL = 0x40000 -CO_CONTAINSGLOBALS = 0x80000 # pypy-specific: need to check that it's not used - # by any other flag PyCF_MASK = (CO_FUTURE_DIVISION | CO_FUTURE_ABSOLUTE_IMPORT | CO_FUTURE_WITH_STATEMENT | CO_FUTURE_PRINT_FUNCTION | diff --git a/pypy/interpreter/pycode.py b/pypy/interpreter/pycode.py --- a/pypy/interpreter/pycode.py +++ b/pypy/interpreter/pycode.py @@ -12,7 +12,7 @@ from pypy.interpreter.gateway import unwrap_spec from pypy.interpreter.astcompiler.consts import ( CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS, CO_NESTED, - CO_GENERATOR, CO_CONTAINSGLOBALS) + CO_GENERATOR) from pypy.tool.stdlib_opcode import opcodedesc, HAVE_ARGUMENT from rpython.rlib.rarithmetic import intmask from rpython.rlib.objectmodel import compute_hash, we_are_translated @@ -106,8 +106,6 @@ self._initialize() def _initialize(self): - self._init_flags() - if self.co_cellvars: argcount = self.co_argcount argcount += self.co_kwonlyargcount @@ -153,22 +151,6 @@ '__pypy__' not in sys.builtin_module_names): raise Exception("CPython host codes should not be rendered") - def _init_flags(self): - co_code = self.co_code - next_instr = 0 - while next_instr < len(co_code): - opcode = ord(co_code[next_instr]) - next_instr += 1 - if opcode >= HAVE_ARGUMENT: - next_instr += 2 - while opcode == opcodedesc.EXTENDED_ARG.index: - opcode = ord(co_code[next_instr]) - next_instr += 3 - if opcode == opcodedesc.LOAD_GLOBAL.index: - self.co_flags |= CO_CONTAINSGLOBALS - elif opcode == opcodedesc.LOAD_NAME.index: - self.co_flags |= CO_CONTAINSGLOBALS - co_names = property(lambda self: [self.space.str_w(w_name) for w_name in self.co_names_w]) # for trace def signature(self): diff --git a/pypy/interpreter/test/test_code.py b/pypy/interpreter/test/test_code.py --- a/pypy/interpreter/test/test_code.py +++ b/pypy/interpreter/test/test_code.py @@ -9,7 +9,6 @@ filename = filename[:-1] cls.w_file = cls.space.wrap(filename) - cls.w_CO_CONTAINSGLOBALS = cls.space.wrap(consts.CO_CONTAINSGLOBALS) cls.w_CO_NOFREE = cls.space.wrap(consts.CO_NOFREE) def test_attributes(self): @@ -193,27 +192,3 @@ # CO_NESTED assert d['f'](4).__code__.co_flags & 0x10 assert d['f'].__code__.co_flags & 0x10 == 0 - # check for CO_CONTAINSGLOBALS - assert not d['f'].__code__.co_flags & self.CO_CONTAINSGLOBALS - - - exec("""if 1: - r = range - def f(): - return [l for l in r(100)] - def g(): - return [l for l in [1, 2, 3, 4]] -""", d) - - # check for CO_CONTAINSGLOBALS - assert d['f'].__code__.co_flags & self.CO_CONTAINSGLOBALS - assert not d['g'].__code__.co_flags & self.CO_CONTAINSGLOBALS - - exec("""if 1: - b = 2 - def f(x): - exec("a = 1") - return a + b + x -""", d) - # check for CO_CONTAINSGLOBALS - assert d['f'].__code__.co_flags & self.CO_CONTAINSGLOBALS diff --git a/pypy/interpreter/test/test_compiler.py b/pypy/interpreter/test/test_compiler.py --- a/pypy/interpreter/test/test_compiler.py +++ b/pypy/interpreter/test/test_compiler.py @@ -861,6 +861,9 @@ class AppTestOptimizer: + def setup_class(cls): + cls.w_runappdirect = cls.space.wrap(cls.runappdirect) + def test_remove_ending(self): source = """def f(): return 3 @@ -885,7 +888,8 @@ for name in "None", "True", "False": snip = "def f(): return " + name co = compile(snip, "", "exec").co_consts[0] - assert name not in co.co_names + if not self.runappdirect: # This is a pypy optimization + assert name not in co.co_names co = co.co_code op = co[0] assert op == opcode.opmap["LOAD_CONST"] @@ -904,27 +908,46 @@ def code(source): return compile(source, "", "exec") co = code("x = 10//4") - assert len(co.co_consts) == 2 - assert co.co_consts[0] == 2 + if self.runappdirect: + assert 2 in co.co_consts + else: + # PyPy is more precise + assert len(co.co_consts) == 2 + assert co.co_consts[0] == 2 co = code("x = 10/4") - assert len(co.co_consts) == 2 - assert co.co_consts[0] == 2.5 + if self.runappdirect: + assert 2.5 in co.co_consts + else: + assert len(co.co_consts) == 2 + assert co.co_consts[0] == 2.5 def test_tuple_folding(self): co = compile("x = (1, 2, 3)", "", "exec") - assert co.co_consts == ((1, 2, 3), None) + if not self.runappdirect: + # PyPy is more precise + assert co.co_consts == ((1, 2, 3), None) + else: + assert (1, 2, 3) in co.co_consts + assert None in co.co_consts co = compile("x = ()", "", "exec") - assert co.co_consts == ((), None) + assert set(co.co_consts) == set(((), None)) def test_unary_folding(self): + def check_const(co, value): + assert value in co.co_consts + if not self.runappdirect: + # This is a pypy optimization + assert co.co_consts[0] == value co = compile("x = -(3)", "", "exec") - assert co.co_consts[0] == -3 + check_const(co, -3) co = compile("x = ~3", "", "exec") - assert co.co_consts[0] == ~3 + check_const(co, ~3) co = compile("x = +(-3)", "", "exec") - assert co.co_consts[0] == -3 + check_const(co, -3) co = compile("x = not None", "", "exec") - assert co.co_consts[0] is True + if not self.runappdirect: + # CPython does not have this optimization + assert co.co_consts == (True, None) def test_folding_of_binops_on_constants(self): def disassemble(func): diff --git a/rpython/jit/backend/arm/codebuilder.py b/rpython/jit/backend/arm/codebuilder.py --- a/rpython/jit/backend/arm/codebuilder.py +++ b/rpython/jit/backend/arm/codebuilder.py @@ -335,7 +335,7 @@ # XXX remove and setup aligning in llsupport def materialize(self, asmmemmgr, allblocks, gcrootmap=None): - size = self.get_relative_pos() + size = self.get_relative_pos() + WORD malloced = asmmemmgr.malloc(size, size + 7) allblocks.append(malloced) rawstart = malloced[0] diff --git a/rpython/jit/backend/test/runner_test.py b/rpython/jit/backend/test/runner_test.py --- a/rpython/jit/backend/test/runner_test.py +++ b/rpython/jit/backend/test/runner_test.py @@ -41,8 +41,8 @@ class Runner(object): - add_loop_instruction = ['overload for a specific cpu'] - bridge_loop_instruction = ['overload for a specific cpu'] + add_loop_instructions = ['overload for a specific cpu'] + bridge_loop_instructions = ['overload for a specific cpu'] def execute_operation(self, opname, valueboxes, result_type, descr=None): inputargs, operations = self._get_single_operation_list(opname, diff --git a/rpython/jit/codewriter/support.py b/rpython/jit/codewriter/support.py --- a/rpython/jit/codewriter/support.py +++ b/rpython/jit/codewriter/support.py @@ -203,7 +203,6 @@ _ll_2_list_append = rlist.ll_append _ll_2_list_extend = rlist.ll_extend _ll_3_list_insert = rlist.ll_insert_nonneg -_ll_4_list_setslice = rlist.ll_listsetslice _ll_2_list_delslice_startonly = rlist.ll_listdelslice_startonly _ll_3_list_delslice_startstop = rlist.ll_listdelslice_startstop _ll_2_list_inplace_mul = rlist.ll_inplace_mul diff --git a/rpython/jit/metainterp/heapcache.py b/rpython/jit/metainterp/heapcache.py --- a/rpython/jit/metainterp/heapcache.py +++ b/rpython/jit/metainterp/heapcache.py @@ -125,7 +125,7 @@ for descr, cache in self.heap_array_cache.iteritems(): for idx, cache in cache.iteritems(): for frombox in cache.keys(): - if frombox not in self.new_boxes: + if not self.new_boxes.get(frombox, False): del cache[frombox] return else: diff --git a/rpython/jit/metainterp/test/test_list.py b/rpython/jit/metainterp/test/test_list.py --- a/rpython/jit/metainterp/test/test_list.py +++ b/rpython/jit/metainterp/test/test_list.py @@ -128,10 +128,10 @@ res = self.interp_operations(f, [], listops=True) assert res == 10 - def test_arraycopy_bug(self): + def test_arraycopy_bug(self): def f(): l = [1, 2, 3, 4] - l2 = [1, 2, 3, 4] + l2 = [1, 2, 3, 5] l[2] = 13 l2[0:len(l2)] = l[:] return l2[0] + l2[1] + l2[2] + l2[3] diff --git a/rpython/memory/test/test_generational_gc.py b/rpython/memory/test/test_generational_gc.py --- a/rpython/memory/test/test_generational_gc.py +++ b/rpython/memory/test/test_generational_gc.py @@ -1,4 +1,4 @@ -from rpython.memory.test.test_semispace_gc import TestSemiSpaceGC +from rpython.memory.test import test_semispace_gc -class TestGenerationalGC(TestSemiSpaceGC): +class TestGenerationalGC(test_semispace_gc.TestSemiSpaceGC): from rpython.memory.gc.generation import GenerationGC as GCClass diff --git a/rpython/memory/test/test_growingsemispace_gc.py b/rpython/memory/test/test_growingsemispace_gc.py --- a/rpython/memory/test/test_growingsemispace_gc.py +++ b/rpython/memory/test/test_growingsemispace_gc.py @@ -1,8 +1,8 @@ from rpython.rlib.rarithmetic import LONG_BIT -from rpython.memory.test.test_semispace_gc import TestSemiSpaceGC +from rpython.memory.test import test_semispace_gc WORD = LONG_BIT // 8 -class TestGrowingSemiSpaceGC(TestSemiSpaceGC): +class TestGrowingSemiSpaceGC(test_semispace_gc.TestSemiSpaceGC): GC_PARAMS = {'space_size': 16*WORD} diff --git a/rpython/memory/test/test_hybrid_gc.py b/rpython/memory/test/test_hybrid_gc.py --- a/rpython/memory/test/test_hybrid_gc.py +++ b/rpython/memory/test/test_hybrid_gc.py @@ -3,10 +3,10 @@ from rpython.rtyper.lltypesystem import lltype from rpython.rtyper.lltypesystem.lloperation import llop -from rpython.memory.test.test_generational_gc import TestGenerationalGC +from rpython.memory.test import test_generational_gc -class TestHybridGC(TestGenerationalGC): +class TestHybridGC(test_generational_gc.TestGenerationalGC): from rpython.memory.gc.hybrid import HybridGC as GCClass GC_CAN_MALLOC_NONMOVABLE = True GC_CAN_SHRINK_BIG_ARRAY = False diff --git a/rpython/memory/test/test_minimark_gc.py b/rpython/memory/test/test_minimark_gc.py --- a/rpython/memory/test/test_minimark_gc.py +++ b/rpython/memory/test/test_minimark_gc.py @@ -1,10 +1,10 @@ from rpython.rlib.rarithmetic import LONG_BIT -from rpython.memory.test.test_semispace_gc import TestSemiSpaceGC +from rpython.memory.test import test_semispace_gc WORD = LONG_BIT // 8 -class TestMiniMarkGC(TestSemiSpaceGC): +class TestMiniMarkGC(test_semispace_gc.TestSemiSpaceGC): from rpython.memory.gc.minimark import MiniMarkGC as GCClass GC_CAN_SHRINK_BIG_ARRAY = False GC_CAN_MALLOC_NONMOVABLE = True diff --git a/rpython/memory/test/test_minimark_gc_cardmarking.py b/rpython/memory/test/test_minimark_gc_cardmarking.py --- a/rpython/memory/test/test_minimark_gc_cardmarking.py +++ b/rpython/memory/test/test_minimark_gc_cardmarking.py @@ -1,4 +1,4 @@ -from rpython.memory.test.test_minimark_gc import TestMiniMarkGC +from rpython.memory.test import test_minimark_gc -class TestMiniMarkGCCardMarking(TestMiniMarkGC): +class TestMiniMarkGCCardMarking(test_minimark_gc.TestMiniMarkGC): GC_PARAMS = {'card_page_indices': 4} diff --git a/rpython/rtyper/rlist.py b/rpython/rtyper/rlist.py --- a/rpython/rtyper/rlist.py +++ b/rpython/rtyper/rlist.py @@ -955,7 +955,7 @@ "setslice cannot resize lists in RPython") # XXX ...but it would be easy enough to support if really needed ll_arraycopy(l2, l1, 0, start, count) -ll_listsetslice.oopspec = 'list.setslice(l1, start, stop, l2)' + # ____________________________________________________________ # From noreply at buildbot.pypy.org Fri Apr 26 22:33:38 2013 From: noreply at buildbot.pypy.org (amauryfa) Date: Fri, 26 Apr 2013 22:33:38 +0200 (CEST) Subject: [pypy-commit] pypy py3k: merge heads Message-ID: <20130426203338.2EA261C31EC@cobra.cs.uni-duesseldorf.de> Author: Amaury Forgeot d'Arc Branch: py3k Changeset: r63668:18cdece25b93 Date: 2013-04-26 22:31 +0200 http://bitbucket.org/pypy/pypy/changeset/18cdece25b93/ Log: merge heads diff --git a/pypy/module/_ffi/test/test_funcptr.py b/pypy/module/_ffi/test/test_funcptr.py --- a/pypy/module/_ffi/test/test_funcptr.py +++ b/pypy/module/_ffi/test/test_funcptr.py @@ -113,7 +113,6 @@ return x+y; } """ - py3k_skip('missing support for longs') import sys from _ffi import CDLL, types libfoo = CDLL(self.libfoo_name) @@ -195,17 +194,16 @@ return len; } """ - py3k_skip('missing support for unicode') from _ffi import CDLL, types import _rawffi libfoo = CDLL(self.libfoo_name) mystrlen = libfoo.getfunc('mystrlen', [types.char_p], types.slong) # # first, try automatic conversion from a string - assert mystrlen('foobar') == 6 + assert mystrlen(b'foobar') == 6 # then, try to pass an explicit pointer CharArray = _rawffi.Array('c') - mystr = CharArray(7, 'foobar') + mystr = CharArray(7, b'foobar') assert mystrlen(mystr.buffer) == 6 mystr.free() mystrlen.free_temp_buffers() @@ -246,16 +244,15 @@ return s; } """ - py3k_skip('missing support for unicode') from _ffi import CDLL, types import _rawffi libfoo = CDLL(self.libfoo_name) do_nothing = libfoo.getfunc('do_nothing', [types.char_p], types.char_p) CharArray = _rawffi.Array('c') # - ptr = do_nothing('foobar') + ptr = do_nothing(b'foobar') array = CharArray.fromaddress(ptr, 7) - assert list(array) == list('foobar\00') + assert bytes(array) == b'foobar\00' do_nothing.free_temp_buffers() def test_typed_pointer_args(self): @@ -295,7 +292,6 @@ return x+y; } """ - py3k_skip('missing support for longs') import sys from _ffi import CDLL, types libfoo = CDLL(self.libfoo_name) @@ -438,7 +434,6 @@ return x+y; } """ - py3k_skip('missing support for ulonglong') from _ffi import CDLL, types maxint64 = 9223372036854775807 # maxint64+1 does not fit into a # longlong, but it does into a diff --git a/pypy/module/_multiprocessing/test/test_memory.py b/pypy/module/_multiprocessing/test/test_memory.py --- a/pypy/module/_multiprocessing/test/test_memory.py +++ b/pypy/module/_multiprocessing/test/test_memory.py @@ -8,7 +8,6 @@ raises(TypeError, _multiprocessing.address_of_buffer, "a") def test_mmap_address(self): - py3k_skip('ctypes not working yet') import mmap import _multiprocessing @@ -19,7 +18,7 @@ sizeof_double = _ctypes.sizeof(c_double) buf = mmap.mmap(-1, 300) - buf[0:300] = '\0' * 300 + buf[0:300] = b'\0' * 300 # Get the address of shared memory address, length = _multiprocessing.address_of_buffer(buf) @@ -27,11 +26,11 @@ # build a ctypes object from it var = c_double.from_address(address) - assert buf[0:sizeof_double] == '\0' * sizeof_double + assert buf[0:sizeof_double] == b'\0' * sizeof_double assert var.value == 0 # check that both objects share the same memory var.value = 123.456 - assert buf[0:sizeof_double] != '\0' * sizeof_double - buf[0:sizeof_double] = '\0' * sizeof_double + assert buf[0:sizeof_double] != b'\0' * sizeof_double + buf[0:sizeof_double] = b'\0' * sizeof_double assert var.value == 0 diff --git a/pypy/module/_rawffi/test/test__rawffi.py b/pypy/module/_rawffi/test/test__rawffi.py --- a/pypy/module/_rawffi/test/test__rawffi.py +++ b/pypy/module/_rawffi/test/test__rawffi.py @@ -557,7 +557,6 @@ raises(ValueError, "_rawffi.Array('xx')") def test_longs_ulongs(self): - py3k_skip('fails on 32bit') import _rawffi lib = _rawffi.CDLL(self.lib_name) some_huge_value = lib.ptr('some_huge_value', [], 'q') @@ -610,7 +609,6 @@ cb.free() def test_another_callback(self): - py3k_skip('fails on 32bit') import _rawffi lib = _rawffi.CDLL(self.lib_name) runcallback = lib.ptr('runcallback', ['P'], 'q') @@ -776,7 +774,6 @@ a.free() def test_truncate(self): - py3k_skip('int vs long') import _rawffi, struct a = _rawffi.Array('b')(1) a[0] = -5 From noreply at buildbot.pypy.org Fri Apr 26 23:09:18 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 26 Apr 2013 23:09:18 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Fix pyexpat. Message-ID: <20130426210918.673331C00BD@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63669:8896103629f9 Date: 2013-04-26 22:46 +0200 http://bitbucket.org/pypy/pypy/changeset/8896103629f9/ Log: Fix pyexpat. diff --git a/pypy/module/pyexpat/interp_pyexpat.py b/pypy/module/pyexpat/interp_pyexpat.py --- a/pypy/module/pyexpat/interp_pyexpat.py +++ b/pypy/module/pyexpat/interp_pyexpat.py @@ -441,7 +441,9 @@ CallbackData(space, self)) XML_SetUserData(self.itself, rffi.cast(rffi.VOIDP, self.id)) - def __del__(self): + self.register_finalizer() + + def invoke_finalizer(self): if XML_ParserFree: # careful with CPython interpreter shutdown XML_ParserFree(self.itself) if global_storage: From noreply at buildbot.pypy.org Fri Apr 26 23:09:19 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 26 Apr 2013 23:09:19 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Fixes Message-ID: <20130426210919.C27AF1C00BD@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63670:89bcb5d5942a Date: 2013-04-26 22:46 +0200 http://bitbucket.org/pypy/pypy/changeset/89bcb5d5942a/ Log: Fixes diff --git a/pypy/module/_cffi_backend/ccallback.py b/pypy/module/_cffi_backend/ccallback.py --- a/pypy/module/_cffi_backend/ccallback.py +++ b/pypy/module/_cffi_backend/ccallback.py @@ -54,12 +54,13 @@ if rffi.cast(lltype.Signed, res) != clibffi.FFI_OK: raise OperationError(space.w_SystemError, space.wrap("libffi failed to build this callback")) + # + self.register_finalizer() def get_closure(self): return rffi.cast(clibffi.FFI_CLOSUREP, self._cdata) - #@rgc.must_be_light_finalizer - def __del__(self): + def invoke_finalizer(self): clibffi.closureHeap.free(self.get_closure()) if self.ll_error: lltype.free(self.ll_error, flavor='raw') diff --git a/pypy/module/_hashlib/interp_hashlib.py b/pypy/module/_hashlib/interp_hashlib.py --- a/pypy/module/_hashlib/interp_hashlib.py +++ b/pypy/module/_hashlib/interp_hashlib.py @@ -38,8 +38,9 @@ except: lltype.free(ctx, flavor='raw') raise + self.register_finalizer() - def __del__(self): + def invoke_finalizer(self): if self.ctx: ropenssl.EVP_MD_CTX_cleanup(self.ctx) lltype.free(self.ctx, flavor='raw') From noreply at buildbot.pypy.org Fri Apr 26 23:09:21 2013 From: noreply at buildbot.pypy.org (arigo) Date: Fri, 26 Apr 2013 23:09:21 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Fix the oracle module (blindly) Message-ID: <20130426210921.09BAA1C00BD@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63671:022f6153a022 Date: 2013-04-26 22:50 +0200 http://bitbucket.org/pypy/pypy/changeset/022f6153a022/ Log: Fix the oracle module (blindly) diff --git a/pypy/module/oracle/interp_connect.py b/pypy/module/oracle/interp_connect.py --- a/pypy/module/oracle/interp_connect.py +++ b/pypy/module/oracle/interp_connect.py @@ -29,6 +29,8 @@ self.w_version = None self.release = False + self.register_finalizer() + @unwrap_spec(mode=int, handle=int, threaded=bool, twophase=bool, events=bool, @@ -80,13 +82,11 @@ self.connect(space, mode, twophase) return space.wrap(self) - def __del__(self): - self.enqueue_for_destruction(self.environment.space, - W_Connection.destructor, - '__del__ method of ') + def invoke_finalizer(self): + self.finalizer_perform(self.environment.space, '__del__ method of ', + self.destructor) def destructor(self): - assert isinstance(self, W_Connection) if self.release: roci.OCITransRollback( self.handle, self.environment.errorHandle, diff --git a/pypy/module/oracle/interp_object.py b/pypy/module/oracle/interp_object.py --- a/pypy/module/oracle/interp_object.py +++ b/pypy/module/oracle/interp_object.py @@ -14,14 +14,14 @@ self.environment = connection.environment self.isCollection = False self.initialize(connection, param) + self.register_finalizer() - def __del__(self): - self.enqueue_for_destruction(self.environment.space, - W_ObjectType.destructor, - '__del__ method of ') + def invoke_finalizer(self): + if self.tdo: + self.finalizer_perform(self.environment.space, '__del__ method of ', + self.destructor) def destructor(self): - assert isinstance(self, W_ObjectType) if self.tdo: roci.OCIObjectUnpin( self.environment.handle, diff --git a/pypy/module/oracle/interp_variable.py b/pypy/module/oracle/interp_variable.py --- a/pypy/module/oracle/interp_variable.py +++ b/pypy/module/oracle/interp_variable.py @@ -166,13 +166,13 @@ # perform extended initialization self.initialize(self.environment.space, cursor) - def __del__(self): - self.enqueue_for_destruction(self.environment.space, - W_Variable.destructor, - '__del__ method of ') + self.register_finalizer() + + def invoke_finalizer(self): + self.finalizer_perform(self.environment.space, '__del__ method of ', + self.destructor) def destructor(self): - assert isinstance(self, W_Variable) self.finalize() lltype.free(self.actualElementsPtr, flavor='raw') if self.actualLength: From noreply at buildbot.pypy.org Sat Apr 27 01:27:18 2013 From: noreply at buildbot.pypy.org (amauryfa) Date: Sat, 27 Apr 2013 01:27:18 +0200 (CEST) Subject: [pypy-commit] pypy py3k: Fix termios test: the script contains '\000', not the NUL character. Message-ID: <20130426232718.3A4021C0328@cobra.cs.uni-duesseldorf.de> Author: Amaury Forgeot d'Arc Branch: py3k Changeset: r63673:82f1bb404898 Date: 2013-04-27 01:26 +0200 http://bitbucket.org/pypy/pypy/changeset/82f1bb404898/ Log: Fix termios test: the script contains '\000', not the NUL character. diff --git a/pypy/module/termios/test/test_termios.py b/pypy/module/termios/test/test_termios.py --- a/pypy/module/termios/test/test_termios.py +++ b/pypy/module/termios/test/test_termios.py @@ -82,7 +82,7 @@ child.expect('ok!') def test_ioctl_termios(self): - source = py.code.Source(""" + source = py.code.Source(r""" import termios import fcntl lgt = len(fcntl.ioctl(2, termios.TIOCGWINSZ, b'\000'*8)) From noreply at buildbot.pypy.org Sat Apr 27 01:27:17 2013 From: noreply at buildbot.pypy.org (amauryfa) Date: Sat, 27 Apr 2013 01:27:17 +0200 (CEST) Subject: [pypy-commit] pypy py3k: Easy fix for a cpyext test failure. Message-ID: <20130426232717.09BDA1C02DA@cobra.cs.uni-duesseldorf.de> Author: Amaury Forgeot d'Arc Branch: py3k Changeset: r63672:3162f06e9e0a Date: 2013-04-27 01:06 +0200 http://bitbucket.org/pypy/pypy/changeset/3162f06e9e0a/ Log: Easy fix for a cpyext test failure. diff --git a/pypy/module/cpyext/include/patchlevel.h b/pypy/module/cpyext/include/patchlevel.h --- a/pypy/module/cpyext/include/patchlevel.h +++ b/pypy/module/cpyext/include/patchlevel.h @@ -21,12 +21,12 @@ /* Version parsed out into numeric values */ #define PY_MAJOR_VERSION 3 #define PY_MINOR_VERSION 2 -#define PY_MICRO_VERSION 2 +#define PY_MICRO_VERSION 3 #define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_FINAL #define PY_RELEASE_SERIAL 0 /* Version as a string */ -#define PY_VERSION "3.2.2" +#define PY_VERSION "3.2.3" /* PyPy version as a string */ #define PYPY_VERSION "2.0.0-beta2" From noreply at buildbot.pypy.org Sat Apr 27 09:01:06 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sat, 27 Apr 2013 09:01:06 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Fixes. Now an -O2 translates :-) Message-ID: <20130427070106.5B9A91C02DA@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63674:1a9bed8849c5 Date: 2013-04-27 09:03 +0200 http://bitbucket.org/pypy/pypy/changeset/1a9bed8849c5/ Log: Fixes. Now an -O2 translates :-) diff --git a/pypy/module/_multibytecodec/interp_incremental.py b/pypy/module/_multibytecodec/interp_incremental.py --- a/pypy/module/_multibytecodec/interp_incremental.py +++ b/pypy/module/_multibytecodec/interp_incremental.py @@ -21,9 +21,6 @@ self.name = codec.name self._initialize() - def __del__(self): - self._free() - def reset_w(self): self._free() self._initialize() @@ -36,13 +33,14 @@ class MultibyteIncrementalDecoder(MultibyteIncrementalBase): + def __del__(self): + self._free() def _initialize(self): self.decodebuf = c_codecs.pypy_cjk_dec_new(self.codec) self.pending = "" def _free(self): - self.pending = None if self.decodebuf: c_codecs.pypy_cjk_dec_free(self.decodebuf) self.decodebuf = lltype.nullptr(c_codecs.DECODEBUF_P.TO) @@ -85,13 +83,14 @@ class MultibyteIncrementalEncoder(MultibyteIncrementalBase): + def __del__(self): + self._free() def _initialize(self): self.encodebuf = c_codecs.pypy_cjk_enc_new(self.codec) self.pending = u"" def _free(self): - self.pending = None if self.encodebuf: c_codecs.pypy_cjk_enc_free(self.encodebuf) self.encodebuf = lltype.nullptr(c_codecs.ENCODEBUF_P.TO) diff --git a/pypy/module/_rawffi/callback.py b/pypy/module/_rawffi/callback.py --- a/pypy/module/_rawffi/callback.py +++ b/pypy/module/_rawffi/callback.py @@ -72,12 +72,12 @@ except LibFFIError: raise got_libffi_error(space) self.ll_buffer = rffi.cast(rffi.VOIDP, self.ll_callback.ll_closure) - if tracker.DO_TRACING: + if tracker.do_tracing(): addr = rffi.cast(lltype.Signed, self.ll_callback.ll_closure) tracker.trace_allocation(addr, self) def free(self): - if tracker.DO_TRACING: + if tracker.do_tracing(): addr = rffi.cast(lltype.Signed, self.ll_callback.ll_closure) tracker.trace_free(addr) global_counter.remove(self.number) diff --git a/pypy/module/_rawffi/interp_rawffi.py b/pypy/module/_rawffi/interp_rawffi.py --- a/pypy/module/_rawffi/interp_rawffi.py +++ b/pypy/module/_rawffi/interp_rawffi.py @@ -277,7 +277,7 @@ else: self.ll_buffer = lltype.malloc(rffi.VOIDP.TO, size, flavor='raw', zero=True, add_memory_pressure=True) - if tracker.DO_TRACING: + if tracker.do_tracing(): ll_buf = rffi.cast(lltype.Signed, self.ll_buffer) tracker.trace_allocation(ll_buf, self) @@ -296,7 +296,7 @@ self._free() def _free(self): - if tracker.DO_TRACING: + if tracker.do_tracing(): ll_buf = rffi.cast(lltype.Signed, self.ll_buffer) tracker.trace_free(ll_buf) lltype.free(self.ll_buffer, flavor='raw') @@ -392,7 +392,7 @@ from pypy.module._rawffi.array import ARRAY_OF_PTRS array = ARRAY_OF_PTRS.allocate(space, 1) array.setitem(space, 0, self.getbuffer(space)) - if tracker.DO_TRACING: + 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(lltype.Signed, array.ll_buffer)] diff --git a/pypy/module/_rawffi/tracker.py b/pypy/module/_rawffi/tracker.py --- a/pypy/module/_rawffi/tracker.py +++ b/pypy/module/_rawffi/tracker.py @@ -2,6 +2,8 @@ """ The file that keeps track about freed/kept-alive objects allocated by _rawffi. Used for debugging ctypes """ +from rpython.rlib.objectmodel import we_are_translated + class Tracker(object): DO_TRACING = True @@ -9,12 +11,17 @@ def __init__(self): self.alloced = {} + def do_tracing(self): + return not we_are_translated() and self.DO_TRACING + def trace_allocation(self, address, obj): - self.alloced[address] = None + if not we_are_translated(): + self.alloced[address] = None def trace_free(self, address): - if address in self.alloced: - del self.alloced[address] + if not we_are_translated(): + if address in self.alloced: + del self.alloced[address] # single, global, static object to keep all tracker info tracker = Tracker() From noreply at buildbot.pypy.org Sat Apr 27 10:03:00 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sat, 27 Apr 2013 10:03:00 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Minimal support for register_finalizer() in the JIT Message-ID: <20130427080300.985261C026F@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63675:bc7623f7e088 Date: 2013-04-27 10:05 +0200 http://bitbucket.org/pypy/pypy/changeset/bc7623f7e088/ Log: Minimal support for register_finalizer() in the JIT diff --git a/rpython/jit/backend/llsupport/gc.py b/rpython/jit/backend/llsupport/gc.py --- a/rpython/jit/backend/llsupport/gc.py +++ b/rpython/jit/backend/llsupport/gc.py @@ -534,7 +534,7 @@ if self.layoutbuilder is not None: type_id = self.layoutbuilder.get_type_id(S) assert not self.layoutbuilder.is_weakref_type(S) - assert not self.layoutbuilder.has_finalizer(S) + assert not self.layoutbuilder.has_destructor(S) descr.tid = llop.combine_ushort(lltype.Signed, type_id, 0) def init_array_descr(self, A, descr): diff --git a/rpython/jit/codewriter/jtransform.py b/rpython/jit/codewriter/jtransform.py --- a/rpython/jit/codewriter/jtransform.py +++ b/rpython/jit/codewriter/jtransform.py @@ -482,6 +482,7 @@ rewrite_op_ullong_mod_zer = _do_builtin_call rewrite_op_gc_identityhash = _do_builtin_call rewrite_op_gc_id = _do_builtin_call + rewrite_op_gc_register_finalizer = _do_builtin_call rewrite_op_uint_mod = _do_builtin_call rewrite_op_cast_float_to_uint = _do_builtin_call rewrite_op_cast_uint_to_float = _do_builtin_call diff --git a/rpython/jit/codewriter/support.py b/rpython/jit/codewriter/support.py --- a/rpython/jit/codewriter/support.py +++ b/rpython/jit/codewriter/support.py @@ -217,7 +217,6 @@ def _ll_1_gc_identityhash(x): return lltype.identityhash(x) - # the following function should not be "@elidable": I can think of # a corner case in which id(const) is constant-folded, and then 'const' # disappears and is collected too early (possibly causing another object @@ -225,6 +224,9 @@ def _ll_1_gc_id(ptr): return llop.gc_id(lltype.Signed, ptr) +def _ll_2_gc_register_finalizer(obj, func): + return llop.gc_register_finalizer(lltype.Void, obj, func) + @oopspec("jit.force_virtual(inst)") def _ll_1_jit_force_virtual(inst): @@ -839,6 +841,9 @@ def get_gcid_oopspec(op): return 'gc_id', op.args +def get_gcregisterfinalizer_oopspec(op): + return 'gc_register_finalizer', op.args + RENAMED_ADT_NAME = { 'list': { @@ -871,6 +876,8 @@ return get_identityhash_oopspec(op) elif op.opname == 'gc_id': return get_gcid_oopspec(op) + elif op.opname == 'gc_register_finalizer': + return get_gcregisterfinalizer_oopspec(op) else: raise ValueError(op.opname) diff --git a/rpython/jit/codewriter/test/test_flatten.py b/rpython/jit/codewriter/test/test_flatten.py --- a/rpython/jit/codewriter/test/test_flatten.py +++ b/rpython/jit/codewriter/test/test_flatten.py @@ -11,7 +11,7 @@ from rpython.rlib.rarithmetic import ovfcheck, r_uint, r_longlong, r_ulonglong from rpython.rlib.jit import dont_look_inside, _we_are_jitted, JitDriver from rpython.rlib.objectmodel import keepalive_until_here -from rpython.rlib import jit +from rpython.rlib import jit, rgc class FakeRegAlloc: @@ -999,6 +999,19 @@ float_return %(result_var)s """ % {"result_var": result_var, "tmp_var": tmp_var}, transform=True) + def test_register_finalizer(self): + class A(object): + def finalizer(self): + pass + glob_a = A() + def f(): + rgc.register_finalizer(glob_a.finalizer) + self.encoding_test(f, [], """ + residual_call_ir_v $<* fn gc_register_finalizer>, I[$<* fn A.finalizer>], R[$<* struct object>], + -live- + void_return + """, transform=True) + def check_force_cast(FROM, TO, operations, value): """Check that the test is correctly written...""" diff --git a/rpython/jit/metainterp/test/test_del.py b/rpython/jit/metainterp/test/test_del.py --- a/rpython/jit/metainterp/test/test_del.py +++ b/rpython/jit/metainterp/test/test_del.py @@ -123,8 +123,34 @@ res = self.meta_interp(main, [20]) assert res == 1001 + class TestLLtype(DelTests, LLJitMixin): - pass + + def test_finalizer(self): + mydriver = JitDriver(reds = ['n'], greens = []) + class Glob(object): + seen = 0 + glob = Glob() + class A(object): + def __init__(self): + rgc.register_finalizer(self.finalizer) + def finalizer(self): + glob.seen += 1 + @dont_look_inside + def do_collect(): + rgc.collect(); rgc.collect() + def main(n): + glob.seen = 0 + while n > 0: + mydriver.jit_merge_point(n=n) + A(); A(); A() + n -= 1 + do_collect() + return glob.seen + assert main(10) == 30 + res = self.meta_interp(main, [20]) + assert res >= 54 + class TestOOtype(DelTests, OOJitMixin): def setup_class(cls): diff --git a/rpython/memory/gctransform/framework.py b/rpython/memory/gctransform/framework.py --- a/rpython/memory/gctransform/framework.py +++ b/rpython/memory/gctransform/framework.py @@ -1204,9 +1204,11 @@ v_obj, v_func = hop.spaceop.args v_obj_addr = hop.genop("cast_ptr_to_adr", [v_obj], resulttype = llmemory.Address) + v_func_addr = hop.genop("cast_ptr_to_adr", [v_func], + resulttype = llmemory.Address) hop.genop("direct_call", [self.register_finalizer_ptr, self.c_const_gc, - v_obj_addr, v_func], + v_obj_addr, v_func_addr], resultvar = hop.spaceop.result) diff --git a/rpython/rlib/rgc.py b/rpython/rlib/rgc.py --- a/rpython/rlib/rgc.py +++ b/rpython/rlib/rgc.py @@ -384,12 +384,10 @@ r_func, is_method = hop.args_r[0].get_r_implfunc() assert is_method c_llfn = r_func.get_unique_llfn() - v_llfn = hop.genop('cast_ptr_to_adr', [c_llfn], - resulttype=llmemory.Address) v_self = hop.genop('cast_pointer', [v_self], resulttype=base_ptr_lltype()) hop.exception_cannot_occur() - return hop.genop('gc_register_finalizer', [v_self, v_llfn], + return hop.genop('gc_register_finalizer', [v_self, c_llfn], resulttype=lltype.Void) class ProgressThroughFinalizerQueueEntry(ExtRegistryEntry): diff --git a/rpython/rtyper/llinterp.py b/rpython/rtyper/llinterp.py --- a/rpython/rtyper/llinterp.py +++ b/rpython/rtyper/llinterp.py @@ -815,6 +815,7 @@ self.llinterpreter.finalizer_queue.append((llobj, llfn)) def op_gc_register_finalizer(self, llptr, llfn): + llfn = llmemory.cast_ptr_to_adr(llfn) if self.heap is llheap: llobj = llptr._obj for llobj1, llfn1 in self.llinterpreter.finalizer_queue: From noreply at buildbot.pypy.org Sat Apr 27 11:05:58 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sat, 27 Apr 2013 11:05:58 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Fix. Message-ID: <20130427090558.C49201C11C6@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63676:5b73e19cd57a Date: 2013-04-27 11:08 +0200 http://bitbucket.org/pypy/pypy/changeset/5b73e19cd57a/ Log: Fix. diff --git a/rpython/jit/backend/model.py b/rpython/jit/backend/model.py --- a/rpython/jit/backend/model.py +++ b/rpython/jit/backend/model.py @@ -1,4 +1,5 @@ import weakref +from rpython.rlib import rgc from rpython.rlib.debug import debug_start, debug_print, debug_stop from rpython.rtyper.lltypesystem import lltype, llmemory @@ -312,6 +313,7 @@ # a list of weakrefs to looptokens that has been redirected to # this one self.looptokens_redirected_to = [] + rgc.register_finalizer(self.finalizer) debug_start("jit-mem-looptoken-alloc") debug_print("allocating Loop #", self.number) debug_stop("jit-mem-looptoken-alloc") @@ -338,7 +340,7 @@ new_loop_tokens.append(weakref.ref(oldlooptoken)) self.looptokens_redirected_to = new_loop_tokens - def __del__(self): + def finalizer(self): #debug_start("jit-mem-looptoken-free") #debug_print("freeing Loop #", self.number, 'with', # self.bridges_count, 'attached bridges') From noreply at buildbot.pypy.org Sat Apr 27 11:11:23 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sat, 27 Apr 2013 11:11:23 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Document the limitations of __del__ methods. Message-ID: <20130427091123.1C7731C026F@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63677:3cf9d416b252 Date: 2013-04-27 11:10 +0200 http://bitbucket.org/pypy/pypy/changeset/3cf9d416b252/ Log: Document the limitations of __del__ methods. diff --git a/pypy/doc/coding-guide.rst b/pypy/doc/coding-guide.rst --- a/pypy/doc/coding-guide.rst +++ b/pypy/doc/coding-guide.rst @@ -347,7 +347,11 @@ **objects** Normal rules apply. Special methods are not honoured, except ``__init__``, - ``__del__`` and ``__iter__``. + ``__del__`` and ``__iter__``. The destructor ``__del__`` must only contain + `simple operations`__; for any kind of more complex destructor, see + ``rpython.rlib.rgc.register_finalizer()``. + +.. __: garbage_collection.html This layout makes the number of types to take care about quite limited. diff --git a/pypy/doc/faq.rst b/pypy/doc/faq.rst --- a/pypy/doc/faq.rst +++ b/pypy/doc/faq.rst @@ -247,9 +247,12 @@ to mix types in arbitrary ways. RPython does not allow the binding of two different types in the same variable. In this respect (and in some others) it feels a bit like Java. Other features not allowed in RPython are the use of -special methods (``__xxx__``) except ``__init__`` and ``__del__``, and the +special methods (``__xxx__``) except ``__init__`` and ``__del__`` +(see `garbage collection`__), and the use of reflection capabilities (e.g. ``__dict__``). +.. __: garbage_collection.html + You cannot use most existing standard library modules from RPython. The exceptions are some functions in ``os``, ``math`` and ``time`` that have native support. From noreply at buildbot.pypy.org Sat Apr 27 11:55:38 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sat, 27 Apr 2013 11:55:38 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Fix the JIT. Message-ID: <20130427095538.40D441C11C6@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63678:22647ef08aef Date: 2013-04-27 11:58 +0200 http://bitbucket.org/pypy/pypy/changeset/22647ef08aef/ Log: Fix the JIT. diff --git a/rpython/jit/backend/llsupport/gc.py b/rpython/jit/backend/llsupport/gc.py --- a/rpython/jit/backend/llsupport/gc.py +++ b/rpython/jit/backend/llsupport/gc.py @@ -414,7 +414,7 @@ type_id = rffi.cast(llgroup.HALFWORD, 0) # missing here return llop1.do_malloc_fixedsize_clear(llmemory.GCREF, type_id, size, - False, False, False) + False, False) self.generate_function('malloc_nursery', malloc_nursery_slowpath, [lltype.Signed]) @@ -481,7 +481,7 @@ check_typeid(type_id) return llop1.do_malloc_fixedsize_clear(llmemory.GCREF, type_id, size, - False, False, False) + False, False) self.generate_function('malloc_big_fixedsize', malloc_big_fixedsize, [lltype.Signed] * 2) @@ -492,7 +492,7 @@ check_typeid(type_id) return llop1.do_malloc_fixedsize_clear(llmemory.GCREF, type_id, sizedescr.size, - False, False, False) + False, False) def _bh_malloc_array(self, num_elem, arraydescr): from rpython.memory.gctypelayout import check_typeid From noreply at buildbot.pypy.org Sat Apr 27 12:30:16 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sat, 27 Apr 2013 12:30:16 +0200 (CEST) Subject: [pypy-commit] pypy default: Use %r in case it is a random character Message-ID: <20130427103016.2C2DB1C026F@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63679:11228d2fa0bb Date: 2013-04-27 12:29 +0200 http://bitbucket.org/pypy/pypy/changeset/11228d2fa0bb/ Log: Use %r in case it is a random character diff --git a/rpython/translator/backendopt/merge_if_blocks.py b/rpython/translator/backendopt/merge_if_blocks.py --- a/rpython/translator/backendopt/merge_if_blocks.py +++ b/rpython/translator/backendopt/merge_if_blocks.py @@ -37,7 +37,7 @@ default.args = [get_new_arg(arg) for arg in default.args] for block, case in chain: if case.value in values: - log.WARNING("unreachable code with value %s in graph %s" % ( + log.WARNING("unreachable code with value %r in graph %s" % ( case.value, graph)) continue values[case.value] = True From noreply at buildbot.pypy.org Sat Apr 27 13:34:12 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sat, 27 Apr 2013 13:34:12 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Constant-fold some more checks of GCFLAG_HAS_CARDS for the case Message-ID: <20130427113412.5923F1C11C6@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63680:2e7d8798d967 Date: 2013-04-27 12:55 +0200 http://bitbucket.org/pypy/pypy/changeset/2e7d8798d967/ Log: Constant-fold some more checks of GCFLAG_HAS_CARDS for the case where we're compiled without card support. diff --git a/rpython/memory/gc/minimark.py b/rpython/memory/gc/minimark.py --- a/rpython/memory/gc/minimark.py +++ b/rpython/memory/gc/minimark.py @@ -1020,7 +1020,7 @@ ll_assert(self.header(obj).tid & GCFLAG_CARDS_SET == 0, "unexpected GCFLAG_CARDS_SET") # if the GCFLAG_HAS_CARDS is set, check that all bits are zero now - if self.header(obj).tid & GCFLAG_HAS_CARDS: + if self.has_card(self.header(obj)): if self.card_page_indices <= 0: ll_assert(False, "GCFLAG_HAS_CARDS but not using card marking") return @@ -1085,6 +1085,12 @@ def JIT_minimal_size_in_nursery(cls): return cls.minimal_size_in_nursery + def has_card(self, objhdr): + if self.card_page_indices <= 0: # check constant-folded + return False + else: + return (objhdr.tid & GCFLAG_HAS_CARDS) != 0 + def write_barrier(self, newvalue, addr_struct): if self.header(addr_struct).tid & GCFLAG_TRACK_YOUNG_PTRS: self.remember_young_pointer(addr_struct, newvalue) @@ -1109,7 +1115,7 @@ # if DEBUG: # note: PYPY_GC_DEBUG=1 does not enable this ll_assert(self.debug_is_old_object(addr_struct) or - self.header(addr_struct).tid & GCFLAG_HAS_CARDS != 0, + self.has_card(self.header(addr_struct)), "young object with GCFLAG_TRACK_YOUNG_PTRS and no cards") # # If it seems that what we are writing is a pointer to a young obj @@ -1159,7 +1165,7 @@ # We know that 'addr_array' has GCFLAG_TRACK_YOUNG_PTRS so far. # objhdr = self.header(addr_array) - if objhdr.tid & GCFLAG_HAS_CARDS == 0: + if not self.has_card(objhdr): # if DEBUG: # note: PYPY_GC_DEBUG=1 does not enable this ll_assert(self.debug_is_old_object(addr_array), @@ -1207,7 +1213,7 @@ # GCFLAG_CARDS_SET if possible; otherwise, it falls back # to jit_remember_young_pointer(). objhdr = self.header(addr_array) - if objhdr.tid & GCFLAG_HAS_CARDS: + if self.has_card(objhdr): self.old_objects_with_cards_set.append(addr_array) objhdr.tid |= GCFLAG_CARDS_SET else: @@ -1248,7 +1254,7 @@ return True # ^^^ a fast path of write-barrier # - if source_hdr.tid & GCFLAG_HAS_CARDS != 0: + if self.has_card(source_hdr): # if source_hdr.tid & GCFLAG_TRACK_YOUNG_PTRS == 0: # The source object may have random young pointers. @@ -1259,7 +1265,7 @@ # The source object has no young pointers at all. Done. return True # - if dest_hdr.tid & GCFLAG_HAS_CARDS == 0: + if not self.has_card(dest_hdr): # The dest object doesn't have cards. Do it manually. return False # @@ -1593,7 +1599,7 @@ self.old_objects_pointing_to_young.append(obj) added_somewhere = True # - if hdr.tid & GCFLAG_HAS_CARDS != 0: + if self.has_card(hdr): ll_assert(hdr.tid & GCFLAG_CARDS_SET != 0, "young array: GCFLAG_HAS_CARDS without GCFLAG_CARDS_SET") self.old_objects_with_cards_set.append(obj) @@ -1772,8 +1778,7 @@ arena = llarena.getfakearenaaddress(obj - size_gc_header) # # Must also include the card marker area, if any - if (self.card_page_indices > 0 # <- this is constant-folded - and self.header(obj).tid & GCFLAG_HAS_CARDS): + if self.has_card(self.header(obj)): # # Get the length and compute the number of extra bytes typeid = self.get_type_id(obj) From noreply at buildbot.pypy.org Sat Apr 27 13:34:13 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sat, 27 Apr 2013 13:34:13 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Remove the semispace, generational, and hybrid GCs, after discussing Message-ID: <20130427113413.902501C11C6@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63681:24b1a13f0f35 Date: 2013-04-27 12:57 +0200 http://bitbucket.org/pypy/pypy/changeset/24b1a13f0f35/ Log: Remove the semispace, generational, and hybrid GCs, after discussing on IRC their remaining value. Even the educational value is very low because of the 3-GCs-in-one approach, and the fact that starting from a semispace GC is really the wrong approach for PyPy --- semispace GCs work very badly in this context. diff too long, truncating to 2000 out of 2477 lines diff --git a/rpython/memory/gc/base.py b/rpython/memory/gc/base.py --- a/rpython/memory/gc/base.py +++ b/rpython/memory/gc/base.py @@ -425,10 +425,7 @@ if config.translation.gctransformer != "framework": raise AssertionError("fix this test") - classes = {"semispace": "semispace.SemiSpaceGC", - "generation": "generation.GenerationGC", - "hybrid": "hybrid.HybridGC", - "minimark" : "minimark.MiniMarkGC", + classes = {"minimark" : "minimark.MiniMarkGC", } try: modulename, classname = classes[config.translation.gc].split('.') diff --git a/rpython/memory/gc/generation.py b/rpython/memory/gc/generation.py deleted file mode 100644 --- a/rpython/memory/gc/generation.py +++ /dev/null @@ -1,639 +0,0 @@ -import sys -from rpython.memory.gc.semispace import SemiSpaceGC -from rpython.memory.gc.semispace import GCFLAG_EXTERNAL, GCFLAG_FORWARDED -from rpython.memory.gc.semispace import GC_HASH_TAKEN_ADDR -from rpython.memory.gc import env -from rpython.rtyper.lltypesystem.llmemory import NULL, raw_malloc_usage -from rpython.rtyper.lltypesystem import lltype, llmemory, llarena -from rpython.rlib.objectmodel import free_non_gc_object -from rpython.rlib.debug import ll_assert -from rpython.rlib.debug import debug_print, debug_start, debug_stop -from rpython.rlib.rarithmetic import intmask, LONG_BIT -from rpython.rtyper.lltypesystem.lloperation import llop - -WORD = LONG_BIT // 8 - -# 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, -# and gets cleared by the write_barrier() when we write in them a -# pointer to a young object. -GCFLAG_NO_YOUNG_PTRS = SemiSpaceGC.first_unused_gcflag << 0 - -# 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): - """A basic generational GC: it's a SemiSpaceGC with an additional - nursery for young objects. A write barrier is used to ensure that - old objects that contain pointers to young objects are recorded in - a list. - """ - inline_simple_malloc = True - inline_simple_malloc_varsize = True - needs_write_barrier = True - prebuilt_gc_objects_are_static_roots = False - first_unused_gcflag = SemiSpaceGC.first_unused_gcflag << 2 - - # the following values override the default arguments of __init__ when - # translating to a real backend. - TRANSLATION_PARAMS = {'space_size': 8*1024*1024, # 8 MB - 'nursery_size': 3*1024*1024, # 3 MB - 'min_nursery_size': 48*1024, - 'auto_nursery_size': True} - - nursery_hash_base = -1 - - def __init__(self, config, - nursery_size=32*WORD, - min_nursery_size=32*WORD, - auto_nursery_size=False, - space_size=1024*WORD, - max_space_size=sys.maxint//2+1, - **kwds): - SemiSpaceGC.__init__(self, config, - space_size = space_size, - max_space_size = max_space_size, - **kwds) - assert min_nursery_size <= nursery_size <= space_size // 2 - self.initial_nursery_size = nursery_size - self.auto_nursery_size = auto_nursery_size - self.min_nursery_size = min_nursery_size - - # define nursery fields - self.reset_nursery() - self._setup_wb() - - # compute the constant lower bounds for the attributes - # largest_young_fixedsize and largest_young_var_basesize. - # It is expected that most (or all) objects have a fixedsize - # that is much lower anyway. - sz = self.get_young_fixedsize(self.min_nursery_size) - self.lb_young_fixedsize = sz - sz = self.get_young_var_basesize(self.min_nursery_size) - self.lb_young_var_basesize = sz - - def setup(self): - self.old_objects_pointing_to_young = self.AddressStack() - # ^^^ a list of addresses inside the old objects space; it - # may contain static prebuilt objects as well. More precisely, - # 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.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. - if self.auto_nursery_size: - newsize = nursery_size_from_env() - #if newsize <= 0: - # ---disabled--- just use the default value. - # newsize = env.estimate_best_nursery_size() - if newsize > 0: - self.set_nursery_size(newsize) - - self.reset_nursery() - - def _teardown(self): - self.collect() # should restore last gen objects flags - SemiSpaceGC._teardown(self) - - def reset_nursery(self): - self.nursery = NULL - self.nursery_top = NULL - self.nursery_free = NULL - - def set_nursery_size(self, newsize): - debug_start("gc-set-nursery-size") - if newsize < self.min_nursery_size: - newsize = self.min_nursery_size - if newsize > self.space_size // 2: - newsize = self.space_size // 2 - - # Compute the new bounds for how large young objects can be - # (larger objects are allocated directly old). XXX adjust - self.nursery_size = newsize - self.largest_young_fixedsize = self.get_young_fixedsize(newsize) - self.largest_young_var_basesize = self.get_young_var_basesize(newsize) - scale = 0 - while (self.min_nursery_size << (scale+1)) <= newsize: - scale += 1 - self.nursery_scale = scale - debug_print("nursery_size =", newsize) - debug_print("largest_young_fixedsize =", - self.largest_young_fixedsize) - debug_print("largest_young_var_basesize =", - self.largest_young_var_basesize) - debug_print("nursery_scale =", scale) - # we get the following invariant: - assert self.nursery_size >= (self.min_nursery_size << scale) - - # Force a full collect to remove the current nursery whose size - # no longer matches the bounds that we just computed. This must - # be done after changing the bounds, because it might re-create - # a new nursery (e.g. if it invokes finalizers). - self.semispace_collect() - debug_stop("gc-set-nursery-size") - - @staticmethod - def get_young_fixedsize(nursery_size): - return nursery_size // 2 - 1 - - @staticmethod - def get_young_var_basesize(nursery_size): - return nursery_size // 4 - 1 - - @classmethod - def JIT_max_size_of_young_obj(cls): - min_nurs_size = cls.TRANSLATION_PARAMS['min_nursery_size'] - return cls.get_young_fixedsize(min_nurs_size) - - def is_in_nursery(self, addr): - ll_assert(llmemory.cast_adr_to_int(addr) & 1 == 0, - "odd-valued (i.e. tagged) pointer unexpected here") - return self.nursery <= addr < self.nursery_top - - def appears_to_be_in_nursery(self, addr): - # same as is_in_nursery(), but may return True accidentally if - # 'addr' is a tagged pointer with just the wrong value. - if not self.translated_to_c: - if not self.is_valid_gc_object(addr): - return False - return self.nursery <= addr < self.nursery_top - - def malloc_fixedsize_clear(self, typeid, size, - has_finalizer=False, - is_finalizer_light=False, - contains_weakptr=False): - if (has_finalizer or - (raw_malloc_usage(size) > self.lb_young_fixedsize and - raw_malloc_usage(size) > self.largest_young_fixedsize)): - # ^^^ we do two size comparisons; the first one appears redundant, - # but it can be constant-folded if 'size' is a constant; then - # it almost always folds down to False, which kills the - # second comparison as well. - ll_assert(not contains_weakptr, "wrong case for mallocing weakref") - # "non-simple" case or object too big: don't use the nursery - return SemiSpaceGC.malloc_fixedsize_clear(self, typeid, size, - has_finalizer, - is_finalizer_light, - contains_weakptr) - size_gc_header = self.gcheaderbuilder.size_gc_header - totalsize = size_gc_header + size - result = self.nursery_free - if raw_malloc_usage(totalsize) > self.nursery_top - result: - result = self.collect_nursery() - llarena.arena_reserve(result, totalsize) - # GCFLAG_NO_YOUNG_PTRS is never set on young objs - self.init_gc_object(result, typeid, flags=0) - self.nursery_free = result + totalsize - if contains_weakptr: - self.young_objects_with_weakrefs.append(result + size_gc_header) - return llmemory.cast_adr_to_ptr(result+size_gc_header, llmemory.GCREF) - - def malloc_varsize_clear(self, typeid, length, size, itemsize, - offset_to_length): - # Only use the nursery if there are not too many items. - if not raw_malloc_usage(itemsize): - too_many_items = False - else: - # The following line is usually constant-folded because both - # min_nursery_size and itemsize are constants (the latter - # due to inlining). - maxlength_for_minimal_nursery = (self.min_nursery_size // 4 // - raw_malloc_usage(itemsize)) - - # The actual maximum length for our nursery depends on how - # many times our nursery is bigger than the minimal size. - # The computation is done in this roundabout way so that - # only the only remaining computation is the following - # shift. - maxlength = maxlength_for_minimal_nursery << self.nursery_scale - too_many_items = length > maxlength - - if (too_many_items or - (raw_malloc_usage(size) > self.lb_young_var_basesize and - raw_malloc_usage(size) > self.largest_young_var_basesize)): - # ^^^ we do two size comparisons; the first one appears redundant, - # but it can be constant-folded if 'size' is a constant; then - # it almost always folds down to False, which kills the - # second comparison as well. - return SemiSpaceGC.malloc_varsize_clear(self, typeid, length, size, - itemsize, offset_to_length) - # with the above checks we know now that totalsize cannot be more - # than about half of the nursery size; in particular, the + and * - # cannot overflow - size_gc_header = self.gcheaderbuilder.size_gc_header - totalsize = size_gc_header + size + itemsize * length - result = self.nursery_free - if raw_malloc_usage(totalsize) > self.nursery_top - result: - result = self.collect_nursery() - llarena.arena_reserve(result, totalsize) - # GCFLAG_NO_YOUNG_PTRS is never set on young objs - self.init_gc_object(result, typeid, flags=0) - (result + size_gc_header + offset_to_length).signed[0] = length - self.nursery_free = result + llarena.round_up_for_allocation(totalsize) - return llmemory.cast_adr_to_ptr(result+size_gc_header, llmemory.GCREF) - - # 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. - def init_gc_object(self, addr, typeid, flags=GCFLAG_NO_YOUNG_PTRS): - SemiSpaceGC.init_gc_object(self, addr, typeid, flags) - - def init_gc_object_immortal(self, addr, typeid, - flags=GCFLAG_NO_YOUNG_PTRS|GCFLAG_NO_HEAP_PTRS): - SemiSpaceGC.init_gc_object_immortal(self, addr, typeid, flags) - - # flags exposed for the HybridGC subclass - GCFLAGS_FOR_NEW_YOUNG_OBJECTS = 0 # NO_YOUNG_PTRS never set on young objs - GCFLAGS_FOR_NEW_EXTERNAL_OBJECTS = (GCFLAG_EXTERNAL | GCFLAG_FORWARDED | - GCFLAG_NO_YOUNG_PTRS | - GC_HASH_TAKEN_ADDR) - - # ____________________________________________________________ - # Support code for full collections - - def collect(self, gen=1): - if gen == 0: - self.collect_nursery() - else: - SemiSpaceGC.collect(self) - - 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() - SemiSpaceGC.semispace_collect(self, size_changing) - - def make_a_copy(self, obj, objsize): - tid = self.header(obj).tid - # During a full collect, all copied objects might implicitly come - # from the nursery. In case they do, we must add this flag: - tid |= GCFLAG_NO_YOUNG_PTRS - return self._make_a_copy_with_tid(obj, objsize, tid) - # history: this was missing and caused an object to become old but without the - # flag set. Such an object is bogus in the sense that the write_barrier doesn't - # work on it. So it can eventually contain a ptr to a young object but we didn't - # know about it. That ptr was not updated in the next minor collect... boom at - # the next usage. - - def reset_young_gcflags(self): - # This empties self.old_objects_pointing_to_young, and puts the - # GCFLAG_NO_YOUNG_PTRS back on all these objects. We could put - # the flag back more lazily but we expect this list to be short - # anyway, and it's much saner to stick to the invariant: - # non-young objects all have GCFLAG_NO_YOUNG_PTRS set unless - # they are listed in old_objects_pointing_to_young. - oldlist = self.old_objects_pointing_to_young - while oldlist.non_empty(): - obj = oldlist.pop() - hdr = self.header(obj) - hdr.tid |= GCFLAG_NO_YOUNG_PTRS - - def weakrefs_grow_older(self): - while self.young_objects_with_weakrefs.non_empty(): - 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] - newaddr = self.copy(addr) - pointer.address[0] = newaddr - self.write_into_last_generation_obj(obj, newaddr) - - # ____________________________________________________________ - # Implementation of nursery-only collections - - def collect_nursery(self): - if self.nursery_size > self.top_of_space - self.free: - # the semispace is running out, do a full collect - self.obtain_free_space(self.nursery_size) - ll_assert(self.nursery_size <= self.top_of_space - self.free, - "obtain_free_space failed to do its job") - if self.nursery: - debug_start("gc-minor") - debug_print("--- minor collect ---") - debug_print("nursery:", self.nursery, "to", self.nursery_top) - # a nursery-only collection - scan = beginning = self.free - self.collect_oldrefs_to_nursery() - self.collect_roots_in_nursery() - scan = self.scan_objects_just_copied_out_of_nursery(scan) - # at this point, all static and old objects have got their - # 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() - 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, 2) - debug_print("survived (fraction of the size):", - float(scan - beginning) / self.nursery_size) - debug_stop("gc-minor") - #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. - # Grab a piece of the current space for the nursery. - self.nursery = self.free - self.nursery_top = self.nursery + self.nursery_size - self.free = self.nursery_top - self.nursery_free = self.nursery - # at this point we know that the nursery is empty - self.change_nursery_hash_base() - return self.nursery_free - - def change_nursery_hash_base(self): - # The following should be enough to ensure that young objects - # tend to always get a different hash. It also makes sure that - # nursery_hash_base is not a multiple of 4, to avoid collisions - # with the hash of non-young objects. - hash_base = self.nursery_hash_base - hash_base += self.nursery_size - 1 - if (hash_base & 3) == 0: - hash_base -= 1 - self.nursery_hash_base = intmask(hash_base) - - # NB. we can use self.copy() to move objects out of the nursery, - # but only if the object was really in the nursery. - - def collect_oldrefs_to_nursery(self): - # Follow the old_objects_pointing_to_young list and move the - # young objects they point to out of the nursery. - count = 0 - oldlist = self.old_objects_pointing_to_young - while oldlist.non_empty(): - count += 1 - obj = oldlist.pop() - hdr = self.header(obj) - hdr.tid |= GCFLAG_NO_YOUNG_PTRS - self.trace_and_drag_out_of_nursery(obj) - debug_print("collect_oldrefs_to_nursery", count) - - def collect_roots_in_nursery(self): - # we don't need to trace prebuilt GcStructs during a minor collect: - # if a prebuilt GcStruct contains a pointer to a young object, - # then the write_barrier must have ensured that the prebuilt - # GcStruct is in the list self.old_objects_pointing_to_young. - self.root_walker.walk_roots( - GenerationGC._collect_root_in_nursery, # stack roots - GenerationGC._collect_root_in_nursery, # static in prebuilt non-gc - None) # static in prebuilt gc - - def _collect_root_in_nursery(self, root): - obj = root.address[0] - if self.is_in_nursery(obj): - root.address[0] = self.copy(obj) - - def scan_objects_just_copied_out_of_nursery(self, scan): - while scan < self.free: - curr = scan + self.size_gc_header() - self.trace_and_drag_out_of_nursery(curr) - scan += self.size_gc_header() + self.get_size_incl_hash(curr) - return scan - - def trace_and_drag_out_of_nursery(self, obj): - """obj must not be in the nursery. This copies all the - young objects it references out of the nursery. - """ - self.trace(obj, self._trace_drag_out, None) - - def _trace_drag_out(self, pointer, ignored): - if self.is_in_nursery(pointer.address[0]): - pointer.address[0] = self.copy(pointer.address[0]) - - # The code relies on the fact that no weakref can be an old object - # weakly pointing to a young object. Indeed, weakrefs are immutable - # so they cannot point to an object that was created after it. - def invalidate_young_weakrefs(self): - # walk over the list of objects that contain weakrefs and are in the - # nursery. if the object it references survives then update the - # weakref; otherwise invalidate the weakref - while self.young_objects_with_weakrefs.non_empty(): - obj = self.young_objects_with_weakrefs.pop() - if not self.surviving(obj): - continue # weakref itself dies - obj = self.get_forwarding_address(obj) - offset = self.weakpointer_offset(self.get_type_id(obj)) - pointing_to = (obj + offset).address[0] - if self.is_in_nursery(pointing_to): - if self.surviving(pointing_to): - (obj + offset).address[0] = self.get_forwarding_address( - pointing_to) - else: - (obj + offset).address[0] = NULL - continue # no need to remember this weakref any longer - self.objects_with_weakrefs.append(obj) - - # for the JIT: a minimal description of the write_barrier() method - # (the JIT assumes it is of the shape - # "if addr_struct.int0 & JIT_WB_IF_FLAG: remember_young_pointer()") - JIT_WB_IF_FLAG = GCFLAG_NO_YOUNG_PTRS - - def write_barrier(self, newvalue, addr_struct): - if self.header(addr_struct).tid & GCFLAG_NO_YOUNG_PTRS: - self.remember_young_pointer(addr_struct, newvalue) - - def _setup_wb(self): - DEBUG = self.DEBUG - # The purpose of attaching remember_young_pointer to the instance - # instead of keeping it as a regular method is to help the JIT call it. - # Additionally, it makes the code in write_barrier() marginally smaller - # (which is important because it is inlined *everywhere*). - # For x86, there is also an extra requirement: when the JIT calls - # remember_young_pointer(), it assumes that it will not touch the SSE - # registers, so it does not save and restore them (that's a *hack*!). - def remember_young_pointer(addr_struct, addr): - #llop.debug_print(lltype.Void, "\tremember_young_pointer", - # addr_struct, "<-", addr) - if DEBUG: - ll_assert(not self.is_in_nursery(addr_struct), - "nursery object with GCFLAG_NO_YOUNG_PTRS") - # - # What is important in this function is that it *must* - # clear the flag GCFLAG_NO_YOUNG_PTRS from 'addr_struct' - # if 'addr' is in the nursery. It is ok if, accidentally, - # it also clears the flag in some more rare cases, like - # 'addr' being a tagged pointer whose value happens to be - # a large integer that fools is_in_nursery(). - if self.appears_to_be_in_nursery(addr): - self.old_objects_pointing_to_young.append(addr_struct) - self.header(addr_struct).tid &= ~GCFLAG_NO_YOUNG_PTRS - self.write_into_last_generation_obj(addr_struct, addr) - remember_young_pointer._dont_inline_ = True - self.remember_young_pointer = remember_young_pointer - - def write_into_last_generation_obj(self, addr_struct, addr): - objhdr = self.header(addr_struct) - if objhdr.tid & GCFLAG_NO_HEAP_PTRS: - if (self.is_valid_gc_object(addr) and - not self.is_last_generation(addr)): - objhdr.tid &= ~GCFLAG_NO_HEAP_PTRS - self.last_generation_root_objects.append(addr_struct) - write_into_last_generation_obj._always_inline_ = True - - def assume_young_pointers(self, addr_struct): - objhdr = self.header(addr_struct) - if objhdr.tid & GCFLAG_NO_YOUNG_PTRS: - self.old_objects_pointing_to_young.append(addr_struct) - objhdr.tid &= ~GCFLAG_NO_YOUNG_PTRS - if objhdr.tid & GCFLAG_NO_HEAP_PTRS: - objhdr.tid &= ~GCFLAG_NO_HEAP_PTRS - self.last_generation_root_objects.append(addr_struct) - - def writebarrier_before_copy(self, source_addr, dest_addr, - source_start, dest_start, length): - """ This has the same effect as calling writebarrier over - each element in dest copied from source, except it might reset - one of the following flags a bit too eagerly, which means we'll have - a bit more objects to track, but being on the safe side. - """ - source_hdr = self.header(source_addr) - dest_hdr = self.header(dest_addr) - if dest_hdr.tid & GCFLAG_NO_YOUNG_PTRS == 0: - return True - # ^^^ a fast path of write-barrier - if source_hdr.tid & GCFLAG_NO_YOUNG_PTRS == 0: - # there might be an object in source that is in nursery - self.old_objects_pointing_to_young.append(dest_addr) - dest_hdr.tid &= ~GCFLAG_NO_YOUNG_PTRS - if dest_hdr.tid & GCFLAG_NO_HEAP_PTRS: - if source_hdr.tid & GCFLAG_NO_HEAP_PTRS == 0: - # ^^^ equivalend of addr from source not being in last - # gen - dest_hdr.tid &= ~GCFLAG_NO_HEAP_PTRS - self.last_generation_root_objects.append(dest_addr) - return True - - 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 _compute_current_nursery_hash(self, obj): - return intmask(llmemory.cast_adr_to_int(obj) + self.nursery_hash_base) - - def enumerate_all_roots(self, callback, arg): - self.last_generation_root_objects.foreach(callback, arg) - SemiSpaceGC.enumerate_all_roots(self, callback, arg) - enumerate_all_roots._annspecialcase_ = 'specialize:arg(1)' - - 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) - - -# ____________________________________________________________ - -def nursery_size_from_env(): - return env.read_from_env('PYPY_GENERATIONGC_NURSERY') diff --git a/rpython/memory/gc/hybrid.py b/rpython/memory/gc/hybrid.py deleted file mode 100644 --- a/rpython/memory/gc/hybrid.py +++ /dev/null @@ -1,559 +0,0 @@ -import sys -from rpython.memory.gc.semispace import SemiSpaceGC -from rpython.memory.gc.generation import GenerationGC, WORD -from rpython.memory.gc.semispace import GCFLAG_EXTERNAL, GCFLAG_FORWARDED -from rpython.memory.gc.semispace import GCFLAG_HASHMASK -from rpython.memory.gc.generation import GCFLAG_NO_YOUNG_PTRS -from rpython.memory.gc.generation import GCFLAG_NO_HEAP_PTRS -from rpython.memory.gc.semispace import GC_HASH_TAKEN_ADDR -from rpython.memory.gc.semispace import GC_HASH_HASFIELD -from rpython.rtyper.lltypesystem import lltype, llmemory, llarena -from rpython.rtyper.lltypesystem.llmemory import raw_malloc_usage -from rpython.rtyper.lltypesystem.lloperation import llop -from rpython.rlib.debug import ll_assert, have_debug_prints -from rpython.rlib.debug import debug_print, debug_start, debug_stop -from rpython.rlib.rarithmetic import ovfcheck -from rpython.rtyper.lltypesystem import rffi - -# _______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 = 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 -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, - 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 = _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. - TRANSLATION_PARAMS = GenerationGC.TRANSLATION_PARAMS.copy() - TRANSLATION_PARAMS['large_object'] = 6*1024 # XXX adjust - TRANSLATION_PARAMS['large_object_gcptrs'] = 31*1024 # XXX adjust - TRANSLATION_PARAMS['min_nursery_size'] = 128*1024 - # condition: large_object <= large_object_gcptrs < min_nursery_size/4 - - def __init__(self, *args, **kwds): - large_object = kwds.pop('large_object', 6*WORD) - large_object_gcptrs = kwds.pop('large_object_gcptrs', 8*WORD) - 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 - # allocated separately in a mark-n-sweep fashion. If the object - # has GC pointers in its varsized part, we use instead the - # higher limit 'large_object_gcptrs'. The idea is that - # separately allocated objects are allocated immediately "old" - # and it's not good to have too many pointers from old to young - # objects. - - # In this class, we assume that the 'large_object' limit is not - # very high, so that all objects that wouldn't easily fit in the - # nursery are considered large by this limit. This is the - # meaning of the 'assert' below. - self.nonlarge_max = large_object - 1 - self.nonlarge_gcptrs_max = large_object_gcptrs - 1 - assert self.nonlarge_gcptrs_max <= self.lb_young_var_basesize - assert self.nonlarge_max <= self.nonlarge_gcptrs_max - - def setup(self): - self.large_objects_collect_trigger = self.param_space_size - self._initial_trigger = self.large_objects_collect_trigger - self.rawmalloced_objects_to_trace = self.AddressStack() - self.count_semispaceonly_collects = 0 - - self.gen2_rawmalloced_objects = self.AddressStack() - self.gen3_rawmalloced_objects = self.AddressStack() - GenerationGC.setup(self) - - def set_max_heap_size(self, size): - raise NotImplementedError - - # NB. to simplify the code, only varsized objects can be considered - # 'large'. - - def malloc_varsize_clear(self, typeid, length, size, itemsize, - offset_to_length): - size_gc_header = self.gcheaderbuilder.size_gc_header - nonvarsize = size_gc_header + size - - # Compute the maximal length that makes the object still - # below 'nonlarge_max'. All the following logic is usually - # constant-folded because self.nonlarge_max, size and itemsize - # are all constants (the arguments are constant due to - # inlining) and self.has_gcptr_in_varsize() is constant-folded. - if self.has_gcptr_in_varsize(typeid): - nonlarge_max = self.nonlarge_gcptrs_max - else: - nonlarge_max = self.nonlarge_max - - if not raw_malloc_usage(itemsize): - too_many_items = raw_malloc_usage(nonvarsize) > nonlarge_max - else: - maxlength = nonlarge_max - raw_malloc_usage(nonvarsize) - maxlength = maxlength // raw_malloc_usage(itemsize) - too_many_items = length > maxlength - - if not too_many_items: - # With the above checks we know now that totalsize cannot be more - # than 'nonlarge_max'; in particular, the + and * cannot overflow. - # Let's try to fit the object in the nursery. - totalsize = nonvarsize + itemsize * length - result = self.nursery_free - if raw_malloc_usage(totalsize) <= self.nursery_top - result: - llarena.arena_reserve(result, totalsize) - # GCFLAG_NO_YOUNG_PTRS is never set on young objs - self.init_gc_object(result, typeid, flags=0) - (result + size_gc_header + offset_to_length).signed[0] = length - self.nursery_free = result + llarena.round_up_for_allocation( - totalsize) - return llmemory.cast_adr_to_ptr(result+size_gc_header, - llmemory.GCREF) - return self.malloc_varsize_slowpath(typeid, length) - - def malloc_varsize_slowpath(self, typeid, length, force_nonmovable=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 - # it all as function arguments. - size_gc_header = self.gcheaderbuilder.size_gc_header - nonvarsize = size_gc_header + self.fixed_size(typeid) - itemsize = self.varsize_item_sizes(typeid) - offset_to_length = self.varsize_offset_to_length(typeid) - try: - varsize = ovfcheck(itemsize * length) - totalsize = ovfcheck(nonvarsize + varsize) - except OverflowError: - raise MemoryError() - if self.has_gcptr_in_varsize(typeid): - nonlarge_max = self.nonlarge_gcptrs_max - else: - nonlarge_max = self.nonlarge_max - if force_nonmovable or raw_malloc_usage(totalsize) > nonlarge_max: - result = self.malloc_varsize_marknsweep(totalsize) - flags = self.GCFLAGS_FOR_NEW_EXTERNAL_OBJECTS | GCFLAG_UNVISITED - else: - result = self.malloc_varsize_collecting_nursery(totalsize) - flags = self.GCFLAGS_FOR_NEW_YOUNG_OBJECTS - self.init_gc_object(result, typeid, flags) - (result + size_gc_header + offset_to_length).signed[0] = length - return llmemory.cast_adr_to_ptr(result+size_gc_header, llmemory.GCREF) - - malloc_varsize_slowpath._dont_inline_ = True - - 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): - gcref = self.malloc_varsize_slowpath(typeid, length, True) - else: - raise NotImplementedError("Not supported") - return llmemory.cast_ptr_to_adr(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, - "not enough room in malloc_varsize_collecting_nursery()") - llarena.arena_reserve(result, totalsize) - self.nursery_free = result + llarena.round_up_for_allocation( - totalsize) - return result - - def _check_rawsize_alloced(self, size_estimate): - self.large_objects_collect_trigger -= size_estimate - if self.large_objects_collect_trigger < 0: - debug_start("gc-rawsize-collect") - debug_print("allocated", (self._initial_trigger - - self.large_objects_collect_trigger), - "bytes, triggering full collection") - self.semispace_collect() - debug_stop("gc-rawsize-collect") - - def malloc_varsize_marknsweep(self, totalsize): - # 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 + rawmalloced bytes of large objects. - self._check_rawsize_alloced(raw_malloc_usage(totalsize)) - result = self.allocate_external_object(totalsize) - if not result: - raise MemoryError() - # The parent classes guarantee zero-filled allocations, so we - # 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) - return result - - def allocate_external_object(self, totalsize): - # XXX maybe we should use arena_malloc() above a certain size? - # 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, gen=2): - if gen > 1: - self.count_semispaceonly_collects = self.generation3_collect_threshold - GenerationGC.collect(self, gen) - - 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, 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") - 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. - # This is equivalent to self.is_forwarded() for all objects except - # the ones obtained by raw_malloc. - 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.rawmalloced_objects_to_trace.append(obj) - - def make_a_copy(self, obj, objsize): - # During a full collect, all copied objects might implicitly come - # 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. 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: - tid += GCFLAG_AGE_ONE - else: - newobj = self.make_a_nonmoving_copy(obj, objsize) - if newobj: - return newobj - tid &= ~GCFLAG_AGE_MASK - # skip GenerationGC.make_a_copy() as we already did the right - # thing about GCFLAG_NO_YOUNG_PTRS - return self._make_a_copy_with_tid(obj, objsize, tid) - - def make_a_nonmoving_copy(self, obj, objsize): - # NB. the object can have a finalizer or be a weakref, but - # it's not an issue. - totalsize = self.size_gc_header() + objsize - tid = self.header(obj).tid - if tid & GCFLAG_HASHMASK: - totalsize_incl_hash = totalsize + llmemory.sizeof(lltype.Signed) - else: - totalsize_incl_hash = totalsize - newaddr = self.allocate_external_object(totalsize_incl_hash) - if not newaddr: - return llmemory.NULL # can't raise MemoryError during a collect() - self._nonmoving_copy_count += 1 - self._nonmoving_copy_size += raw_malloc_usage(totalsize) - - llmemory.raw_memcopy(obj - self.size_gc_header(), newaddr, totalsize) - if tid & GCFLAG_HASHMASK: - hash = self._get_object_hash(obj, objsize, tid) - (newaddr + totalsize).signed[0] = hash - tid |= GC_HASH_HASFIELD - # - # GCFLAG_UNVISITED is not set - # 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. - newobj = newaddr + self.size_gc_header() - hdr = self.header(newobj) - hdr.tid = tid | self.GCFLAGS_FOR_NEW_EXTERNAL_OBJECTS - 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): - # Alternate between scanning the regular objects we just moved - # and scanning the raw_malloc'ed object we just visited. - progress = True - while progress: - newscan = GenerationGC.scan_copied(self, scan) - progress = newscan != scan - scan = newscan - 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.rawmalloced_objects_to_trace.non_empty(), - "rawmalloced_objects_to_trace should be empty at end") - debug_print("| [hybrid] made nonmoving: ", - self._nonmoving_copy_size, "bytes in", - self._nonmoving_copy_count, "objs") - rawmalloced_trigger = 0 - # sweep the nonmarked rawmalloced objects - if self.is_collecting_gen3(): - rawmalloced_trigger += self.sweep_rawmalloced_objects(generation=3) - rawmalloced_trigger += self.sweep_rawmalloced_objects(generation=2) - self.large_objects_collect_trigger = (rawmalloced_trigger + - self.space_size) - if self.is_collecting_gen3(): - self.count_semispaceonly_collects = 0 - 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(). - 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 - 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 - else: - ll_assert(False, "bogus 'generation'") - return 0 # to please the flowspace - - surviving_objects = self.AddressStack() - # Help the flow space - alive_count = alive_size = dead_count = dead_size = 0 - debug = have_debug_prints() - while objects.non_empty(): - obj = objects.pop() - tid = self.header(obj).tid - if tid & GCFLAG_UNVISITED: - if debug: - dead_count+=1 - dead_size+=raw_malloc_usage(self.get_size_incl_hash(obj)) - addr = obj - self.gcheaderbuilder.size_gc_header - llmemory.raw_free(addr) - else: - if debug: - alive_count+=1 - alive_size+=raw_malloc_usage(self.get_size_incl_hash(obj)) - if generation == 3: - surviving_objects.append(obj) - elif generation == 2: - 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 - elif generation == 3: - self.gen3_rawmalloced_objects = surviving_objects - debug_print("| [hyb] gen", generation, - "nonmoving now alive: ", - alive_size, "bytes in", - alive_count, "objs") - debug_print("| [hyb] gen", generation, - "nonmoving freed: ", - dead_size, "bytes in", - dead_count, "objs") - return alive_size - - def id(self, ptr): - obj = llmemory.cast_ptr_to_adr(ptr) - - # is it a tagged pointer? - if not self.is_valid_gc_object(obj): - return llmemory.cast_adr_to_int(obj) - - if self._is_external(obj): - # a prebuilt or rawmalloced object - if self.is_last_generation(obj): - # a generation 3 object may be one that used to live in - # the semispace. So we still need to check if the object had - # its id taken before. If not, we can use its address as its - # id as it is not going to move any more. - result = 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. - result = obj - else: - result = self._compute_id(obj) # common case - return llmemory.cast_adr_to_int(result) * 2 # see comment in base.py - # 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 & GC_HASH_TAKEN_ADDR), - "gen2: missing GC_HASH_TAKEN_ADDR") - 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(bool(tid & GC_HASH_TAKEN_ADDR), - "gen3: missing GC_HASH_TAKEN_ADDR") - ll_assert(not (tid & GCFLAG_UNVISITED), - "gen3: unexpected GCFLAG_UNVISITED") - ll_assert((tid & GCFLAG_AGE_MASK) == GCFLAG_AGE_MAX, - "gen3: wrong age field") - - def can_malloc_nonmovable(self): - return True diff --git a/rpython/memory/gc/semispace.py b/rpython/memory/gc/semispace.py deleted file mode 100644 --- a/rpython/memory/gc/semispace.py +++ /dev/null @@ -1,745 +0,0 @@ -from rpython.rtyper.lltypesystem.llmemory import raw_malloc, raw_free -from rpython.rtyper.lltypesystem.llmemory import raw_memcopy, raw_memclear -from rpython.rtyper.lltypesystem.llmemory import NULL, raw_malloc_usage -from rpython.memory.support import get_address_stack, get_address_deque -from rpython.memory.support import AddressDict -from rpython.rtyper.lltypesystem import lltype, llmemory, llarena, rffi, llgroup -from rpython.rlib.objectmodel import free_non_gc_object -from rpython.rlib.debug import ll_assert, have_debug_prints -from rpython.rlib.debug import debug_print, debug_start, debug_stop -from rpython.rtyper.lltypesystem.lloperation import llop -from rpython.rlib.rarithmetic import ovfcheck, LONG_BIT -from rpython.memory.gc.base import MovingGCBase, ARRAY_TYPEID_MAP,\ - TYPEID_MAP - -import sys, os - -first_gcflag = 1 << (LONG_BIT//2) -GCFLAG_FORWARDED = first_gcflag -# GCFLAG_EXTERNAL is set on objects not living in the semispace: -# either immortal objects or (for HybridGC) externally raw_malloc'ed -GCFLAG_EXTERNAL = first_gcflag << 1 -GCFLAG_FINALIZATION_ORDERING = first_gcflag << 2 - -_GCFLAG_HASH_BASE = first_gcflag << 3 -GCFLAG_HASHMASK = _GCFLAG_HASH_BASE * 0x3 # also consumes 'first_gcflag << 4' -# the two bits in GCFLAG_HASHMASK can have one of the following values: -# - nobody ever asked for the hash of the object -GC_HASH_NOTTAKEN = _GCFLAG_HASH_BASE * 0x0 -# - someone asked, and we gave the address of the object -GC_HASH_TAKEN_ADDR = _GCFLAG_HASH_BASE * 0x1 -# - someone asked, and we gave the address plus 'nursery_hash_base' -GC_HASH_TAKEN_NURS = _GCFLAG_HASH_BASE * 0x2 -# - we have our own extra field to store the hash -GC_HASH_HASFIELD = _GCFLAG_HASH_BASE * 0x3 - -GCFLAG_EXTRA = first_gcflag << 5 # for RPython abuse only - -memoryError = MemoryError() - - -class SemiSpaceGC(MovingGCBase): - _alloc_flavor_ = "raw" - inline_simple_malloc = True - inline_simple_malloc_varsize = True - malloc_zero_filled = True - first_unused_gcflag = first_gcflag << 6 - gcflag_extra = GCFLAG_EXTRA - - HDR = lltype.Struct('header', ('tid', lltype.Signed)) # XXX or rffi.INT? - typeid_is_in_field = 'tid' - withhash_flag_is_in_field = 'tid', _GCFLAG_HASH_BASE * 0x2 - # ^^^ prebuilt objects either have GC_HASH_TAKEN_ADDR or they - # have GC_HASH_HASFIELD (and then they are one word longer). - FORWARDSTUB = lltype.GcStruct('forwarding_stub', - ('forw', llmemory.Address)) - FORWARDSTUBPTR = lltype.Ptr(FORWARDSTUB) - - object_minimal_size = llmemory.sizeof(FORWARDSTUB) - - # the following values override the default arguments of __init__ when - # translating to a real backend. - TRANSLATION_PARAMS = {'space_size': 8*1024*1024} # XXX adjust - - def __init__(self, config, space_size=4096, max_space_size=sys.maxint//2+1, - **kwds): - self.param_space_size = space_size - self.param_max_space_size = max_space_size - MovingGCBase.__init__(self, config, **kwds) - - def setup(self): - #self.total_collection_time = 0.0 - self.total_collection_count = 0 - - self.space_size = self.param_space_size - self.max_space_size = self.param_max_space_size - self.red_zone = 0 - - #self.program_start_time = time.time() - self.tospace = llarena.arena_malloc(self.space_size, True) - ll_assert(bool(self.tospace), "couldn't allocate tospace") - self.top_of_space = self.tospace + self.space_size - self.fromspace = llarena.arena_malloc(self.space_size, True) - ll_assert(bool(self.fromspace), "couldn't allocate fromspace") - self.free = self.tospace - MovingGCBase.setup(self) - self.objects_with_finalizers = self.AddressDeque() - self.objects_with_light_finalizers = self.AddressStack() - self.objects_with_weakrefs = self.AddressStack() - - def _teardown(self): - debug_print("Teardown") - llarena.arena_free(self.fromspace) - llarena.arena_free(self.tospace) - - # This class only defines the malloc_{fixed,var}size_clear() methods - # because the spaces are filled with zeroes in advance. - - def malloc_fixedsize_clear(self, typeid16, size, - has_finalizer=False, - is_finalizer_light=False, - contains_weakptr=False): - size_gc_header = self.gcheaderbuilder.size_gc_header - totalsize = size_gc_header + size - result = self.free - if raw_malloc_usage(totalsize) > self.top_of_space - result: - result = self.obtain_free_space(totalsize) - llarena.arena_reserve(result, totalsize) - self.init_gc_object(result, typeid16) - self.free = result + totalsize - #if is_finalizer_light: - # self.objects_with_light_finalizers.append(result + size_gc_header) - #else: - if has_finalizer: - self.objects_with_finalizers.append(result + size_gc_header) - if contains_weakptr: - self.objects_with_weakrefs.append(result + size_gc_header) - return llmemory.cast_adr_to_ptr(result+size_gc_header, llmemory.GCREF) - - def malloc_varsize_clear(self, typeid16, length, size, itemsize, - offset_to_length): - size_gc_header = self.gcheaderbuilder.size_gc_header - nonvarsize = size_gc_header + size - try: - varsize = ovfcheck(itemsize * length) - totalsize = ovfcheck(nonvarsize + varsize) - except OverflowError: - raise memoryError - result = self.free - if raw_malloc_usage(totalsize) > self.top_of_space - result: - result = self.obtain_free_space(totalsize) - llarena.arena_reserve(result, totalsize) - self.init_gc_object(result, typeid16) - (result + size_gc_header + offset_to_length).signed[0] = length - self.free = result + llarena.round_up_for_allocation(totalsize) - return llmemory.cast_adr_to_ptr(result+size_gc_header, llmemory.GCREF) - - def shrink_array(self, addr, smallerlength): - size_gc_header = self.gcheaderbuilder.size_gc_header - if self._is_in_the_space(addr - size_gc_header): - typeid = self.get_type_id(addr) - totalsmallersize = ( - size_gc_header + self.fixed_size(typeid) + - self.varsize_item_sizes(typeid) * smallerlength) - llarena.arena_shrink_obj(addr - size_gc_header, totalsmallersize) - # - offset_to_length = self.varsize_offset_to_length(typeid) - (addr + offset_to_length).signed[0] = smallerlength - return True - else: - return False - - def obtain_free_space(self, needed): - # a bit of tweaking to maximize the performance and minimize the - # amount of code in an inlined version of malloc_fixedsize_clear() - if not self.try_obtain_free_space(needed): - raise memoryError - return self.free - obtain_free_space._dont_inline_ = True - - def try_obtain_free_space(self, needed): - # XXX for bonus points do big objects differently - needed = raw_malloc_usage(needed) - if (self.red_zone >= 2 and self.space_size < self.max_space_size and - self.double_space_size()): - pass # collect was done during double_space_size() - else: - self.semispace_collect() - missing = needed - (self.top_of_space - self.free) - if missing <= 0: - return True # success - else: - # first check if the object could possibly fit - proposed_size = self.space_size - while missing > 0: - if proposed_size >= self.max_space_size: - return False # no way - missing -= proposed_size - proposed_size *= 2 - # For address space fragmentation reasons, we double the space - # size possibly several times, moving the objects at each step, - # instead of going directly for the final size. We assume that - # it's a rare case anyway. - while self.space_size < proposed_size: - if not self.double_space_size(): - return False - ll_assert(needed <= self.top_of_space - self.free, - "double_space_size() failed to do its job") - return True - - def double_space_size(self): - self.red_zone = 0 - old_fromspace = self.fromspace - newsize = self.space_size * 2 - newspace = llarena.arena_malloc(newsize, True) - if not newspace: - return False # out of memory - llarena.arena_free(old_fromspace) - self.fromspace = newspace - # now self.tospace contains the existing objects and - # self.fromspace is the freshly allocated bigger space - - self.semispace_collect(size_changing=True) - self.top_of_space = self.tospace + newsize - # now self.tospace is the freshly allocated bigger space, - # and self.fromspace is the old smaller space, now empty - llarena.arena_free(self.fromspace) - - newspace = llarena.arena_malloc(newsize, True) - if not newspace: - # Complex failure case: we have in self.tospace a big chunk - # of memory, and the two smaller original spaces are already gone. - # Unsure if it's worth these efforts, but we can artificially - # split self.tospace in two again... - self.max_space_size = self.space_size # don't try to grow again, - # because doing arena_free(self.fromspace) would crash - self.fromspace = self.tospace + self.space_size - self.top_of_space = self.fromspace - ll_assert(self.free <= self.top_of_space, - "unexpected growth of GC space usage during collect") - return False # out of memory - - self.fromspace = newspace - self.space_size = newsize - return True # success - - def set_max_heap_size(self, size): - # Set the maximum semispace size. - # The size is rounded down to the next power of two. Also, this is - # the size of one semispace only, so actual usage can be the double - # during a collection. Finally, note that this will never shrink - # an already-allocated heap. - if size < 1: - size = 1 # actually, the minimum is 8MB in default translations - self.max_space_size = sys.maxint//2+1 - while self.max_space_size > size: - self.max_space_size >>= 1 - - @classmethod - def JIT_minimal_size_in_nursery(cls): - return cls.object_minimal_size - - def collect(self, gen=0): - 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): - debug_start("gc-collect") - debug_print() - debug_print(".----------- Full collection ------------------") - start_usage = self.free - self.tospace - debug_print("| used before collection: ", - start_usage, "bytes") - #start_time = time.time() - #llop.debug_print(lltype.Void, 'semispace_collect', int(size_changing)) - - # Switch the spaces. We copy everything over to the empty space - # (self.fromspace at the beginning of the collection), and clear the old - # one (self.tospace at the beginning). Their purposes will be reversed - # for the next collection. - tospace = self.fromspace - fromspace = self.tospace - self.fromspace = fromspace - self.tospace = tospace - self.top_of_space = tospace + self.space_size - scan = self.free = tospace - self.starting_full_collect() - self.collect_roots() - if self.run_finalizers.non_empty(): - self.update_run_finalizers() - scan = self.scan_copied(scan) - if self.objects_with_light_finalizers.non_empty(): - self.deal_with_objects_with_light_finalizers() - if self.objects_with_finalizers.non_empty(): - 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() - if not size_changing: - llarena.arena_reset(fromspace, self.space_size, True) - self.record_red_zone() - self.execute_finalizers() - #llop.debug_print(lltype.Void, 'collected', self.space_size, size_changing, self.top_of_space - self.free) - if have_debug_prints(): - #end_time = time.time() - #elapsed_time = end_time - start_time - #self.total_collection_time += elapsed_time - self.total_collection_count += 1 - #total_program_time = end_time - self.program_start_time - end_usage = self.free - self.tospace - debug_print("| used after collection: ", - end_usage, "bytes") - debug_print("| freed: ", - start_usage - end_usage, "bytes") - debug_print("| size of each semispace: ", - self.space_size, "bytes") - debug_print("| fraction of semispace now used: ", - end_usage * 100.0 / self.space_size, "%") - #ct = self.total_collection_time - cc = self.total_collection_count - debug_print("| number of semispace_collects: ", - cc) - #debug_print("| i.e.: ", - # cc / total_program_time, "per second") - #debug_print("| total time in semispace_collect: ", - # ct, "seconds") - #debug_print("| i.e.: ", - # ct * 100.0 / total_program_time, "%") - debug_print("`----------------------------------------------") - debug_stop("gc-collect") - - def starting_full_collect(self): - pass # hook for the HybridGC - - def finished_full_collect(self): - pass # hook for the HybridGC - - def record_red_zone(self): - # red zone: if the space is more than 80% full, the next collection - # should double its size. If it is more than 66% full twice in a row, - # then it should double its size too. (XXX adjust) - # The goal is to avoid many repeated collection that don't free a lot - # of memory each, if the size of the live object set is just below the - # size of the space. - free_after_collection = self.top_of_space - self.free - if free_after_collection > self.space_size // 3: - self.red_zone = 0 - else: - self.red_zone += 1 - if free_after_collection < self.space_size // 5: - self.red_zone += 1 - - def get_size_incl_hash(self, obj): - size = self.get_size(obj) - hdr = self.header(obj) - if (hdr.tid & GCFLAG_HASHMASK) == GC_HASH_HASFIELD: - size += llmemory.sizeof(lltype.Signed) - return size - - def scan_copied(self, scan): - while scan < self.free: - curr = scan + self.size_gc_header() - self.trace_and_copy(curr) - scan += self.size_gc_header() + self.get_size_incl_hash(curr) - return scan - - def collect_roots(self): - self.root_walker.walk_roots( - SemiSpaceGC._collect_root, # stack roots - SemiSpaceGC._collect_root, # static in prebuilt non-gc structures - SemiSpaceGC._collect_root) # static in prebuilt gc objects - - def _collect_root(self, root): - 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) - else: - objsize = self.get_size(obj) - newobj = self.make_a_copy(obj, objsize) - #llop.debug_print(lltype.Void, obj, "copied to", newobj, - # "tid", self.header(obj).tid, - # "size", totalsize) - self.set_forwarding_address(obj, newobj, objsize) - return newobj - - def _get_object_hash(self, obj, objsize, tid): - # Returns the hash of the object, which must not be GC_HASH_NOTTAKEN. - gc_hash = tid & GCFLAG_HASHMASK - if gc_hash == GC_HASH_HASFIELD: - obj = llarena.getfakearenaaddress(obj) - return (obj + objsize).signed[0] - elif gc_hash == GC_HASH_TAKEN_ADDR: - return llmemory.cast_adr_to_int(obj) - elif gc_hash == GC_HASH_TAKEN_NURS: - return self._compute_current_nursery_hash(obj) - else: - assert 0, "gc_hash == GC_HASH_NOTTAKEN" - - def _make_a_copy_with_tid(self, obj, objsize, tid): - totalsize = self.size_gc_header() + objsize - newaddr = self.free - llarena.arena_reserve(newaddr, totalsize) - raw_memcopy(obj - self.size_gc_header(), newaddr, totalsize) - if tid & GCFLAG_HASHMASK: - hash = self._get_object_hash(obj, objsize, tid) - llarena.arena_reserve(newaddr + totalsize, - llmemory.sizeof(lltype.Signed)) - (newaddr + totalsize).signed[0] = hash - tid |= GC_HASH_HASFIELD - totalsize += llmemory.sizeof(lltype.Signed) - self.free += totalsize - newhdr = llmemory.cast_adr_to_ptr(newaddr, lltype.Ptr(self.HDR)) - newhdr.tid = tid - newobj = newaddr + self.size_gc_header() - return newobj - - def make_a_copy(self, obj, objsize): - tid = self.header(obj).tid - return self._make_a_copy_with_tid(obj, objsize, tid) - - def trace_and_copy(self, obj): - self.trace(obj, self._trace_copy, None) - - def _trace_copy(self, pointer, ignored): - pointer.address[0] = self.copy(pointer.address[0]) - - def surviving(self, obj): - # To use during a collection. Check if the object is currently - # marked as surviving the collection. This is equivalent to - # self.is_forwarded() for all objects except the nonmoving objects - # created by the HybridGC subclass. In all cases, if an object - # survives, self.get_forwarding_address() returns its new address. - return self.is_forwarded(obj) - - def is_forwarded(self, obj): - return self.header(obj).tid & GCFLAG_FORWARDED != 0 - # note: all prebuilt objects also have this flag set - - def get_forwarding_address(self, obj): - tid = self.header(obj).tid - if tid & GCFLAG_EXTERNAL: - self.visit_external_object(obj) - return obj # external or prebuilt objects are "forwarded" - # to themselves - else: - stub = llmemory.cast_adr_to_ptr(obj, self.FORWARDSTUBPTR) - return stub.forw - - def visit_external_object(self, obj): - pass # hook for the HybridGC - - def get_possibly_forwarded_type_id(self, obj): - tid = self.header(obj).tid - if self.is_forwarded(obj) and not (tid & GCFLAG_EXTERNAL): - obj = self.get_forwarding_address(obj) - return self.get_type_id(obj) - - def set_forwarding_address(self, obj, newobj, objsize): - # To mark an object as forwarded, we set the GCFLAG_FORWARDED and - # overwrite the object with a FORWARDSTUB. Doing so is a bit - # long-winded on llarena, but it all melts down to two memory - # writes after translation to C. - size_gc_header = self.size_gc_header() - stubsize = llmemory.sizeof(self.FORWARDSTUB) - tid = self.header(obj).tid - ll_assert(tid & GCFLAG_EXTERNAL == 0, "unexpected GCFLAG_EXTERNAL") - ll_assert(tid & GCFLAG_FORWARDED == 0, "unexpected GCFLAG_FORWARDED") - # replace the object at 'obj' with a FORWARDSTUB. - hdraddr = obj - size_gc_header - llarena.arena_reset(hdraddr, size_gc_header + objsize, False) - llarena.arena_reserve(hdraddr, size_gc_header + stubsize) - hdr = llmemory.cast_adr_to_ptr(hdraddr, lltype.Ptr(self.HDR)) - hdr.tid = tid | GCFLAG_FORWARDED - stub = llmemory.cast_adr_to_ptr(obj, self.FORWARDSTUBPTR) - stub.forw = newobj - - def combine(self, typeid16, flags): - return llop.combine_ushort(lltype.Signed, typeid16, flags) - - def get_type_id(self, addr): - tid = self.header(addr).tid - ll_assert(tid & (GCFLAG_FORWARDED|GCFLAG_EXTERNAL) != GCFLAG_FORWARDED, - "get_type_id on forwarded obj") - # Non-prebuilt forwarded objects are overwritten with a FORWARDSTUB. - # Although calling get_type_id() on a forwarded object works by itself, - # we catch it as an error because it's likely that what is then - # done with the typeid is bogus. - return llop.extract_ushort(llgroup.HALFWORD, tid) - - def init_gc_object(self, addr, typeid16, flags=0): - hdr = llmemory.cast_adr_to_ptr(addr, lltype.Ptr(self.HDR)) - hdr.tid = self.combine(typeid16, flags) - - def init_gc_object_immortal(self, addr, typeid16, flags=0): - hdr = llmemory.cast_adr_to_ptr(addr, lltype.Ptr(self.HDR)) - flags |= GCFLAG_EXTERNAL | GCFLAG_FORWARDED | GC_HASH_TAKEN_ADDR - hdr.tid = self.combine(typeid16, flags) - # immortal objects always have GCFLAG_FORWARDED set; - # see get_forwarding_address(). - - def deal_with_objects_with_light_finalizers(self): - """ This is a much simpler version of dealing with finalizers - and an optimization - we can reasonably assume that those finalizers - don't do anything fancy and *just* call them. Among other things - they won't resurrect objects - """ - new_objects = self.AddressStack() - while self.objects_with_light_finalizers.non_empty(): - obj = self.objects_with_light_finalizers.pop() - if self.surviving(obj): - new_objects.append(self.get_forwarding_address(obj)) - else: - finalizer = self.getfinalizer(self.get_type_id(obj)) - finalizer(obj) - self.objects_with_light_finalizers.delete() - self.objects_with_light_finalizers = new_objects - - def deal_with_objects_with_finalizers(self, scan): - # walk over list of objects with finalizers - # if it is not copied, add it to the list of to-be-called finalizers - # and copy it, to me make the finalizer runnable - # We try to run the finalizers in a "reasonable" order, like - # CPython does. The details of this algorithm are in - # pypy/doc/discussion/finalizer-order.txt. - new_with_finalizer = self.AddressDeque() - marked = self.AddressDeque() - pending = self.AddressStack() - self.tmpstack = self.AddressStack() - while self.objects_with_finalizers.non_empty(): - x = self.objects_with_finalizers.popleft() - ll_assert(self._finalization_state(x) != 1, - "bad finalization state 1") - if self.surviving(x): - new_with_finalizer.append(self.get_forwarding_address(x)) - continue - marked.append(x) - pending.append(x) - while pending.non_empty(): - y = pending.pop() - state = self._finalization_state(y) - if state == 0: - self._bump_finalization_state_from_0_to_1(y) - self.trace(y, self._append_if_nonnull, pending) - elif state == 2: - self._recursively_bump_finalization_state_from_2_to_3(y) - scan = self._recursively_bump_finalization_state_from_1_to_2( - x, scan) - - while marked.non_empty(): - x = marked.popleft() - state = self._finalization_state(x) - ll_assert(state >= 2, "unexpected finalization state < 2") - newx = self.get_forwarding_address(x) - if state == 2: - self.run_finalizers.append(newx) - # we must also fix the state from 2 to 3 here, otherwise - # we leave the GCFLAG_FINALIZATION_ORDERING bit behind - # which will confuse the next collection - self._recursively_bump_finalization_state_from_2_to_3(x) - else: - new_with_finalizer.append(newx) - - self.tmpstack.delete() - pending.delete() - marked.delete() - self.objects_with_finalizers.delete() - self.objects_with_finalizers = new_with_finalizer - return scan - - def _append_if_nonnull(pointer, stack): - stack.append(pointer.address[0]) - _append_if_nonnull = staticmethod(_append_if_nonnull) - - def _finalization_state(self, obj): - if self.surviving(obj): - newobj = self.get_forwarding_address(obj) - hdr = self.header(newobj) - if hdr.tid & GCFLAG_FINALIZATION_ORDERING: - return 2 - else: - return 3 - else: - hdr = self.header(obj) - if hdr.tid & GCFLAG_FINALIZATION_ORDERING: - return 1 - else: - return 0 - - def _bump_finalization_state_from_0_to_1(self, obj): - ll_assert(self._finalization_state(obj) == 0, - "unexpected finalization state != 0") - hdr = self.header(obj) - hdr.tid |= GCFLAG_FINALIZATION_ORDERING - - def _recursively_bump_finalization_state_from_2_to_3(self, obj): - ll_assert(self._finalization_state(obj) == 2, - "unexpected finalization state != 2") - newobj = self.get_forwarding_address(obj) - pending = self.tmpstack - ll_assert(not pending.non_empty(), "tmpstack not empty") - pending.append(newobj) - while pending.non_empty(): - y = pending.pop() - hdr = self.header(y) - if hdr.tid & GCFLAG_FINALIZATION_ORDERING: # state 2 ? - hdr.tid &= ~GCFLAG_FINALIZATION_ORDERING # change to state 3 - self.trace(y, self._append_if_nonnull, pending) - - def _recursively_bump_finalization_state_from_1_to_2(self, obj, scan): - # recursively convert objects from state 1 to state 2. - # Note that copy() copies all bits, including the - # GCFLAG_FINALIZATION_ORDERING. The mapping between - # state numbers and the presence of this bit was designed - # for the following to work :-) - self.copy(obj) - return self.scan_copied(scan) - - def invalidate_weakrefs(self): - # walk over list of objects that contain weakrefs - # if the object it references survives then update the weakref - # otherwise invalidate the weakref - new_with_weakref = self.AddressStack() - while self.objects_with_weakrefs.non_empty(): - obj = self.objects_with_weakrefs.pop() - if not self.surviving(obj): - continue # weakref itself dies - obj = self.get_forwarding_address(obj) - offset = self.weakpointer_offset(self.get_type_id(obj)) - pointing_to = (obj + offset).address[0] - # XXX I think that pointing_to cannot be NULL here - if pointing_to: - if self.surviving(pointing_to): - (obj + offset).address[0] = self.get_forwarding_address( - pointing_to) - new_with_weakref.append(obj) - else: - (obj + offset).address[0] = NULL - self.objects_with_weakrefs.delete() - self.objects_with_weakrefs = new_with_weakref - - def update_run_finalizers(self): - # we are in an inner collection, caused by a finalizer - # the run_finalizers objects need to be copied - new_run_finalizer = self.AddressDeque() - while self.run_finalizers.non_empty(): - obj = self.run_finalizers.popleft() - new_run_finalizer.append(self.copy(obj)) - self.run_finalizers.delete() - self.run_finalizers = new_run_finalizer - - def _is_external(self, obj): - return (self.header(obj).tid & GCFLAG_EXTERNAL) != 0 - - def _is_in_the_space(self, obj): - return self.tospace <= obj < self.free - - 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 != 0, "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 - - def is_in_nursery(self, addr): - # overridden in generation.py. - return False - - def _compute_current_nursery_hash(self, obj): - # overridden in generation.py. - raise AssertionError("should not be called") - - def identityhash(self, gcobj): - # The following loop should run at most twice. - while 1: - obj = llmemory.cast_ptr_to_adr(gcobj) - hdr = self.header(obj) - if hdr.tid & GCFLAG_HASHMASK: - break - # It's the first time we ask for a hash, and it's not an - # external object. Shrink the top of space by the extra - # hash word that will be needed after a collect. - shrunk_top = self.top_of_space - llmemory.sizeof(lltype.Signed) - if shrunk_top < self.free: - # Cannot shrink! Do a collection, asking for at least - # one word of free space, and try again. May raise - # MemoryError. Obscure: not called directly, but - # across an llop, to make sure that there is the - # correct push_roots/pop_roots around the call... - llop.gc_obtain_free_space(llmemory.Address, - llmemory.sizeof(lltype.Signed)) - continue - else: - # Now we can have side-effects: lower the top of space - # and set one of the GC_HASH_TAKEN_xxx flags. - self.top_of_space = shrunk_top - if self.is_in_nursery(obj): - hdr.tid |= GC_HASH_TAKEN_NURS - else: - hdr.tid |= GC_HASH_TAKEN_ADDR - break - # Now we can return the result - objsize = self.get_size(obj) - return self._get_object_hash(obj, objsize, hdr.tid) - - def track_heap_parent(self, obj, parent): - addr = obj.address[0] - parent_idx = llop.get_member_index(lltype.Signed, - self.get_type_id(parent)) - idx = llop.get_member_index(lltype.Signed, self.get_type_id(addr)) - self._ll_typeid_map[parent_idx].links[idx] += 1 - self.track_heap(addr) - - def track_heap(self, adr): - if self._tracked_dict.contains(adr): - return - self._tracked_dict.add(adr) - idx = llop.get_member_index(lltype.Signed, self.get_type_id(adr)) - self._ll_typeid_map[idx].count += 1 - totsize = self.get_size(adr) + self.size_gc_header() - self._ll_typeid_map[idx].size += llmemory.raw_malloc_usage(totsize) - self.trace(adr, self.track_heap_parent, adr) - - @staticmethod - def _track_heap_root(obj, self): - self.track_heap(obj) - - def heap_stats(self): - self._tracked_dict = self.AddressDict() - max_tid = self.root_walker.gcdata.max_type_id - ll_typeid_map = lltype.malloc(ARRAY_TYPEID_MAP, max_tid, zero=True) - for i in range(max_tid): - ll_typeid_map[i] = lltype.malloc(TYPEID_MAP, max_tid, zero=True) - self._ll_typeid_map = ll_typeid_map - self._tracked_dict.add(llmemory.cast_ptr_to_adr(ll_typeid_map)) - i = 0 - while i < max_tid: - self._tracked_dict.add(llmemory.cast_ptr_to_adr(ll_typeid_map[i])) - i += 1 - self.enumerate_all_roots(SemiSpaceGC._track_heap_root, self) - self._ll_typeid_map = lltype.nullptr(ARRAY_TYPEID_MAP) - self._tracked_dict.delete() - return ll_typeid_map diff --git a/rpython/memory/gc/test/test_direct.py b/rpython/memory/gc/test/test_direct.py --- a/rpython/memory/gc/test/test_direct.py +++ b/rpython/memory/gc/test/test_direct.py @@ -364,120 +364,6 @@ p = self.stackroots[-50+i] assert p[i-1] == chr(i) -class TestSemiSpaceGC(DirectGCTest): - from rpython.memory.gc.semispace import SemiSpaceGC as GCClass - - def test_shrink_array(self): - S1 = lltype.GcStruct('S1', ('h', lltype.Char), - ('v', lltype.Array(lltype.Char))) - p1 = self.malloc(S1, 2) - p1.h = '?' - for i in range(2): - p1.v[i] = chr(50 + i) - addr = llmemory.cast_ptr_to_adr(p1) - ok = self.gc.shrink_array(addr, 1) - assert ok - assert p1.h == '?' - assert len(p1.v) == 1 - for i in range(1): - assert p1.v[i] == chr(50 + i) - - -class TestGenerationGC(TestSemiSpaceGC): From noreply at buildbot.pypy.org Sat Apr 27 13:34:14 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sat, 27 Apr 2013 13:34:14 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Fix test_newgc. Message-ID: <20130427113414.CA9451C11C6@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63682:185c73ab726e Date: 2013-04-27 13:05 +0200 http://bitbucket.org/pypy/pypy/changeset/185c73ab726e/ Log: Fix test_newgc. diff --git a/rpython/memory/test/snippet.py b/rpython/memory/test/snippet.py --- a/rpython/memory/test/snippet.py +++ b/rpython/memory/test/snippet.py @@ -6,7 +6,7 @@ from rpython.rlib import rgc -class SemiSpaceGCTestDefines: +class SnippetTestDefines: large_tests_ok = False def definestr_finalizer_order(cls): @@ -176,7 +176,7 @@ res = self.run('from_objwithfinalizer_to_youngobj') assert res == 1 -class SemiSpaceGCTests(SemiSpaceGCTestDefines): +class SnippetTests(SnippetTestDefines): # xxx messy def run(self, name): # for test_gc.py diff --git a/rpython/memory/test/test_minimark_gc.py b/rpython/memory/test/test_minimark_gc.py --- a/rpython/memory/test/test_minimark_gc.py +++ b/rpython/memory/test/test_minimark_gc.py @@ -9,7 +9,7 @@ WORD = LONG_BIT // 8 -class TestMiniMarkGC(GCTest, snippet.SemiSpaceGCTests): +class TestMiniMarkGC(GCTest, snippet.SnippetTests): from rpython.memory.gc.minimark import MiniMarkGC as GCClass GC_CAN_MOVE = True GC_CAN_SHRINK_ARRAY = True diff --git a/rpython/translator/c/test/test_newgc.py b/rpython/translator/c/test/test_newgc.py --- a/rpython/translator/c/test/test_newgc.py +++ b/rpython/translator/c/test/test_newgc.py @@ -1261,11 +1261,10 @@ self.run("gcflag_extra") -class TestSemiSpaceGC(UsingFrameworkTest, snippet.SemiSpaceGCTestDefines): - gcpolicy = "semispace" +class MovingGCTests(UsingFrameworkTest, snippet.SnippetTestDefines): should_be_moving = True GC_CAN_MOVE = True - GC_CAN_MALLOC_NONMOVABLE = False + GC_CAN_MALLOC_NONMOVABLE = True GC_CAN_SHRINK_ARRAY = True # for snippets @@ -1432,29 +1431,11 @@ assert res >= 195 -class TestGenerationalGC(TestSemiSpaceGC): - gcpolicy = "generation" - should_be_moving = True +# ____________________________________________________________________ -class TestHybridGC(TestGenerationalGC): - gcpolicy = "hybrid" - should_be_moving = True - GC_CAN_MALLOC_NONMOVABLE = True - - def test_gc_set_max_heap_size(self): - py.test.skip("not implemented") - - -class TestHybridGCRemoveTypePtr(TestHybridGC): - removetypeptr = True - - -class TestMiniMarkGC(TestSemiSpaceGC): +class TestMiniMarkGC(MovingGCTests): gcpolicy = "minimark" - should_be_moving = True - GC_CAN_MALLOC_NONMOVABLE = True - GC_CAN_SHRINK_ARRAY = True def test_gc_heap_stats(self): py.test.skip("not implemented") @@ -1517,8 +1498,10 @@ res = self.run("nongc_opaque_attached_to_gc") assert res == 0 + # ____________________________________________________________________ + class TaggedPointersTest(object): taggedpointers = True @@ -1603,9 +1586,6 @@ return self.smallint + x + 3 -class TestHybridTaggedPointers(TaggedPointersTest, TestHybridGC): - pass - - -class TestMiniMarkGCMostCompact(TaggedPointersTest, TestMiniMarkGC): +class TestMiniMarkGCTaggedPointersAndRemoveTypePtr(TaggedPointersTest, + TestMiniMarkGC): removetypeptr = True From noreply at buildbot.pypy.org Sat Apr 27 13:34:16 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sat, 27 Apr 2013 13:34:16 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: More fixes Message-ID: <20130427113416.02D311C11C6@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63683:7c88b2c3b7ca Date: 2013-04-27 13:15 +0200 http://bitbucket.org/pypy/pypy/changeset/7c88b2c3b7ca/ Log: More fixes diff --git a/rpython/memory/gc/minimark.py b/rpython/memory/gc/minimark.py --- a/rpython/memory/gc/minimark.py +++ b/rpython/memory/gc/minimark.py @@ -1020,7 +1020,7 @@ ll_assert(self.header(obj).tid & GCFLAG_CARDS_SET == 0, "unexpected GCFLAG_CARDS_SET") # if the GCFLAG_HAS_CARDS is set, check that all bits are zero now - if self.has_card(self.header(obj)): + if self.header(obj).tid & GCFLAG_HAS_CARDS: if self.card_page_indices <= 0: ll_assert(False, "GCFLAG_HAS_CARDS but not using card marking") return diff --git a/rpython/memory/gc/test/test_direct.py b/rpython/memory/gc/test/test_direct.py --- a/rpython/memory/gc/test/test_direct.py +++ b/rpython/memory/gc/test/test_direct.py @@ -421,14 +421,6 @@ res = self.gc.writebarrier_before_copy(addr_src, addr_dst, 0, 0, 10) assert res # we optimized it assert hdr_dst.tid & minimark.GCFLAG_TRACK_YOUNG_PTRS == 0 # and we copied the flag - # - hdr_src.tid |= minimark.GCFLAG_TRACK_YOUNG_PTRS - hdr_dst.tid |= minimark.GCFLAG_TRACK_YOUNG_PTRS - hdr_src.tid |= minimark.GCFLAG_HAS_CARDS - hdr_src.tid |= minimark.GCFLAG_CARDS_SET - # hdr_dst.tid does not have minimark.GCFLAG_HAS_CARDS - res = self.gc.writebarrier_before_copy(addr_src, addr_dst, 0, 0, 10) - assert not res # there might be young ptrs, let ll_arraycopy to find them def test_writebarrier_before_copy_preserving_cards(self): from rpython.rtyper.lltypesystem import llarena @@ -466,6 +458,43 @@ test_writebarrier_before_copy_preserving_cards.GC_PARAMS = { "card_page_indices": 4} + def test_dst_without_cards(self): + from rpython.memory.gc import minimark + largeobj_size = self.gc.nonlarge_max + 1 + self.gc.next_major_collection_threshold = 99999.0 + p_src = self.malloc(VAR, largeobj_size) + p_dst = self.malloc(VAR, largeobj_size) + # make them old + self.stackroots.append(p_src) + self.stackroots.append(p_dst) + self.gc.collect() + p_dst = self.stackroots.pop() + p_src = self.stackroots.pop() + # + addr_src = llmemory.cast_ptr_to_adr(p_src) + addr_dst = llmemory.cast_ptr_to_adr(p_dst) + hdr_src = self.gc.header(addr_src) + hdr_dst = self.gc.header(addr_dst) + # + assert hdr_src.tid & minimark.GCFLAG_TRACK_YOUNG_PTRS + assert hdr_dst.tid & minimark.GCFLAG_TRACK_YOUNG_PTRS + assert hdr_src.tid & minimark.GCFLAG_HAS_CARDS + assert not (hdr_src.tid & minimark.GCFLAG_CARDS_SET) + hdr_dst.tid &= ~minimark.GCFLAG_HAS_CARDS + res = self.gc.writebarrier_before_copy(addr_src, addr_dst, 0, 0, 10) + assert res + # + assert hdr_src.tid & minimark.GCFLAG_TRACK_YOUNG_PTRS + assert hdr_dst.tid & minimark.GCFLAG_TRACK_YOUNG_PTRS + assert hdr_src.tid & minimark.GCFLAG_HAS_CARDS + hdr_src.tid |= minimark.GCFLAG_CARDS_SET + hdr_dst.tid &= ~minimark.GCFLAG_HAS_CARDS + res = self.gc.writebarrier_before_copy(addr_src, addr_dst, 0, 0, 10) + assert not res # there might be young ptrs, let ll_arraycopy find them + + test_dst_without_cards.GC_PARAMS = { + "card_page_indices": 4} + class TestMiniMarkGCFull(DirectGCTest): from rpython.memory.gc.minimark import MiniMarkGC as GCClass diff --git a/rpython/memory/gc/test/test_inspector.py b/rpython/memory/gc/test/test_inspector.py --- a/rpython/memory/gc/test/test_inspector.py +++ b/rpython/memory/gc/test/test_inspector.py @@ -38,9 +38,6 @@ assert expected == seen -class TestHybridGC(InspectorTest): - from rpython.memory.gc.hybrid import HybridGC as GCClass - class TestMiniMarkGCSimple(InspectorTest): from rpython.memory.gc.minimark import MiniMarkGC as GCClass from rpython.memory.gc.minimarktest import SimpleArenaCollection From noreply at buildbot.pypy.org Sat Apr 27 13:34:17 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sat, 27 Apr 2013 13:34:17 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Fix Message-ID: <20130427113417.2EA031C11C6@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63684:1506fbf06b43 Date: 2013-04-27 13:24 +0200 http://bitbucket.org/pypy/pypy/changeset/1506fbf06b43/ Log: Fix diff --git a/rpython/memory/gctransform/test/test_boehm.py b/rpython/memory/gctransform/test/test_boehm.py --- a/rpython/memory/gctransform/test/test_boehm.py +++ b/rpython/memory/gctransform/test/test_boehm.py @@ -11,7 +11,7 @@ gcpolicy = BoehmGcPolicy def make_boehm_finalizer(TYPE): - return make_deallocator(TYPE, attr="finalizer_funcptr_for_type", + return make_deallocator(TYPE, attr="destructor_funcptr_for_type", cls=BoehmGCTransformer) def test_boehm_simple(): From noreply at buildbot.pypy.org Sat Apr 27 13:34:18 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sat, 27 Apr 2013 13:34:18 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Only call this if cards are enabled. Message-ID: <20130427113418.72E6C1C11C6@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63685:b83f0a157dda Date: 2013-04-27 13:24 +0200 http://bitbucket.org/pypy/pypy/changeset/b83f0a157dda/ Log: Only call this if cards are enabled. diff --git a/rpython/memory/gc/minimark.py b/rpython/memory/gc/minimark.py --- a/rpython/memory/gc/minimark.py +++ b/rpython/memory/gc/minimark.py @@ -2049,7 +2049,8 @@ pending.append(obj) pending.append(NULL) # marker # - if self.header(obj).tid & GCFLAG_CARDS_SET != 0: + if (self.card_page_indices > 0 and + self.header(obj).tid & GCFLAG_CARDS_SET != 0): self.old_objects_with_cards_set.append(obj) self.collect_cardrefs_to_nursery() # From noreply at buildbot.pypy.org Sat Apr 27 13:34:19 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sat, 27 Apr 2013 13:34:19 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Fix test Message-ID: <20130427113419.9508F1C11C6@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63686:ea4247e83d9c Date: 2013-04-27 13:29 +0200 http://bitbucket.org/pypy/pypy/changeset/ea4247e83d9c/ Log: Fix test diff --git a/rpython/jit/backend/llsupport/test/test_gc.py b/rpython/jit/backend/llsupport/test/test_gc.py --- a/rpython/jit/backend/llsupport/test/test_gc.py +++ b/rpython/jit/backend/llsupport/test/test_gc.py @@ -60,11 +60,9 @@ return x, tid def do_malloc_fixedsize_clear(self, RESTYPE, type_id, size, - has_finalizer, has_light_finalizer, - contains_weakptr): + has_destructor, contains_weakptr): assert not contains_weakptr - assert not has_finalizer - assert not has_light_finalizer + assert not has_destructor p, tid = self._malloc(type_id, size) p = llmemory.cast_adr_to_ptr(p, RESTYPE) self.record.append(("fixedsize", repr(size), tid, p)) From noreply at buildbot.pypy.org Sat Apr 27 13:34:55 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sat, 27 Apr 2013 13:34:55 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Fix: directly output the error message here, because we're not in finalizer_perform(). Message-ID: <20130427113455.0170E1C11C6@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63687:5b847a6c3864 Date: 2013-04-27 13:34 +0200 http://bitbucket.org/pypy/pypy/changeset/5b847a6c3864/ Log: Fix: directly output the error message here, because we're not in finalizer_perform(). diff --git a/pypy/module/_file/interp_file.py b/pypy/module/_file/interp_file.py --- a/pypy/module/_file/interp_file.py +++ b/pypy/module/_file/interp_file.py @@ -45,7 +45,7 @@ self.direct_close() except StreamErrors, e: operr = wrap_streamerror(self.space, e, self.w_name) - raise operr + operr.write_unraisable(self.space, "close method of ", self) def fdopenstream(self, stream, fd, mode, w_name=None): self.fd = fd From noreply at buildbot.pypy.org Sat Apr 27 13:42:30 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sat, 27 Apr 2013 13:42:30 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Use minimark here. Message-ID: <20130427114230.8706C1C11C6@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63688:94a009fde44c Date: 2013-04-27 13:38 +0200 http://bitbucket.org/pypy/pypy/changeset/94a009fde44c/ Log: Use minimark here. diff --git a/pypy/module/thread/test/test_gil.py b/pypy/module/thread/test/test_gil.py --- a/pypy/module/thread/test/test_gil.py +++ b/pypy/module/thread/test/test_gil.py @@ -111,5 +111,5 @@ return f class TestUsingFramework(GILTests): - gcpolicy = 'generation' + gcpolicy = 'minimark' bigtest = True diff --git a/rpython/rlib/test/test_rthread.py b/rpython/rlib/test/test_rthread.py --- a/rpython/rlib/test/test_rthread.py +++ b/rpython/rlib/test/test_rthread.py @@ -209,4 +209,4 @@ gcpolicy = 'boehm' class TestUsingFramework(AbstractThreadTests): - gcpolicy = 'generation' + gcpolicy = 'minimark' From noreply at buildbot.pypy.org Sat Apr 27 13:42:31 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sat, 27 Apr 2013 13:42:31 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Remove the "import x" from the same file x... Message-ID: <20130427114231.CE70C1C11C6@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63689:b8bac9d240e7 Date: 2013-04-27 13:38 +0200 http://bitbucket.org/pypy/pypy/changeset/b8bac9d240e7/ Log: Remove the "import x" from the same file x... diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py --- a/pypy/objspace/std/typeobject.py +++ b/pypy/objspace/std/typeobject.py @@ -559,8 +559,6 @@ def _create_new_type(space, w_typetype, w_name, w_bases, w_dict): # this is in its own function because we want the special case 'type(x)' # above to be seen by the jit. - from pypy.objspace.std.typeobject import W_TypeObject - if w_bases is None or w_dict is None: raise OperationError(space.w_TypeError, space.wrap("type() takes 1 or 3 arguments")) @@ -602,7 +600,6 @@ return w_type def _precheck_for_new(space, w_type): - from pypy.objspace.std.typeobject import W_TypeObject if not isinstance(w_type, W_TypeObject): raise operationerrfmt(space.w_TypeError, "X is not a type object (%s)", @@ -612,7 +609,6 @@ # ____________________________________________________________ def _check(space, w_type, w_msg=None): - from pypy.objspace.std.typeobject import W_TypeObject if not isinstance(w_type, W_TypeObject): if w_msg is None: w_msg = space.wrap("descriptor is for 'type'") @@ -645,7 +641,6 @@ return space.newtuple(w_type.bases_w) def mro_subclasses(space, w_type, temp): - from pypy.objspace.std.typeobject import W_TypeObject, compute_mro temp.append((w_type, w_type.mro_w)) compute_mro(w_type) for w_sc in w_type.get_subclasses(): @@ -654,9 +649,6 @@ def descr_set__bases__(space, w_type, w_value): # this assumes all app-level type objects are W_TypeObject - from pypy.objspace.std.typeobject import (W_TypeObject, get_parent_layout, - check_and_find_best_base, is_mro_purely_of_types) - w_type = _check(space, w_type) if not w_type.is_heaptype(): raise operationerrfmt(space.w_TypeError, @@ -723,7 +715,6 @@ assert w_type.w_same_layout_as is get_parent_layout(w_type) # invariant def descr__base(space, w_type): - from pypy.objspace.std.typeobject import find_best_base w_type = _check(space, w_type) return find_best_base(space, w_type.bases_w) From noreply at buildbot.pypy.org Sat Apr 27 13:42:32 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sat, 27 Apr 2013 13:42:32 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: can't use lookup() here, must use _lookup(): see test_methodcache Message-ID: <20130427114232.E99FC1C11C6@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63690:ec1b02874f96 Date: 2013-04-27 13:41 +0200 http://bitbucket.org/pypy/pypy/changeset/ec1b02874f96/ Log: can't use lookup() here, must use _lookup(): see test_methodcache diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py --- a/pypy/objspace/std/typeobject.py +++ b/pypy/objspace/std/typeobject.py @@ -1038,7 +1038,8 @@ if mro_w is None: mro_w = w_self.compute_default_mro()[:] w_self.mro_w = mro_w - w_self.has_del = (w_self.lookup("__del__") is not None) + # can't use lookup() here, must use _lookup(): see test_methodcache + w_self.has_del = (w_self._lookup("__del__") is not None) def validate_custom_mro(space, mro_w): # do some checking here. Note that unlike CPython, strange MROs From noreply at buildbot.pypy.org Sat Apr 27 13:45:15 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sat, 27 Apr 2013 13:45:15 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Add missing operation Message-ID: <20130427114515.4C6621C11C6@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63691:39bf0e2e6e2c Date: 2013-04-27 13:43 +0200 http://bitbucket.org/pypy/pypy/changeset/39bf0e2e6e2c/ Log: Add missing operation diff --git a/rpython/rtyper/llinterp.py b/rpython/rtyper/llinterp.py --- a/rpython/rtyper/llinterp.py +++ b/rpython/rtyper/llinterp.py @@ -826,6 +826,9 @@ else: self.heap.register_finalizer(llptr, llfn) + def op_gc_progress_finalizer_queue(self): + raise NotImplementedError + def op_gc_heap_stats(self): raise NotImplementedError From noreply at buildbot.pypy.org Sat Apr 27 13:45:16 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sat, 27 Apr 2013 13:45:16 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Convert to use minimark. Message-ID: <20130427114516.A45EB1C11C6@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63692:9cfe83160f91 Date: 2013-04-27 13:44 +0200 http://bitbucket.org/pypy/pypy/changeset/9cfe83160f91/ Log: Convert to use minimark. diff --git a/rpython/rtyper/lltypesystem/test/test_rffi.py b/rpython/rtyper/lltypesystem/test/test_rffi.py --- a/rpython/rtyper/lltypesystem/test/test_rffi.py +++ b/rpython/rtyper/lltypesystem/test/test_rffi.py @@ -527,7 +527,7 @@ fn = self.compile(f, [], gcpolicy='ref') assert fn() == len(d) - def test_nonmovingbuffer_semispace(self): + def test_nonmovingbuffer_minimark(self): d = 'cool data' def f(): counter = 0 @@ -540,8 +540,8 @@ finally: free_nonmovingbuffer(d, buf) return counter - fn = self.compile(f, [], gcpolicy='semispace') - # The semispace gc uses raw_malloc for its internal data structs + fn = self.compile(f, [], gcpolicy='minimark') + # The minimark gc uses raw_malloc for its internal data structs # but hopefully less than 30 times. So we should get < 30 leaks # unless the get_nonmovingbuffer()/free_nonmovingbuffer() pair # leaks at each iteration. This is what the following line checks. From noreply at buildbot.pypy.org Sat Apr 27 15:31:16 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sat, 27 Apr 2013 15:31:16 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Fixes Message-ID: <20130427133116.383E11C138A@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63693:5a165d74f315 Date: 2013-04-27 15:30 +0200 http://bitbucket.org/pypy/pypy/changeset/5a165d74f315/ Log: Fixes diff --git a/rpython/translator/c/gcc/test/test_asmgcroot.py b/rpython/translator/c/gcc/test/test_asmgcroot.py --- a/rpython/translator/c/gcc/test/test_asmgcroot.py +++ b/rpython/translator/c/gcc/test/test_asmgcroot.py @@ -11,6 +11,7 @@ from rpython.rtyper.lltypesystem import lltype, rffi from rpython.rlib.entrypoint import entrypoint, secondary_entrypoints from rpython.rtyper.lltypesystem.lloperation import llop +from rpython.translator.backendopt.all import backend_optimizations _MSVC = compiler.name == "msvc" _MINGW = compiler.name == "mingw32" @@ -54,6 +55,7 @@ a.build_types(f, inputtypes, False) a.build_types(main, [s_list_of_strings]) t.buildrtyper().specialize() + backend_optimizations(t) t.checkgraphs() cbuilder = CStandaloneBuilder(t, main, config=config, @@ -130,8 +132,8 @@ def define_callback_with_collect(cls): return lambda: 0 -class TestAsmGCRootWithSemiSpaceGC(AbstractTestAsmGCRoot, - test_newgc.TestSemiSpaceGC): +class TestAsmGCRootWithMiniMarkGC(AbstractTestAsmGCRoot, + test_newgc.TestMiniMarkGC): # for the individual tests see # ====> ../../test/test_newgc.py secondary_entrypoints = [] @@ -227,7 +229,7 @@ res = self.run('secondary_entrypoint_callback') assert res == 4900 -class TestAsmGCRootWithSemiSpaceGC_Mingw32(TestAsmGCRootWithSemiSpaceGC): +class TestAsmGCRootWithMiniMarkGC_Mingw32(TestAsmGCRootWithMiniMarkGC): # for the individual tests see # ====> ../../test/test_newgc.py @@ -239,11 +241,11 @@ 'GNU' in os.popen('make --version').read()): py.test.skip("mingw32 and MSYS are required for this test") - test_newgc.TestSemiSpaceGC.setup_class.im_func(cls) + test_newgc.TestAsmGCRootWithMiniMarkGC.setup_class.im_func(cls) @classmethod def make_config(cls): - config = TestAsmGCRootWithSemiSpaceGC.make_config() + config = TestAsmGCRootWithMiniMarkGC.make_config() config.translation.cc = 'mingw32' return config @@ -254,13 +256,13 @@ def define_callback_with_collect(cls): return lambda: 0 -class TestAsmGCRootWithSemiSpaceGC_Shared(TestAsmGCRootWithSemiSpaceGC): +class TestAsmGCRootWithMiniMarkGC_Shared(TestAsmGCRootWithMiniMarkGC): @classmethod def make_config(cls): - config = TestAsmGCRootWithSemiSpaceGC.make_config() + config = TestAsmGCRootWithMiniMarkGC.make_config() config.translation.shared = True return config -class TestAsmGCRootWithHybridTagged(AbstractTestAsmGCRoot, - test_newgc.TestHybridTaggedPointers): +class TestAsmGCRootWithMiniMarkTagged(AbstractTestAsmGCRoot, + test_newgc.TestMiniMarkGCTaggedPointersAndRemoveTypePtr): pass diff --git a/rpython/translator/c/test/test_standalone.py b/rpython/translator/c/test/test_standalone.py --- a/rpython/translator/c/test/test_standalone.py +++ b/rpython/translator/c/test/test_standalone.py @@ -841,7 +841,7 @@ def compile(self, entry_point): t = TranslationContext(self.config) - t.config.translation.gc = "semispace" + t.config.translation.gc = "minimark" t.config.translation.gcrootfinder = self.gcrootfinder t.config.translation.thread = True t.buildannotator().build_types(entry_point, [s_list_of_strings]) From noreply at buildbot.pypy.org Sat Apr 27 15:34:44 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sat, 27 Apr 2013 15:34:44 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: More fixes Message-ID: <20130427133444.4674E1C13B9@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63694:da5b88a6c4e4 Date: 2013-04-27 15:34 +0200 http://bitbucket.org/pypy/pypy/changeset/da5b88a6c4e4/ Log: More fixes diff --git a/rpython/translator/c/test/test_standalone.py b/rpython/translator/c/test/test_standalone.py --- a/rpython/translator/c/test/test_standalone.py +++ b/rpython/translator/c/test/test_standalone.py @@ -1,6 +1,7 @@ import py import sys, os, re +from rpython.rlib import rgc from rpython.rlib.objectmodel import keepalive_until_here from rpython.rlib.rarithmetic import r_longlong from rpython.rlib.debug import ll_assert, have_debug_prints, debug_flush @@ -1083,7 +1084,9 @@ self.tail = tail class Stuff: - def __del__(self): + def __init__(self): + rgc.register_finalizer(self.finalizer) + def finalizer(self): os.write(state.write_end, 'd') def allocate_stuff(): diff --git a/rpython/translator/test/test_stackcheck.py b/rpython/translator/test/test_stackcheck.py --- a/rpython/translator/test/test_stackcheck.py +++ b/rpython/translator/test/test_stackcheck.py @@ -95,8 +95,7 @@ check(f_graph, 'f') class GCTransform(shadowstack.ShadowStackFrameworkGCTransformer): - from rpython.memory.gc.generation import GenerationGC as \ - GCClass + from rpython.memory.gc.minimark import MiniMarkGC as GCClass GC_PARAMS = {} gctransf = GCTransform(t) From noreply at buildbot.pypy.org Sat Apr 27 15:46:55 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sat, 27 Apr 2013 15:46:55 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Kill the config options for the removed GC, and fix test_sandbox. Message-ID: <20130427134655.A5B8D1C026F@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63695:dc83e26b5a7e Date: 2013-04-27 15:45 +0200 http://bitbucket.org/pypy/pypy/changeset/dc83e26b5a7e/ Log: Kill the config options for the removed GC, and fix test_sandbox. diff --git a/rpython/config/translationoption.py b/rpython/config/translationoption.py --- a/rpython/config/translationoption.py +++ b/rpython/config/translationoption.py @@ -57,17 +57,12 @@ # gc ChoiceOption("gc", "Garbage Collection Strategy", - ["boehm", "ref", "semispace", "statistics", - "generation", "hybrid", "minimark", "none"], + ["boehm", "ref", "minimark", "none"], "ref", requires={ "ref": [("translation.rweakref", False), # XXX ("translation.gctransformer", "ref")], "none": [("translation.rweakref", False), # XXX ("translation.gctransformer", "none")], - "semispace": [("translation.gctransformer", "framework")], - "statistics": [("translation.gctransformer", "framework")], - "generation": [("translation.gctransformer", "framework")], - "hybrid": [("translation.gctransformer", "framework")], "boehm": [("translation.continuation", False), # breaks ("translation.gctransformer", "boehm")], "minimark": [("translation.gctransformer", "framework")], @@ -103,8 +98,7 @@ BoolOption("sandbox", "Produce a fully-sandboxed executable", default=False, cmdline="--sandbox", requires=[("translation.thread", False)], - suggests=[("translation.gc", "generation"), - ("translation.gcrootfinder", "shadowstack")]), + suggests=[("translation.gcrootfinder", "shadowstack")]), BoolOption("rweakref", "The backend supports RPython-level weakrefs", default=True), diff --git a/rpython/translator/sandbox/test/test_sandbox.py b/rpython/translator/sandbox/test/test_sandbox.py --- a/rpython/translator/sandbox/test/test_sandbox.py +++ b/rpython/translator/sandbox/test/test_sandbox.py @@ -9,16 +9,17 @@ from rpython.translator.sandbox.sandlib import write_exception def expect(f, g, fnname, args, result, resulttype=None): - msg = read_message(f, timeout=10.0) - assert msg == fnname - msg = read_message(f, timeout=10.0) - assert msg == args + msg1 = read_message(f, timeout=10.0) + msg2 = read_message(f, timeout=10.0) + assert (msg1, msg2) == (fnname, args), ( + "expected: %r %r\n" % (fnname, args) + + " but got: %r %r" % (msg1, msg2)) if isinstance(result, Exception): write_exception(g, result) else: write_message(g, 0) write_message(g, result, resulttype) - g.flush() + g.flush() def compile(f, gc='ref'): t = Translation(f, backend='c', sandbox=True, gc=gc, @@ -148,22 +149,31 @@ f.close() assert tail == "" -def test_hybrid_gc(): +def test_minimark_gc(): def entry_point(argv): l = [] for i in range(int(argv[1])): l.append("x" * int(argv[2])) return int(len(l) > 1000) - exe = compile(entry_point, gc='hybrid') + exe = compile(entry_point, gc='minimark') pipe = subprocess.Popen([exe, '10', '10000'], stdout=subprocess.PIPE, stdin=subprocess.PIPE) g = pipe.stdin f = pipe.stdout - expect(f, g, "ll_os.ll_os_getenv", ("PYPY_GENERATIONGC_NURSERY",), None) - #if sys.platform.startswith('linux'): - # expect(f, g, "ll_os.ll_os_open", ("/proc/cpuinfo", 0, 420), - # OSError(5232, "xyz")) + expect(f, g, "ll_os.ll_os_getenv", ("PYPY_GC_NURSERY",), None) + if sys.platform.startswith('linux'): + expect(f, g, "ll_os.ll_os_open", ("/proc/cpuinfo", 0, 420), + OSError(5232, "xyz")) + expect(f, g, "ll_os.ll_os_getenv", ("PYPY_GC_NURSERY_CLEANUP",), None) + expect(f, g, "ll_os.ll_os_getenv", ("PYPY_GC_MAJOR_COLLECT",), None) + expect(f, g, "ll_os.ll_os_getenv", ("PYPY_GC_GROWTH",), None) + expect(f, g, "ll_os.ll_os_getenv", ("PYPY_GC_MIN",), None) + expect(f, g, "ll_os.ll_os_getenv", ("PYPY_GC_MAX",), None) + expect(f, g, "ll_os.ll_os_getenv", ("PYPY_GC_MAX_DELTA",), None) + if sys.platform.startswith('linux'): + expect(f, g, "ll_os.ll_os_open", ("/proc/meminfo", 0, 420), + OSError(5232, "xyz")) expect(f, g, "ll_os.ll_os_getenv", ("PYPY_GC_DEBUG",), None) g.close() tail = f.read() From noreply at buildbot.pypy.org Sat Apr 27 15:56:49 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sat, 27 Apr 2013 15:56:49 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Reorganize this document, making it clear that all GCs apart from Message-ID: <20130427135649.DDBD61C138A@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63696:f8dc49da7391 Date: 2013-04-27 15:56 +0200 http://bitbucket.org/pypy/pypy/changeset/f8dc49da7391/ Log: Reorganize this document, making it clear that all GCs apart from minimark have been removed. diff --git a/pypy/doc/garbage_collection.rst b/pypy/doc/garbage_collection.rst --- a/pypy/doc/garbage_collection.rst +++ b/pypy/doc/garbage_collection.rst @@ -5,18 +5,6 @@ .. contents:: -Introduction -============ - -The overview and description of our garbage collection strategy and -framework can be found in the `EU-report on this topic`_. Please refer -to that file for an old, but still more or less accurate, description. -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 ========================================================= @@ -25,122 +13,24 @@ For more details, see the `overview of command line options for translation`_. -The following overview is written in chronological order, so the "best" -GC (which is the default when translating) is the last one below. - .. _`overview of command line options for translation`: config/commandline.html#translation -Mark and Sweep --------------- - -Classical Mark and Sweep collector. Also contained a lot of experimental -and half-unmaintained features. Was removed. - -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`_. - -Mark & Compact GC ------------------ - -Killed in trunk. The following documentation is for historical purposes -only. - -Inspired, at least partially, by Squeak's garbage collector, this is a -single-arena GC in which collection compacts the objects in-place. The -main point of this GC is to save as much memory as possible (to be not -worse than the Semispace), but without the peaks of double memory usage -during collection. - -Unlike the Semispace GC, collection requires a number of passes over the -data. This makes collection quite slower. Future improvements could be -to add a nursery to Mark & Compact in order to mitigate this issue. - -During a collection, we reuse the space in-place if it is still large -enough. If not, we need to allocate a new, larger space, and move the -objects there; however, this move is done chunk by chunk, and chunks are -cleared (i.e. returned to the OS) as soon as they have been moved away. -This means that (from the point of view of the OS) a collection will -never cause an important temporary growth of total memory usage. - -More precisely, a collection is triggered when the space contains more -than N*M bytes, where N is the number of bytes alive after the previous -collection and M is a constant factor, by default 1.5. This guarantees -that the total memory usage of the program never exceeds 1.5 times the -total size of its live objects. - -The objects themselves are quite compact: they are allocated next to -each other in the heap, separated by a GC header of only one word (4 -bytes on 32-bit platforms) and possibly followed by up to 3 bytes of -padding for non-word-sized objects (e.g. strings). There is a small -extra memory usage during collection: an array containing 2 bytes per -surviving object is needed to make a backup of (half of) the surviving -objects' header, in order to let the collector store temporary relation -information in the regular headers. Minimark GC ----------- -This is a simplification and rewrite of the ideas from the Hybrid GC. +This is a simplification and rewrite of the ideas from the old Hybrid GC. It uses a nursery for the young objects, and mark-and-sweep for the old objects. This is a moving GC, but objects may only move once (from the nursery to the old stage). -The main difference with the Hybrid GC is that the mark-and-sweep -objects (the "old stage") are directly handled by the GC's custom -allocator, instead of being handled by malloc() calls. The gain is that +The non-nursery but small objects (the "old stage") are directly handled +by the GC's custom allocator; there are not handled by malloc() calls. +The gain is that it is then possible, during a major collection, to walk through all old generation objects without needing to store a list of pointers to them. -So as a first approximation, when compared to the Hybrid GC, the -Minimark GC saves one word of memory per old object. +(So as a first approximation, when compared to the Hybrid GC, the +Minimark GC saves one word of memory per old object.) There are :ref:`a number of environment variables ` that can be tweaked to influence the @@ -255,4 +145,112 @@ calling `rgc.progress_through_finalizer_queue()`. (This safe point is in the interpreter main loop between two bytecodes, in PyPy.) + +Older GCs of historical interest +================================ + +The overview and description of our garbage collection strategy and +framework can be found in the `EU-report on this topic`_. Please refer +to that file for a description. It is only of historical interest +because all corresponding GCs have been outdated and removed in the +current PyPy repository. + +.. _`EU-report on this topic`: http://codespeak.net/pypy/extradoc/eu-report/D07.1_Massive_Parallelism_and_Translation_Aspects-2007-02-28.pdf + + +Mark and Sweep +-------------- + +Classical Mark and Sweep collector. Also contained a lot of experimental +and half-unmaintained features. + +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. Used to be in ``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. Used to be in +``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, which used to be in ``rpython/memory/gc/hybrid.py``. + +Mark & Compact GC +----------------- + +Inspired, at least partially, by Squeak's garbage collector, this is a +single-arena GC in which collection compacts the objects in-place. The +main point of this GC is to save as much memory as possible (to be not +worse than the Semispace), but without the peaks of double memory usage +during collection. + +Unlike the Semispace GC, collection requires a number of passes over the +data. This makes collection quite slower. Future improvements could be +to add a nursery to Mark & Compact in order to mitigate this issue. + +During a collection, we reuse the space in-place if it is still large +enough. If not, we need to allocate a new, larger space, and move the +objects there; however, this move is done chunk by chunk, and chunks are +cleared (i.e. returned to the OS) as soon as they have been moved away. +This means that (from the point of view of the OS) a collection will +never cause an important temporary growth of total memory usage. + +More precisely, a collection is triggered when the space contains more +than N*M bytes, where N is the number of bytes alive after the previous +collection and M is a constant factor, by default 1.5. This guarantees +that the total memory usage of the program never exceeds 1.5 times the +total size of its live objects. + +The objects themselves are quite compact: they are allocated next to +each other in the heap, separated by a GC header of only one word (4 +bytes on 32-bit platforms) and possibly followed by up to 3 bytes of +padding for non-word-sized objects (e.g. strings). There is a small +extra memory usage during collection: an array containing 2 bytes per +surviving object is needed to make a backup of (half of) the surviving +objects' header, in order to let the collector store temporary relation +information in the regular headers. + + .. include:: _ref.txt From noreply at buildbot.pypy.org Sat Apr 27 16:35:10 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sat, 27 Apr 2013 16:35:10 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Remove this GC from the test Message-ID: <20130427143510.AF8FC1C138A@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63697:808aa174fe40 Date: 2013-04-27 16:13 +0200 http://bitbucket.org/pypy/pypy/changeset/808aa174fe40/ Log: Remove this GC from the test diff --git a/pypy/config/test/test_pypyoption.py b/pypy/config/test/test_pypyoption.py --- a/pypy/config/test/test_pypyoption.py +++ b/pypy/config/test/test_pypyoption.py @@ -24,7 +24,7 @@ def test_frameworkgc(): - for name in ["minimark", "semispace"]: + for name in ["minimark"]: conf = get_pypy_config() assert conf.translation.gctransformer != "framework" conf.translation.gc = name From noreply at buildbot.pypy.org Sat Apr 27 16:35:11 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sat, 27 Apr 2013 16:35:11 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: Fixes Message-ID: <20130427143511.C87C91C138A@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63698:cafd31ba5a2a Date: 2013-04-27 16:34 +0200 http://bitbucket.org/pypy/pypy/changeset/cafd31ba5a2a/ Log: Fixes diff --git a/rpython/jit/backend/llsupport/gc.py b/rpython/jit/backend/llsupport/gc.py --- a/rpython/jit/backend/llsupport/gc.py +++ b/rpython/jit/backend/llsupport/gc.py @@ -236,7 +236,7 @@ arraydescr.lendescr.offset) # ____________________________________________________________ -# All code below is for the hybrid or minimark GC +# All code below is for the minimark GC class GcRootMap_asmgcc(object): is_shadow_stack = False @@ -359,9 +359,8 @@ self.GCClass = None def _check_valid_gc(self): - # we need the hybrid or minimark GC for rgc._make_sure_does_not_move() - # to work. Additionally, 'hybrid' is missing some stuff like - # jit_remember_young_pointer() for now. + # we need the minimark GC for rgc._make_sure_does_not_move() + # to work. if self.gcdescr.config.translation.gc not in ('minimark',): raise NotImplementedError("--gc=%s not implemented with the JIT" % (self.gcdescr.config.translation.gc,)) diff --git a/rpython/jit/backend/x86/test/test_ztranslation_external_exception.py b/rpython/jit/backend/x86/test/test_ztranslation_external_exception.py --- a/rpython/jit/backend/x86/test/test_ztranslation_external_exception.py +++ b/rpython/jit/backend/x86/test/test_ztranslation_external_exception.py @@ -5,7 +5,7 @@ class TestTranslationRemoveTypePtrX86(TranslationRemoveTypePtrTest): def _get_TranslationContext(self): t = TranslationContext() - t.config.translation.gc = DEFL_GC # 'hybrid' or 'minimark' + t.config.translation.gc = DEFL_GC # 'minimark' t.config.translation.gcrootfinder = 'asmgcc' t.config.translation.list_comprehension_operations = True t.config.translation.gcremovetypeptr = True diff --git a/rpython/jit/metainterp/gc.py b/rpython/jit/metainterp/gc.py --- a/rpython/jit/metainterp/gc.py +++ b/rpython/jit/metainterp/gc.py @@ -13,15 +13,6 @@ class GC_boehm(GcDescription): malloc_zero_filled = True -class GC_semispace(GcDescription): - malloc_zero_filled = True - -class GC_generation(GcDescription): - malloc_zero_filled = True - -class GC_hybrid(GcDescription): - malloc_zero_filled = True - class GC_minimark(GcDescription): malloc_zero_filled = True diff --git a/rpython/jit/metainterp/test/test_warmspot.py b/rpython/jit/metainterp/test/test_warmspot.py --- a/rpython/jit/metainterp/test/test_warmspot.py +++ b/rpython/jit/metainterp/test/test_warmspot.py @@ -649,7 +649,7 @@ rtyper = annotate(f, [0]) FakeCPU.rtyper = rtyper translator = rtyper.annotator.translator - translator.config.translation.gc = 'hybrid' + translator.config.translation.gc = 'minimark' cls.desc = WarmRunnerDesc(translator, CPUClass=FakeCPU) cls.FakeDeadFrame = FakeDeadFrame From noreply at buildbot.pypy.org Sat Apr 27 16:52:31 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sat, 27 Apr 2013 16:52:31 +0200 (CEST) Subject: [pypy-commit] pypy gc-del: when not translated, be careful about multiple spaces for Message-ID: <20130427145231.3E2201C026F@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: gc-del Changeset: r63699:b48d17b0ec37 Date: 2013-04-27 16:51 +0200 http://bitbucket.org/pypy/pypy/changeset/b48d17b0ec37/ Log: when not translated, be careful about multiple spaces for the tests: we must not keep calling rgc.finalize_later() for an old object belonging to an old space, when a new space is ready and between bytecodes. diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py --- a/pypy/interpreter/baseobjspace.py +++ b/pypy/interpreter/baseobjspace.py @@ -165,16 +165,6 @@ def _invoke_finalizer(self): # The call-back from rgc.register_finalizer(), cannot be overridden - if not we_are_translated() and hasattr(self, 'space'): - # haaaaaack in case this object is from an older test, to - # prevent it from blocking the future calls of finalizers... - from rpython.rlib import rgc - for x, y in rgc._finalizer_queue: - if getattr(x, 'space', None) not in (self.space, None): - print '-+- skipping finalizer for %r:' % (self,) - print ' self.space = %r' % (id(self.space),) - print ' later_obj.space = %r' % (id(x.space),) - return # there is a pending object with another space self.invoke_finalizer() def invoke_finalizer(self): diff --git a/pypy/interpreter/executioncontext.py b/pypy/interpreter/executioncontext.py --- a/pypy/interpreter/executioncontext.py +++ b/pypy/interpreter/executioncontext.py @@ -2,6 +2,7 @@ from pypy.interpreter.error import OperationError from rpython.rlib.unroll import unrolling_iterable from rpython.rlib import jit +from rpython.rlib.objectmodel import we_are_translated TICK_COUNTER_STEP = 100 @@ -440,14 +441,26 @@ or less anywhere in the middle of code that might not be happy with random app-level code mutating data structures under its feet. """ + _current_space_between_bytecodes = None def __init__(self, space): AsyncAction.__init__(self, space) self.in_user_del_action = False self.finalizers_lock_count = 0 # for use by the gc module self.enabled_at_app_level = True # for use by the gc module + self.fire() def must_be_between_bytecodes(self): + if not we_are_translated(): + # when not translated, be careful about multiple spaces for + # the tests: we must not keep calling rgc.finalize_later() for + # an old object belonging to an old space, when a new space + # is ready and between bytecodes. + if UserDelAction._current_space_between_bytecodes is not None: + space = self.space + if UserDelAction._current_space_between_bytecodes is not space: + return + if self.finalizers_lock_count == 0: if self.in_user_del_action: # we are between bytecodes and finalizers are not disabled, @@ -465,7 +478,12 @@ if not self.in_user_del_action and self.finalizers_lock_count == 0: self.in_user_del_action = True try: + space = executioncontext.space + if not we_are_translated(): + UserDelAction._current_space_between_bytecodes = space rgc.progress_through_finalizer_queue() + if not we_are_translated(): + UserDelAction._current_space_between_bytecodes = None finally: self.in_user_del_action = False From noreply at buildbot.pypy.org Sat Apr 27 21:43:31 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Sat, 27 Apr 2013 21:43:31 +0200 (CEST) Subject: [pypy-commit] pypy default: target .o files to the udir to hopefully avoid clashes between concurrent Message-ID: <20130427194331.2CD811C11C6@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: Changeset: r63700:d41d4710360e Date: 2013-04-27 12:40 -0700 http://bitbucket.org/pypy/pypy/changeset/d41d4710360e/ Log: target .o files to the udir to hopefully avoid clashes between concurrent buildbot runs diff --git a/rpython/translator/platform/__init__.py b/rpython/translator/platform/__init__.py --- a/rpython/translator/platform/__init__.py +++ b/rpython/translator/platform/__init__.py @@ -163,6 +163,15 @@ break return response_file + def _make_o_file(self, cfile, ext): + """Create a .o filename under the udir for a .c file""" + oname = cfile.new(ext=ext) + if oname.relto(udir): + return oname + ofile = udir.join(oname.relto(py.path.local())) + ofile.dirpath().ensure(dir=True) + return ofile + def preprocess_include_dirs(self, include_dirs): if 'PYPY_LOCALBASE' in os.environ: dirs = list(self._preprocess_include_dirs(include_dirs)) diff --git a/rpython/translator/platform/posix.py b/rpython/translator/platform/posix.py --- a/rpython/translator/platform/posix.py +++ b/rpython/translator/platform/posix.py @@ -31,7 +31,7 @@ return list(link_files) def _compile_c_file(self, cc, cfile, compile_args): - oname = cfile.new(ext='o') + oname = self._make_o_file(cfile, ext='o') args = ['-c'] + compile_args + [str(cfile), '-o', str(oname)] self._execute_c_compiler(cc, args, oname, cwd=str(cfile.dirpath())) diff --git a/rpython/translator/platform/windows.py b/rpython/translator/platform/windows.py --- a/rpython/translator/platform/windows.py +++ b/rpython/translator/platform/windows.py @@ -197,7 +197,7 @@ return ["@%s" % (response_file,)] def _compile_c_file(self, cc, cfile, compile_args): - oname = cfile.new(ext='obj') + oname = self._make_o_file(cfile, ext='obj') # notabene: (tismer) # This function may be called for .c but also .asm files. # The c compiler accepts any order of arguments, while From noreply at buildbot.pypy.org Sat Apr 27 21:43:32 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Sat, 27 Apr 2013 21:43:32 +0200 (CEST) Subject: [pypy-commit] pypy py3k: merge default Message-ID: <20130427194332.8FA0D1C138A@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63701:da1f74c2347f Date: 2013-04-27 12:42 -0700 http://bitbucket.org/pypy/pypy/changeset/da1f74c2347f/ Log: merge default diff --git a/rpython/translator/backendopt/merge_if_blocks.py b/rpython/translator/backendopt/merge_if_blocks.py --- a/rpython/translator/backendopt/merge_if_blocks.py +++ b/rpython/translator/backendopt/merge_if_blocks.py @@ -37,7 +37,7 @@ default.args = [get_new_arg(arg) for arg in default.args] for block, case in chain: if case.value in values: - log.WARNING("unreachable code with value %s in graph %s" % ( + log.WARNING("unreachable code with value %r in graph %s" % ( case.value, graph)) continue values[case.value] = True diff --git a/rpython/translator/platform/__init__.py b/rpython/translator/platform/__init__.py --- a/rpython/translator/platform/__init__.py +++ b/rpython/translator/platform/__init__.py @@ -163,6 +163,15 @@ break return response_file + def _make_o_file(self, cfile, ext): + """Create a .o filename under the udir for a .c file""" + oname = cfile.new(ext=ext) + if oname.relto(udir): + return oname + ofile = udir.join(oname.relto(py.path.local())) + ofile.dirpath().ensure(dir=True) + return ofile + def preprocess_include_dirs(self, include_dirs): if 'PYPY_LOCALBASE' in os.environ: dirs = list(self._preprocess_include_dirs(include_dirs)) diff --git a/rpython/translator/platform/posix.py b/rpython/translator/platform/posix.py --- a/rpython/translator/platform/posix.py +++ b/rpython/translator/platform/posix.py @@ -31,7 +31,7 @@ return list(link_files) def _compile_c_file(self, cc, cfile, compile_args): - oname = cfile.new(ext='o') + oname = self._make_o_file(cfile, ext='o') args = ['-c'] + compile_args + [str(cfile), '-o', str(oname)] self._execute_c_compiler(cc, args, oname, cwd=str(cfile.dirpath())) diff --git a/rpython/translator/platform/windows.py b/rpython/translator/platform/windows.py --- a/rpython/translator/platform/windows.py +++ b/rpython/translator/platform/windows.py @@ -197,7 +197,7 @@ return ["@%s" % (response_file,)] def _compile_c_file(self, cc, cfile, compile_args): - oname = cfile.new(ext='obj') + oname = self._make_o_file(cfile, ext='obj') # notabene: (tismer) # This function may be called for .c but also .asm files. # The c compiler accepts any order of arguments, while From noreply at buildbot.pypy.org Sat Apr 27 22:04:30 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Sat, 27 Apr 2013 22:04:30 +0200 (CEST) Subject: [pypy-commit] pypy default: I mean rpythonroot, not py.path.local(), minor cleanup Message-ID: <20130427200430.B60521C138A@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: Changeset: r63702:d50aea69d5ef Date: 2013-04-27 13:03 -0700 http://bitbucket.org/pypy/pypy/changeset/d50aea69d5ef/ Log: I mean rpythonroot, not py.path.local(), minor cleanup diff --git a/rpython/translator/platform/__init__.py b/rpython/translator/platform/__init__.py --- a/rpython/translator/platform/__init__.py +++ b/rpython/translator/platform/__init__.py @@ -4,6 +4,7 @@ from rpython.tool.runsubprocess import run_subprocess as _run_subprocess from rpython.tool.udir import udir +from rpython.tool.version import rpythonroot log = py.log.Producer("platform") @@ -164,11 +165,11 @@ return response_file def _make_o_file(self, cfile, ext): - """Create a .o filename under the udir for a .c file""" - oname = cfile.new(ext=ext) - if oname.relto(udir): - return oname - ofile = udir.join(oname.relto(py.path.local())) + """Create an object file name under the udir for a .c file""" + ofile = cfile.new(ext=ext) + if ofile.relto(udir): + return ofile + ofile = udir.join(ofile.relto(rpythonroot)) ofile.dirpath().ensure(dir=True) return ofile From noreply at buildbot.pypy.org Sat Apr 27 22:04:32 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Sat, 27 Apr 2013 22:04:32 +0200 (CEST) Subject: [pypy-commit] pypy py3k: merge default Message-ID: <20130427200432.0D2751C138A@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63703:8cf10874388f Date: 2013-04-27 13:03 -0700 http://bitbucket.org/pypy/pypy/changeset/8cf10874388f/ Log: merge default diff --git a/rpython/translator/platform/__init__.py b/rpython/translator/platform/__init__.py --- a/rpython/translator/platform/__init__.py +++ b/rpython/translator/platform/__init__.py @@ -4,6 +4,7 @@ from rpython.tool.runsubprocess import run_subprocess as _run_subprocess from rpython.tool.udir import udir +from rpython.tool.version import rpythonroot log = py.log.Producer("platform") @@ -164,11 +165,11 @@ return response_file def _make_o_file(self, cfile, ext): - """Create a .o filename under the udir for a .c file""" - oname = cfile.new(ext=ext) - if oname.relto(udir): - return oname - ofile = udir.join(oname.relto(py.path.local())) + """Create an object file name under the udir for a .c file""" + ofile = cfile.new(ext=ext) + if ofile.relto(udir): + return ofile + ofile = udir.join(ofile.relto(rpythonroot)) ofile.dirpath().ensure(dir=True) return ofile From noreply at buildbot.pypy.org Sat Apr 27 22:13:08 2013 From: noreply at buildbot.pypy.org (alex_gaynor) Date: Sat, 27 Apr 2013 22:13:08 +0200 (CEST) Subject: [pypy-commit] pypy default: Added str.isalnum for strings (it already existed on chars) Message-ID: <20130427201308.1392C1C0149@cobra.cs.uni-duesseldorf.de> Author: Alex Gaynor Branch: Changeset: r63704:2523e1972966 Date: 2013-04-27 13:11 -0700 http://bitbucket.org/pypy/pypy/changeset/2523e1972966/ Log: Added str.isalnum for strings (it already existed on chars) diff --git a/rpython/annotator/unaryop.py b/rpython/annotator/unaryop.py --- a/rpython/annotator/unaryop.py +++ b/rpython/annotator/unaryop.py @@ -541,10 +541,13 @@ class __extend__(SomeString): - def method_isdigit(chr): + def method_isdigit(str): return s_Bool - def method_isalpha(chr): + def method_isalpha(str): + return s_Bool + + def method_isalnum(str): return s_Bool def method_upper(str): diff --git a/rpython/rtyper/rstr.py b/rpython/rtyper/rstr.py --- a/rpython/rtyper/rstr.py +++ b/rpython/rtyper/rstr.py @@ -259,6 +259,12 @@ hop.exception_cannot_occur() return hop.gendirectcall(self.ll.ll_isalpha, v_str) + def rtype_method_isalnum(self, hop): + string_repr = hop.args_r[0].repr + [v_str] = hop.inputargs(string_repr) + hop.exception_cannot_occur() + return hop.gendirectcall(self.ll.ll_isalnum, v_str) + def _list_length_items(self, hop, v_lst, LIST): """Return two Variables containing the length and items of a list. Need to be overriden because it is typesystem-specific.""" @@ -779,6 +785,17 @@ return False return True + def ll_isalnum(s): + from rpython.rtyper.annlowlevel import hlstr + + s = hlstr(s) + if not s: + return False + for ch in s: + if not ch.isalnum(): + return False + return True + def ll_char_isspace(ch): c = ord(ch) return c == 32 or (9 <= c <= 13) # c in (9, 10, 11, 12, 13, 32) diff --git a/rpython/rtyper/test/test_rstr.py b/rpython/rtyper/test/test_rstr.py --- a/rpython/rtyper/test/test_rstr.py +++ b/rpython/rtyper/test/test_rstr.py @@ -156,6 +156,15 @@ for i in xrange(3): assert self.interpret(fn, [i]) == fn(i) + def test_str_isalnum(self): + const = self.const + + def fn(i): + consts = [const(''), const('abc'), const('abc123'), const('abc123!')] + return consts[i].isalnum() + for i in xrange(3): + assert self.interpret(fn, [i]) == fn(i) + def test_char_compare(self): const = self.const res = self.interpret(lambda c1, c2: c1 == c2, [const('a'), From noreply at buildbot.pypy.org Sat Apr 27 22:13:09 2013 From: noreply at buildbot.pypy.org (alex_gaynor) Date: Sat, 27 Apr 2013 22:13:09 +0200 (CEST) Subject: [pypy-commit] pypy default: merged upstream Message-ID: <20130427201309.4441D1C0149@cobra.cs.uni-duesseldorf.de> Author: Alex Gaynor Branch: Changeset: r63705:1d8dd0055879 Date: 2013-04-27 13:12 -0700 http://bitbucket.org/pypy/pypy/changeset/1d8dd0055879/ Log: merged upstream diff --git a/rpython/translator/platform/__init__.py b/rpython/translator/platform/__init__.py --- a/rpython/translator/platform/__init__.py +++ b/rpython/translator/platform/__init__.py @@ -4,6 +4,7 @@ from rpython.tool.runsubprocess import run_subprocess as _run_subprocess from rpython.tool.udir import udir +from rpython.tool.version import rpythonroot log = py.log.Producer("platform") @@ -163,6 +164,15 @@ break return response_file + def _make_o_file(self, cfile, ext): + """Create an object file name under the udir for a .c file""" + ofile = cfile.new(ext=ext) + if ofile.relto(udir): + return ofile + ofile = udir.join(ofile.relto(rpythonroot)) + ofile.dirpath().ensure(dir=True) + return ofile + def preprocess_include_dirs(self, include_dirs): if 'PYPY_LOCALBASE' in os.environ: dirs = list(self._preprocess_include_dirs(include_dirs)) diff --git a/rpython/translator/platform/posix.py b/rpython/translator/platform/posix.py --- a/rpython/translator/platform/posix.py +++ b/rpython/translator/platform/posix.py @@ -31,7 +31,7 @@ return list(link_files) def _compile_c_file(self, cc, cfile, compile_args): - oname = cfile.new(ext='o') + oname = self._make_o_file(cfile, ext='o') args = ['-c'] + compile_args + [str(cfile), '-o', str(oname)] self._execute_c_compiler(cc, args, oname, cwd=str(cfile.dirpath())) diff --git a/rpython/translator/platform/windows.py b/rpython/translator/platform/windows.py --- a/rpython/translator/platform/windows.py +++ b/rpython/translator/platform/windows.py @@ -197,7 +197,7 @@ return ["@%s" % (response_file,)] def _compile_c_file(self, cc, cfile, compile_args): - oname = cfile.new(ext='obj') + oname = self._make_o_file(cfile, ext='obj') # notabene: (tismer) # This function may be called for .c but also .asm files. # The c compiler accepts any order of arguments, while From noreply at buildbot.pypy.org Sat Apr 27 23:45:04 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Sat, 27 Apr 2013 23:45:04 +0200 (CEST) Subject: [pypy-commit] pypy py3k: on CPython, fallback to importing usemodules incase they're extension modules Message-ID: <20130427214504.CD6541C138A@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63706:0d7e97357d2b Date: 2013-04-27 14:44 -0700 http://bitbucket.org/pypy/pypy/changeset/0d7e97357d2b/ Log: on CPython, fallback to importing usemodules incase they're extension modules diff --git a/pypy/tool/pytest/apptest.py b/pypy/tool/pytest/apptest.py --- a/pypy/tool/pytest/apptest.py +++ b/pypy/tool/pytest/apptest.py @@ -131,8 +131,22 @@ usemodules = [str(RENAMED_USEMODULES.get(name, name)) for name in usemodules] check_usemodules = """\ - if not set(%r).issubset(sys.builtin_module_names): - sys.exit(81)""" % usemodules + missing = set(%r).difference(sys.builtin_module_names) + if missing: + if not hasattr(sys, 'pypy_version_info'): + # They may be extension modules on CPython + name = None + for name in missing.copy(): + try: + __import__(name) + except ImportError: + pass + else: + missing.remove(name) + del name + if missing: + sys.exit(81) + del missing""" % usemodules source = list(py.code.Source(target_)) while source[0].startswith(('@py.test.mark.', '@pytest.mark.')): From noreply at buildbot.pypy.org Sat Apr 27 23:55:13 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Sat, 27 Apr 2013 23:55:13 +0200 (CEST) Subject: [pypy-commit] pypy py3k: CO_CONTAINSGLOBALS was killed Message-ID: <20130427215513.B2FE41C3305@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63707:aaeb66e0ab84 Date: 2013-04-27 14:54 -0700 http://bitbucket.org/pypy/pypy/changeset/aaeb66e0ab84/ Log: CO_CONTAINSGLOBALS was killed diff --git a/lib-python/3/test/test_code.py b/lib-python/3/test/test_code.py --- a/lib-python/3/test/test_code.py +++ b/lib-python/3/test/test_code.py @@ -63,7 +63,7 @@ cellvars: () freevars: () nlocals: 1 -flags: 524355 +flags: 67 consts: ('None',) >>> def optimize_away(): From noreply at buildbot.pypy.org Sat Apr 27 23:58:25 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Sat, 27 Apr 2013 23:58:25 +0200 (CEST) Subject: [pypy-commit] pypy py3k: backout 631a86b75fe6: CO_CONTAINSGLOBALS was killed Message-ID: <20130427215825.D5AF11C3368@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63708:3adfaa9d590f Date: 2013-04-27 14:57 -0700 http://bitbucket.org/pypy/pypy/changeset/3adfaa9d590f/ Log: backout 631a86b75fe6: CO_CONTAINSGLOBALS was killed diff --git a/lib-python/3/test/test_dis.py b/lib-python/3/test/test_dis.py --- a/lib-python/3/test/test_dis.py +++ b/lib-python/3/test/test_dis.py @@ -218,7 +218,7 @@ Kw-only arguments: 0 Number of locals: 1 Stack size: 4 -Flags: OPTIMIZED, NEWLOCALS, NOFREE, 0x80000 +Flags: OPTIMIZED, NEWLOCALS, NOFREE Constants: 0: %r 1: '__func__' @@ -285,7 +285,7 @@ Kw-only arguments: 0 Number of locals: 1 Stack size: 8 -Flags: OPTIMIZED, NEWLOCALS, NESTED, 0x80000 +Flags: OPTIMIZED, NEWLOCALS, NESTED Constants: 0: None Names: @@ -307,7 +307,7 @@ Kw-only arguments: 0 Number of locals: 0 Stack size: 2 -Flags: NOFREE, 0x80000 +Flags: NOFREE Constants: 0: 1 Names: @@ -320,7 +320,7 @@ Kw-only arguments: 0 Number of locals: 0 Stack size: 2 -Flags: NOFREE, 0x80000 +Flags: NOFREE Constants: 0: 1 1: None @@ -334,7 +334,7 @@ Kw-only arguments: 0 Number of locals: 0 Stack size: 2 -Flags: NOFREE, 0x80000 +Flags: NOFREE Constants: 0: 0 1: 1 From noreply at buildbot.pypy.org Sun Apr 28 00:03:50 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Sun, 28 Apr 2013 00:03:50 +0200 (CEST) Subject: [pypy-commit] pypy default: apply 95eb1111a1b0 from upstream: py3 compat Message-ID: <20130427220350.30CFD1C3371@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: Changeset: r63709:4a26bf1ffb4f Date: 2013-04-27 15:01 -0700 http://bitbucket.org/pypy/pypy/changeset/4a26bf1ffb4f/ Log: apply 95eb1111a1b0 from upstream: py3 compat diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_verify.py b/pypy/module/test_lib_pypy/cffi_tests/test_verify.py --- a/pypy/module/test_lib_pypy/cffi_tests/test_verify.py +++ b/pypy/module/test_lib_pypy/cffi_tests/test_verify.py @@ -8,7 +8,7 @@ if sys.platform == 'win32': pass # no obvious -Werror equivalent on MSVC elif (sys.platform == 'darwin' and - map(int, os.uname()[2].split('.')) >= [11, 0, 0]): + [int(x) for x in os.uname()[2].split('.')] >= [11, 0, 0]): pass # recent MacOSX come with clang by default, and passing some # flags from the interpreter (-mno-fused-madd) generates a # warning --- which is interpreted as an error with -Werror From noreply at buildbot.pypy.org Sun Apr 28 00:03:51 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Sun, 28 Apr 2013 00:03:51 +0200 (CEST) Subject: [pypy-commit] pypy default: apply e2b9db908b90 from upstream: Message-ID: <20130427220351.91F0B1C3371@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: Changeset: r63710:c4ecb23cac56 Date: 2013-04-27 15:02 -0700 http://bitbucket.org/pypy/pypy/changeset/c4ecb23cac56/ Log: apply e2b9db908b90 from upstream: fix handling w/ py3 hasattr, which only swallows AttributeErrors diff --git a/lib_pypy/cffi/api.py b/lib_pypy/cffi/api.py --- a/lib_pypy/cffi/api.py +++ b/lib_pypy/cffi/api.py @@ -370,7 +370,10 @@ if key in ffi._parser._declarations: tp = ffi._parser._declarations[key] BType = ffi._get_cached_btype(tp) - value = backendlib.load_function(BType, name) + try: + value = backendlib.load_function(BType, name) + except KeyError: + raise AttributeError(name) library.__dict__[name] = value return # diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_function.py b/pypy/module/test_lib_pypy/cffi_tests/test_function.py --- a/pypy/module/test_lib_pypy/cffi_tests/test_function.py +++ b/pypy/module/test_lib_pypy/cffi_tests/test_function.py @@ -333,3 +333,11 @@ assert lib.DD == 6 assert lib.EE == -5 assert lib.FF == -4 + + def test_missing_function(self): + ffi = FFI(backend=self.Backend()) + ffi.cdef(""" + int nonexistent(); + """) + m = ffi.dlopen("m") + assert not hasattr(m, 'nonexistent') From noreply at buildbot.pypy.org Sun Apr 28 00:03:52 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Sun, 28 Apr 2013 00:03:52 +0200 (CEST) Subject: [pypy-commit] pypy py3k: merge default Message-ID: <20130427220352.C56291C3371@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63711:1d8fa565aa74 Date: 2013-04-27 15:03 -0700 http://bitbucket.org/pypy/pypy/changeset/1d8fa565aa74/ Log: merge default diff --git a/lib_pypy/cffi/api.py b/lib_pypy/cffi/api.py --- a/lib_pypy/cffi/api.py +++ b/lib_pypy/cffi/api.py @@ -370,7 +370,10 @@ if key in ffi._parser._declarations: tp = ffi._parser._declarations[key] BType = ffi._get_cached_btype(tp) - value = backendlib.load_function(BType, name) + try: + value = backendlib.load_function(BType, name) + except KeyError: + raise AttributeError(name) library.__dict__[name] = value return # diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_function.py b/pypy/module/test_lib_pypy/cffi_tests/test_function.py --- a/pypy/module/test_lib_pypy/cffi_tests/test_function.py +++ b/pypy/module/test_lib_pypy/cffi_tests/test_function.py @@ -333,3 +333,11 @@ assert lib.DD == 6 assert lib.EE == -5 assert lib.FF == -4 + + def test_missing_function(self): + ffi = FFI(backend=self.Backend()) + ffi.cdef(""" + int nonexistent(); + """) + m = ffi.dlopen("m") + assert not hasattr(m, 'nonexistent') diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_verify.py b/pypy/module/test_lib_pypy/cffi_tests/test_verify.py --- a/pypy/module/test_lib_pypy/cffi_tests/test_verify.py +++ b/pypy/module/test_lib_pypy/cffi_tests/test_verify.py @@ -8,7 +8,7 @@ if sys.platform == 'win32': pass # no obvious -Werror equivalent on MSVC elif (sys.platform == 'darwin' and - map(int, os.uname()[2].split('.')) >= [11, 0, 0]): + [int(x) for x in os.uname()[2].split('.')] >= [11, 0, 0]): pass # recent MacOSX come with clang by default, and passing some # flags from the interpreter (-mno-fused-madd) generates a # warning --- which is interpreted as an error with -Werror diff --git a/rpython/annotator/unaryop.py b/rpython/annotator/unaryop.py --- a/rpython/annotator/unaryop.py +++ b/rpython/annotator/unaryop.py @@ -541,10 +541,13 @@ class __extend__(SomeString): - def method_isdigit(chr): + def method_isdigit(str): return s_Bool - def method_isalpha(chr): + def method_isalpha(str): + return s_Bool + + def method_isalnum(str): return s_Bool def method_upper(str): diff --git a/rpython/rtyper/rstr.py b/rpython/rtyper/rstr.py --- a/rpython/rtyper/rstr.py +++ b/rpython/rtyper/rstr.py @@ -259,6 +259,12 @@ hop.exception_cannot_occur() return hop.gendirectcall(self.ll.ll_isalpha, v_str) + def rtype_method_isalnum(self, hop): + string_repr = hop.args_r[0].repr + [v_str] = hop.inputargs(string_repr) + hop.exception_cannot_occur() + return hop.gendirectcall(self.ll.ll_isalnum, v_str) + def _list_length_items(self, hop, v_lst, LIST): """Return two Variables containing the length and items of a list. Need to be overriden because it is typesystem-specific.""" @@ -779,6 +785,17 @@ return False return True + def ll_isalnum(s): + from rpython.rtyper.annlowlevel import hlstr + + s = hlstr(s) + if not s: + return False + for ch in s: + if not ch.isalnum(): + return False + return True + def ll_char_isspace(ch): c = ord(ch) return c == 32 or (9 <= c <= 13) # c in (9, 10, 11, 12, 13, 32) diff --git a/rpython/rtyper/test/test_rstr.py b/rpython/rtyper/test/test_rstr.py --- a/rpython/rtyper/test/test_rstr.py +++ b/rpython/rtyper/test/test_rstr.py @@ -156,6 +156,15 @@ for i in xrange(3): assert self.interpret(fn, [i]) == fn(i) + def test_str_isalnum(self): + const = self.const + + def fn(i): + consts = [const(''), const('abc'), const('abc123'), const('abc123!')] + return consts[i].isalnum() + for i in xrange(3): + assert self.interpret(fn, [i]) == fn(i) + def test_char_compare(self): const = self.const res = self.interpret(lambda c1, c2: c1 == c2, [const('a'), From noreply at buildbot.pypy.org Sun Apr 28 03:41:17 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Sun, 28 Apr 2013 03:41:17 +0200 (CEST) Subject: [pypy-commit] pypy py3k: kill the deflated test, it's been duplicated in test_zipimport_deflated Message-ID: <20130428014117.07D1D1C138A@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63712:5006546b372b Date: 2013-04-27 18:40 -0700 http://bitbucket.org/pypy/pypy/changeset/5006546b372b/ Log: kill the deflated test, it's been duplicated in test_zipimport_deflated diff --git a/pypy/module/zipimport/test/test_zipimport.py b/pypy/module/zipimport/test/test_zipimport.py --- a/pypy/module/zipimport/test/test_zipimport.py +++ b/pypy/module/zipimport/test/test_zipimport.py @@ -378,20 +378,6 @@ os.remove(filename) -class AppTestZipimportDeflated(AppTestZipimport): - compression = ZIP_DEFLATED - spaceconfig = { - "usemodules": ['zipimport', 'zlib', 'rctime', 'struct', 'binascii'], - } - - def setup_class(cls): - try: - import rpython.rlib.rzlib - except ImportError: - py.test.skip("zlib not available, cannot test compressed zipfiles") - cls.make_class() - - if os.sep != '/': class AppTestNativePathSep(AppTestZipimport): pathsep = os.sep From noreply at buildbot.pypy.org Sun Apr 28 04:09:48 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Sun, 28 Apr 2013 04:09:48 +0200 (CEST) Subject: [pypy-commit] pypy py3k: fix for dict_keys Message-ID: <20130428020948.531AA1C026F@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63713:089b85bb1c93 Date: 2013-04-27 19:09 -0700 http://bitbucket.org/pypy/pypy/changeset/089b85bb1c93/ Log: fix for dict_keys diff --git a/pypy/objspace/std/test/test_proxy_object.py b/pypy/objspace/std/test/test_proxy_object.py --- a/pypy/objspace/std/test/test_proxy_object.py +++ b/pypy/objspace/std/test/test_proxy_object.py @@ -89,7 +89,7 @@ obj = self.proxy(self.A, c.perform) obj.__dict__ = {'x':3} assert obj.x == 3 - assert obj.__dict__.keys() == ['x'] + assert obj.__dict__.keys() == set(['x']) def test_repr(self): a = self.A() From noreply at buildbot.pypy.org Sun Apr 28 04:09:49 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Sun, 28 Apr 2013 04:09:49 +0200 (CEST) Subject: [pypy-commit] pypy py3k: file is dead, kill Message-ID: <20130428020949.A94AA1C026F@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63714:429037cfae60 Date: 2013-04-27 19:09 -0700 http://bitbucket.org/pypy/pypy/changeset/429037cfae60/ Log: file is dead, kill diff --git a/pypy/objspace/std/test/test_proxy_internals.py b/pypy/objspace/std/test/test_proxy_internals.py --- a/pypy/objspace/std/test/test_proxy_internals.py +++ b/pypy/objspace/std/test/test_proxy_internals.py @@ -148,11 +148,3 @@ pass lst = tproxy(A, f) assert get_tproxy_controller(lst) is f - - def test_proxy_file(self): - from __pypy__ import tproxy - - def f(name, *args, **kwds): - pass - - t = tproxy(file, f) From noreply at buildbot.pypy.org Sun Apr 28 12:27:19 2013 From: noreply at buildbot.pypy.org (fijal) Date: Sun, 28 Apr 2013 12:27:19 +0200 (CEST) Subject: [pypy-commit] pypy kill-gen-store-back-in: Progress on frameless-resume Message-ID: <20130428102719.2D5FD1C2FB2@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: kill-gen-store-back-in Changeset: r63715:595d39856824 Date: 2013-04-28 12:26 +0200 http://bitbucket.org/pypy/pypy/changeset/595d39856824/ Log: Progress on frameless-resume diff --git a/rpython/jit/backend/llgraph/runner.py b/rpython/jit/backend/llgraph/runner.py --- a/rpython/jit/backend/llgraph/runner.py +++ b/rpython/jit/backend/llgraph/runner.py @@ -258,6 +258,9 @@ def get_latest_descr(self, deadframe): return deadframe._latest_descr + def get_force_descr(self, deadframe): + xxx + def grab_exc_value(self, deadframe): if deadframe._last_exception is not None: result = deadframe._last_exception.args[1] @@ -271,15 +274,6 @@ assert isinstance(frame, LLFrame) assert frame.forced_deadframe is None values = [] - if frame.force_guard_op is None: - if frame.current_op.opnum == rop.FINISH: - values = [frame.env[arg] for arg in - frame.current_op.getarglist()] - else: - xxx - frame.forced_deadframe = LLDeadFrame( - _getdescr(frame.current_op), values) - return frame.forced_deadframe for box in frame.force_guard_op.getfailargs(): if box is not None: if box is not frame.current_op.result: @@ -602,11 +596,12 @@ _TYPE = llmemory.GCREF def __init__(self, latest_descr, values, - last_exception=None, saved_data=None): + last_exception=None, saved_data=None, force_descr=None): self._latest_descr = latest_descr self._values = values self._last_exception = last_exception self._saved_data = saved_data + self.force_descr = force_descr class LLFrame(object): @@ -712,15 +707,24 @@ values = [value for value in values if value is not None] raise Jump(target, values) else: + if self.force_guard_op is not None: + force_descr = self.force_guard_op.getdescr() + else: + force_descr = None raise ExecutionFinished(LLDeadFrame(descr, values, self.last_exception, - saved_data)) + saved_data, force_descr)) def execute_force_spill(self, _, arg): pass def execute_finish(self, descr, *args): - raise ExecutionFinished(LLDeadFrame(descr, args)) + if self.force_guard_op is not None: + force_descr = self.force_guard_op.getdescr() + else: + force_descr = None + raise ExecutionFinished(LLDeadFrame(descr, args, + force_descr=force_descr)) def execute_label(self, descr, *args): argboxes = self.current_op.getarglist() @@ -782,6 +786,7 @@ if self.forced_deadframe is not None: saved_data = self.forced_deadframe._saved_data self.fail_guard(descr, saved_data) + self.force_guard_op = self.current_op def execute_guard_not_invalidated(self, descr): if self.lltrace.invalid: diff --git a/rpython/jit/backend/model.py b/rpython/jit/backend/model.py --- a/rpython/jit/backend/model.py +++ b/rpython/jit/backend/model.py @@ -101,6 +101,11 @@ """Returns the Descr for the last operation executed by the frame.""" raise NotImplementedError + def get_force_descr(self, deadframe): + """Returns the Descr of last GUARD_NOT_FORCED + """ + raise NotImplementedError + def get_int_value(self, deadframe, index): """Returns the value for the index'th argument to the last executed operation (from 'fail_args' if it was a guard, diff --git a/rpython/jit/metainterp/compile.py b/rpython/jit/metainterp/compile.py --- a/rpython/jit/metainterp/compile.py +++ b/rpython/jit/metainterp/compile.py @@ -85,7 +85,7 @@ # exported_state is clear by optimizeopt when the short preamble is # constrcucted. if that did not happen the label should not show up # in a trace that will be used - assert descr.exported_state is None + assert descr.exported_state is None if not we_are_translated(): op._descr_wref = weakref.ref(op._descr) op.cleardescr() # clear reference to prevent the history.Stats @@ -704,6 +704,10 @@ try: deadframe = cpu.force(token) faildescr = cpu.get_latest_descr(deadframe) + if not isinstance(faildescr, ResumeGuardForcedDescr): + assert faildescr.final_descr # we have to fish from + # guard_exc_descr instead + faildescr = cpu.get_force_descr(deadframe) assert isinstance(faildescr, ResumeGuardForcedDescr) faildescr.handle_async_forcing(deadframe) finally: @@ -819,7 +823,7 @@ # The history contains new operations to attach as the code for the # failure of 'resumekey.guard_op'. - # + # # Attempt to use optimize_bridge(). This may return None in case # it does not work -- i.e. none of the existing old_loop_tokens match. new_trace = create_empty_loop(metainterp) diff --git a/rpython/jit/metainterp/pyjitpl.py b/rpython/jit/metainterp/pyjitpl.py --- a/rpython/jit/metainterp/pyjitpl.py +++ b/rpython/jit/metainterp/pyjitpl.py @@ -314,7 +314,7 @@ opnum = rop.GUARD_TRUE else: opnum = rop.GUARD_FALSE - self.generate_guard(opnum, box) + self.metainterp.generate_guard(opnum, box) if not switchcase: self.pc = target @@ -342,10 +342,12 @@ value = box.nonnull() if value: if not self.metainterp.heapcache.is_class_known(box): - self.generate_guard(rop.GUARD_NONNULL, box, resumepc=orgpc) + self.metainterp.generate_guard(rop.GUARD_NONNULL, box, + resumepc=orgpc) else: if not isinstance(box, Const): - self.generate_guard(rop.GUARD_ISNULL, box, resumepc=orgpc) + self.metainterp.generate_guard(rop.GUARD_ISNULL, box, + resumepc=orgpc) promoted_box = box.constbox() self.metainterp.replace_box(box, promoted_box) return value @@ -680,7 +682,8 @@ descr = QuasiImmutDescr(cpu, box, fielddescr, mutatefielddescr) self.metainterp.history.record(rop.QUASIIMMUT_FIELD, [box], None, descr=descr) - self.generate_guard(rop.GUARD_NOT_INVALIDATED, resumepc=orgpc) + self.metainterp.generate_guard(rop.GUARD_NOT_INVALIDATED, + resumepc=orgpc) @arguments("box", "descr", "orgpc") def opimpl_jit_force_quasi_immutable(self, box, mutatefielddescr, orgpc): @@ -699,7 +702,8 @@ do_force_quasi_immutable(self.metainterp.cpu, box.getref_base(), mutatefielddescr) raise SwitchToBlackhole(Counters.ABORT_FORCE_QUASIIMMUT) - self.generate_guard(rop.GUARD_ISNULL, mutatebox, resumepc=orgpc) + self.metainterp.generate_guard(rop.GUARD_ISNULL, mutatebox, + resumepc=orgpc) def _nonstandard_virtualizable(self, pc, box, fielddescr): # returns True if 'box' is actually not the "standard" virtualizable @@ -950,8 +954,9 @@ promoted_box = resbox.constbox() # This is GUARD_VALUE because GUARD_TRUE assumes the existance # of a label when computing resumepc - self.generate_guard(rop.GUARD_VALUE, resbox, [promoted_box], - resumepc=orgpc) + self.metainterp.generate_guard(rop.GUARD_VALUE, resbox, + [promoted_box], + resumepc=orgpc) self.metainterp.replace_box(box, constbox) return constbox @@ -963,7 +968,8 @@ def opimpl_guard_class(self, box, orgpc): clsbox = self.cls_of_box(box) if not self.metainterp.heapcache.is_class_known(box): - self.generate_guard(rop.GUARD_CLASS, box, [clsbox], resumepc=orgpc) + self.metainterp.generate_guard(rop.GUARD_CLASS, box, [clsbox], + resumepc=orgpc) self.metainterp.heapcache.class_now_known(box) return clsbox @@ -981,7 +987,7 @@ def opimpl_jit_merge_point(self, jdindex, greenboxes, jcposition, redboxes, orgpc): resumedescr = compile.ResumeAtPositionDescr() - self.capture_resumedata(resumedescr, orgpc) + self.metainterp.capture_resumedata(resumedescr, orgpc) any_operation = len(self.metainterp.history.operations) > 0 jitdriver_sd = self.metainterp.staticdata.jitdrivers_sd[jdindex] @@ -1062,8 +1068,8 @@ def opimpl_raise(self, exc_value_box, orgpc): # xxx hack clsbox = self.cls_of_box(exc_value_box) - self.generate_guard(rop.GUARD_CLASS, exc_value_box, [clsbox], - resumepc=orgpc) + self.metainterp.generate_guard(rop.GUARD_CLASS, exc_value_box, [clsbox], + resumepc=orgpc) self.metainterp.class_of_last_exc_is_const = True self.metainterp.last_exc_value_box = exc_value_box self.metainterp.popframe() @@ -1261,43 +1267,6 @@ except ChangeFrame: pass - def generate_guard(self, opnum, box=None, extraargs=[], resumepc=-1): - if isinstance(box, Const): # no need for a guard - return - metainterp = self.metainterp - if box is not None: - moreargs = [box] + extraargs - else: - moreargs = list(extraargs) - metainterp_sd = metainterp.staticdata - if opnum == rop.GUARD_NOT_FORCED: - resumedescr = compile.ResumeGuardForcedDescr(metainterp_sd, - metainterp.jitdriver_sd) - elif opnum == rop.GUARD_NOT_INVALIDATED: - resumedescr = compile.ResumeGuardNotInvalidated() - else: - resumedescr = compile.ResumeGuardDescr() - guard_op = metainterp.history.record(opnum, moreargs, None, - descr=resumedescr) - self.capture_resumedata(resumedescr, resumepc) - self.metainterp.staticdata.profiler.count_ops(opnum, Counters.GUARDS) - # count - metainterp.attach_debug_info(guard_op) - return guard_op - - def capture_resumedata(self, resumedescr, resumepc=-1): - metainterp = self.metainterp - virtualizable_boxes = None - if (metainterp.jitdriver_sd.virtualizable_info is not None or - metainterp.jitdriver_sd.greenfield_info is not None): - virtualizable_boxes = metainterp.virtualizable_boxes - saved_pc = self.pc - if resumepc >= 0: - self.pc = resumepc - resume.capture_resumedata(metainterp.framestack, virtualizable_boxes, - metainterp.virtualref_boxes, resumedescr) - self.pc = saved_pc - def implement_guard_value(self, box, orgpc): """Promote the given Box into a Const. Note: be careful, it's a bit unclear what occurs if a single opcode needs to generate @@ -1306,8 +1275,8 @@ return box # no promotion needed, already a Const else: promoted_box = box.constbox() - self.generate_guard(rop.GUARD_VALUE, box, [promoted_box], - resumepc=orgpc) + self.metainterp.generate_guard(rop.GUARD_VALUE, box, [promoted_box], + resumepc=orgpc) self.metainterp.replace_box(box, promoted_box) return promoted_box @@ -1397,7 +1366,7 @@ if resbox is not None: self.make_result_of_lastop(resbox) self.metainterp.vable_after_residual_call() - self.generate_guard(rop.GUARD_NOT_FORCED, None) + self.metainterp.generate_guard(rop.GUARD_NOT_FORCED, None) if vablebox is not None: self.metainterp.history.record(rop.KEEPALIVE, [vablebox], None) self.metainterp.handle_possible_exception() @@ -1694,11 +1663,6 @@ def finishframe(self, resultbox): # handle a non-exceptional return from the current frame self.last_exc_value_box = None - if len(self.framestack) == 1: - # we should call store_token_in_vable here and not in - # compile_done_with_this_frame, so we have the frame to implement - # guard not forced - self.store_token_in_vable() self.popframe() if self.framestack: if resultbox is not None: @@ -1765,6 +1729,44 @@ print jitcode.name raise AssertionError + def generate_guard(self, opnum, box=None, extraargs=[], resumepc=-1): + if isinstance(box, Const): # no need for a guard + return + if box is not None: + moreargs = [box] + extraargs + else: + moreargs = list(extraargs) + metainterp_sd = self.staticdata + if opnum == rop.GUARD_NOT_FORCED: + resumedescr = compile.ResumeGuardForcedDescr(metainterp_sd, + self.jitdriver_sd) + elif opnum == rop.GUARD_NOT_INVALIDATED: + resumedescr = compile.ResumeGuardNotInvalidated() + else: + resumedescr = compile.ResumeGuardDescr() + guard_op = self.history.record(opnum, moreargs, None, + descr=resumedescr) + self.capture_resumedata(resumedescr, resumepc) + self.staticdata.profiler.count_ops(opnum, Counters.GUARDS) + # count + self.attach_debug_info(guard_op) + return guard_op + + def capture_resumedata(self, resumedescr, resumepc=-1): + virtualizable_boxes = None + if (self.jitdriver_sd.virtualizable_info is not None or + self.jitdriver_sd.greenfield_info is not None): + virtualizable_boxes = self.virtualizable_boxes + if self.framestack: + frame = self.framestack[-1] + saved_pc = frame.pc + if resumepc >= 0: + frame.pc = resumepc + resume.capture_resumedata(self.framestack, virtualizable_boxes, + self.virtualref_boxes, resumedescr) + if self.framestack: + self.framestack[-1].pc = saved_pc + def create_empty_history(self): self.history = history.History() self.staticdata.stats.set_history(self.history) @@ -2234,6 +2236,7 @@ def compile_done_with_this_frame(self, exitbox): # temporarily put a JUMP to a pseudo-loop + self.store_token_in_vable() sd = self.staticdata result_type = self.jitdriver_sd.result_type if result_type == history.VOID: @@ -2268,8 +2271,7 @@ # in case the force_token has not been recorded, record it here # to make sure we know the virtualizable can be broken. However, the # contents of the virtualizable should be generally correct - assert len(self.framestack) == 1 - self.framestack[0].generate_guard(rop.GUARD_NOT_FORCED, None) + self.generate_guard(rop.GUARD_NOT_FORCED, None) self.history.record(rop.FORCE_TOKEN, [], force_token_box) self.history.record(rop.SETFIELD_GC, [vbox, force_token_box], None, descr=vinfo.vable_token_descr) @@ -2414,27 +2416,25 @@ self.virtualref_boxes[i+1] = self.cpu.ts.CONST_NULL def handle_possible_exception(self): - frame = self.framestack[-1] if self.last_exc_value_box is not None: exception_box = self.cpu.ts.cls_of_box(self.last_exc_value_box) - op = frame.generate_guard(rop.GUARD_EXCEPTION, - None, [exception_box]) + op = self.generate_guard(rop.GUARD_EXCEPTION, + None, [exception_box]) assert op is not None op.result = self.last_exc_value_box self.class_of_last_exc_is_const = True self.finishframe_exception() else: - frame.generate_guard(rop.GUARD_NO_EXCEPTION, None, []) + self.generate_guard(rop.GUARD_NO_EXCEPTION, None, []) def handle_possible_overflow_error(self): - frame = self.framestack[-1] if self.last_exc_value_box is not None: - frame.generate_guard(rop.GUARD_OVERFLOW, None) + self.generate_guard(rop.GUARD_OVERFLOW, None) assert isinstance(self.last_exc_value_box, Const) assert self.class_of_last_exc_is_const self.finishframe_exception() else: - frame.generate_guard(rop.GUARD_NO_OVERFLOW, None) + self.generate_guard(rop.GUARD_NO_OVERFLOW, None) def assert_no_exception(self): assert self.last_exc_value_box is None diff --git a/rpython/jit/metainterp/resume.py b/rpython/jit/metainterp/resume.py --- a/rpython/jit/metainterp/resume.py +++ b/rpython/jit/metainterp/resume.py @@ -50,20 +50,24 @@ def capture_resumedata(framestack, virtualizable_boxes, virtualref_boxes, storage): - n = len(framestack)-1 - top = framestack[n] - _ensure_parent_resumedata(framestack, n) - frame_info_list = FrameInfo(top.parent_resumedata_frame_info_list, - top.jitcode, top.pc) - storage.rd_frame_info_list = frame_info_list - snapshot = Snapshot(top.parent_resumedata_snapshot, - top.get_list_of_active_boxes(False)) + n = len(framestack) - 1 if virtualizable_boxes is not None: boxes = virtualref_boxes + virtualizable_boxes else: boxes = virtualref_boxes[:] - snapshot = Snapshot(snapshot, boxes) - storage.rd_snapshot = snapshot + if n >= 0: + top = framestack[n] + _ensure_parent_resumedata(framestack, n) + frame_info_list = FrameInfo(top.parent_resumedata_frame_info_list, + top.jitcode, top.pc) + storage.rd_frame_info_list = frame_info_list + snapshot = Snapshot(top.parent_resumedata_snapshot, + top.get_list_of_active_boxes(False)) + snapshot = Snapshot(snapshot, boxes) + storage.rd_snapshot = snapshot + else: + storage.rd_frame_info_list = None + storage.rd_snapshot = Snapshot(None, boxes) # # The following is equivalent to the RPython-level declaration: @@ -461,7 +465,7 @@ def debug_prints(self): raise NotImplementedError - + class AbstractVirtualStructInfo(AbstractVirtualInfo): def __init__(self, fielddescrs): @@ -547,7 +551,7 @@ class VRawBufferStateInfo(AbstractVirtualInfo): kind = INT - + def __init__(self, size, offsets, descrs): self.size = size self.offsets = offsets From noreply at buildbot.pypy.org Sun Apr 28 12:28:31 2013 From: noreply at buildbot.pypy.org (fijal) Date: Sun, 28 Apr 2013 12:28:31 +0200 (CEST) Subject: [pypy-commit] pypy kill-gen-store-back-in: fix the test Message-ID: <20130428102831.E08D91C2FB2@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: kill-gen-store-back-in Changeset: r63716:9ec8638e50a4 Date: 2013-04-28 12:27 +0200 http://bitbucket.org/pypy/pypy/changeset/9ec8638e50a4/ Log: fix the test diff --git a/rpython/jit/metainterp/test/test_virtualizable.py b/rpython/jit/metainterp/test/test_virtualizable.py --- a/rpython/jit/metainterp/test/test_virtualizable.py +++ b/rpython/jit/metainterp/test/test_virtualizable.py @@ -280,6 +280,7 @@ while m > 0: g(xy2, n) m -= 1 + promote_virtualizable(xy2, 'inst_l2') return xy2.inst_l2[0] assert f(18) == 10360 res = self.meta_interp(f, [18]) From noreply at buildbot.pypy.org Sun Apr 28 12:29:47 2013 From: noreply at buildbot.pypy.org (fijal) Date: Sun, 28 Apr 2013 12:29:47 +0200 (CEST) Subject: [pypy-commit] pypy kill-gen-store-back-in: one more of those Message-ID: <20130428102947.C4FDC1C2FB2@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: kill-gen-store-back-in Changeset: r63717:0273e684b6e7 Date: 2013-04-28 12:29 +0200 http://bitbucket.org/pypy/pypy/changeset/0273e684b6e7/ Log: one more of those diff --git a/rpython/jit/metainterp/test/test_virtualizable.py b/rpython/jit/metainterp/test/test_virtualizable.py --- a/rpython/jit/metainterp/test/test_virtualizable.py +++ b/rpython/jit/metainterp/test/test_virtualizable.py @@ -427,6 +427,7 @@ while m > 0: g(xy2, n) m -= 1 + promote_virtualizable(xy2, 'inst_l2') return xy2.parent.inst_l2[0] assert f(18) == 10360 res = self.meta_interp(f, [18]) From noreply at buildbot.pypy.org Sun Apr 28 12:34:29 2013 From: noreply at buildbot.pypy.org (fijal) Date: Sun, 28 Apr 2013 12:34:29 +0200 (CEST) Subject: [pypy-commit] pypy kill-gen-store-back-in: kill some strange test classes Message-ID: <20130428103429.9FAD91C034A@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: kill-gen-store-back-in Changeset: r63718:0425807a20cf Date: 2013-04-28 12:32 +0200 http://bitbucket.org/pypy/pypy/changeset/0425807a20cf/ Log: kill some strange test classes diff --git a/rpython/jit/metainterp/test/test_virtualizable.py b/rpython/jit/metainterp/test/test_virtualizable.py --- a/rpython/jit/metainterp/test/test_virtualizable.py +++ b/rpython/jit/metainterp/test/test_virtualizable.py @@ -1474,22 +1474,8 @@ }) -class TestOOtype(#ExplicitVirtualizableTests, - ImplicitVirtualizableTests, - OOJitMixin): - pass - class TestLLtype(ExplicitVirtualizableTests, ImplicitVirtualizableTests, LLJitMixin): pass - -class TestLLtype2(ImplicitVirtualizableTests, - LLJitMixin): - def meta_interp(self, *args, **kwds): - class VInfo(object): - pass - - kwds['vinfo_for_tests'] = VInfo() - return LLJitMixin.meta_interp(*args, **kwds) From noreply at buildbot.pypy.org Sun Apr 28 12:46:50 2013 From: noreply at buildbot.pypy.org (arigo) Date: Sun, 28 Apr 2013 12:46:50 +0200 (CEST) Subject: [pypy-commit] buildbot default: Disable nightly mac32. Minime is old enough to not have clang. Message-ID: <20130428104650.8840A1C026F@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r795:87d22fbd77d6 Date: 2013-04-28 12:46 +0200 http://bitbucket.org/pypy/buildbot/changeset/87d22fbd77d6/ Log: Disable nightly mac32. Minime is old enough to not have clang. diff --git a/bot2/pypybuildbot/master.py b/bot2/pypybuildbot/master.py --- a/bot2/pypybuildbot/master.py +++ b/bot2/pypybuildbot/master.py @@ -207,7 +207,7 @@ APPLVLLINUX32, # on tannit32, uses 1 core APPLVLLINUX64, # on allegro64, uses 1 core # other platforms - MACOSX32, # on minime + #MACOSX32, # on minime JITWIN32, # on aurora JITFREEBSD764, # on headless JITFREEBSD864, # on ananke From noreply at buildbot.pypy.org Sun Apr 28 16:37:16 2013 From: noreply at buildbot.pypy.org (amauryfa) Date: Sun, 28 Apr 2013 16:37:16 +0200 (CEST) Subject: [pypy-commit] pypy py3k: Applevel tests now create sys.stdout in line-buffered mode. Message-ID: <20130428143716.6593D1C2FF1@cobra.cs.uni-duesseldorf.de> Author: Amaury Forgeot d'Arc Branch: py3k Changeset: r63720:e06da28508f3 Date: 2013-04-27 12:10 +0200 http://bitbucket.org/pypy/pypy/changeset/e06da28508f3/ Log: Applevel tests now create sys.stdout in line-buffered mode. This should fix some threaded tests, which rely on a print() call to trigger a thread switch. diff --git a/pypy/module/sys/__init__.py b/pypy/module/sys/__init__.py --- a/pypy/module/sys/__init__.py +++ b/pypy/module/sys/__init__.py @@ -112,17 +112,21 @@ space.setitem(self.w_dict, space.wrap("dllhandle"), w_handle) if not space.config.translating: - # Install standard streams for tests that don't call app_main + # Install standard streams for tests that don't call app_main. + # Always use line buffering, even for tests that capture + # standard descriptors. space.appexec([], """(): import sys, io sys.stdin = sys.__stdin__ = io.open(0, "r", encoding="ascii", closefd=False) sys.stdin.buffer.raw.name = "" sys.stdout = sys.__stdout__ = io.open(1, "w", encoding="ascii", + buffering=1, closefd=False) sys.stdout.buffer.raw.name = "" sys.stderr = sys.__stderr__ = io.open(2, "w", encoding="ascii", errors="backslashreplace", + buffering=1, closefd=False) sys.stderr.buffer.raw.name = "" """) From noreply at buildbot.pypy.org Sun Apr 28 16:37:15 2013 From: noreply at buildbot.pypy.org (amauryfa) Date: Sun, 28 Apr 2013 16:37:15 +0200 (CEST) Subject: [pypy-commit] pypy py3k: Fix _cffi_backendi/test/test_translation.py Message-ID: <20130428143715.032E01C2FF0@cobra.cs.uni-duesseldorf.de> Author: Amaury Forgeot d'Arc Branch: py3k Changeset: r63719:0aea4b24a65c Date: 2013-04-27 01:54 +0200 http://bitbucket.org/pypy/pypy/changeset/0aea4b24a65c/ Log: Fix _cffi_backendi/test/test_translation.py diff --git a/pypy/objspace/fake/objspace.py b/pypy/objspace/fake/objspace.py --- a/pypy/objspace/fake/objspace.py +++ b/pypy/objspace/fake/objspace.py @@ -108,6 +108,12 @@ self._seen_extras = [] ObjSpace.__init__(self, config=config) + # Be sure to annotate W_SliceObject constructor. + # In Python2, this is triggered by W_InstanceObject.__getslice__. + def build_slice(): + self.newslice(self.w_None, self.w_None, self.w_None) + self._seen_extras.append(build_slice) + def float_w(self, w_obj): is_root(w_obj) return NonConstant(42.5) From noreply at buildbot.pypy.org Sun Apr 28 16:37:17 2013 From: noreply at buildbot.pypy.org (amauryfa) Date: Sun, 28 Apr 2013 16:37:17 +0200 (CEST) Subject: [pypy-commit] pypy py3k: Fix parsing of complex literals: Message-ID: <20130428143717.AE2541C2FF3@cobra.cs.uni-duesseldorf.de> Author: Amaury Forgeot d'Arc Branch: py3k Changeset: r63721:b76887f8dc72 Date: 2013-04-28 16:35 +0200 http://bitbucket.org/pypy/pypy/changeset/b76887f8dc72/ Log: Fix parsing of complex literals: - complex('-1j') is parsed as 0-1j - unary minus should not be parsed with the numeric literal: -1 is parsed as -(1), -1j is parsed as -(1j) - Unary minus will be constant-folded, but as an optimization pass on the tree. Yes, this means that -1j is now (-0-1j) and complex(-1j) is not identical to complex('-1j'). Even more obscure: >>> -1j (-0-1j) >>> (-0-1j) -1j diff --git a/pypy/interpreter/astcompiler/astbuilder.py b/pypy/interpreter/astcompiler/astbuilder.py --- a/pypy/interpreter/astcompiler/astbuilder.py +++ b/pypy/interpreter/astcompiler/astbuilder.py @@ -902,19 +902,6 @@ return result def handle_factor(self, factor_node): - # Fold '-' on constant numbers. - if factor_node.children[0].type == tokens.MINUS and \ - len(factor_node.children) == 2: - factor = factor_node.children[1] - if factor.type == syms.factor and len(factor.children) == 1: - power = factor.children[0] - if power.type == syms.power and len(power.children) == 1: - atom = power.children[0] - if atom.type == syms.atom and \ - atom.children[0].type == tokens.NUMBER: - num = atom.children[0] - num.value = "-" + num.value - return self.handle_atom(atom) expr = self.handle_expr(factor_node.children[1]) op_type = factor_node.children[0].type if op_type == tokens.PLUS: diff --git a/pypy/interpreter/astcompiler/test/test_astbuilder.py b/pypy/interpreter/astcompiler/test/test_astbuilder.py --- a/pypy/interpreter/astcompiler/test/test_astbuilder.py +++ b/pypy/interpreter/astcompiler/test/test_astbuilder.py @@ -1200,11 +1200,6 @@ assert space.eq_w(get_num("0X53"), space.wrap(0x53)) assert space.eq_w(get_num("0"), space.wrap(0)) assert space.eq_w(get_num("00000"), space.wrap(0)) - assert space.eq_w(get_num("-3"), space.wrap(-3)) - assert space.eq_w(get_num("-0"), space.wrap(0)) - assert space.eq_w(get_num("-0xAAAAAA"), space.wrap(-0xAAAAAAL)) - n = get_num(str(-sys.maxint - 1)) - assert space.isinstance_w(n, space.w_int) for num in ("0o53", "0O53", "0o0000053", "0O00053"): assert space.eq_w(get_num(num), space.wrap(053)) for num in ("0b00101", "0B00101", "0b101", "0B101"): diff --git a/pypy/interpreter/test/test_compiler.py b/pypy/interpreter/test/test_compiler.py --- a/pypy/interpreter/test/test_compiler.py +++ b/pypy/interpreter/test/test_compiler.py @@ -741,9 +741,9 @@ import math code = compile("x = -0.0; y = 0.0", "", "exec") consts = code.co_consts - x, y, z = consts - assert isinstance(x, float) and isinstance(y, float) - assert math.copysign(1, x) != math.copysign(1, y) + x, y = consts + assert isinstance(x, float) + assert math.copysign(1, x) == 1 ns = {} exec("z1, z2 = 0j, -0j", ns) assert math.atan2(ns["z1"].imag, -1.) == math.atan2(0., -1.) diff --git a/pypy/objspace/std/complextype.py b/pypy/objspace/std/complextype.py --- a/pypy/objspace/std/complextype.py +++ b/pypy/objspace/std/complextype.py @@ -71,10 +71,7 @@ imagpart = '-1.0' else: imagpart = s[realstart:newstop] - if imagpart[0] == '-': - return '-0.0', imagpart - else: - return '0.0', imagpart + return '0.0', imagpart else: return s[realstart:realstop], '0.0' diff --git a/pypy/objspace/std/test/test_complexobject.py b/pypy/objspace/std/test/test_complexobject.py --- a/pypy/objspace/std/test/test_complexobject.py +++ b/pypy/objspace/std/test/test_complexobject.py @@ -44,7 +44,7 @@ test_cparse('(1-6j)', '1', '-6') test_cparse(' ( +3.14-6J )', '+3.14', '-6') test_cparse(' +J', '0.0', '1.0') - test_cparse(' -J', '-0.0', '-1.0') + test_cparse(' -J', '0.0', '-1.0') def test_unpackcomplex(self): space = self.space @@ -135,6 +135,23 @@ else: return a - b < eps + def w_floats_identical(self, x, y): + from math import isnan, copysign + msg = 'floats {!r} and {!r} are not identical' + + if isnan(x) or isnan(y): + if isnan(x) and isnan(y): + return + elif x == y: + if x != 0.0: + return + # both zero; check that signs match + elif copysign(1.0, x) == copysign(1.0, y): + return + else: + msg += ': zeros have different signs' + assert False, msg.format(x, y) + def test_div(self): from random import random # XXX this test passed but took waaaaay to long @@ -420,6 +437,36 @@ assert repr(complex(1e200*1e200)) == '(inf+0j)' assert repr(complex(1,-float("nan"))) == '(1+nanj)' + def test_repr_roundtrip(self): + # Copied from CPython + INF = float("inf") + NAN = float("nan") + vals = [0.0, 1e-500, 1e-315, 1e-200, 0.0123, 3.1415, 1e50, INF, NAN] + vals += [-v for v in vals] + + # complex(repr(z)) should recover z exactly, even for complex + # numbers involving an infinity, nan, or negative zero + for x in vals: + for y in vals: + z = complex(x, y) + roundtrip = complex(repr(z)) + self.floats_identical(z.real, roundtrip.real) + self.floats_identical(z.imag, roundtrip.imag) + + # if we predefine some constants, then eval(repr(z)) should + # also work, except that it might change the sign of zeros + inf, nan = float('inf'), float('nan') + infj, nanj = complex(0.0, inf), complex(0.0, nan) + for x in vals: + for y in vals: + z = complex(x, y) + roundtrip = eval(repr(z)) + # adding 0.0 has no effect beside changing -0.0 to 0.0 + self.floats_identical(0.0 + z.real, + 0.0 + roundtrip.real) + self.floats_identical(0.0 + z.imag, + 0.0 + roundtrip.imag) + def test_neg(self): assert -(1+6j) == -1-6j From noreply at buildbot.pypy.org Sun Apr 28 18:00:49 2013 From: noreply at buildbot.pypy.org (amauryfa) Date: Sun, 28 Apr 2013 18:00:49 +0200 (CEST) Subject: [pypy-commit] pypy py3k: with pypy int("\ud800") does not raise UnicodeError, Message-ID: <20130428160049.C35541C2FEF@cobra.cs.uni-duesseldorf.de> Author: Amaury Forgeot d'Arc Branch: py3k Changeset: r63722:85b7df90925f Date: 2013-04-28 17:00 +0200 http://bitbucket.org/pypy/pypy/changeset/85b7df90925f/ Log: with pypy int("\ud800") does not raise UnicodeError, because no utf8 conversion is needed. ValueError is just as good. diff --git a/lib-python/3/test/test_float.py b/lib-python/3/test/test_float.py --- a/lib-python/3/test/test_float.py +++ b/lib-python/3/test/test_float.py @@ -42,7 +42,7 @@ self.assertRaises(ValueError, float, b"-") self.assertRaises(TypeError, float, {}) # Lone surrogate - self.assertRaises(UnicodeEncodeError, float, '\uD8F0') + self.assertRaises((UnicodeEncodeError, ValueError), float, '\uD8F0') # check that we don't accept alternate exponent markers self.assertRaises(ValueError, float, "-1.7d29") self.assertRaises(ValueError, float, "3D-14") diff --git a/lib-python/3/test/test_unicode.py b/lib-python/3/test/test_unicode.py --- a/lib-python/3/test/test_unicode.py +++ b/lib-python/3/test/test_unicode.py @@ -1354,12 +1354,12 @@ self.assertRaises(TypeError, "hello".encode, 42, 42, 42) # Error handling (lone surrogate in PyUnicode_TransformDecimalToASCII()) - self.assertRaises(UnicodeError, int, "\ud800") - self.assertRaises(UnicodeError, int, "\udf00") - self.assertRaises(UnicodeError, float, "\ud800") - self.assertRaises(UnicodeError, float, "\udf00") - self.assertRaises(UnicodeError, complex, "\ud800") - self.assertRaises(UnicodeError, complex, "\udf00") + self.assertRaises((UnicodeError, ValueError), int, "\ud800") + self.assertRaises((UnicodeError, ValueError), int, "\udf00") + self.assertRaises((UnicodeError, ValueError), float, "\ud800") + self.assertRaises((UnicodeError, ValueError), float, "\udf00") + self.assertRaises((UnicodeError, ValueError), complex, "\ud800") + self.assertRaises((UnicodeError, ValueError), complex, "\udf00") def test_codecs(self): # Encoding From noreply at buildbot.pypy.org Sun Apr 28 18:00:51 2013 From: noreply at buildbot.pypy.org (amauryfa) Date: Sun, 28 Apr 2013 18:00:51 +0200 (CEST) Subject: [pypy-commit] pypy py3k: Fix uninitialized variable in _testcapi. Message-ID: <20130428160051.02BA01C2FEF@cobra.cs.uni-duesseldorf.de> Author: Amaury Forgeot d'Arc Branch: py3k Changeset: r63723:96314c1d3a60 Date: 2013-04-28 17:17 +0200 http://bitbucket.org/pypy/pypy/changeset/96314c1d3a60/ Log: Fix uninitialized variable in _testcapi. Should be backported to CPython... diff --git a/lib_pypy/_testcapimodule.c b/lib_pypy/_testcapimodule.c --- a/lib_pypy/_testcapimodule.c +++ b/lib_pypy/_testcapimodule.c @@ -1479,7 +1479,7 @@ unicode_transformdecimaltoascii(PyObject *self, PyObject *args) { Py_UNICODE *unicode; - Py_ssize_t length; + Py_ssize_t length = 0; if (!PyArg_ParseTuple(args, "u#|s", &unicode, &length)) return NULL; return PyUnicode_TransformDecimalToASCII(unicode, length); From noreply at buildbot.pypy.org Sun Apr 28 20:33:06 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Sun, 28 Apr 2013 20:33:06 +0200 (CEST) Subject: [pypy-commit] pypy py3k: this assert seems no longer needed, remove it to allow proxy tbs Message-ID: <20130428183306.C915C1C2FEE@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63724:769ebfa2b7f5 Date: 2013-04-28 11:32 -0700 http://bitbucket.org/pypy/pypy/changeset/769ebfa2b7f5/ Log: this assert seems no longer needed, remove it to allow proxy tbs diff --git a/pypy/interpreter/error.py b/pypy/interpreter/error.py --- a/pypy/interpreter/error.py +++ b/pypy/interpreter/error.py @@ -345,8 +345,6 @@ only if the exception really propagates out of this frame, by executioncontext.leave() being called with got_exception=True. """ - from pypy.interpreter.pytraceback import PyTraceback - assert isinstance(traceback, PyTraceback) self._application_traceback = traceback # ____________________________________________________________ From noreply at buildbot.pypy.org Sun Apr 28 20:33:08 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Sun, 28 Apr 2013 20:33:08 +0200 (CEST) Subject: [pypy-commit] pypy py3k: we get an additional frame here on py3 Message-ID: <20130428183308.30E571C2FF1@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63725:3f9b9be002c0 Date: 2013-04-28 11:32 -0700 http://bitbucket.org/pypy/pypy/changeset/3f9b9be002c0/ Log: we get an additional frame here on py3 diff --git a/pypy/objspace/std/test/test_proxy_internals.py b/pypy/objspace/std/test/test_proxy_internals.py --- a/pypy/objspace/std/test/test_proxy_internals.py +++ b/pypy/objspace/std/test/test_proxy_internals.py @@ -136,7 +136,7 @@ except: e = sys.exc_info() - assert traceback.format_tb(last_tb) == traceback.format_tb(e[2]) + assert traceback.format_tb(last_tb) == traceback.format_tb(e[2])[1:] def test_proxy_get(self): from __pypy__ import tproxy, get_tproxy_controller From noreply at buildbot.pypy.org Sun Apr 28 20:34:27 2013 From: noreply at buildbot.pypy.org (fijal) Date: Sun, 28 Apr 2013 20:34:27 +0200 (CEST) Subject: [pypy-commit] pypy kill-gen-store-back-in: oops Message-ID: <20130428183427.85FC21C2FEE@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: kill-gen-store-back-in Changeset: r63726:47ff1f11d5f0 Date: 2013-04-28 20:22 +0200 http://bitbucket.org/pypy/pypy/changeset/47ff1f11d5f0/ Log: oops diff --git a/rpython/jit/metainterp/test/test_virtualizable.py b/rpython/jit/metainterp/test/test_virtualizable.py --- a/rpython/jit/metainterp/test/test_virtualizable.py +++ b/rpython/jit/metainterp/test/test_virtualizable.py @@ -427,8 +427,9 @@ while m > 0: g(xy2, n) m -= 1 - promote_virtualizable(xy2, 'inst_l2') - return xy2.parent.inst_l2[0] + parent = xy2.parent + promote_virtualizable(parent, 'inst_l2') + return parent.inst_l2[0] assert f(18) == 10360 res = self.meta_interp(f, [18]) assert res == 10360 From noreply at buildbot.pypy.org Sun Apr 28 20:34:28 2013 From: noreply at buildbot.pypy.org (fijal) Date: Sun, 28 Apr 2013 20:34:28 +0200 (CEST) Subject: [pypy-commit] pypy kill-gen-store-back-in: I think enough to pass test_virtualizable Message-ID: <20130428183428.CCE0F1C2FEE@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: kill-gen-store-back-in Changeset: r63727:0e2f25bbead4 Date: 2013-04-28 20:33 +0200 http://bitbucket.org/pypy/pypy/changeset/0e2f25bbead4/ Log: I think enough to pass test_virtualizable diff --git a/rpython/jit/metainterp/compile.py b/rpython/jit/metainterp/compile.py --- a/rpython/jit/metainterp/compile.py +++ b/rpython/jit/metainterp/compile.py @@ -714,12 +714,18 @@ rstack._stack_criticalcode_stop() def handle_async_forcing(self, deadframe): - from rpython.jit.metainterp.resume import force_from_resumedata + from rpython.jit.metainterp.resume import (force_from_resumedata, + AlreadyForced) metainterp_sd = self.metainterp_sd vinfo = self.jitdriver_sd.virtualizable_info ginfo = self.jitdriver_sd.greenfield_info - all_virtuals = force_from_resumedata(metainterp_sd, self, deadframe, - vinfo, ginfo) + # there is some chance that this is already forced. In this case + # the virtualizable would have a token = NULL + try: + all_virtuals = force_from_resumedata(metainterp_sd, self, deadframe, + vinfo, ginfo) + except AlreadyForced: + return # The virtualizable data was stored on the real virtualizable above. # Handle all_virtuals: keep them for later blackholing from the # future failure of the GUARD_NOT_FORCED diff --git a/rpython/jit/metainterp/pyjitpl.py b/rpython/jit/metainterp/pyjitpl.py --- a/rpython/jit/metainterp/pyjitpl.py +++ b/rpython/jit/metainterp/pyjitpl.py @@ -2461,12 +2461,13 @@ if vinfo is not None: self.virtualizable_boxes = virtualizable_boxes # just jumped away from assembler (case 4 in the comment in - # virtualizable.py) into tracing (case 2); check that vable_token - # is and stays NULL. Note the call to reset_vable_token() in - # warmstate.py. + # virtualizable.py) into tracing (case 2); if we get the + # virtualizable from somewhere strange it might not be forced, + # do it virtualizable_box = self.virtualizable_boxes[-1] virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box) - assert not vinfo.is_token_nonnull_gcref(virtualizable) + if vinfo.is_token_nonnull_gcref(virtualizable): + vinfo.clear_vable_token(virtualizable) # fill the virtualizable with the local boxes self.synchronize_virtualizable() # diff --git a/rpython/jit/metainterp/resume.py b/rpython/jit/metainterp/resume.py --- a/rpython/jit/metainterp/resume.py +++ b/rpython/jit/metainterp/resume.py @@ -16,6 +16,9 @@ # because it needs to support optimize.py which encodes virtuals with # arbitrary cycles and also to compress the information +class AlreadyForced(Exception): + pass + class Snapshot(object): __slots__ = ('prev', 'boxes') @@ -1215,14 +1218,16 @@ virtualizable = self.decode_ref(numb.nums[index]) if self.resume_after_guard_not_forced == 1: # in the middle of handle_async_forcing() - assert vinfo.is_token_nonnull_gcref(virtualizable) + if not vinfo.is_token_nonnull_gcref(virtualizable): + raise AlreadyForced vinfo.reset_token_gcref(virtualizable) else: # just jumped away from assembler (case 4 in the comment in - # virtualizable.py) into tracing (case 2); check that vable_token - # is and stays NULL. Note the call to reset_vable_token() in - # warmstate.py. - assert not vinfo.is_token_nonnull_gcref(virtualizable) + # virtualizable.py) into tracing (case 2); we might have non-forced + # virtualizable here, in case it comes from somewhere strange, just + # force it + if vinfo.is_token_nonnull_gcref(virtualizable): + vinfo.clear_vable_token(virtualizable) return vinfo.write_from_resume_data_partial(virtualizable, self, numb) def load_value_of_type(self, TYPE, tagged): From noreply at buildbot.pypy.org Sun Apr 28 21:11:08 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Sun, 28 Apr 2013 21:11:08 +0200 (CEST) Subject: [pypy-commit] pypy py3k: we can't always pass in arbitrary unicode values when the filesystemencoding is Message-ID: <20130428191108.85AD21C0246@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63728:d531b90c42b5 Date: 2013-04-28 12:10 -0700 http://bitbucket.org/pypy/pypy/changeset/d531b90c42b5/ Log: we can't always pass in arbitrary unicode values when the filesystemencoding is ascii or similar diff --git a/pypy/module/posix/test/test_posix2.py b/pypy/module/posix/test/test_posix2.py --- a/pypy/module/posix/test/test_posix2.py +++ b/pypy/module/posix/test/test_posix2.py @@ -302,8 +302,14 @@ assert expected in result def test_undecodable_filename(self): + import sys posix = self.posix - assert posix.access('caf\xe9', posix.R_OK) is False + try: + 'caf\xe9'.encode(sys.getfilesystemencoding(), 'surrogateescape') + except UnicodeEncodeError: + pass # probably ascii + else: + assert posix.access('caf\xe9', posix.R_OK) is False assert posix.access(b'caf\xe9', posix.R_OK) is False assert posix.access('caf\udcc0', posix.R_OK) is False assert posix.access(b'caf\xc3', posix.R_OK) is False @@ -959,8 +965,18 @@ @py.test.mark.dont_track_allocations('putenv intentionally keeps strings alive') def test_environ_nonascii(self): + import sys + name, value = 'PYPY_TEST_日本', 'foobar日本' + if not sys.platform == 'win32': + fsencoding = sys.getfilesystemencoding() + for s in name, value: + try: + s.encode(fsencoding, 'surrogateescape') + except UnicodeEncodeError: + skip("Requires %s.encode(sys.getfilesystemencoding(), " + "'surogateescape') to succeed (or win32)" % ascii(s)) + os = self.os - name, value = 'PYPY_TEST_日本', 'foobar日本' os.environ[name] = value assert os.environ[name] == value assert os.getenv(name) == value From noreply at buildbot.pypy.org Sun Apr 28 22:32:19 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Sun, 28 Apr 2013 22:32:19 +0200 (CEST) Subject: [pypy-commit] pypy py3k: don't hardcode maxsize Message-ID: <20130428203219.2903E1C0246@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63737:573f90ac6468 Date: 2013-04-28 13:29 -0700 http://bitbucket.org/pypy/pypy/changeset/573f90ac6468/ Log: don't hardcode maxsize diff --git a/pypy/module/cpyext/test/test_longobject.py b/pypy/module/cpyext/test/test_longobject.py --- a/pypy/module/cpyext/test/test_longobject.py +++ b/pypy/module/cpyext/test/test_longobject.py @@ -125,7 +125,7 @@ def test_as_ulongmask(self, space, api): assert api.PyLong_AsUnsignedLongMask( - space.wrap(sys.maxsize * 2 + 1)) == 18446744073709551615 + space.wrap(sys.maxsize * 2 + 1)) == sys.maxsize * 2 + 1 assert api.PyLong_AsUnsignedLongMask( space.wrap(sys.maxsize * 2 + 2)) == 0 From noreply at buildbot.pypy.org Sun Apr 28 22:32:20 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Sun, 28 Apr 2013 22:32:20 +0200 (CEST) Subject: [pypy-commit] pypy py3k: use a surrogateescape'd test that will actually work w/ an ascii fs encoding Message-ID: <20130428203220.7EAA41C034A@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63738:f003e101612d Date: 2013-04-28 13:31 -0700 http://bitbucket.org/pypy/pypy/changeset/f003e101612d/ Log: use a surrogateescape'd test that will actually work w/ an ascii fs encoding diff --git a/pypy/module/cpyext/test/test_unicodeobject.py b/pypy/module/cpyext/test/test_unicodeobject.py --- a/pypy/module/cpyext/test/test_unicodeobject.py +++ b/pypy/module/cpyext/test/test_unicodeobject.py @@ -297,7 +297,7 @@ assert s == "12ሴ" def test_encode_fsdefault(self, space, api): - w_u = space.wrap(u'sp�m') + w_u = space.wrap(u'sp\udcc3\udca4m') w_s = api.PyUnicode_EncodeFSDefault(w_u) with rffi.scoped_str2charp(space.str_w(w_s)) as encoded: w_decoded = api.PyUnicode_DecodeFSDefaultAndSize(encoded, space.len_w(w_s)) From noreply at buildbot.pypy.org Sun Apr 28 22:46:17 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Sun, 28 Apr 2013 22:46:17 +0200 (CEST) Subject: [pypy-commit] pypy py3k: forgot these along w/ 680b7dc2e00a Message-ID: <20130428204617.81C121C034A@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63739:1eeb42a109e1 Date: 2013-04-28 13:45 -0700 http://bitbucket.org/pypy/pypy/changeset/1eeb42a109e1/ Log: forgot these along w/ 680b7dc2e00a diff --git a/pypy/interpreter/test2/mypackage/__init__.py b/pypy/interpreter/test2/mypackage/__init__.py new file mode 100644 --- /dev/null +++ b/pypy/interpreter/test2/mypackage/__init__.py @@ -0,0 +1,2 @@ +import sys +print("__init__ argv:", sys.argv) diff --git a/pypy/interpreter/test2/mypackage/__main__.py b/pypy/interpreter/test2/mypackage/__main__.py new file mode 100644 --- /dev/null +++ b/pypy/interpreter/test2/mypackage/__main__.py @@ -0,0 +1,2 @@ +import sys +print("__main__ argv:", sys.argv) From noreply at buildbot.pypy.org Mon Apr 29 01:05:13 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Mon, 29 Apr 2013 01:05:13 +0200 (CEST) Subject: [pypy-commit] pypy py3k: fix test_c.test_wchar, re-decode the repr data on the way back out Message-ID: <20130428230513.956EC1C2FF0@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63740:b6db8a247eae Date: 2013-04-28 16:04 -0700 http://bitbucket.org/pypy/pypy/changeset/b6db8a247eae/ Log: fix test_c.test_wchar, re-decode the repr data on the way back out diff --git a/pypy/module/_cffi_backend/cdataobj.py b/pypy/module/_cffi_backend/cdataobj.py --- a/pypy/module/_cffi_backend/cdataobj.py +++ b/pypy/module/_cffi_backend/cdataobj.py @@ -42,16 +42,16 @@ def repr(self): extra2 = self._repr_extra() - extra1 = '' + extra1 = u'' if not isinstance(self, W_CDataNewOwning): # it's slightly confusing to get "" # because the struct foo is not owned. Trying to make it # clearer, write in this case "". from pypy.module._cffi_backend import ctypestruct if isinstance(self.ctype, ctypestruct.W_CTypeStructOrUnion): - extra1 = ' &' - return self.space.wrap("" % ( - self.ctype.name, extra1, extra2)) + extra1 = u' &' + return self.space.wrap(u"" % ( + self.ctype.name.decode('utf-8'), extra1, extra2.decode('utf-8'))) def bool(self): return self.space.wrap(bool(self._cdata)) From noreply at buildbot.pypy.org Mon Apr 29 01:05:14 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Mon, 29 Apr 2013 01:05:14 +0200 (CEST) Subject: [pypy-commit] pypy py3k: hack hack hack around appdirect failures Message-ID: <20130428230514.E8D331C2FF0@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63741:7ce5e8dbcb61 Date: 2013-04-28 16:04 -0700 http://bitbucket.org/pypy/pypy/changeset/7ce5e8dbcb61/ Log: hack hack hack around appdirect failures diff --git a/pypy/module/imp/test/test_import.py b/pypy/module/imp/test/test_import.py --- a/pypy/module/imp/test/test_import.py +++ b/pypy/module/imp/test/test_import.py @@ -167,7 +167,10 @@ def _setup(cls): space = cls.space dn = setup_directory_structure(cls) - return space.appexec([space.wrap(dn)], """ + return _setup_path(space, dn) + +def _setup_path(space, path): + return space.appexec([space.wrap(path)], """ (dn): import sys path = list(sys.path) @@ -573,9 +576,8 @@ import time time.sleep(1) - f = open(test_reload.__file__, "w") - f.write("def test():\n raise NotImplementedError\n") - f.close() + with open(test_reload.__file__, "w") as f: + f.write("def test():\n raise NotImplementedError\n") imp.reload(test_reload) try: test_reload.test() @@ -587,6 +589,10 @@ import os os.unlink(test_reload.__file__) + # restore it for later tests + with open(test_reload.__file__, "w") as f: + f.write("def test():\n raise ValueError\n") + def test_reload_failing(self): import test_reload import time, imp @@ -1149,11 +1155,9 @@ def setup_class(cls): mydir = os.path.dirname(__file__) cls.w_hooktest = cls.space.wrap(os.path.join(mydir, 'hooktest')) - cls.space.appexec([cls.space.wrap(mydir)], """ - (mydir): - import sys - sys.path.append(mydir) - + cls.w_saved_modules = _setup_path(cls.space, mydir) + cls.space.appexec([], """ + (): # Obscure: manually bootstrap the utf-8/latin1 codecs # for TextIOs opened by imp.find_module. It's not # otherwise loaded by the test infrastructure but would @@ -1163,11 +1167,7 @@ """) def teardown_class(cls): - cls.space.appexec([], """ - (): - import sys - sys.path.pop() - """) + _teardown(cls.space, cls.w_saved_modules) def test_meta_path(self): tried_imports = [] From noreply at buildbot.pypy.org Mon Apr 29 01:18:29 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Mon, 29 Apr 2013 01:18:29 +0200 (CEST) Subject: [pypy-commit] pypy py3k: don't assume errno carried over from the previous test Message-ID: <20130428231829.0EEF51C2FB2@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63742:b443b8cf6741 Date: 2013-04-28 16:17 -0700 http://bitbucket.org/pypy/pypy/changeset/b443b8cf6741/ Log: don't assume errno carried over from the previous test diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py --- a/pypy/module/_cffi_backend/test/_backend_test_c.py +++ b/pypy/module/_cffi_backend/test/_backend_test_c.py @@ -2136,6 +2136,7 @@ def test_errno_callback(): if globals().get('PY_DOT_PY') == '2.5': py.test.skip("cannot run this test on py.py with Python 2.5") + set_errno(95) def cb(): e = get_errno() set_errno(e - 6) From noreply at buildbot.pypy.org Mon Apr 29 01:53:35 2013 From: noreply at buildbot.pypy.org (alex_gaynor) Date: Mon, 29 Apr 2013 01:53:35 +0200 (CEST) Subject: [pypy-commit] pypy default: (zooko) fixed a typo Message-ID: <20130428235335.86CE01C0246@cobra.cs.uni-duesseldorf.de> Author: Alex Gaynor Branch: Changeset: r63743:ff887e0bb838 Date: 2013-04-28 16:52 -0700 http://bitbucket.org/pypy/pypy/changeset/ff887e0bb838/ Log: (zooko) fixed a typo diff --git a/pypy/doc/getting-started-python.rst b/pypy/doc/getting-started-python.rst --- a/pypy/doc/getting-started-python.rst +++ b/pypy/doc/getting-started-python.rst @@ -46,7 +46,7 @@ 2. Install build-time dependencies. On a Debian box these are:: [user at debian-box ~]$ sudo apt-get install \ - gcc make python-dev libffi-dev lib-sqlite3-dev pkg-config \ + gcc make python-dev libffi-dev libsqlite3-dev pkg-config \ libz-dev libbz2-dev libncurses-dev libexpat1-dev \ libssl-dev libgc-dev python-sphinx python-greenlet From noreply at buildbot.pypy.org Mon Apr 29 09:21:28 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Mon, 29 Apr 2013 09:21:28 +0200 (CEST) Subject: [pypy-commit] cffi default: don't assume errno carried over from the previous test Message-ID: <20130429072128.A4B861C0246@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: Changeset: r1246:46fc16921624 Date: 2013-04-28 16:14 -0700 http://bitbucket.org/cffi/cffi/changeset/46fc16921624/ Log: don't assume errno carried over from the previous test diff --git a/c/test_c.py b/c/test_c.py --- a/c/test_c.py +++ b/c/test_c.py @@ -2147,6 +2147,7 @@ def test_errno_callback(): if globals().get('PY_DOT_PY') == '2.5': py.test.skip("cannot run this test on py.py with Python 2.5") + set_errno(95) def cb(): e = get_errno() set_errno(e - 6) From noreply at buildbot.pypy.org Mon Apr 29 09:25:47 2013 From: noreply at buildbot.pypy.org (arigo) Date: Mon, 29 Apr 2013 09:25:47 +0200 (CEST) Subject: [pypy-commit] pypy default: Update to cffi/46fc16921624 Message-ID: <20130429072547.52F991C026F@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63744:10a58971c4db Date: 2013-04-29 09:25 +0200 http://bitbucket.org/pypy/pypy/changeset/10a58971c4db/ Log: Update to cffi/46fc16921624 diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py --- a/pypy/module/_cffi_backend/test/_backend_test_c.py +++ b/pypy/module/_cffi_backend/test/_backend_test_c.py @@ -2136,6 +2136,7 @@ def test_errno_callback(): if globals().get('PY_DOT_PY') == '2.5': py.test.skip("cannot run this test on py.py with Python 2.5") + set_errno(95) def cb(): e = get_errno() set_errno(e - 6) From noreply at buildbot.pypy.org Mon Apr 29 09:51:05 2013 From: noreply at buildbot.pypy.org (arigo) Date: Mon, 29 Apr 2013 09:51:05 +0200 (CEST) Subject: [pypy-commit] pypy default: Add test_str_isalnum in the unsupported-for-unicode list. Message-ID: <20130429075105.2958F1C034A@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63745:defc92217d56 Date: 2013-04-29 09:50 +0200 http://bitbucket.org/pypy/pypy/changeset/defc92217d56/ Log: Add test_str_isalnum in the unsupported-for-unicode list. diff --git a/rpython/rtyper/test/test_runicode.py b/rpython/rtyper/test/test_runicode.py --- a/rpython/rtyper/test/test_runicode.py +++ b/rpython/rtyper/test/test_runicode.py @@ -274,6 +274,7 @@ test_char_isxxx = unsupported test_isdigit = unsupported test_str_isalpha = unsupported + test_str_isalnum = unsupported test_upper = unsupported test_lower = unsupported test_splitlines = unsupported From noreply at buildbot.pypy.org Mon Apr 29 09:56:00 2013 From: noreply at buildbot.pypy.org (arigo) Date: Mon, 29 Apr 2013 09:56:00 +0200 (CEST) Subject: [pypy-commit] pypy default: Don't crash when hitting ImportError when trying to import a built-in Message-ID: <20130429075600.EB3E11C1387@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63746:3aa8d355bd4c Date: 2013-04-29 09:55 +0200 http://bitbucket.org/pypy/pypy/changeset/3aa8d355bd4c/ Log: Don't crash when hitting ImportError when trying to import a built- in module. This can occur with 'cppyy'. diff --git a/lib-python/2.7/pydoc.py b/lib-python/2.7/pydoc.py --- a/lib-python/2.7/pydoc.py +++ b/lib-python/2.7/pydoc.py @@ -1953,7 +1953,11 @@ if key is None: callback(None, modname, '') else: - desc = split(__import__(modname).__doc__ or '', '\n')[0] + try: + module_doc = __import__(modname).__doc__ + except ImportError: + module_doc = None + desc = split(module_doc or '', '\n')[0] if find(lower(modname + ' - ' + desc), key) >= 0: callback(None, modname, desc) From noreply at buildbot.pypy.org Mon Apr 29 10:52:25 2013 From: noreply at buildbot.pypy.org (arigo) Date: Mon, 29 Apr 2013 10:52:25 +0200 (CEST) Subject: [pypy-commit] pypy default: Be more multiprocess-safe. Message-ID: <20130429085225.38F531C01C2@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63747:b5c330a7b172 Date: 2013-04-29 10:51 +0200 http://bitbucket.org/pypy/pypy/changeset/b5c330a7b172/ Log: Be more multiprocess-safe. diff --git a/rpython/rtyper/tool/rffi_platform.py b/rpython/rtyper/tool/rffi_platform.py --- a/rpython/rtyper/tool/rffi_platform.py +++ b/rpython/rtyper/tool/rffi_platform.py @@ -721,6 +721,8 @@ eci = eci.convert_sources_to_files() files = [filepath] output = build_executable_cache(files, eci, ignore_errors=ignore_errors) + if not output.startswith('-+- '): + raise Exception("run_example_code failed!\nlocals = %r" % (locals(),)) section = None for line in output.splitlines(): line = line.strip() diff --git a/rpython/tool/gcc_cache.py b/rpython/tool/gcc_cache.py --- a/rpython/tool/gcc_cache.py +++ b/rpython/tool/gcc_cache.py @@ -1,7 +1,7 @@ from rpython.translator.platform import CompilationError from rpython.conftest import cache_dir from hashlib import md5 -import py +import py, os cache_dir_root = py.path.local(cache_dir).ensure(dir=1) @@ -35,37 +35,45 @@ # compare equal to another instance without it if platform.log_errors != _previous: platform.log_errors = _previous - path.write(result.out) + try_atomic_write(path, result.out) return result.out +def try_atomic_write(path, data): + path = str(path) + tmppath = '%s~%d' % (path, os.getpid()) + f = open(tmppath, 'wb') + f.write(data) + f.close() + try: + os.rename(tmppath, path) + except OSError: + try: + os.unlink(tmppath) + except OSError: + pass + def try_compile_cache(c_files, eci): - "Try to compile a program; caches the result (starts with 'True' or 'FAIL')" + "Try to compile a program. If it works, caches this fact." # Import 'platform' every time, the compiler may have been changed from rpython.translator.platform import platform path = cache_file_path(c_files, eci, 'try_compile_cache') try: data = path.read() + if data == 'True': + return True except py.error.Error: - data = '' - if not (data.startswith('True') or data.startswith('FAIL\n')): - try: - _previous = platform.log_errors - try: - platform.log_errors = False - platform.compile(c_files, eci) - finally: - del platform.log_errors - # ^^^remove from the instance --- needed so that it can - # compare equal to another instance without it - if platform.log_errors != _previous: - platform.log_errors = _previous - data = 'True' - path.write(data) - except CompilationError, e: - data = 'FAIL\n%s\n' % (e,) - if data.startswith('True'): - return True - else: - assert data.startswith('FAIL\n') - msg = data[len('FAIL\n'):] - raise CompilationError(msg.strip(), '') + pass + # + _previous = platform.log_errors + try: + platform.log_errors = False + platform.compile(c_files, eci) + # ^^^ may raise CompilationError. We don't cache such results. + finally: + del platform.log_errors + # ^^^remove from the instance --- needed so that it can + # compare equal to another instance without it + if platform.log_errors != _previous: + platform.log_errors = _previous + path.write('True') + return True From noreply at buildbot.pypy.org Mon Apr 29 11:01:49 2013 From: noreply at buildbot.pypy.org (bivab) Date: Mon, 29 Apr 2013 11:01:49 +0200 (CEST) Subject: [pypy-commit] buildbot buildbot-0.8.7: A branch to update the pypy-buildbot to the latest buildbot Message-ID: <20130429090149.E7CEA1C026F@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: buildbot-0.8.7 Changeset: r796:2dd933150b4f Date: 2013-04-25 10:28 +0200 http://bitbucket.org/pypy/buildbot/changeset/2dd933150b4f/ Log: A branch to update the pypy-buildbot to the latest buildbot From noreply at buildbot.pypy.org Mon Apr 29 11:01:51 2013 From: noreply at buildbot.pypy.org (bivab) Date: Mon, 29 Apr 2013 11:01:51 +0200 (CEST) Subject: [pypy-commit] buildbot buildbot-0.8.7: update dependencies Message-ID: <20130429090151.07AA31C026F@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: buildbot-0.8.7 Changeset: r797:db264641a37f Date: 2013-04-25 10:28 +0200 http://bitbucket.org/pypy/buildbot/changeset/db264641a37f/ Log: update dependencies diff --git a/requirements.txt b/requirements.txt --- a/requirements.txt +++ b/requirements.txt @@ -1,15 +1,16 @@ Flask==0.9 Jinja2==2.6 -SQLAlchemy==0.7.8 +SQLAlchemy==0.8.0 Tempita==0.5.1 -Twisted==8.2.0 +Twisted==13.0.0 Werkzeug==0.8.3 argparse==1.2.1 -buildbot==0.8.4 +buildbot==0.8.7p1 buildbot-slave==0.8.6p1 -decorator==3.3.3 +decorator==3.4.0 py==1.4.9 pytest==2.2.4 -sqlalchemy-migrate==0.6 +python-dateutil==1.5 +sqlalchemy-migrate==0.7.2 wsgiref==0.1.2 -zope.interface==4.0.1 +zope.interface==4.0.5 From noreply at buildbot.pypy.org Mon Apr 29 11:01:52 2013 From: noreply at buildbot.pypy.org (bivab) Date: Mon, 29 Apr 2013 11:01:52 +0200 (CEST) Subject: [pypy-commit] buildbot buildbot-0.8.7: remove html comment Message-ID: <20130429090152.111BE1C026F@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: buildbot-0.8.7 Changeset: r798:2a7ce9fa446e Date: 2013-04-25 11:25 +0200 http://bitbucket.org/pypy/buildbot/changeset/2a7ce9fa446e/ Log: remove html comment diff --git a/master/templates/root.html b/master/templates/root.html --- a/master/templates/root.html +++ b/master/templates/root.html @@ -26,7 +26,7 @@ The Performance Plots will give you an overview of performance for recent revisions.
          • - +
          • The Summary Display <trunk> will give you a failure-oriented summary for recent @@ -53,7 +53,7 @@
          • The Transposed Grid Display presents the same information as the grid, but lists the revisions down the side.
          • -
          • The Console presents +
          • The Console presents a user-oriented status page.
          • The Builders and their most recent builds are @@ -68,19 +68,6 @@
          • About this Buildbot
          -
          From noreply at buildbot.pypy.org Mon Apr 29 11:01:53 2013 From: noreply at buildbot.pypy.org (bivab) Date: Mon, 29 Apr 2013 11:01:53 +0200 (CEST) Subject: [pypy-commit] buildbot buildbot-0.8.7: update calls to authz.advertiseAction Message-ID: <20130429090153.1FBCA1C026F@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: buildbot-0.8.7 Changeset: r799:2d89931081d5 Date: 2013-04-25 19:22 +0200 http://bitbucket.org/pypy/buildbot/changeset/2d89931081d5/ Log: update calls to authz.advertiseAction diff --git a/master/templates/build.html b/master/templates/build.html --- a/master/templates/build.html +++ b/master/templates/build.html @@ -21,18 +21,18 @@ {% endif %} {{ current_step }} - - {% if authz.advertiseAction('stopBuild') %} + + {% if authz.advertiseAction('stopBuild', request) %}

          Stop Build

          {{ forms.stop_build(build_url+"/stop", authz, on_all=False, short=False, label='This Build') }} {% endif %} {% else %}

          Results:

          -

          +

          {{ b.getText()|join(' ')|capitalize }}

          - + {% if b.getTestResults() %}

          {% endif %} @@ -82,13 +82,13 @@ # TODO: turn this into a table, or some other sort of definition-list # that doesn't take up quite so much vertical space #} - +

          BuildSlave:

          - -{% if slave_url %} + +{% if slave_url %}
          {{ b.getSlavename()|e }} {% else %} - {{ b.getSlavename()|e }} + {{ b.getSlavename()|e }} {% endif %}

          Reason:

          @@ -111,7 +111,7 @@ {% for s in steps %}
        2. - {{ s.name }} + {{ s.name }} {{ s.text }} {{ '( ' + s.time_to_run + ' )' if s.time_to_run else '' }}
          @@ -122,11 +122,11 @@ {% else %}
        3. - no logs -
        4. {% endfor %} - + {% for u in s.urls %}
        5. {{ u.logname }}
        6. {% endfor %} -
        +
    • {% endfor %} @@ -176,7 +176,7 @@ +    (view in summary) @@ -44,6 +44,7 @@ {% set ss_class = cycler('alt','') %} +{% set ss = sourcestamps[0] %} {% if ss.project %} {% endif %} From noreply at buildbot.pypy.org Mon Apr 29 11:01:55 2013 From: noreply at buildbot.pypy.org (bivab) Date: Mon, 29 Apr 2013 11:01:55 +0200 (CEST) Subject: [pypy-commit] buildbot buildbot-0.8.7: add force build form and scheduler Message-ID: <20130429090155.1FE4E1C026F@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: buildbot-0.8.7 Changeset: r801:4b13cd229f4f Date: 2013-04-25 20:34 +0200 http://bitbucket.org/pypy/buildbot/changeset/4b13cd229f4f/ Log: add force build form and scheduler diff --git a/bot2/pypybuildbot/arm_master.py b/bot2/pypybuildbot/arm_master.py --- a/bot2/pypybuildbot/arm_master.py +++ b/bot2/pypybuildbot/arm_master.py @@ -101,6 +101,21 @@ BUILDLINUXARMHF_RASPBIAN = "build-pypy-c-linux-armhf-raspbian" BUILDJITLINUXARMHF_RASPBIAN = "build-pypy-c-jit-linux-armhf-raspbian" +builderNames = [ + APPLVLLINUXARM, + APPLVLLINUXARMHF_v7, + APPLVLLINUXARMHF_RASPBIAN, + JITLINUXARM, + JITLINUXARMHF_v7, + JITLINUXARMHF_RASPBIAN, + JITBACKENDONLYLINUXARMEL, + JITBACKENDONLYLINUXARMHF, + JITBACKENDONLYLINUXARMHF_v7, + BUILDLINUXARM, + BUILDJITLINUXARM, + BUILDLINUXARMHF_RASPBIAN, + BUILDJITLINUXARMHF_RASPBIAN, +] schedulers = [ Nightly("nighly-arm-0-00", [ diff --git a/bot2/pypybuildbot/master.py b/bot2/pypybuildbot/master.py --- a/bot2/pypybuildbot/master.py +++ b/bot2/pypybuildbot/master.py @@ -2,6 +2,7 @@ import os import getpass from buildbot.scheduler import Nightly, Triggerable +from buildbot.schedulers.forcesched import ForceScheduler from buildbot.buildslave import BuildSlave from buildbot.status.html import WebStatus from buildbot.process.builder import Builder @@ -228,6 +229,35 @@ Nightly("nighly-ppc", [ JITONLYLINUXPPC64, # on gcc1 ], branch='ppc-jit-backend', hour=1, minute=0), + ForceScheduler('Force Scheduler', [ + LINUX32, + LINUX64, + INDIANA32, + + MACOSX32, + WIN32, + WIN64, + APPLVLLINUX32, + APPLVLLINUX64, + APPLVLWIN32, + + LIBPYTHON_LINUX32, + LIBPYTHON_LINUX64, + + JITLINUX32, + JITLINUX64, + JITMACOSX64, + JITWIN32, + JITWIN64, + JITFREEBSD764, + JITFREEBSD864, + JITFREEBSD964, + JITINDIANA32, + + JITONLYLINUXPPC64, + JITBENCH, + JITBENCH64, + ] + ARM.builderNames), ] + ARM.schedulers, 'status': [status, ircbot], diff --git a/master/templates/builder.html b/master/templates/builder.html --- a/master/templates/builder.html +++ b/master/templates/builder.html @@ -103,9 +103,9 @@ {{ forms.ping_builder(builder_url+"/ping", authz) }} {% endif %} -{% if authz.advertiseAction('forceBuild', request) %} +{% if authz.advertiseAction('forceBuild', request) and force_schedulers != {} %}

      Force build

      - {{ forms.force_build(builder_url+"/force", authz, False) }} + {{ forms.force_build(builder_url+"/force", authz, request, False, force_schedulers=force_schedulers,default_props=default_props) }} {% endif %} From noreply at buildbot.pypy.org Mon Apr 29 11:01:56 2013 From: noreply at buildbot.pypy.org (bivab) Date: Mon, 29 Apr 2013 11:01:56 +0200 (CEST) Subject: [pypy-commit] buildbot buildbot-0.8.7: update ircbot for 0.8.7 Message-ID: <20130429090156.170641C026F@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: buildbot-0.8.7 Changeset: r802:3b5b00554251 Date: 2013-04-26 19:45 +0200 http://bitbucket.org/pypy/buildbot/changeset/3b5b00554251/ Log: update ircbot for 0.8.7 diff --git a/bot2/pypybuildbot/ircbot.py b/bot2/pypybuildbot/ircbot.py --- a/bot2/pypybuildbot/ircbot.py +++ b/bot2/pypybuildbot/ircbot.py @@ -7,54 +7,64 @@ the customized IRC messages. """ -import re -from buildbot.status.words import Contact, IRC, log +from buildbot.status.words import IRC, log, IRCContact +# see http://www.mirc.com/colors.html USE_COLOR_CODES = True -GREEN = '\x033' -RED = '\x034' -AZURE = '\x0311' -BLUE = '\x0312' -PURPLE = '\x0313' -GRAY = '\x0315' -BOLD = '\x02' -def color(code, s): +BOLD = '\x02' +COLORS = { + 'WHITE': '\x030', + 'BLACK': '\x031', + 'GREEN': '\x033', + 'RED': '\x034', + 'AZURE': '\x0311', + 'BLUE': '\x0312', + 'PURPLE': '\x0313', + 'GRAY': '\x0315', +} + + +def color(s, code=None, bold=False): if USE_COLOR_CODES: - return '%s%s\x0F' % (code, s) + c = BOLD if bold else '' + if code in COLORS: + c += COLORS[code] + return '%s%s\x0F' % (c, s) return s + def extract_username(build): - regexp = r"The web-page 'force build' button was pressed by '(.*)': .*" - match = re.match(regexp, build.getReason()) - if match: - return match.group(1) - return None + owner = build.getProperty("owner") + reason = build.getProperty("reason") + return ": ".join(k for k in (owner, reason) if k) def get_description_for_build(url, build): - url = color(GRAY, url) # in gray + url = color(url, 'GRAY') # in gray infos = [] username = extract_username(build) if username: - infos.append(color(BLUE, username)) # in blue + infos.append(color(username, 'BLUE')) # in blue # - branch = build.source.branch + branch = build.getProperty('branch') if branch: - infos.append(color(BOLD, branch)) # in bold + infos.append(color(branch, bold=True)) # in bold # if infos: return '%s [%s]' % (url, ', '.join(infos)) else: return url + def buildStarted(self, builderName, build): builder = build.getBuilder() - log.msg('[Contact] Builder %r in category %s started' % (builder, builder.category)) + log.msg('[Contact] Builder %r in category %s started' % + (builder, builder.category)) # only notify about builders we are interested in - if (self.channel.categories != None and - builder.category not in self.channel.categories): + if (self.bot.categories is not None and + builder.category not in self.bot.categories): log.msg('Not notifying for a build in the wrong category') return @@ -62,7 +72,7 @@ log.msg('Not notifying for a build when started-notification disabled') return - buildurl = self.channel.status.getURLForThing(build) + buildurl = self.bot.status.getURLForThing(build) descr = get_description_for_build(buildurl, build) msg = "Started: %s" % descr self.send(msg) @@ -72,29 +82,28 @@ builder = build.getBuilder() # only notify about builders we are interested in - log.msg('[Contact] builder %r in category %s finished' % (builder, builder.category)) + log.msg('[Contact] builder %r in category %s finished' % + (builder, builder.category)) - if (self.channel.categories != None and - builder.category not in self.channel.categories): + if (self.bot.categories is not None and + builder.category not in self.bot.categories): return if not self.notify_for_finished(build): return - buildurl = self.channel.status.getURLForThing(build) + buildurl = self.bot.status.getURLForThing(build) descr = get_description_for_build(buildurl, build) - result = self.results_descriptions.get(build.getResults(), "Finished ??") - if result == 'Success': - result = color(BOLD+GREEN, result) - elif result == 'Exception': - result = color(BOLD+PURPLE, result) - else: - result = color(BOLD+RED, result) + result, c = self.results_descriptions.get(build.getResults(), + ("Finished ??", 'RED')) + if c not in COLORS: + c = 'RED' + result = color(result, c, bold=True) msg = "%s: %s" % (result, descr) self.send(msg) -Contact.buildStarted = buildStarted -Contact.buildFinished = buildFinished +IRCContact.buildStarted = buildStarted +IRCContact.buildFinished = buildFinished ## def send_message(message, test=False): From noreply at buildbot.pypy.org Mon Apr 29 11:01:57 2013 From: noreply at buildbot.pypy.org (bivab) Date: Mon, 29 Apr 2013 11:01:57 +0200 (CEST) Subject: [pypy-commit] buildbot buildbot-0.8.7: update 'Forbid "force build" with empty user name' workaround Message-ID: <20130429090157.0C8621C026F@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: buildbot-0.8.7 Changeset: r803:2ad99834f44f Date: 2013-04-26 20:42 +0200 http://bitbucket.org/pypy/buildbot/changeset/2ad99834f44f/ Log: update 'Forbid "force build" with empty user name' workaround diff --git a/bot2/pypybuildbot/master.py b/bot2/pypybuildbot/master.py --- a/bot2/pypybuildbot/master.py +++ b/bot2/pypybuildbot/master.py @@ -1,26 +1,21 @@ import os -import getpass -from buildbot.scheduler import Nightly, Triggerable +from buildbot.scheduler import Nightly from buildbot.schedulers.forcesched import ForceScheduler from buildbot.buildslave import BuildSlave from buildbot.status.html import WebStatus -from buildbot.process.builder import Builder #from buildbot import manhole from pypybuildbot.pypylist import PyPyList, NumpyStatusList -from pypybuildbot.ircbot import IRC # side effects +from pypybuildbot.ircbot import IRC # side effects from pypybuildbot.util import we_are_debugging # Forbid "force build" with empty user name -from buildbot.status.web.builder import StatusResourceBuilder -def my_force(self, req, *args, **kwds): - name = req.args.get("username", [""])[0] - assert name, "Please write your name in the corresponding field." - return _previous_force(self, req, *args, **kwds) -_previous_force = StatusResourceBuilder.force -if _previous_force.__name__ == 'force': - StatusResourceBuilder.force = my_force -# Done + +class CustomForceScheduler(ForceScheduler): + def force(self, owner, builder_name, **kwargs): + assert owner, "Please write your name in the corresponding field." + return ForceScheduler.force(self, owner, builder_name, **kwargs) + if we_are_debugging(): channel = '#buildbot-test' @@ -229,7 +224,8 @@ Nightly("nighly-ppc", [ JITONLYLINUXPPC64, # on gcc1 ], branch='ppc-jit-backend', hour=1, minute=0), - ForceScheduler('Force Scheduler', [ + CustomForceScheduler('Force Scheduler', + builderNames=[ LINUX32, LINUX64, INDIANA32, @@ -257,7 +253,7 @@ JITONLYLINUXPPC64, JITBENCH, JITBENCH64, - ] + ARM.builderNames), + ] + ARM.builderNames), ] + ARM.schedulers, 'status': [status, ircbot], From noreply at buildbot.pypy.org Mon Apr 29 11:01:58 2013 From: noreply at buildbot.pypy.org (bivab) Date: Mon, 29 Apr 2013 11:01:58 +0200 (CEST) Subject: [pypy-commit] buildbot buildbot-0.8.7: update default.css Message-ID: <20130429090158.00DA01C026F@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: buildbot-0.8.7 Changeset: r804:2d04f6444708 Date: 2013-04-26 21:03 +0200 http://bitbucket.org/pypy/buildbot/changeset/2d04f6444708/ Log: update default.css diff --git a/master/public_html/default.css b/master/public_html/default.css --- a/master/public_html/default.css +++ b/master/public_html/default.css @@ -10,6 +10,22 @@ color: #333; } +.auth { +position:absolute; +top:5px; +right:40px; +} + +.alert { + color: #c30000; + background-color: #f2dcdc; + padding: 5px 5px 5px 25px; + margin-bottom: 20px; + border-top:1px solid #ccc; + border-bottom:1px solid #ccc; + border-color: #c30000; + font-size: 20px; +} a:link,a:visited,a:active { color: #444; } @@ -197,14 +213,17 @@ font-weight: normal; padding: 8px 8px 8px 8px; color: #333333; + background-color: #eee; + text-align: left; +} + +td.DevBottom { border-bottom-right-radius: 5px; -webkit-border-bottom-right-radius: 5px; -moz-border-radius-bottomright: 5px; border-bottom-left-radius: 5px; -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px; - background-color: #eee; - text-align: left; } td.Alt { @@ -212,9 +231,9 @@ } .legend { - border-radius: 5px; - -webkit-border-radius: 5px; - -moz-border-radius: 5px; + border-radius: 5px !important; + -webkit-border-radius: 5px !important; + -moz-border-radius: 5px !important; width: 100px; max-width: 100px; text-align: center; @@ -542,3 +561,27 @@ pre.comments>a:active { color: purple; } + +form.command_forcebuild { + border-top: 1px solid black; + padding: .5em; + margin: .5em; +} + +form.command_forcebuild > .row { + border-top: 1px dotted gray; + padding: .5em 0; +} + +form.command_forcebuild .force-textarea > .label { + display: block; +} + +form.command_forcebuild .force-nested > .label { + font-weight: bold; + display: list-item; +} + +form.command_forcebuild .force-any .force-text { + display: inline; +} From noreply at buildbot.pypy.org Mon Apr 29 11:01:58 2013 From: noreply at buildbot.pypy.org (bivab) Date: Mon, 29 Apr 2013 11:01:58 +0200 (CEST) Subject: [pypy-commit] buildbot buildbot-0.8.7: raise a validation error instead of crashing if the username is missing Message-ID: <20130429090158.EA4581C026F@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: buildbot-0.8.7 Changeset: r805:b48b1aac38d1 Date: 2013-04-26 21:04 +0200 http://bitbucket.org/pypy/buildbot/changeset/b48b1aac38d1/ Log: raise a validation error instead of crashing if the username is missing diff --git a/bot2/pypybuildbot/master.py b/bot2/pypybuildbot/master.py --- a/bot2/pypybuildbot/master.py +++ b/bot2/pypybuildbot/master.py @@ -2,6 +2,7 @@ import os from buildbot.scheduler import Nightly from buildbot.schedulers.forcesched import ForceScheduler +from buildbot.schedulers.forcesched import ValidationError from buildbot.buildslave import BuildSlave from buildbot.status.html import WebStatus #from buildbot import manhole @@ -10,10 +11,10 @@ from pypybuildbot.util import we_are_debugging # Forbid "force build" with empty user name - class CustomForceScheduler(ForceScheduler): def force(self, owner, builder_name, **kwargs): - assert owner, "Please write your name in the corresponding field." + if not owner: + raise ValidationError, "Please write your name in the corresponding field." return ForceScheduler.force(self, owner, builder_name, **kwargs) From noreply at buildbot.pypy.org Mon Apr 29 11:01:59 2013 From: noreply at buildbot.pypy.org (bivab) Date: Mon, 29 Apr 2013 11:01:59 +0200 (CEST) Subject: [pypy-commit] buildbot buildbot-0.8.7: add an alert box to the template Message-ID: <20130429090159.E278B1C026F@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: buildbot-0.8.7 Changeset: r806:8fd9b1250f55 Date: 2013-04-26 21:07 +0200 http://bitbucket.org/pypy/buildbot/changeset/8fd9b1250f55/ Log: add an alert box to the template diff --git a/master/templates/layout.html b/master/templates/layout.html --- a/master/templates/layout.html +++ b/master/templates/layout.html @@ -20,9 +20,9 @@ {% block header -%} -
      +
      Home - - + - Speed Summary (trunk) @@ -46,13 +46,19 @@ {%- block barecontent -%}
      + {% if alert_msg != '' %} +
      + {{alert_msg}} +
      + {% endif %} +
      - {%- block content -%} + {%- block content -%} {%- endblock -%}
      {%- endblock -%} - {%- block footer -%} + {%- block footer -%}
      Project{{ ss.project|projectlink }}
      + {% set ss_class = cycler('alt','') %} -
      -{% set ss_class = cycler('alt','') %} + {% if ss.project %} + + {% endif %} -{% set ss = sourcestamps[0] %} -{% if ss.project %} - -{% endif %} + {% if ss.repository %} + + {% endif %} -{% if ss.repository %} - -{% endif %} + {% if ss.branch %} + + {% endif %} -{% if ss.branch %} - -{% endif %} + {% if ss.revision %} + + {% endif %} -{% if ss.revision %} - -{% endif %} + {% if got_revisions[ss.codebase] %} + + {% endif %} -{% if got_revision %} - -{% endif %} + {% if ss.patch %} + + {% endif %} -{% if ss.patch %} - -{% endif %} + {% if ss.changes %} + + {% endif %} -{% if ss.changes %} - -{% endif %} - -{% if most_recent_rev_build %} - -{% endif %} - -
      Project{{ ss.project|projectlink }}
      Project{{ ss.project|projectlink }}
      Repository{{ ss.repository|repolink }}
      Repository{{ ss.repository|repolink }}
      Branch{{ ss.branch|e }}
      Branch{{ ss.branch|e }}
      Revision{{ ss.revision|revlink(ss.repository) }}
      Revision{{ ss.revision|revlink(ss.repository) }}
      Got Revision{{ got_revisions[ss.codebase]|revlink(ss.repository) }}
      Got Revision{{ got_revision|revlink(ss.repository) }}
      PatchYES
      PatchYES
      Changes{{ ss.changes|count }} change{{ 's' if ss.changes|count > 1 else '' }}
      Changessee below
      Build of most recent revision
      + {% if not ss.branch and not ss.revision and not ss.patch and not ss.changes %} + Build of most recent revision + {% endif %} + +{% endfor %} {# # TODO: turn this into a table, or some other sort of definition-list @@ -141,20 +147,53 @@ NameValueSource {% for p in properties %} +{% if p.source != "Force Build Form" %} {{ p.name|e }} - {% if p.short_value %} - {{ p.short_value|e }} .. [property value too long] - {% else %} - {{ p.value|e }} - {% endif %} + {% if p.short_value %} + {{ p.short_value|e }} .. [property value too long] + {% else %} + {% if p.value is not mapping %} + {{ p.value|e }} + {% else %} + + + {%- for key, value in p.value.items() recursive %} + + {% endfor %} +
      {{ key|e }}{{ value|e }}
      + + {% endif %} + {% endif %} {{ p.source|e }} +{% endif %} {% endfor %} + +

      Forced Build Properties:

      + + +{% for p in properties %} + {% if p.source == "Force Build Form" %} + + + + {% if p.text %} + + {% else %} + + {% endif %} + + {% endif %} +{% endfor %}
      NameLabelValue
      {{ p.name|e }} + {% if p.label %} + {{ p.label }} + {% endif %} + {{ p.value|e }}
      -

      Blamelist:

      +

      Responsible Users:

      {% if responsible_users %}
        @@ -179,27 +218,30 @@ + --!>
        -{% if ss.changes %} -
        -

        All Changes:

        -
          - {% for c in ss.changes %} -
        1. Change #{{ c.number }}

          - {{ change(c.asDict()) }} -
        2. - {% else %} -
        3. no changes
        4. - {% endfor %} -
        -
        +{% if has_changes %} +
        +

        All Changes:

        + {% for ss in sourcestamps %} + {% if ss.changes %} +

        {{ ss.codebase }}:

        +
          + {% for c in ss.changes %} +
        1. Change #{{ c.number }}

          + {{ change(c.asDict()) }} +
        2. + {% endfor %} +
        + {% endif %} + {% endfor %} +
        {% endif %} {% endblock %} diff --git a/master/templates/builder.html b/master/templates/builder.html --- a/master/templates/builder.html +++ b/master/templates/builder.html @@ -5,7 +5,6 @@ {% block content %}

        Builder {{ name }}

        -

        (view in waterfall) @@ -48,17 +47,22 @@ {% if b.num_changes < 4 %} {% for c in b.changes %}{{ c.revision|shortrev(c.repo) }} - ({{ c.who }}){% if not loop.last %},{% endif %} + ({{ c.who|email }}){% if not loop.last %},{% endif %} {% endfor %} {% else %} ({{ b.num_changes }} changes) {% endif %} + {% if 'owner' in b.properties %} + Forced build + by {{b.properties['owner'][0]}} + {{b.properties['reason'][0]}} + {% endif %} {% endfor %}

    - {% if authz.advertiseAction('cancelPendingBuild', requeset) %} + {% if authz.advertiseAction('cancelPendingBuild', request) %} {{ forms.cancel_pending_build(builder_url+"/cancelbuild", authz, short=False, id='all') }} {% endif %} From noreply at buildbot.pypy.org Mon Apr 29 11:02:03 2013 From: noreply at buildbot.pypy.org (bivab) Date: Mon, 29 Apr 2013 11:02:03 +0200 (CEST) Subject: [pypy-commit] buildbot buildbot-0.8.7: fix tests for ircbot Message-ID: <20130429090203.5C8B71C026F@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: buildbot-0.8.7 Changeset: r809:83ae0f7c3a32 Date: 2013-04-28 19:12 +0200 http://bitbucket.org/pypy/buildbot/changeset/83ae0f7c3a32/ Log: fix tests for ircbot diff --git a/bot2/pypybuildbot/ircbot.py b/bot2/pypybuildbot/ircbot.py --- a/bot2/pypybuildbot/ircbot.py +++ b/bot2/pypybuildbot/ircbot.py @@ -33,7 +33,7 @@ return s -def extract_username(build): +def get_build_information(build): owner = build.getProperty("owner") reason = build.getProperty("reason") return ": ".join(k for k in (owner, reason) if k) @@ -42,9 +42,9 @@ def get_description_for_build(url, build): url = color(url, 'GRAY') # in gray infos = [] - username = extract_username(build) - if username: - infos.append(color(username, 'BLUE')) # in blue + buildinfo = get_build_information(build) + if buildinfo: + infos.append(color(buildinfo, 'BLUE')) # in blue # branch = build.getProperty('branch') if branch: diff --git a/bot2/pypybuildbot/test/test_ircbot.py b/bot2/pypybuildbot/test/test_ircbot.py --- a/bot2/pypybuildbot/test/test_ircbot.py +++ b/bot2/pypybuildbot/test/test_ircbot.py @@ -1,50 +1,48 @@ from pypybuildbot import ircbot + def setup_module(mod): ircbot.USE_COLOR_CODES = False + def teardown_module(mod): ircbot.USE_COLOR_CODES = True + class FakeBuild(object): - def __init__(self, reason=None, source=None): - self.reason = reason - self.source = source + def __init__(self, reason=None, owner=None, branch=None): + self.properties = {'owner': owner, 'branch': branch, 'reason': reason} - def getReason(self): - return self.reason + def getProperty(self, name): + return self.properties.get(name, None) - def getSourceStamp(self): - return self.source -class FakeSource(object): - - def __init__(self, branch): - self.branch = branch - -def test_extract_username(): - a = FakeBuild("The web-page 'force build' button was pressed by 'antocuni': foo") +def test_get_build_information(): + a = FakeBuild(owner='antocuni', + reason="The web-page 'force build' button was pressed") b = FakeBuild("The web-page 'force build' button was ...") - assert ircbot.extract_username(a) == 'antocuni' - assert ircbot.extract_username(b) is None + assert ircbot.get_build_information(a) == \ + "antocuni: The web-page 'force build' button was pressed" + assert ircbot.get_build_information(b) == \ + "The web-page 'force build' button was ..." def test_get_description_for_build(): - a = FakeBuild('foobar', source=FakeSource(None)) + a = FakeBuild() msg = ircbot.get_description_for_build("http://myurl", a) assert msg == "http://myurl" - a = FakeBuild("The web-page 'force build' button was pressed by 'antocuni': foo", - source=FakeSource(None)) + a = FakeBuild(owner='antocuni', + reason="The web-page 'force build' button was pressed") msg = ircbot.get_description_for_build("http://myurl", a) - assert msg == "http://myurl [antocuni]" + assert msg == "http://myurl [antocuni: " \ + + "The web-page 'force build' button was pressed]" - a = FakeBuild('foobar', source=FakeSource('mybranch')) + a = FakeBuild(branch='mybranch') msg = ircbot.get_description_for_build("http://myurl", a) assert msg == "http://myurl [mybranch]" - a = FakeBuild("The web-page 'force build' button was pressed by 'antocuni': foo", - source=FakeSource('mybranch')) + a = FakeBuild(owner='antocuni', branch='mybranch') msg = ircbot.get_description_for_build("http://myurl", a) assert msg == "http://myurl [antocuni, mybranch]" From noreply at buildbot.pypy.org Mon Apr 29 11:02:04 2013 From: noreply at buildbot.pypy.org (bivab) Date: Mon, 29 Apr 2013 11:02:04 +0200 (CEST) Subject: [pypy-commit] buildbot buildbot-0.8.7: fix test_build tests Message-ID: <20130429090204.7D0FE1C026F@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: buildbot-0.8.7 Changeset: r810:91a1ce34b245 Date: 2013-04-28 20:04 +0200 http://bitbucket.org/pypy/buildbot/changeset/91a1ce34b245/ Log: fix test_build tests diff --git a/bot2/pypybuildbot/test/test_builds.py b/bot2/pypybuildbot/test/test_builds.py --- a/bot2/pypybuildbot/test/test_builds.py +++ b/bot2/pypybuildbot/test/test_builds.py @@ -5,8 +5,7 @@ class FakeProperties(object): def __init__(self): - from buildbot.process.properties import PropertyMap - self.pmap = PropertyMap(self) + pass def __getitem__(self, item): if item == 'branch': @@ -42,15 +41,16 @@ return FakeDeferred() def test_Translate(): - expected = ['translate.py', '--batch', '-O0', + expected = ['pypy', '../../rpython/bin/rpython', '--batch', '-O0', 'targetpypystandalone', '--no-allworkingmodules'] translateInst = builds.Translate(['-O0'], ['--no-allworkingmodules']) assert translateInst.command[-len(expected):] == expected - translateFactory, kw = translateInst.factory - rebuiltTranslate = translateFactory(**kw) + translateFactory = translateInst._getStepFactory().factory + args = translateInst._getStepFactory().args + rebuiltTranslate = translateFactory(*args) assert rebuiltTranslate.command[-len(expected):] == expected @@ -64,7 +64,8 @@ inst = builds.PyPyUpload(slavesrc='slavesrc', masterdest=str(pth.join('mstr')), basename='base-%(final_file_name)s', workdir='.', blocksize=100) - factory, kw = inst.factory + factory = inst._getStepFactory().factory + kw = inst._getStepFactory().kwargs rebuilt = factory(**kw) rebuilt.build = FakeBuild() rebuilt.step_status = FakeStepStatus() From noreply at buildbot.pypy.org Mon Apr 29 11:02:05 2013 From: noreply at buildbot.pypy.org (bivab) Date: Mon, 29 Apr 2013 11:02:05 +0200 (CEST) Subject: [pypy-commit] buildbot buildbot-0.8.7: fix pypylist tests Message-ID: <20130429090205.75AFA1C026F@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: buildbot-0.8.7 Changeset: r811:d196315b882f Date: 2013-04-28 21:07 +0200 http://bitbucket.org/pypy/buildbot/changeset/d196315b882f/ Log: fix pypylist tests diff --git a/bot2/pypybuildbot/test/test_pypylist.py b/bot2/pypybuildbot/test/test_pypylist.py --- a/bot2/pypybuildbot/test/test_pypylist.py +++ b/bot2/pypybuildbot/test/test_pypylist.py @@ -78,18 +78,20 @@ newdir.setmtime(oldtime + ascii * 10) pypylist = PyPyList(tmpdir.strpath) listener = pypylist.directoryListing() - assert listener.dirs == ['trunk', 'mmmm', 'llll', + assert listener.dirs == ['trunk', 'llll', 'kkkk','jjjj','iiii','hhhh','gggg','ffff','eeee', 'dddd','cccc','bbbb','aaaa'] def load_BuildmasterConfig(): import os - from pypybuildbot import summary, builds + from pypybuildbot import summary, builds, arm_master def load(name): if name == 'pypybuildbot.summary': return summary elif name == 'pypybuildbot.builds': return builds + elif name == 'pypybuildbot.arm_master': + return arm_master else: assert False From noreply at buildbot.pypy.org Mon Apr 29 11:25:30 2013 From: noreply at buildbot.pypy.org (arigo) Date: Mon, 29 Apr 2013 11:25:30 +0200 (CEST) Subject: [pypy-commit] pypy default: Increase the resistence of make_numbered_dir() against multiple Message-ID: <20130429092530.503201C1000@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63748:c6f52c21fe7e Date: 2013-04-29 11:24 +0200 http://bitbucket.org/pypy/pypy/changeset/c6f52c21fe7e/ Log: Increase the resistence of make_numbered_dir() against multiple processes diff --git a/py/_path/local.py b/py/_path/local.py --- a/py/_path/local.py +++ b/py/_path/local.py @@ -655,7 +655,8 @@ mkdtemp = classmethod(mkdtemp) def make_numbered_dir(cls, prefix='session-', rootdir=None, keep=3, - lock_timeout = 172800): # two days + lock_timeout = 172800, # two days + min_timeout = 300): # five minutes """ return unique directory with a number greater than the current maximum one. The number is assumed to start directly after prefix. if keep is true directories with a number less than (maxnum-keep) @@ -723,6 +724,20 @@ for path in rootdir.listdir(): num = parse_num(path) if num is not None and num <= (maxnum - keep): + if min_timeout: + # NB: doing this is needed to prevent (or reduce + # a lot the chance of) the following situation: + # 'keep+1' processes call make_numbered_dir() at + # the same time, they create dirs, but then the + # last process notices the first dir doesn't have + # (yet) a .lock in it and kills it. + try: + t1 = path.lstat().mtime + t2 = lockfile.lstat().mtime + if abs(t2-t1) < min_timeout: + continue # skip directories too recent + except py.error.Error: + continue # failure to get a time, better skip lf = path.join('.lock') try: t1 = lf.lstat().mtime From noreply at buildbot.pypy.org Mon Apr 29 11:42:24 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Mon, 29 Apr 2013 11:42:24 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: enable conntect switch when idle also before waiting Message-ID: <20130429094224.0ACB11C026F@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r344:6282c37ab8cd Date: 2013-04-25 17:29 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/6282c37ab8cd/ Log: enable conntect switch when idle also before waiting diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -1352,10 +1352,12 @@ @expose_primitive(IDLE_FOR_MICROSECONDS, unwrap_spec=[object, int], no_result=True, clean_stack=False) def func(interp, s_frame, w_rcvr, time_mu_s): import time + s_frame.pop() time_s = time_mu_s / 1000000.0 + interp.interrupt_check_counter = 0 + interp.quick_check_for_interrupt(s_frame, dec=0) time.sleep(time_s) interp.interrupt_check_counter = 0 - s_frame.pop() interp.quick_check_for_interrupt(s_frame, dec=0) @expose_primitive(FORCE_DISPLAY_UPDATE, unwrap_spec=[object]) From noreply at buildbot.pypy.org Mon Apr 29 11:42:25 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Mon, 29 Apr 2013 11:42:25 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: merge with tip Message-ID: <20130429094225.498DB1C026F@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r345:7b329d83cd57 Date: 2013-04-25 18:41 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/7b329d83cd57/ Log: merge with tip diff --git a/benchmarks.py b/benchmarks.py new file mode 100644 --- /dev/null +++ b/benchmarks.py @@ -0,0 +1,131 @@ +# -*- coding: utf-8 -*- +import os +import socket +import subprocess +import sys +import time +import urllib +import urllib2 + +SqueakImage = "Squeak4.4-12327" + +# You need to enter the real URL and have the server running +CODESPEED_URL = 'http://speed.bithug.org/' + +# Executables (assumed to be in the local directory) +executables = ["targetimageloadingsmalltalk-c"] + +# Arguments (inserted between executable and benchmark) +executable_arguments = ["%s.image" % SqueakImage, "-m"] + +# Benchmarks (run for each executable) +benchmarks = ["tinyBenchmarks"] + +def build_data(executable, benchmark, result): + # Mandatory fields + return { + 'commitid': get_commitid(), + 'branch': 'default', + 'project': 'lang-smalltalk', + 'executable': executable, + 'benchmark': benchmark, + 'environment': socket.gethostname(), + 'result_value': str(result), + } + # Optional fields + # data.update({ + # 'std_dev': 1.11111, # Optional. Default is blank + # 'max': 4001.6, # Optional. Default is blank + # 'min': 3995.1, # Optional. Default is blank + # }) + + +def download_prerequesites(): + clean_workspace() + import gzip, tarfile + image = urllib2.urlopen("http://ftp.squeak.org/4.4/%s.tgz" % SqueakImage).read() + sources = urllib2.urlopen('http://ftp.squeak.org/4.4/SqueakV41.sources.gz').read() + with open("image.tgz", "w") as f: + f.write(image) + f = gzip.open("image.tgz") + tar = f.read() + f.close() + with open("image.tar", "w") as f: + f.write(tar) + f = tarfile.open("image.tar") + f.extractall(".") + f.close() + with open("sources.gz", "w") as f: + f.write(sources) + f = gzip.open("sources.gz") + with open("SqueakV41.sources", "w") as s: + s.write(f.read()) + f.close() + +def clean_workspace(): + for f in ["image.tgz", "image.tar", "sources.gz", + "SqueakV41.sources", + "%s.image" % SqueakImage, "%s.changes" % SqueakImage]: + try: + os.remove(f) + except: + pass + + +def get_commitid(): + try: + pipe = subprocess.Popen( + ["hg", "log", "-l", "1", "--template", "{node}"], + stdout=subprocess.PIPE + ) + if pipe.wait() == 0: + return pipe.stdout.read() + except: + pass + try: + pipe = subprocess.Popen( + ["git", "log", "-1", "--pretty=%H"], + stdout=subprocess.PIPE + ) + if pipe.wait() == 0: + return pipe.stdout.read() + except: + pass + raise Exception("commitid not found. not a git or hg repo") + + +def add(executable, benchmark, result): + print "Saving result %s for executable %s, benchmark %s" % ( + result, executable, benchmark) + data = build_data(executable, benchmark, result) + params = urllib.urlencode(data) + response = "None" + print "Saving result for executable %s, revision %s, benchmark %s" % ( + data['executable'], data['commitid'], data['benchmark']) + try: + f = urllib2.urlopen(CODESPEED_URL + 'result/add/', params) + except urllib2.HTTPError as e: + print str(e) + print e.read() + return + response = f.read() + f.close() + print "Server (%s) response: %s\n" % (CODESPEED_URL, response) + + +def run(): + suffix = ".exe" if sys.platform == "win32" else "" + for executable in executables: + for benchmark in benchmarks: + start = time.time() + pipe = subprocess.Popen( + ["./%s%s" % (executable, suffix)] + executable_arguments + [benchmark] + ) + pipe.wait() + result = time.time() - start + add(executable, benchmark, result) + + +if __name__ == "__main__": + download_prerequesites() + run() diff --git a/spyvm/model.py b/spyvm/model.py --- a/spyvm/model.py +++ b/spyvm/model.py @@ -14,7 +14,7 @@ W_BlockContext and W_MethodContext classes have been replaced by functions that create W_PointersObjects of correct size with attached shadows. """ -import sys +import sys, weakref from spyvm import constants, error from rpython.rlib import rrandom, objectmodel, jit, signature @@ -335,6 +335,8 @@ def fillin(self, space, g_self): high, low = g_self.get_ruints(required_len=2) + if g_self.reader.version.has_floats_reversed: + low, high = high, low self.fillin_fromwords(space, high, low) def getclass(self, space): @@ -466,32 +468,23 @@ assert s_class is not None return s_class -class W_PointersObject(W_AbstractObjectWithClassReference): +class W_AbstractPointersObject(W_AbstractObjectWithClassReference): """Common object.""" - _attrs_ = ['_shadow', '_vars', 'fieldtypes'] + _attrs_ = ['_shadow'] _shadow = None # Default value @jit.unroll_safe def __init__(self, space, w_class, size): - from spyvm.fieldtypes import fieldtypes_of_length """Create new object with size = fixed + variable size.""" W_AbstractObjectWithClassReference.__init__(self, space, w_class) - - vars = self._vars = [None] * size - self.fieldtypes = fieldtypes_of_length(self.s_class, size) - - for i in range(size): # do it by hand for the JIT's sake - vars[i] = w_nil self._shadow = None # Default value def fillin(self, space, g_self): from spyvm.fieldtypes import fieldtypes_of - self._vars = g_self.get_pointers() self.s_class = g_self.get_class().as_class_get_penumbra(space) self.hash = g_self.get_hash() self.space = space - self.fieldtypes = fieldtypes_of(self) def at0(self, space, index0): # To test, at0 = in varsize part @@ -506,21 +499,11 @@ return self._shadow.fetch(n0) return self._fetch(n0) - def _fetch(self, n0): - # return self._vars[n0] - fieldtypes = jit.promote(self.fieldtypes) - return fieldtypes.fetch(self, n0) - def store(self, space, n0, w_value): if self.has_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 - fieldtypes = jit.promote(self.fieldtypes) - return fieldtypes.store(self, n0, w_value) - def varsize(self, space): return self.size() - self.instsize(space) @@ -535,13 +518,6 @@ return self._shadow.size() return self._size() - def _size(self): - return len(self._vars) - - def invariant(self): - return (W_AbstractObjectWithClassReference.invariant(self) and - isinstance(self._vars, list)) - def store_shadow(self, shadow): assert self._shadow is None or self._shadow is shadow self._shadow = shadow @@ -615,9 +591,8 @@ return self._shadow is not None def become(self, w_other): - if not isinstance(w_other, W_PointersObject): + if not isinstance(w_other, W_AbstractPointersObject): return False - self._vars, w_other._vars = w_other._vars, self._vars # switching means also switching shadows self._shadow, w_other._shadow = w_other._shadow, self._shadow # shadow links are in both directions -> also update shadows @@ -626,22 +601,106 @@ W_AbstractObjectWithClassReference._become(self, w_other) return True + @jit.elidable + def as_repr_string(self): + return W_AbstractObjectWithClassReference.as_embellished_string(self, + className='W_PointersObject', + additionalInformation='len=%d' % self.size()) + +class W_PointersObject(W_AbstractPointersObject): + _attrs_ = ['_vars', 'fieldtypes'] + + @jit.unroll_safe + def __init__(self, space, w_class, size): + from spyvm.fieldtypes import fieldtypes_of_length + """Create new object with size = fixed + variable size.""" + W_AbstractPointersObject.__init__(self, space, w_class, size) + vars = self._vars = [None] * size + self.fieldtypes = fieldtypes_of_length(self.s_class, size) + for i in range(size): # do it by hand for the JIT's sake + vars[i] = w_nil + + def fillin(self, space, g_self): + W_AbstractPointersObject.fillin(self, space, g_self) + from spyvm.fieldtypes import fieldtypes_of + self._vars = g_self.get_pointers() + self.fieldtypes = fieldtypes_of(self) + + def _fetch(self, n0): + # return self._vars[n0] + fieldtypes = jit.promote(self.fieldtypes) + return fieldtypes.fetch(self, n0) + + def _store(self, n0, w_value): + # self._vars[n0] = w_value + fieldtypes = jit.promote(self.fieldtypes) + return fieldtypes.store(self, n0, w_value) + + def _size(self): + return len(self._vars) + + def invariant(self): + return (W_AbstractObjectWithClassReference.invariant(self) and + isinstance(self._vars, list)) + + 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_AbstractPointersObject.become(self, w_other) + def clone(self, space): w_result = W_PointersObject(self.space, self.getclass(space), len(self._vars)) w_result._vars = [self.fetch(space, i) for i in range(len(self._vars))] return w_result - @jit.elidable - def as_repr_string(self): - return W_AbstractObjectWithClassReference.as_embellished_string(self, - className='W_PointersObject', - additionalInformation='len=%d' % self.size()) - def fieldtype(self): from spyvm.fieldtypes import obj return obj +class W_WeakPointersObject(W_AbstractPointersObject): + _attrs_ = ['_weakvars'] + + @jit.unroll_safe + def __init__(self, space, w_class, size): + W_AbstractPointersObject.__init__(self, space, w_class, size) + self._weakvars = [weakref.ref(w_nil)] * size + + def fillin(self, space, g_self): + raise NotImplementedError("we don't expect weak objects in a fresh image") + + def _fetch(self, n0): + weakobj = self._weakvars[n0] + return weakobj() or w_nil + + def _store(self, n0, w_value): + assert w_value is not None + self._weakvars[n0] = weakref.ref(w_value) + + def _size(self): + return len(self._weakvars) + + def invariant(self): + return (W_AbstractObjectWithClassReference.invariant(self) and + isinstance(self._weakvars, list)) + + def become(self, w_other): + if not isinstance(w_other, W_WeakPointersObject): + return False + self._weakvars, w_other._weakvars = w_other._weakvars, self._weakvars + return W_AbstractPointersObject.become(self, w_other) + + def clone(self, space): + w_result = W_WeakPointersObject(self.space, self.getclass(space), + len(self._weakvars)) + for i, var in enumerate(self._weakvars): + w_obj = var() + if w_obj is None: + w_obj = w_nil + w_result._weakvars[i] = weakref.ref(w_obj) + return w_result + class W_BytesObject(W_AbstractObjectWithClassReference): _attrs_ = ['bytes'] diff --git a/spyvm/shadow.py b/spyvm/shadow.py --- a/spyvm/shadow.py +++ b/spyvm/shadow.py @@ -216,6 +216,9 @@ w_new = model.W_LargePositiveInteger1Word(0, extrasize) else: w_new = model.W_BytesObject(self.space, w_cls, extrasize) + elif self.instance_kind == WEAK_POINTERS: + size = self.instsize() + extrasize + w_new = model.W_WeakPointersObject(self.space, w_cls, size) else: raise NotImplementedError(self.instance_kind) return w_new diff --git a/targetimageloadingsmalltalk.py b/targetimageloadingsmalltalk.py --- a/targetimageloadingsmalltalk.py +++ b/targetimageloadingsmalltalk.py @@ -32,7 +32,7 @@ w_benchmark_proc.store(space, 1, s_frame.w_self()) # third variable is priority - priority = 40 + priority = space.unwrap_int(w_hpp.fetch(space, 2)) / 2 + 1 w_benchmark_proc.store(space, 2, space.wrap_int(priority)) # make process eligible for scheduling From noreply at buildbot.pypy.org Mon Apr 29 11:42:26 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Mon, 29 Apr 2013 11:42:26 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: added test for weak pointersobjects Message-ID: <20130429094226.58F921C026F@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r346:92f8216c6434 Date: 2013-04-29 11:42 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/92f8216c6434/ Log: added test for weak pointersobjects diff --git a/spyvm/test/test_model.py b/spyvm/test/test_model.py --- a/spyvm/test/test_model.py +++ b/spyvm/test/test_model.py @@ -314,3 +314,19 @@ assert target.pixelbuffer[i] == 0xff000000 for i in xrange(24, 32): assert target.pixelbuffer[i] == 0xffffffff + + +def test_weak_pointers(): + from spyvm.shadow import WEAK_POINTERS + + w_cls = mockclass(space, 1) + s_cls = w_cls.as_class_get_shadow(space) + s_cls.instance_kind = WEAK_POINTERS + + weak_object = s_cls.new() + referenced = model.W_SmallInteger(10) + weak_object.store(space, 0, referenced) + + assert weak_object.fetch(space, 0) is referenced + del referenced + assert weak_object.fetch(space, 0) is space.w_nil From noreply at buildbot.pypy.org Mon Apr 29 16:33:02 2013 From: noreply at buildbot.pypy.org (fijal) Date: Mon, 29 Apr 2013 16:33:02 +0200 (CEST) Subject: [pypy-commit] pypy kill-gen-store-back-in: kill the pointless ootype tests Message-ID: <20130429143302.E2EC71C1000@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: kill-gen-store-back-in Changeset: r63749:bf4f6792a37d Date: 2013-04-29 16:32 +0200 http://bitbucket.org/pypy/pypy/changeset/bf4f6792a37d/ Log: kill the pointless ootype tests diff --git a/rpython/jit/metainterp/test/test_recursive.py b/rpython/jit/metainterp/test/test_recursive.py --- a/rpython/jit/metainterp/test/test_recursive.py +++ b/rpython/jit/metainterp/test/test_recursive.py @@ -1269,6 +1269,3 @@ class TestLLtype(RecursiveTests, LLJitMixin): pass - -class TestOOtype(RecursiveTests, OOJitMixin): - pass From noreply at buildbot.pypy.org Mon Apr 29 16:33:58 2013 From: noreply at buildbot.pypy.org (fijal) Date: Mon, 29 Apr 2013 16:33:58 +0200 (CEST) Subject: [pypy-commit] pypy kill-gen-store-back-in: remove pointless import Message-ID: <20130429143358.8101D1C1000@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: kill-gen-store-back-in Changeset: r63750:24f9ea70f0ee Date: 2013-04-29 16:33 +0200 http://bitbucket.org/pypy/pypy/changeset/24f9ea70f0ee/ Log: remove pointless import diff --git a/rpython/jit/metainterp/test/test_recursive.py b/rpython/jit/metainterp/test/test_recursive.py --- a/rpython/jit/metainterp/test/test_recursive.py +++ b/rpython/jit/metainterp/test/test_recursive.py @@ -3,7 +3,7 @@ from rpython.rlib.jit import unroll_safe, dont_look_inside, promote from rpython.rlib.objectmodel import we_are_translated from rpython.rlib.debug import fatalerror -from rpython.jit.metainterp.test.support import LLJitMixin, OOJitMixin +from rpython.jit.metainterp.test.support import LLJitMixin from rpython.jit.codewriter.policy import StopAtXPolicy from rpython.rtyper.annlowlevel import hlstr from rpython.jit.metainterp.warmspot import get_stats From noreply at buildbot.pypy.org Mon Apr 29 16:52:30 2013 From: noreply at buildbot.pypy.org (alex_gaynor) Date: Mon, 29 Apr 2013 16:52:30 +0200 (CEST) Subject: [pypy-commit] pypy default: Added support for reversed() on lists Message-ID: <20130429145230.2ECB61C01C2@cobra.cs.uni-duesseldorf.de> Author: Alex Gaynor Branch: Changeset: r63751:0b9b94e3b630 Date: 2013-04-29 07:50 -0700 http://bitbucket.org/pypy/pypy/changeset/0b9b94e3b630/ Log: Added support for reversed() on lists diff --git a/rpython/annotator/builtin.py b/rpython/annotator/builtin.py --- a/rpython/annotator/builtin.py +++ b/rpython/annotator/builtin.py @@ -89,9 +89,15 @@ builtin_xrange = builtin_range # xxx for now allow it + def builtin_enumerate(s_obj): return SomeIterator(s_obj, "enumerate") + +def builtin_reversed(s_obj): + return SomeIterator(s_obj, "reversed") + + def builtin_bool(s_obj): return s_obj.is_true() diff --git a/rpython/annotator/test/test_annrpython.py b/rpython/annotator/test/test_annrpython.py --- a/rpython/annotator/test/test_annrpython.py +++ b/rpython/annotator/test/test_annrpython.py @@ -3837,6 +3837,16 @@ s = a.build_types(fn, [int]) assert isinstance(s, annmodel.SomeInteger) + def test_reversed(self): + def fn(n): + for elem in reversed([1, 2, 3, 4, 5]): + return elem + return n + + a = self.RPythonAnnotator() + s = a.build_types(fn, [int]) + assert isinstance(s, annmodel.SomeInteger) + def test_no_attr_on_common_exception_classes(self): for cls in [ValueError, Exception]: def fn(): diff --git a/rpython/annotator/unaryop.py b/rpython/annotator/unaryop.py --- a/rpython/annotator/unaryop.py +++ b/rpython/annotator/unaryop.py @@ -616,7 +616,10 @@ if itr.variant == ("enumerate",): s_item = itr.s_container.getanyitem() return SomeTuple((SomeInteger(nonneg=True), s_item)) - return itr.s_container.getanyitem(*itr.variant) + variant = itr.variant + if variant == ("reversed",): + variant = () + return itr.s_container.getanyitem(*variant) next.can_only_throw = _can_only_throw method_next = next diff --git a/rpython/rtyper/lltypesystem/rlist.py b/rpython/rtyper/lltypesystem/rlist.py --- a/rpython/rtyper/lltypesystem/rlist.py +++ b/rpython/rtyper/lltypesystem/rlist.py @@ -52,8 +52,13 @@ def get_eqfunc(self): return inputconst(Void, self.item_repr.get_ll_eq_function()) - def make_iterator_repr(self): - return ListIteratorRepr(self) + def make_iterator_repr(self, *variant): + if not variant: + return ListIteratorRepr(self) + elif variant == ("reversed",): + return ReversedListIteratorRepr(self) + else: + raise NotImplementedError(variant) def get_itemarray_lowleveltype(self): ITEM = self.item_repr.lowleveltype @@ -432,6 +437,7 @@ self.ll_listnext = ll_listnext self.ll_getnextindex = ll_getnextindex + def ll_listiter(ITERPTR, lst): iter = malloc(ITERPTR.TO) iter.list = lst @@ -457,3 +463,30 @@ def ll_getnextindex(iter): return iter.index + + +class ReversedListIteratorRepr(AbstractListIteratorRepr): + def __init__(self, r_list): + self.r_list = r_list + self.lowleveltype = Ptr(GcStruct('revlistiter', + ('list', r_list.lowleveltype), + ('index', Signed), + )) + self.ll_listnext = ll_revlistnext + self.ll_listiter = ll_revlistiter + + +def ll_revlistiter(ITERPTR, lst): + iter = malloc(ITERPTR.TO) + iter.list = lst + iter.index = lst.ll_length() - 1 + return iter + + +def ll_revlistnext(iter): + l = iter.list + index = iter.index + if index < 0: + raise StopIteration + iter.index -= 1 + return l.ll_getitem_fast(index) diff --git a/rpython/rtyper/rbuiltin.py b/rpython/rtyper/rbuiltin.py --- a/rpython/rtyper/rbuiltin.py +++ b/rpython/rtyper/rbuiltin.py @@ -261,6 +261,12 @@ hop.exception_cannot_occur() return hop.gendirectcall(ll_max, v1, v2) + +def rtype_builtin_reversed(hop): + hop.exception_cannot_occur() + return hop.r_result.newiter(hop) + + def ll_max(i1, i2): if i1 > i2: return i1 diff --git a/rpython/rtyper/test/test_rlist.py b/rpython/rtyper/test/test_rlist.py --- a/rpython/rtyper/test/test_rlist.py +++ b/rpython/rtyper/test/test_rlist.py @@ -510,6 +510,17 @@ res = self.interpret(dummyfn, ()) assert res == 235 + def test_reversed(self): + klist = [1, 2, 3] + + def fn(): + res = [] + for elem in reversed(klist): + res.append(elem) + return res[0] * 100 + res[1] * 10 + res[2] + res = self.interpret(fn, []) + assert res == fn() + def test_prebuilt_list(self): klist = [6, 7, 8, 9] def dummyfn(n): @@ -1604,3 +1615,6 @@ class TestOOtype(BaseTestRlist, OORtypeMixin): rlist = oo_rlist type_system = 'ootype' + + def test_reversed(self): + py.test.skip("unsupported") From noreply at buildbot.pypy.org Mon Apr 29 16:52:31 2013 From: noreply at buildbot.pypy.org (alex_gaynor) Date: Mon, 29 Apr 2013 16:52:31 +0200 (CEST) Subject: [pypy-commit] pypy default: merged upstream Message-ID: <20130429145231.BE2E51C0246@cobra.cs.uni-duesseldorf.de> Author: Alex Gaynor Branch: Changeset: r63752:580451252cc7 Date: 2013-04-29 07:51 -0700 http://bitbucket.org/pypy/pypy/changeset/580451252cc7/ Log: merged upstream diff --git a/lib-python/2.7/pydoc.py b/lib-python/2.7/pydoc.py --- a/lib-python/2.7/pydoc.py +++ b/lib-python/2.7/pydoc.py @@ -1953,7 +1953,11 @@ if key is None: callback(None, modname, '') else: - desc = split(__import__(modname).__doc__ or '', '\n')[0] + try: + module_doc = __import__(modname).__doc__ + except ImportError: + module_doc = None + desc = split(module_doc or '', '\n')[0] if find(lower(modname + ' - ' + desc), key) >= 0: callback(None, modname, desc) diff --git a/py/_path/local.py b/py/_path/local.py --- a/py/_path/local.py +++ b/py/_path/local.py @@ -655,7 +655,8 @@ mkdtemp = classmethod(mkdtemp) def make_numbered_dir(cls, prefix='session-', rootdir=None, keep=3, - lock_timeout = 172800): # two days + lock_timeout = 172800, # two days + min_timeout = 300): # five minutes """ return unique directory with a number greater than the current maximum one. The number is assumed to start directly after prefix. if keep is true directories with a number less than (maxnum-keep) @@ -723,6 +724,20 @@ for path in rootdir.listdir(): num = parse_num(path) if num is not None and num <= (maxnum - keep): + if min_timeout: + # NB: doing this is needed to prevent (or reduce + # a lot the chance of) the following situation: + # 'keep+1' processes call make_numbered_dir() at + # the same time, they create dirs, but then the + # last process notices the first dir doesn't have + # (yet) a .lock in it and kills it. + try: + t1 = path.lstat().mtime + t2 = lockfile.lstat().mtime + if abs(t2-t1) < min_timeout: + continue # skip directories too recent + except py.error.Error: + continue # failure to get a time, better skip lf = path.join('.lock') try: t1 = lf.lstat().mtime diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py --- a/pypy/module/_cffi_backend/test/_backend_test_c.py +++ b/pypy/module/_cffi_backend/test/_backend_test_c.py @@ -2136,6 +2136,7 @@ def test_errno_callback(): if globals().get('PY_DOT_PY') == '2.5': py.test.skip("cannot run this test on py.py with Python 2.5") + set_errno(95) def cb(): e = get_errno() set_errno(e - 6) diff --git a/rpython/rtyper/test/test_runicode.py b/rpython/rtyper/test/test_runicode.py --- a/rpython/rtyper/test/test_runicode.py +++ b/rpython/rtyper/test/test_runicode.py @@ -274,6 +274,7 @@ test_char_isxxx = unsupported test_isdigit = unsupported test_str_isalpha = unsupported + test_str_isalnum = unsupported test_upper = unsupported test_lower = unsupported test_splitlines = unsupported diff --git a/rpython/rtyper/tool/rffi_platform.py b/rpython/rtyper/tool/rffi_platform.py --- a/rpython/rtyper/tool/rffi_platform.py +++ b/rpython/rtyper/tool/rffi_platform.py @@ -721,6 +721,8 @@ eci = eci.convert_sources_to_files() files = [filepath] output = build_executable_cache(files, eci, ignore_errors=ignore_errors) + if not output.startswith('-+- '): + raise Exception("run_example_code failed!\nlocals = %r" % (locals(),)) section = None for line in output.splitlines(): line = line.strip() diff --git a/rpython/tool/gcc_cache.py b/rpython/tool/gcc_cache.py --- a/rpython/tool/gcc_cache.py +++ b/rpython/tool/gcc_cache.py @@ -1,7 +1,7 @@ from rpython.translator.platform import CompilationError from rpython.conftest import cache_dir from hashlib import md5 -import py +import py, os cache_dir_root = py.path.local(cache_dir).ensure(dir=1) @@ -35,37 +35,45 @@ # compare equal to another instance without it if platform.log_errors != _previous: platform.log_errors = _previous - path.write(result.out) + try_atomic_write(path, result.out) return result.out +def try_atomic_write(path, data): + path = str(path) + tmppath = '%s~%d' % (path, os.getpid()) + f = open(tmppath, 'wb') + f.write(data) + f.close() + try: + os.rename(tmppath, path) + except OSError: + try: + os.unlink(tmppath) + except OSError: + pass + def try_compile_cache(c_files, eci): - "Try to compile a program; caches the result (starts with 'True' or 'FAIL')" + "Try to compile a program. If it works, caches this fact." # Import 'platform' every time, the compiler may have been changed from rpython.translator.platform import platform path = cache_file_path(c_files, eci, 'try_compile_cache') try: data = path.read() + if data == 'True': + return True except py.error.Error: - data = '' - if not (data.startswith('True') or data.startswith('FAIL\n')): - try: - _previous = platform.log_errors - try: - platform.log_errors = False - platform.compile(c_files, eci) - finally: - del platform.log_errors - # ^^^remove from the instance --- needed so that it can - # compare equal to another instance without it - if platform.log_errors != _previous: - platform.log_errors = _previous - data = 'True' - path.write(data) - except CompilationError, e: - data = 'FAIL\n%s\n' % (e,) - if data.startswith('True'): - return True - else: - assert data.startswith('FAIL\n') - msg = data[len('FAIL\n'):] - raise CompilationError(msg.strip(), '') + pass + # + _previous = platform.log_errors + try: + platform.log_errors = False + platform.compile(c_files, eci) + # ^^^ may raise CompilationError. We don't cache such results. + finally: + del platform.log_errors + # ^^^remove from the instance --- needed so that it can + # compare equal to another instance without it + if platform.log_errors != _previous: + platform.log_errors = _previous + path.write('True') + return True From noreply at buildbot.pypy.org Mon Apr 29 17:51:33 2013 From: noreply at buildbot.pypy.org (ltratt) Date: Mon, 29 Apr 2013 17:51:33 +0200 (CEST) Subject: [pypy-commit] pypy default: Update import to reflect pypy/rpython directory split. Message-ID: <20130429155133.E55771C00BD@cobra.cs.uni-duesseldorf.de> Author: Laurence Tratt Branch: Changeset: r63753:5ddc7be1ee16 Date: 2013-04-29 17:50 +0200 http://bitbucket.org/pypy/pypy/changeset/5ddc7be1ee16/ Log: Update import to reflect pypy/rpython directory split. diff --git a/rpython/translator/platform/openbsd.py b/rpython/translator/platform/openbsd.py --- a/rpython/translator/platform/openbsd.py +++ b/rpython/translator/platform/openbsd.py @@ -2,7 +2,7 @@ import os -from pypy.translator.platform.bsd import BSD +from rpython.translator.platform.bsd import BSD class OpenBSD(BSD): name = "openbsd" From noreply at buildbot.pypy.org Mon Apr 29 17:53:37 2013 From: noreply at buildbot.pypy.org (ltratt) Date: Mon, 29 Apr 2013 17:53:37 +0200 (CEST) Subject: [pypy-commit] pypy default: The default compiler on OpenBSD isn't clang. Message-ID: <20130429155337.226D31C0246@cobra.cs.uni-duesseldorf.de> Author: Laurence Tratt Branch: Changeset: r63754:dbd71b24f537 Date: 2013-04-29 17:53 +0200 http://bitbucket.org/pypy/pypy/changeset/dbd71b24f537/ Log: The default compiler on OpenBSD isn't clang. There's no reason to hard-code a compiler name: cc will always point to the operating system blessed compiler. diff --git a/rpython/translator/platform/openbsd.py b/rpython/translator/platform/openbsd.py --- a/rpython/translator/platform/openbsd.py +++ b/rpython/translator/platform/openbsd.py @@ -5,6 +5,7 @@ from rpython.translator.platform.bsd import BSD class OpenBSD(BSD): + DEFAULT_CC = "cc" name = "openbsd" link_flags = os.environ.get("LDFLAGS", '-pthread').split() From noreply at buildbot.pypy.org Mon Apr 29 19:19:39 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Mon, 29 Apr 2013 19:19:39 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: added filetree repository to the hg repository to enable smalltalk source control e.g. for benchmarks and formatting code Message-ID: <20130429171939.527BF1C026F@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r347:36fa25ccafbe Date: 2013-04-29 13:50 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/36fa25ccafbe/ Log: added filetree repository to the hg repository to enable smalltalk source control e.g. for benchmarks and formatting code diff --git a/.filetree b/.filetree new file mode 100644 --- /dev/null +++ b/.filetree @@ -0,0 +1,1 @@ +{ "packageExtension" : ".package" } diff --git a/SPy-Benchmarks.package/.filetree b/SPy-Benchmarks.package/.filetree new file mode 100644 --- /dev/null +++ b/SPy-Benchmarks.package/.filetree @@ -0,0 +1,4 @@ +{ + "noMethodMetaData" : true, + "separateMethodMetaAndSource" : false, + "useCypressPropertiesFile" : true } diff --git a/SPy-Benchmarks.package/Integer.extension/instance/runSPyBenchmarks.st b/SPy-Benchmarks.package/Integer.extension/instance/runSPyBenchmarks.st new file mode 100644 --- /dev/null +++ b/SPy-Benchmarks.package/Integer.extension/instance/runSPyBenchmarks.st @@ -0,0 +1,3 @@ +*SPy-Benchmarks +runSPyBenchmarks + ^ SPyRunner run \ No newline at end of file diff --git a/SPy-Benchmarks.package/Integer.extension/methodProperties.json b/SPy-Benchmarks.package/Integer.extension/methodProperties.json new file mode 100644 --- /dev/null +++ b/SPy-Benchmarks.package/Integer.extension/methodProperties.json @@ -0,0 +1,5 @@ +{ + "class" : { + }, + "instance" : { + "runSPyBenchmarks" : "lw 4/29/2013 13:20" } } diff --git a/SPy-Benchmarks.package/Integer.extension/properties.json b/SPy-Benchmarks.package/Integer.extension/properties.json new file mode 100644 --- /dev/null +++ b/SPy-Benchmarks.package/Integer.extension/properties.json @@ -0,0 +1,2 @@ +{ + "name" : "Integer" } diff --git a/SPy-Benchmarks.package/SPyRunner.class/README.md b/SPy-Benchmarks.package/SPyRunner.class/README.md new file mode 100644 diff --git a/SPy-Benchmarks.package/SPyRunner.class/class/format..st b/SPy-Benchmarks.package/SPyRunner.class/class/format..st new file mode 100644 --- /dev/null +++ b/SPy-Benchmarks.package/SPyRunner.class/class/format..st @@ -0,0 +1,14 @@ +benchmarks +format: result + "self run" + "runs all the benchmarks and creates a string of csv format with one column per benchmarks" + ^ String streamContents: + [ :aStream | | someSymbols | + someSymbols := result keys. + someSymbols + do: [ :aSymbol | aStream << aSymbol] + separatedBy: [ aStream << ';' ]. + aStream << String lf. + someSymbols + do: [ :aSymbol | aStream << (result at: aSymbol)] + separatedBy: [aStream << ';']] \ No newline at end of file diff --git a/SPy-Benchmarks.package/SPyRunner.class/class/run.st b/SPy-Benchmarks.package/SPyRunner.class/class/run.st new file mode 100644 --- /dev/null +++ b/SPy-Benchmarks.package/SPyRunner.class/class/run.st @@ -0,0 +1,9 @@ +benchmarks +run + "self run" + | result printString | + result := self runShootout. + printString := self format: result. + (Smalltalk vmParameterAt: 3) = 0 + ifTrue: [^printString] "SPy VM does not support stdout, yet" + ifFalse: [FileStream stdout nextPutAll: printString] \ No newline at end of file diff --git a/SPy-Benchmarks.package/SPyRunner.class/class/runShootout.st b/SPy-Benchmarks.package/SPyRunner.class/class/runShootout.st new file mode 100644 --- /dev/null +++ b/SPy-Benchmarks.package/SPyRunner.class/class/runShootout.st @@ -0,0 +1,15 @@ +benchmarks +runShootout + "self runShootout explore" + | stream times | + stream := (ByteString new: 10000) writeStream. + times := Dictionary new. + { [ShootoutTests nbody: 200000 "20000000" to: stream]. + [ShootoutTests binarytrees: 17 to: stream]. + [ShootoutTests chameneosredux: 2600000 to: stream]. + [ShootoutTests threadring: 100000000 to: stream] } do: + [:block | | benchmark t | + benchmark := (ShootoutTests selectorForSimpleBlock: block) copyUpTo: $:. + "Smalltalk garbageCollect." + times at: benchmark put: (t := Time millisecondsToRun: block)]. + ^times \ No newline at end of file diff --git a/SPy-Benchmarks.package/SPyRunner.class/methodProperties.json b/SPy-Benchmarks.package/SPyRunner.class/methodProperties.json new file mode 100644 --- /dev/null +++ b/SPy-Benchmarks.package/SPyRunner.class/methodProperties.json @@ -0,0 +1,7 @@ +{ + "class" : { + "format:" : "lw 4/29/2013 13:34", + "run" : "lw 4/29/2013 13:37", + "runShootout" : "lw 4/29/2013 13:17" }, + "instance" : { + } } diff --git a/SPy-Benchmarks.package/SPyRunner.class/properties.json b/SPy-Benchmarks.package/SPyRunner.class/properties.json new file mode 100644 --- /dev/null +++ b/SPy-Benchmarks.package/SPyRunner.class/properties.json @@ -0,0 +1,14 @@ +{ + "category" : "SPy-Benchmarks", + "classinstvars" : [ + ], + "classvars" : [ + ], + "commentStamp" : "", + "instvars" : [ + ], + "name" : "SPyRunner", + "pools" : [ + ], + "super" : "Object", + "type" : "normal" } diff --git a/SPy-Benchmarks.package/monticello.meta/categories.st b/SPy-Benchmarks.package/monticello.meta/categories.st new file mode 100644 --- /dev/null +++ b/SPy-Benchmarks.package/monticello.meta/categories.st @@ -0,0 +1,1 @@ +SystemOrganization addCategory: #'SPy-Benchmarks'! diff --git a/SPy-Benchmarks.package/monticello.meta/initializers.st b/SPy-Benchmarks.package/monticello.meta/initializers.st new file mode 100644 diff --git a/SPy-Benchmarks.package/monticello.meta/package b/SPy-Benchmarks.package/monticello.meta/package new file mode 100644 --- /dev/null +++ b/SPy-Benchmarks.package/monticello.meta/package @@ -0,0 +1,1 @@ +(name 'SPy-Benchmarks') \ No newline at end of file diff --git a/SPy-Benchmarks.package/monticello.meta/version b/SPy-Benchmarks.package/monticello.meta/version new file mode 100644 --- /dev/null +++ b/SPy-Benchmarks.package/monticello.meta/version @@ -0,0 +1,1 @@ +(name 'SPy-Benchmarks-lw.2' message 'second try for an initial commit with shootout tests' id 'e538d5dc-ff13-4753-a166-bb95af0c7e0b' date '29 April 2013' time '1:41:50.098 pm' author 'lw' ancestors ((name 'SPy-Benchmarks-lw.1' message 'initial commit with existing Shootout tests' id '67ba6a6a-5476-4dc0-892f-de76933491e8' date '29 April 2013' time '1:40:20.34 pm' author 'lw' ancestors () stepChildren ())) stepChildren ()) \ No newline at end of file diff --git a/SPy-Benchmarks.package/properties.json b/SPy-Benchmarks.package/properties.json new file mode 100644 --- /dev/null +++ b/SPy-Benchmarks.package/properties.json @@ -0,0 +1,2 @@ +{ + } From noreply at buildbot.pypy.org Mon Apr 29 19:19:40 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Mon, 29 Apr 2013 19:19:40 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: new version of SPy-Benchmarks: Message-ID: <20130429171940.732FF1C026F@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r348:53e6327fd264 Date: 2013-04-29 18:09 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/53e6327fd264/ Log: new version of SPy-Benchmarks: changes needed to be able to run with spy diff --git a/SPy-Benchmarks.package/SPyRunner.class/class/format..st b/SPy-Benchmarks.package/SPyRunner.class/class/format..st --- a/SPy-Benchmarks.package/SPyRunner.class/class/format..st +++ b/SPy-Benchmarks.package/SPyRunner.class/class/format..st @@ -3,12 +3,7 @@ "self run" "runs all the benchmarks and creates a string of csv format with one column per benchmarks" ^ String streamContents: - [ :aStream | | someSymbols | - someSymbols := result keys. - someSymbols - do: [ :aSymbol | aStream << aSymbol] - separatedBy: [ aStream << ';' ]. - aStream << String lf. - someSymbols - do: [ :aSymbol | aStream << (result at: aSymbol)] - separatedBy: [aStream << ';']] \ No newline at end of file + [ :aStream | + result keysAndValuesDo: + [ :key :value | + aStream << key << ';' << value << String lf]] \ No newline at end of file diff --git a/SPy-Benchmarks.package/SPyRunner.class/class/run.st b/SPy-Benchmarks.package/SPyRunner.class/class/run.st --- a/SPy-Benchmarks.package/SPyRunner.class/class/run.st +++ b/SPy-Benchmarks.package/SPyRunner.class/class/run.st @@ -1,9 +1,11 @@ benchmarks run "self run" - | result printString | + | result result2 | result := self runShootout. - printString := self format: result. - (Smalltalk vmParameterAt: 3) = 0 - ifTrue: [^printString] "SPy VM does not support stdout, yet" - ifFalse: [FileStream stdout nextPutAll: printString] \ No newline at end of file + result2 := self runTinyBenchmarks. + result at: #benchmark put: (result2 at: #benchmark). + result at: #benchFib put: (result2 at: #benchFib). + + ^self format: result. + \ No newline at end of file diff --git a/SPy-Benchmarks.package/SPyRunner.class/class/runShootout.st b/SPy-Benchmarks.package/SPyRunner.class/class/runShootout.st --- a/SPy-Benchmarks.package/SPyRunner.class/class/runShootout.st +++ b/SPy-Benchmarks.package/SPyRunner.class/class/runShootout.st @@ -6,8 +6,8 @@ times := Dictionary new. { [ShootoutTests nbody: 200000 "20000000" to: stream]. [ShootoutTests binarytrees: 17 to: stream]. - [ShootoutTests chameneosredux: 2600000 to: stream]. - [ShootoutTests threadring: 100000000 to: stream] } do: + "[ShootoutTests chameneosredux: 2600000 to: stream]. + [ShootoutTests threadring: 100000000 to: stream]" } do: [:block | | benchmark t | benchmark := (ShootoutTests selectorForSimpleBlock: block) copyUpTo: $:. "Smalltalk garbageCollect." diff --git a/SPy-Benchmarks.package/SPyRunner.class/methodProperties.json b/SPy-Benchmarks.package/SPyRunner.class/methodProperties.json --- a/SPy-Benchmarks.package/SPyRunner.class/methodProperties.json +++ b/SPy-Benchmarks.package/SPyRunner.class/methodProperties.json @@ -1,7 +1,8 @@ { "class" : { - "format:" : "lw 4/29/2013 13:34", - "run" : "lw 4/29/2013 13:37", - "runShootout" : "lw 4/29/2013 13:17" }, + "format:" : "lw 4/29/2013 17:13", + "run" : "lw 4/29/2013 17:51", + "runShootout" : "lw 4/29/2013 18:05", + "runTinyBenchmarks" : "lw 4/29/2013 17:39" }, "instance" : { } } diff --git a/SPy-Benchmarks.package/monticello.meta/version b/SPy-Benchmarks.package/monticello.meta/version --- a/SPy-Benchmarks.package/monticello.meta/version +++ b/SPy-Benchmarks.package/monticello.meta/version @@ -1,1 +1,1 @@ -(name 'SPy-Benchmarks-lw.2' message 'second try for an initial commit with shootout tests' id 'e538d5dc-ff13-4753-a166-bb95af0c7e0b' date '29 April 2013' time '1:41:50.098 pm' author 'lw' ancestors ((name 'SPy-Benchmarks-lw.1' message 'initial commit with existing Shootout tests' id '67ba6a6a-5476-4dc0-892f-de76933491e8' date '29 April 2013' time '1:40:20.34 pm' author 'lw' ancestors () stepChildren ())) stepChildren ()) \ No newline at end of file +(name 'SPy-Benchmarks-lw.4' message 'changed the test running and collecting to work with the current spy vm removed two of the shootout tests due to failure on spy' id '9d1c1e0a-0209-45d3-8e0a-220919ab5701' date '29 April 2013' time '6:07:26.686 pm' author 'lw' ancestors ((name 'SPy-Benchmarks-lw.3' message 'added tiny benchmarks' id 'c8214449-4009-4a64-8284-3c58395fe2bc' date '29 April 2013' time '2:15:43.242 pm' author 'lw' ancestors ((name 'SPy-Benchmarks-lw.2' message 'second try for an initial commit with shootout tests' id 'e538d5dc-ff13-4753-a166-bb95af0c7e0b' date '29 April 2013' time '1:41:50.098 pm' author 'lw' ancestors ((name 'SPy-Benchmarks-lw.1' message 'initial commit with existing Shootout tests' id '67ba6a6a-5476-4dc0-892f-de76933491e8' date '29 April 2013' time '1:40:20.34 pm' author 'lw' ancestors () stepChildren ())) stepChildren ())) stepChildren ())) stepChildren ()) \ No newline at end of file From noreply at buildbot.pypy.org Mon Apr 29 19:19:41 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Mon, 29 Apr 2013 19:19:41 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: Redid benchmark.py to execute cog and spy both and parse their output looking for 'k; v' lines, which are interpreted as benchmarks. Message-ID: <20130429171941.8AE5F1C026F@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r349:b3e0adff55bb Date: 2013-04-29 19:14 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/b3e0adff55bb/ Log: Redid benchmark.py to execute cog and spy both and parse their output looking for 'k;v' lines, which are interpreted as benchmarks. This way, we can run more than one benchmark in one execution Added update step. The intent is to update the committed image based on the filetree information. The actual updating is still missing. The differences between cog and spy startup and returns are factored out into benchmarks.st, thus removing the neccessity to do VM- guessing inside the image-code. diff --git a/benchmarks.py b/benchmarks.py --- a/benchmarks.py +++ b/benchmarks.py @@ -7,19 +7,16 @@ import urllib import urllib2 -SqueakImage = "Squeak4.4-12327" +SqueakImage = "Squeak4.5-12568" # You need to enter the real URL and have the server running CODESPEED_URL = 'http://speed.bithug.org/' # Executables (assumed to be in the local directory) -executables = ["targetimageloadingsmalltalk-c"] +executables = ["targetimageloadingsmalltalk-c", "coglinux/squeak"] # Arguments (inserted between executable and benchmark) -executable_arguments = ["%s.image" % SqueakImage, "-m"] - -# Benchmarks (run for each executable) -benchmarks = ["tinyBenchmarks"] +executable_arguments = [["images/%s.image" % SqueakImage, '-m', 'runSPyBenchmarks'], ["images/%s.image" % SqueakImage, '../benchmarks.st']] def build_data(executable, benchmark, result): # Mandatory fields @@ -33,49 +30,69 @@ 'result_value': str(result), } # Optional fields - # data.update({ + # { # 'std_dev': 1.11111, # Optional. Default is blank # 'max': 4001.6, # Optional. Default is blank # 'min': 3995.1, # Optional. Default is blank - # }) + # } +def ungzip(url, name, target): + import gzip + zip_contents = urllib2.urlopen(url).read() + with open(name, "w") as f: + f.write(zip_contents) + f = gzip.open(name) + with open(target, "w") as s: + s.write(f.read()) + +def untar(name, target): + import tarfile + try: + f = tarfile.open(name) + f.extractall(target) + finally: + f.close() + def download_prerequesites(): clean_workspace() - import gzip, tarfile - image = urllib2.urlopen("http://ftp.squeak.org/4.4/%s.tgz" % SqueakImage).read() - sources = urllib2.urlopen('http://ftp.squeak.org/4.4/SqueakV41.sources.gz').read() - with open("image.tgz", "w") as f: - f.write(image) - f = gzip.open("image.tgz") - tar = f.read() - f.close() - with open("image.tar", "w") as f: - f.write(tar) - f = tarfile.open("image.tar") - f.extractall(".") - f.close() - with open("sources.gz", "w") as f: - f.write(sources) - f = gzip.open("sources.gz") - with open("SqueakV41.sources", "w") as s: - s.write(f.read()) - f.close() + print 'Downloading', + download_cog() + print 'done' + +def download_cog(): + if sys.platform == "win32": + url = "http://www.mirandabanda.org/files/Cog/VM/VM.r2714/cogwin-13.13.2714.zip" + unzip(url, 'cogwin.zip', '.') + else: + url = "http://www.mirandabanda.org/files/Cog/VM/VM.r2714/coglinux-13.13.2714.tgz" + print '.', + ungzip(url, 'coglinux.tgz', 'coglinux.tar') + print '.', + untar('coglinux.tar', '.') def clean_workspace(): - for f in ["image.tgz", "image.tar", "sources.gz", - "SqueakV41.sources", - "%s.image" % SqueakImage, "%s.changes" % SqueakImage]: + print 'Cleaning workspace', + for f in ["image.tgz", "image.tar", + 'coglinux.tgz', 'coglinux.tar', + 'cogwin.zip']: try: os.remove(f) except: pass - + print '.', + for d in ['coglinux', 'cogwin']: + try: + shutil.rmtree(d) + except: + pass + print '.', + print 'done' def get_commitid(): try: pipe = subprocess.Popen( - ["hg", "log", "-l", "1", "--template", "{node}"], + ["hg", "log", "-l", "1", "--template", "{branch}-{rev} {date|shortdate}"], stdout=subprocess.PIPE ) if pipe.wait() == 0: @@ -112,19 +129,34 @@ f.close() print "Server (%s) response: %s\n" % (CODESPEED_URL, response) +def update_image(suffix): + with open('update.st', 'w') as f: + f.write('''Smalltalk snapshot: true andQuit: true.''') + pipe = subprocess.Popen( + ['cogmtlinux/squeak%s images/%s ../update.st' % (suffix, SqueakImage)], + shell=True) + pipe.wait() + os.remove('update.st') + def run(): suffix = ".exe" if sys.platform == "win32" else "" - for executable in executables: - for benchmark in benchmarks: - start = time.time() - pipe = subprocess.Popen( - ["./%s%s" % (executable, suffix)] + executable_arguments + [benchmark] - ) - pipe.wait() - result = time.time() - start - add(executable, benchmark, result) + update_image(suffix) + for i, executable in enumerate(executables): + print 'Calling %s ...' % executable + pipe = subprocess.Popen( + ["./%s%s" % (executable, suffix)] + executable_arguments[i], + stdout=subprocess.PIPE + ) + out, err = pipe.communicate() + errcode = pipe.wait() + benchmarks = out.split('\n') + print out + for s in benchmarks: + if ';' in s: + name, time = s.split(';') + add(executable, name, time) if __name__ == "__main__": download_prerequesites() diff --git a/benchmarks.st b/benchmarks.st new file mode 100644 --- /dev/null +++ b/benchmarks.st @@ -0,0 +1,2 @@ +FileStream stdout nextPutAll: 0 runSPyBenchmarks. +Smalltalk snapshot: false andQuit: true diff --git a/spyvm/squeakimage.py b/spyvm/squeakimage.py --- a/spyvm/squeakimage.py +++ b/spyvm/squeakimage.py @@ -248,7 +248,7 @@ # 1 word last used hash lasthash = self.stream.next() savedwindowssize = self.stream.next() - print "savedwindowssize", savedwindowssize + # print "savedwindowssize", savedwindowssize fullscreenflag = self.stream.next() extravmmemory = self.stream.next() self.stream.skipbytes(headersize - self.stream.pos) From noreply at buildbot.pypy.org Mon Apr 29 19:19:56 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Mon, 29 Apr 2013 19:19:56 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: adding the image used by benchmarks.py for stuff Message-ID: <20130429171956.A1E091C026F@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r350:5df83dc92910 Date: 2013-04-29 19:16 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/5df83dc92910/ Log: adding the image used by benchmarks.py for stuff diff too long, truncating to 2000 out of 246604 lines diff --git a/SPy-Benchmarks.package/SPyRunner.class/class/runTinyBenchmarks.st b/SPy-Benchmarks.package/SPyRunner.class/class/runTinyBenchmarks.st new file mode 100644 --- /dev/null +++ b/SPy-Benchmarks.package/SPyRunner.class/class/runTinyBenchmarks.st @@ -0,0 +1,17 @@ +benchmarks +runTinyBenchmarks + | t1 t2 r n1 n2 | + n1 := 5200. + t1 := Time millisecondsToRun: [n1 benchmark]. + "Note: #benchmark's runtime is about O(n)" + + n2 := 42. + t2 := Time millisecondsToRun: [r := n2 benchFib]. + "Note: #benchFib's runtime is about O(k^n), + where k is the golden number = (1 + 5 sqrt) / 2 = 1.618...." + + ^ Dictionary new + at: #benchmark put: t1; + at: #benchFib put: t2; + yourself "((n1 * 500000 * 1000) // t1) printString, ' bytecodes/sec; ', + ((r * 1000) // t2) printString, ' sends/sec'" \ No newline at end of file diff --git a/images/Squeak4.5-12568.changes b/images/Squeak4.5-12568.changes new file mode 100644 --- /dev/null +++ b/images/Squeak4.5-12568.changes @@ -0,0 +1,39 @@ +'From Squeak4.1 of 17 April 2010 [latest update: #9957] on 17 April 2010 at 5:22:05 pm'! ----STARTUP----{17 April 2010 . 5:21:54 pm} as C:\Squeak\4.0\4.1-final\Squeak4.1.image! Smalltalk appendChangesTo: 'SqueakV41.sources'.! ----QUIT----{17 April 2010 . 5:22:11 pm} Squeak4.1.image priorSource: 89! ----STARTUP----{24 May 2010 . 8:07:26 pm} as C:\Squeak\4.2\Squeak4.1.image! ----SNAPSHOT----{24 May 2010 . 8:08:14 pm} Squeak4.2.image priorSource: 229! !HashedCollection commentStamp: 'ul 4/12/2010 22:37' prior: 0! I am an abstract collection of objects that implement hash and equality in a consitent way. This means that whenever two objects are equal, their hashes have to be equal too. If two objects are equal then I can only store one of them. Hashes are expected to be integers (preferably SmallIntegers). I also expect that the objects contained by me do not change their hashes. If that happens, hash invariants have to be re-established, which can be done by #rehash. Since I'm abstract, no instances of me should exist. My subclasses should implement #scanFor:, #fixCollisionsFrom: and #noCheckNoGrowFillFrom:. Instance Variables array: (typically Array or WeakArray) tally: (non-negative) array - An array whose size is a prime number, it's non-nil elements are the elements of the collection, and whose nil elements are empty slots. There is always at least one nil. In fact I try to keep my "load" at 75% or less so that hashing will work well. tally - The number of elements in the collection. The array size is always greater than this. Implementation details: I implement a hash table which uses open addressing with linear probing as the method of collision resolution. Searching for an element or a free slot for an element is done by #scanFor: which should return the index of the slot in array corresponding to it's argument. When an element is removed #fixCollisionsFrom: should rehash all elements in array between the original index of the removed element, wrapping around after the last slot until reaching an empty slot. My maximum load factor (75%) is hardcoded in #atNewIndex:put:, so it can only be changed by overriding that method. When my load factor reaches this limit I replace my array with a larger one (see #grow) ensuring that my load factor will be less than or equal to 50%. The new array is filled by #noCheckNoGrowFillFrom: which should use #scanForEmptySlotFor: instead of #scanFor: for better performance. I do not shrink. ! !WeakKeyDictionary methodsFor: 'private' stamp: 'ul 4/12/2010 22:59'! compact "Reduce the size of array so that the load factor will be ~75%." | newCapacity | newCapacity := self class goodPrimeAtLeast: self slowSize * 4 // 3. self growTo: newCapacity! ! !Collection methodsFor: 'adding' stamp: 'ul 4/12/2010 22:33' prior: 18816249! add: newObject withOccurrences: anInteger "Add newObject anInteger times to the receiver. Do nothing if anInteger is less than one. Answer newObject." anInteger timesRepeat: [self add: newObject]. ^ newObject! ! !HashedCollection class methodsFor: 'initialize-release' stamp: 'ul 4/12/2010 23:49'! compactAll "HashedCollection compactAll" self allSubclassesDo: #compactAllInstances! ! !HashedCollection class methodsFor: 'initialize-release' stamp: 'ul 4/12/2010 23:49'! compactAllInstances "Do not use #allInstancesDo: because compact may create new instances." self allInstances do: #compact! ! !HashedCollection class methodsFor: 'sizing' stamp: 'ul 4/7/2010 00:17' prior: 55063414! goodPrimes "Answer a sorted array of prime numbers less than one billion that make good hash table sizes. Should be expanded as needed. See comments below code" ^#( 5 11 17 23 31 43 59 79 107 149 199 269 359 479 641 857 1151 1549 2069 2237 2423 2617 2797 2999 3167 3359 3539 3727 3911 4441 4787 5119 5471 5801 6143 6521 6827 7177 7517 7853 8783 9601 10243 10867 11549 12239 12919 13679 14293 15013 15731 17569 19051 20443 21767 23159 24611 25847 27397 28571 30047 31397 35771 38201 40841 43973 46633 48989 51631 54371 57349 60139 62969 70589 76091 80347 85843 90697 95791 101051 106261 111143 115777 120691 126311 140863 150523 160969 170557 181243 190717 201653 211891 221251 232591 242873 251443 282089 300869 321949 341227 362353 383681 401411 422927 443231 464951 482033 504011 562621 605779 647659 681607 723623 763307 808261 844709 886163 926623 967229 1014617 1121987 1201469 1268789 1345651 1429531 1492177 1577839 1651547 1722601 1800377 1878623 1942141 2028401 2242727 2399581 2559173 2686813 2836357 3005579 3144971 3283993 3460133 3582923 3757093 3903769 4061261 4455361 4783837 5068529 5418079 5680243 6000023 6292981 6611497 6884641 7211599 7514189 7798313 8077189 9031853 9612721 10226107 10745291 11338417 11939203 12567671 13212697 13816333 14337529 14938571 15595673 16147291 17851577 18993941 20180239 21228533 22375079 23450491 24635579 25683871 26850101 27921689 29090911 30153841 31292507 32467307 35817611 37983761 40234253 42457253 44750177 46957969 49175831 51442639 53726417 55954637 58126987 60365939 62666977 64826669 71582779 76039231 80534381 84995153 89500331 93956777 98470819 102879613 107400389 111856841 116365721 120819287 125246581 129732203 143163379 152076289 161031319 169981667 179000669 187913573 196826447 205826729 214748357 223713691 232679021 241591901 250504801 259470131 285162679 301939921 318717121 335494331 352271573 369148753 385926017 402603193 419480419 436157621 453034849 469712051 486589307 503366497 520043707 570475349 603929813 637584271 671138659 704693081 738247541 771801929 805356457 838910803 872365267 905919671 939574117 973128521 1006682977 1040137411 1073741833) "The above primes past 2069 were chosen carefully so that they do not interact badly with 1664525 (used by hashMultiply), and so that gcd(p, (256^k) +/- a) = 1, for 0 cost ifTrue: [ cost := newCost ] ]. cost ]."! ! !HashedCollection methodsFor: 'adding' stamp: 'ul 4/12/2010 22:38' prior: 53647096! add: newObject withOccurrences: anInteger "Add newObject anInteger times to the receiver. Do nothing if anInteger is less than one. Answer newObject." anInteger < 1 ifTrue: [ ^newObject ]. ^self add: newObject "I can only store an object once." ! ! !HashedCollection methodsFor: 'private' stamp: 'ul 4/12/2010 22:53'! compact "Reduce the size of array so that the load factor will be ~75%." | newCapacity | newCapacity := self class goodPrimeAtLeast: tally * 4 // 3. self growTo: newCapacity! ! !WeakSet methodsFor: 'private' stamp: 'ul 4/12/2010 22:59'! compact "Reduce the size of array so that the load factor will be ~75%." | newCapacity | newCapacity := self class goodPrimeAtLeast: self slowSize * 4 // 3. self growTo: newCapacity! ! !Symbol class methodsFor: 'class initialization' stamp: 'ul 4/13/2010 00:00' prior: 30357901! compactSymbolTable "Reduce the size of the symbol table so that it holds all existing symbols with 25% free space." | oldSize | Smalltalk garbageCollect. oldSize := SymbolTable capacity. SymbolTable compact. ^(oldSize - SymbolTable capacity) printString, ' slot(s) reclaimed'! ! KeyedIdentitySet class removeSelector: #goodPrimes! WeakIdentityKeyDictionary class removeSelector: #goodPrimes! IdentitySet class removeSelector: #goodPrimes! IdentityDictionary class removeSelector: #goodPrimes! "Collections"! !HashedCollectionTest methodsFor: 'test - class - sizing' stamp: 'ul 4/7/2010 00:18' prior: 58761579! testPrimes: primes | badPrimes | badPrimes := #(3 5 71 139 479 5861 277421). "These primes are less than the hashMultiply constant (1664525) and 1664525 \\ prime is close to 0 (mod prime). The following snippet reproduces these numbers: | hashMultiplyConstant | hashMultiplyConstant := 1 hashMultiply. (Integer primesUpTo: hashMultiplyConstant) select: [ :each | | remainder | remainder := hashMultiplyConstant \\ each. remainder <= 1 or: [ remainder + 1 = each ] ]." self assert: primes isSorted. primes do: [ :each | self assert: each isPrime. self deny: (each > 2069 and: [ badPrimes includes: each ]) ]. self assert: ( primes select: [ :p | | result | result := false. p > 2069 ifTrue: [ 1 to: 8 do: [ :k | 1 to: 32 do: [ :a | (p gcd: (256 raisedTo: k) + a) = 1 ifFalse: [ result := true ]. (p gcd: (256 raisedTo: k) - a) = 1 ifFalse: [ result := true ] ] ] ]. result ]) isEmpty.! ! HashedCollectionTest removeSelector: #testGoodPrimesForIdentityBasedHashedCollections! "CollectionsTests"! !MCMczReader methodsFor: 'as yet unclassified' stamp: 'bf 4/18/2010 18:38' prior: 22938947! extractInfoFrom: dict ^MCWorkingCopy infoFromDictionary: dict cache: self infoCache! ! !MCWorkingCopy class methodsFor: 'as yet unclassified' stamp: 'bf 4/19/2010 00:39' prior: 23215403! infoFromDictionary: aDictionary cache: cache | id | id := (aDictionary at: #id) asString. ^ cache at: id ifAbsentPut: [MCVersionInfo name: (aDictionary at: #name ifAbsent: ['']) id: (UUID fromString: id) message: (aDictionary at: #message ifAbsent: ['']) date: ([Date fromString: (aDictionary at: #date)] ifError: [nil]) time: ([Time fromString: (aDictionary at: #time)] ifError: [nil]) author: (aDictionary at: #author ifAbsent: ['']) ancestors: (self ancestorsFromArray: (aDictionary at: #ancestors ifAbsent: []) cache: cache) stepChildren: (self ancestorsFromArray: (aDictionary at: #stepChildren ifAbsent: []) cache: cache)]! ! !MCVersionInfo methodsFor: 'converting' stamp: 'bf 4/18/2010 23:25' prior: 23175569! asDictionary ^ Dictionary new at: #name put: name; at: #id put: id asString; at: #message put: message; at: #date put: date; at: #time put: time; at: #author put: author; at: #ancestors put: (self ancestors collect: [:a | a asDictionary]); yourself! ! "Monticello"! !BlockContextTest methodsFor: 'running' stamp: 'md 9/6/2005 19:56' prior: 50431957! setUp super setUp. aBlockContext := [100 at 100 corner: 200 at 200]. contextOfaBlockContext := thisContext.! ! !BehaviorTest methodsFor: 'tests' stamp: 'md 2/18/2006 16:42' prior: 17365994! testBinding self assert: Object binding value = Object. self assert: Object binding key = #Object. self assert: Object class binding value = Object class. "returns nil for Metaclasses... like Encoder>>#associationFor:" self assert: Object class binding key = nil.! ! !CompledMethodTrailerTest methodsFor: 'testing' stamp: 'Igor.Stasenko 12/13/2009 21:13' prior: 53956757! testEmbeddingSourceCode | trailer newTrailer code | trailer := CompiledMethodTrailer new. code := 'foo'. trailer sourceCode: code. newTrailer := trailer testEncoding. self assert: (trailer kind == #EmbeddedSourceQCompress ). self assert: (newTrailer sourceCode = code). "the last bytecode index must be at 0" self assert: (newTrailer endPC = 0). code := 'testEmbeddingSourceCode | trailer newTrailer code | trailer := CompiledMethodTrailer new. trailer sourceCode: code. newTrailer := trailer testEncoding. self assert: (newTrailer sourceCode = code).'. trailer sourceCode: code. self assert: (trailer kind == #EmbeddedSourceZip ). newTrailer := trailer testEncoding. self assert: (newTrailer sourceCode = code). "the last bytecode index must be at 0" self assert: (newTrailer endPC = 0). ! ! !CompledMethodTrailerTest methodsFor: 'testing' stamp: 'Igor.Stasenko 12/13/2009 21:13' prior: 53957691! testEmbeddingTempNames | trailer newTrailer code | trailer := CompiledMethodTrailer new. code := 'foo'. trailer tempNames: code. newTrailer := trailer testEncoding. self assert: (trailer kind == #TempsNamesQCompress ). self assert: (newTrailer tempNames = code). "the last bytecode index must be at 0" self assert: (newTrailer endPC = 0). code := 'testEmbeddingSourceCode | trailer newTrailer code | trailer := CompiledMethodTrailer new. trailer sourceCode: code. newTrailer := trailer testEncoding. self assert: (newTrailer sourceCode = code).'. trailer tempNames: code. self assert: (trailer kind == #TempsNamesZip ). newTrailer := trailer testEncoding. self assert: (newTrailer tempNames = code). "the last bytecode index must be at 0" self assert: (newTrailer endPC = 0). ! ! !CompledMethodTrailerTest methodsFor: 'testing' stamp: 'Igor.Stasenko 12/13/2009 21:17' prior: 53958613! testEncodingNoTrailer | trailer | trailer := CompiledMethodTrailer new. "by default it should be a no-trailer" self assert: (trailer kind == #NoTrailer ). self assert: (trailer size = 1). trailer := trailer testEncoding. self assert: (trailer kind == #NoTrailer ). self assert: (trailer size = 1). "the last bytecode index must be at 0" self assert: (trailer endPC = 0). ! ! !CompledMethodTrailerTest methodsFor: 'testing' stamp: 'Igor.Stasenko 12/13/2009 21:14' prior: 53959109! testEncodingSourcePointer | trailer | trailer := CompiledMethodTrailer new. CompiledMethod allInstancesDo: [:method | | ptr | trailer method: method. self assert: ( (ptr := method sourcePointer) == trailer sourcePointer). "the last bytecode index must be at 0" ptr ~= 0 ifTrue: [ self assert: (method endPC = trailer endPC) ]. ].! ! !CompledMethodTrailerTest methodsFor: 'testing' stamp: 'Igor.Stasenko 12/13/2009 21:15' prior: 53959564! testEncodingVarLengthSourcePointer | trailer newTrailer | trailer := CompiledMethodTrailer new. trailer sourcePointer: 1. newTrailer := trailer testEncoding. self assert: (newTrailer sourcePointer = 1). trailer sourcePointer: 16r100000000000000. newTrailer := trailer testEncoding. self assert: (newTrailer sourcePointer = 16r100000000000000). "the last bytecode index must be at 0" self assert: (newTrailer endPC = 0). ! ! !CompledMethodTrailerTest methodsFor: 'testing' stamp: 'Igor.Stasenko 12/13/2009 21:15' prior: 53960108! testSourceByIdentifierEncoding | trailer id | trailer := CompiledMethodTrailer new. id := UUID new asString. trailer sourceIdentifier: id. self assert: (trailer kind == #SourceByStringIdentifier ). trailer := trailer testEncoding. self assert: (trailer kind == #SourceByStringIdentifier ). self assert: (trailer sourceIdentifier = id). "the last bytecode index must be at 0" self assert: (trailer endPC = 0). ! ! !CompledMethodTrailerTest methodsFor: 'testing' stamp: 'Igor.Stasenko 12/13/2009 21:49' prior: 53960643! testSourceBySelectorEncoding | trailer | trailer := CompiledMethodTrailer new. trailer setSourceBySelector. self assert: (trailer kind == #SourceBySelector ). self assert: (trailer size = 1). trailer := trailer testEncoding. self assert: (trailer kind == #SourceBySelector ). self assert: (trailer size = 1). "the last bytecode index must be at 0" self assert: (trailer endPC = 0). ! ! !CategorizerTest methodsFor: 'running' stamp: 'mtf 9/10/2007 10:10' prior: 18074036! setUp categorizer := Categorizer defaultList: #(a b c d e). categorizer classifyAll: #(a b c) under: 'abc'. categorizer addCategory: 'unreal'.! ! !CategorizerTest methodsFor: 'testing' stamp: 'mtf 9/10/2007 10:17' prior: 18074267! testClassifyNewElementNewCategory categorizer classify: #f under: #nice. self assert: categorizer printString = '(''as yet unclassified'' d e) (''abc'' a b c) (''unreal'') (''nice'' f) '! ! !CategorizerTest methodsFor: 'testing' stamp: 'mtf 9/10/2007 10:18' prior: 18074541! testClassifyNewElementOldCategory categorizer classify: #f under: #unreal. self assert: categorizer printString = '(''as yet unclassified'' d e) (''abc'' a b c) (''unreal'' f) '! ! !CategorizerTest methodsFor: 'testing' stamp: 'mtf 9/10/2007 10:17' prior: 18074806! testClassifyOldElementNewCategory categorizer classify: #e under: #nice. self assert: categorizer printString = '(''as yet unclassified'' d) (''abc'' a b c) (''unreal'') (''nice'' e) '! ! !CategorizerTest methodsFor: 'testing' stamp: 'mtf 9/10/2007 12:54' prior: 18075078! testClassifyOldElementOldCategory categorizer classify: #e under: #unreal. self assert: categorizer printString = '(''as yet unclassified'' d) (''abc'' a b c) (''unreal'' e) '! ! !CategorizerTest methodsFor: 'testing' stamp: 'mtf 9/10/2007 10:22' prior: 18075341! testDefaultCategoryIsTransient "Test that category 'as yet unclassified' disapears when all it's elements are removed'" categorizer classifyAll: #(d e) under: #abc. self assert: categorizer printString = '(''abc'' a b c d e) (''unreal'') '! ! !CategorizerTest methodsFor: 'testing' stamp: 'mtf 9/11/2007 15:15' prior: 18075669! testNullCategory "Test that category 'as yet unclassified' disapears when all it's elements are removed'" | aCategorizer | aCategorizer := Categorizer defaultList: #(). self assert: aCategorizer printString = '(''as yet unclassified'') '. self assert: aCategorizer categories = #('no messages'). aCategorizer classify: #a under: #b. self assert: aCategorizer printString = '(''b'' a) '. self assert: aCategorizer categories = #(b).! ! !CategorizerTest methodsFor: 'testing' stamp: 'mtf 9/10/2007 12:57' prior: 18076194! testRemoveEmptyCategory categorizer removeCategory: #unreal. self assert: categorizer printString = '(''as yet unclassified'' d e) (''abc'' a b c) '! ! !CategorizerTest methodsFor: 'testing' stamp: 'mtf 9/10/2007 12:55' prior: 18076430! testRemoveExistingElement categorizer removeElement: #a. self assert: categorizer printString = '(''as yet unclassified'' d e) (''abc'' b c) (''unreal'') '! ! !CategorizerTest methodsFor: 'testing' stamp: 'mtf 9/10/2007 12:59' prior: 18076673! testRemoveNonEmptyCategory self should: [categorizer removeCategory: #abc] raise: Error. self assert: categorizer printString = '(''as yet unclassified'' d e) (''abc'' a b c) (''unreal'') '! ! !CategorizerTest methodsFor: 'testing' stamp: 'mtf 9/10/2007 12:59' prior: 18076950! testRemoveNonExistingCategory categorizer removeCategory: #nice. self assert: categorizer printString = '(''as yet unclassified'' d e) (''abc'' a b c) (''unreal'') '! ! !CategorizerTest methodsFor: 'testing' stamp: 'mtf 9/10/2007 12:57' prior: 18077203! testRemoveNonExistingElement categorizer removeElement: #f. self assert: categorizer printString = '(''as yet unclassified'' d e) (''abc'' a b c) (''unreal'') '! ! !CategorizerTest methodsFor: 'testing' stamp: 'mtf 9/11/2007 14:49' prior: 18077451! testRemoveThenRename categorizer removeCategory: #unreal. categorizer renameCategory: #abc toBe: #unreal. self assert: categorizer printString = '(''as yet unclassified'' d e) (''unreal'' a b c) '! ! !CategorizerTest methodsFor: 'testing' stamp: 'mtf 9/10/2007 10:14' prior: 18077736! testUnchanged self assert: categorizer printString = '(''as yet unclassified'' d e) (''abc'' a b c) (''unreal'') '! ! "KernelTests"! !SmalltalkImage methodsFor: 'accessing' stamp: 'ul 4/18/2010 22:22'! at: key ifPresentAndInMemory: aBlock "Lookup the given key in the receiver. If it is present, answer the value of evaluating the given block with the value associated with the key. Otherwise, answer nil." ^globals at: key ifPresentAndInMemory: aBlock! ! !SmalltalkImage methodsFor: 'image' stamp: 'dtl 4/11/2010 11:45'! image "Answer the object to query about the current object memory and execution environment." ^self! ! !SmalltalkImage methodsFor: 'image' stamp: 'dtl 4/11/2010 11:47'! imageFormatVersion "Answer an integer identifying the type of image. The image version number may identify the format of the image (e.g. 32 or 64-bit word size) or specific requirements of the image (e.g. block closure support required). This invokes an optional primitive that may not be available on all virtual machines." "Smalltalk image imageFormatVersion" self notify: 'This virtual machine does not support the optional primitive #primitiveImageFormatVersion' translated. ^''! ! !SmalltalkImage methodsFor: 'vm' stamp: 'dtl 4/11/2010 11:38'! interpreterSourceVersion "Answer a string corresponding to the version of the interpreter source. This represents the version level of the Smalltalk source code (interpreter and various plugins) that is translated to C by a CCodeGenerator, as distinct from the external platform source code, typically written in C and managed separately for each platform. An optional primitive is invoked that may not be available on all virtual machines." "Smalltalk vm interpreterSourceVersion" self notify: 'This virtual machine does not support the optional primitive #primitiveInterpreterSourceVersion' translated. ^''! ! !SmalltalkImage methodsFor: 'vm' stamp: 'dtl 4/11/2010 11:39'! platformSourceVersion "Answer a string corresponding to the version of the external platform source code, typically written in C and managed separately for each platform. This invokes an optional primitive that may not be available on all virtual machines." "Smalltalk vm platformSourceVersion" self notify: 'This virtual machine does not support the optional primitive #primitivePlatformSourceVersion' translated. ^''! ! !SmalltalkImage methodsFor: 'image' stamp: 'md 5/16/2006 12:34' prior: 58536670! version "Answer the version of this release." ^SystemVersion current version! ! !SmalltalkImage methodsFor: 'vm' stamp: 'dtl 4/11/2010 11:39'! versionLabel "Answer a string corresponding to the version of virtual machine. This represents the version level of the Smalltalk source code (interpreter and various plugins) that is translated to C by a CCodeGenerator, in addition to the external platform source code, typically written in C and managed separately for each platform. This invokes an optional primitive that may not be available on all virtual machines. See also vmVersion, which answers a string identifying the image from which virtual machine sources were generated." "Smalltalk vm versionLabel" self notify: 'This virtual machine does not support the optional primitive #primitiveVMVersion' translated. ^''! ! !SmalltalkImage methodsFor: 'vm' stamp: 'dtl 4/11/2010 11:15'! vm "Answer the object to query about virtual machine." ^self! ! !SmalltalkImage methodsFor: 'image' stamp: 'dtl 1/4/2010 21:40' prior: 58537225! wordSize "Answer the size in bytes of an object pointer or word in the object memory. The value does not change for a given image, but may be modified by a SystemTracer when converting the image to another format. The value is cached in WordSize to avoid the performance overhead of repeatedly consulting the VM." "Smalltalk wordSize" ^ WordSize ifNil: [WordSize := [SmalltalkImage current vmParameterAt: 40] on: Error do: [4]]! ! "System"! !SMLoaderPlus commentStamp: 'btr 12/1/2006 15:16' prior: 0! A simple package loader that is currently the standard UI for SqueakMap (the model is an SMSqueakMap instance). It uses ToolBuilder to construct its window. You can open one with: SMLoaderPlus open Instance Variables categoriesToFilterIds: The set of categories to filter the packages list. filters: The set of filters to apply to the packages list. map: The model SqueakMap. packagesList: The list of packages from the map. selectedCategory: The current category. selectedItem: The selected package or release. window: The window, held only so we can reOpen.! !SMLoaderCategoricalPlus commentStamp: 'btr 12/4/2006 15:47' prior: 0! A variant package loader that uses a more-or-less standard Smalltalk-80 browser perspective of selecting categories in one pane and then selecting items within in the next pane. You can open one with: SMLoaderCategoricalPlus open! !SMLoader commentStamp: 'btr 11/30/2006 18:00' prior: 27913009! A simple package loader that is currently the standard UI for SqueakMap (the model is an SMSqueakMap instance). You can open one with: SMLoader open! !SMLoaderCategorical commentStamp: 'btr 12/1/2006 15:16' prior: 0! A variant package loader that uses a more-or-less standard Smalltalk-80 browser perspective of selecting categories in one pane and then selecting items within in the next pane. You can open one with: SMLoaderCategorical open! !SMLoaderCategoricalPlus class methodsFor: 'menu registration' stamp: 'btr 12/1/2006 18:06'! initialize Smalltalk at: #ToolBuilder ifPresent: [:tb | (TheWorldMenu respondsTo: #registerOpenCommand:) ifTrue: [TheWorldMenu registerOpenCommand: {self openMenuString. {self. #open}}]]! ! !SMLoaderCategoricalPlus class methodsFor: 'menu registration' stamp: 'btr 12/1/2006 17:34'! openMenuString ^ 'SqueakMap Categories'! ! !SMLoaderCategoricalPlus class methodsFor: 'menu registration' stamp: 'btr 12/1/2006 17:34'! removeFromSystem (TheWorldMenu respondsTo: #registerOpenCommand:) ifTrue: [TheWorldMenu unregisterOpenCommand: self openMenuString]. self removeFromSystem: true! ! !SMLoaderCategoricalPlus class methodsFor: 'menu registration' stamp: 'btr 12/1/2006 17:34'! unload (TheWorldMenu respondsTo: #registerOpenCommand:) ifTrue: [TheWorldMenu unregisterOpenCommand: self openMenuString].! ! !SMLoaderCategoricalPlus methodsFor: 'interface' stamp: 'btr 12/5/2006 06:50'! buildFancyWith: aBuilder "Creates a variant of the window where the package pane is split between installed and uninstalled packages." | buttonBarHeight searchHeight vertDivide horizDivide | buttonBarHeight := 0.07. searchHeight := 0.07. vertDivide := 0.5. horizDivide := 0.6. builder := aBuilder. window := builder build: (builder pluggableWindowSpec new model: self; label: #label; children: (OrderedCollection new add: ((self buildButtonBarWith: builder) frame: (0 @ 0 corner: 1 @ buttonBarHeight); yourself); add: ((self buildCategoriesListWith: builder) frame: (0 @ buttonBarHeight corner: vertDivide @ horizDivide); yourself); add: ((self buildSearchPaneWith: builder) frame: (vertDivide @ buttonBarHeight corner: 1 @ (buttonBarHeight + searchHeight)); yourself); add: ((self buildNotInstalledPackagesListWith: builder) frame: (vertDivide @ (buttonBarHeight + searchHeight) corner: 1 @ (horizDivide / 2)); yourself); add: ((self buildInstalledPackagesListWith: builder) frame: (vertDivide @ (horizDivide / 2) corner: 1 @ horizDivide); yourself); add: ((self buildPackagePaneWith: builder) frame: (0 @ horizDivide corner: 1 @ 1); yourself); yourself)). window on: #mouseEnter send: #paneTransition: to: window. window on: #mouseLeave send: #paneTransition: to: window. self setUpdatablePanesFrom: #(#installedPackageList #notInstalledPackageList ). currentPackageList := #notInstalled. window extent: self initialExtent. ^ window! ! !SMLoaderCategoricalPlus methodsFor: 'interface' stamp: 'btr 12/1/2006 17:56'! buildInstalledPackagesListWith: aBuilder ^ aBuilder pluggableTreeSpec new model: self; roots: #installedPackageList; getSelectedPath: #selectedItemPath; setSelected: #selectedItem:; menu: #packagesMenu:; label: #itemLabel:; getChildren: #itemChildren:; hasChildren: #itemHasChildren:; autoDeselect: true; wantsDrop: true; yourself! ! !SMLoaderCategoricalPlus methodsFor: 'interface' stamp: 'btr 12/1/2006 17:52'! buildNotInstalledPackagesListWith: aBuilder ^ aBuilder pluggableTreeSpec new model: self; roots: #notInstalledPackageList; getSelectedPath: #selectedItemPath; setSelected: #selectedItem:; menu: #packagesMenu:; label: #itemLabel:; getChildren: #itemChildren:; hasChildren: #itemHasChildren:; autoDeselect: true; wantsDrop: true; yourself! ! !SMLoaderCategoricalPlus methodsFor: 'interface' stamp: 'btr 12/5/2006 06:55'! buildWith: aBuilder | buttonBarHeight searchHeight vertDivide horizDivide | buttonBarHeight := 0.07. searchHeight := 0.07. vertDivide := 0.5. horizDivide := 0.6. builder := aBuilder. window := builder build: (builder pluggableWindowSpec new model: self; label: #label; children: (OrderedCollection new add: ((self buildButtonBarWith: builder) frame: (0 @ 0 corner: 1 @ buttonBarHeight); yourself); add: ((self buildCategoriesListWith: builder) frame: (0 @ buttonBarHeight corner: vertDivide @ horizDivide); yourself); add: ((self buildSearchPaneWith: builder) frame: (vertDivide @ buttonBarHeight corner: 1 @ (buttonBarHeight + searchHeight))); add: ((self buildPackagesListWith: builder) frame: (vertDivide @ (buttonBarHeight + searchHeight) corner: 1 @ horizDivide)); add: ((self buildPackagePaneWith: builder) frame: (0 @ horizDivide corner: 1 @ 1)); yourself)). window on: #mouseEnter send: #paneTransition: to: window. window on: #mouseLeave send: #paneTransition: to: window. window extent: self initialExtent. ^ window! ! !SMLoaderCategoricalPlus methodsFor: 'accessing' stamp: 'btr 12/1/2006 17:34'! currentPackageList ^currentPackageList! ! !SMLoaderCategoricalPlus methodsFor: 'accessing' stamp: 'btr 12/1/2006 17:34'! currentPackageList: aSymbol currentPackageList := aSymbol. self changed: #installButtonLabel.! ! !SMLoaderCategoricalPlus methodsFor: 'interface' stamp: 'btr 12/4/2006 15:55'! defaultLabel ^ 'Categorical ' , super defaultLabel! ! !SMLoaderCategoricalPlus methodsFor: 'interface' stamp: 'btr 12/4/2006 15:58'! installButtonLabel ^ self currentPackageList = #notInstalled ifTrue: ['Install the above package'] ifFalse: ['Remove the above package']! ! !SMLoaderCategoricalPlus methodsFor: 'lists' stamp: 'btr 12/1/2006 17:52'! installedPackageList ^self packageList select: [:e | e isInstalled]! ! !SMLoaderCategoricalPlus methodsFor: 'accessing' stamp: 'btr 12/1/2006 18:02'! installedPackagesListIndex ^ self currentPackageList = #installed ifTrue: [self packagesListIndex] ifFalse: [0]! ! !SMLoaderCategoricalPlus methodsFor: 'accessing' stamp: 'btr 12/1/2006 17:34'! installedPackagesListIndex: anObject packagesListIndex := anObject. self currentPackageList ~= #installed ifTrue: [self currentPackageList: #installed. self changed: #currentPackageList]. self noteChanged! ! !SMLoaderCategoricalPlus methodsFor: 'accessing' stamp: 'btr 12/1/2006 17:34'! isOn ^false! ! !SMLoaderCategoricalPlus methodsFor: 'lists' stamp: 'btr 12/1/2006 17:53'! notInstalledPackageList ^self packageList reject: [:e | e isInstalled]! ! !SMLoaderCategoricalPlus methodsFor: 'accessing' stamp: 'btr 12/1/2006 18:02'! notInstalledPackagesListIndex ^ self currentPackageList = #notInstalled ifTrue: [self packagesListIndex] ifFalse: [0]! ! !SMLoaderCategoricalPlus methodsFor: 'accessing' stamp: 'btr 12/1/2006 18:03'! notInstalledPackagesListIndex: anObject packagesListIndex := anObject. self currentPackageList ~= #notInstalled ifTrue: [self currentPackageList: #notInstalled. self changed: #currentPackageList]. self changed: #packagesListIndex. "update my selection" self noteChanged. self contentsChanged! ! !SMLoaderCategoricalPlus methodsFor: 'private' stamp: 'btr 12/1/2006 17:53'! noteChanged self changed: #installedPackageList. self changed: #notInstalledPackageList. super noteChanged." self changed: #packageNameList. self changed: #packagesListIndex. self changed: #categoriesForPackage. self contentsChanged."! ! !SMLoaderCategoricalPlus methodsFor: 'lists' stamp: 'btr 12/1/2006 17:34'! packageList ^ self packages select: [:e | (e categories anySatisfy: [:cat | cat = self selectedCategory]) and: [(filters ifNil: [#()]) allSatisfy: [:currFilter | (self perform: currFilter) value: e]]]! ! !SMLoaderPlus class methodsFor: 'parts bin' stamp: 'btr 11/22/2006 15:02'! descriptionForPartsBin ^self partName: 'Package Loader' categories: #(Tools) documentation: 'SqueakMap UI' ! ! !SMLoaderPlus class methodsFor: 'class initialization' stamp: 'btr 12/1/2006 15:47'! initialize "Hook us up in the world menu." "self initialize" Smalltalk at: #ToolBuilder ifPresent: [:tb | self registerInFlapsRegistry. (Preferences windowColorFor: #SMLoader) = Color white "not set" ifTrue: [ Preferences setWindowColorFor: #SMLoader to: (Color colorFrom: self windowColorSpecification brightColor) ]. (TheWorldMenu respondsTo: #registerOpenCommand:) ifTrue: [| oldCmds | oldCmds := TheWorldMenu registry select: [:cmd | cmd first includesSubString: 'Package Loader']. oldCmds do: [:cmd | TheWorldMenu unregisterOpenCommand: cmd first]. TheWorldMenu registerOpenCommand: {self openMenuString. {self. #open}}]]. DefaultFilters := OrderedCollection new. DefaultCategoriesToFilterIds := OrderedCollection new! ! !SMLoaderPlus class methodsFor: 'new-morph participation' stamp: 'btr 11/22/2006 15:16'! initializedInstance ^ (ToolBuilder open: self new) extent: 400 at 400! ! !SMLoaderPlus class methodsFor: 'instance creation' stamp: 'btr 11/22/2006 15:02'! new "Create a SqueakMap loader on the default map." ^self newOn: SMSqueakMap default! ! !SMLoaderPlus class methodsFor: 'instance creation' stamp: 'btr 11/22/2006 15:02'! newOn: aMap "Create a SqueakMap loader on given map." ^super new on: aMap; yourself! ! !SMLoaderPlus class methodsFor: 'new-morph participation' stamp: 'btr 11/22/2006 15:16'! newStandAlone ^ ToolBuilder open: self new! ! !SMLoaderPlus class methodsFor: 'instance creation' stamp: 'btr 11/23/2006 11:13'! open "Create and open a SqueakMap Loader." "SMLoaderPlus open" ^ (Smalltalk at: #ToolBuilder) open: self new! ! !SMLoaderPlus class methodsFor: 'class initialization' stamp: 'btr 11/30/2006 21:50'! openMenuString ^ 'SqueakMap Catalog'! ! !SMLoaderPlus class methodsFor: 'instance creation' stamp: 'btr 11/23/2006 11:21'! openOn: aSqueakMap "Create and open a SqueakMap Loader on a given map." "self openOn: SqueakMap default" ^ (Smalltalk at: #ToolBuilder) open: (self newOn: aSqueakMap)! ! !SMLoaderPlus class methodsFor: 'new-morph participation' stamp: 'btr 11/22/2006 15:18'! prototypicalToolWindow ^ ToolBuilder open: self new; applyModelExtent; yourself! ! !SMLoaderPlus class methodsFor: 'new-morph participation' stamp: 'btr 11/22/2006 15:02'! registerInFlapsRegistry "Register the receiver in the system's flaps registry." self environment at: #Flaps ifPresent: [:cl | (cl respondsTo: #registerQuad:forFlapNamed:) ifTrue: [cl registerQuad: #(#SMLoader #prototypicalToolWindow 'Package Loader' 'The SqueakMap Package Loader' ) forFlapNamed: 'Tools']]! ! !SMLoaderPlus class methodsFor: 'class initialization' stamp: 'btr 11/30/2006 21:50'! unload (TheWorldMenu respondsTo: #registerOpenCommand:) ifTrue: [TheWorldMenu unregisterOpenCommand: self openMenuString]. self environment at: #Flaps ifPresent: [:cl | cl unregisterQuadsWithReceiver: self] ! ! !SMLoaderPlus class methodsFor: 'window color' stamp: 'btr 11/22/2006 15:02'! windowColorSpecification "Answer a WindowColorSpec object that declares my preference." ^WindowColorSpec classSymbol: self name wording: 'Package Loader' brightColor: Color yellow muchLighter duller pastelColor: Color yellow veryMuchLighter duller helpMessage: 'The SqueakMap Package Loader'! ! !SMLoaderPlus methodsFor: 'menus' stamp: 'btr 11/22/2006 15:02'! addFiltersToMenu: aMenu | filterSymbol help | self filterSpecs do: [:filterArray | filterSymbol := filterArray second. help := filterArray third. aMenu addUpdating: #showFilterString: target: self selector: #toggleFilterState: argumentList: (Array with: filterSymbol). aMenu balloonTextForLastItem: help]. aMenu addLine; addList: #(('Clear all filters' uncheckFilters 'Unchecks all filters to list all packages')) ! ! !SMLoaderPlus methodsFor: 'actions' stamp: 'btr 11/22/2006 15:02'! addSelectedCategoryAsFilter "Add a new filter that filters on the currently selected category. Make it enabled as default." categoriesToFilterIds add: self selectedCategory id! ! !SMLoaderPlus methodsFor: 'actions' stamp: 'btr 11/22/2006 16:11'! askToLoadUpdates "Check how old the map is and ask to update it if it is older than 10 days or if there is no map on disk." | available | available := map isCheckpointAvailable. (available not or: [ (Date today subtractDate: (Date fromSeconds: (map directory directoryEntryFor: map lastCheckpointFilename) modificationTime)) > 3]) ifTrue: [ (self confirm: (available ifTrue: ['The map on disk is more than 10 days old, update it from the Internet?'] ifFalse: ['There is no map on disk, fetch it from the Internet?'])) ifTrue: [self loadUpdates]]! ! !SMLoaderPlus methodsFor: 'interface' stamp: 'btr 12/1/2006 01:43'! browseCacheDirectory "Open a FileList2 on the directory for the package or release." | item dir win | item := self selectedPackageOrRelease ifNil: [^ nil]. dir := item isPackage ifTrue: [map cache directoryForPackage: item] ifFalse: [map cache directoryForPackageRelease: item]. win := FileList2 morphicViewOnDirectory: dir. "withLabel: item name, ' cache directory'." win openInWorld! ! !SMLoaderPlus methodsFor: 'interface' stamp: 'btr 12/5/2006 06:56'! buildButtonBarWith: aBuilder ^ aBuilder pluggablePanelSpec new model: self; layout: #horizontal; children: (self commandSpecs select: [ :spec | spec fourth includes: #all] thenCollect: [ :spec | aBuilder pluggableActionButtonSpec new model: self; label: spec first; action: spec second; help: spec third; enabled: ((spec fourth includes: #item) ifTrue: [#hasSelectedItem]); yourself]); name: #buttonBar; yourself! ! !SMLoaderPlus methodsFor: 'interface' stamp: 'btr 11/22/2006 15:02'! buildButtonNamed: labelText helpText: balloon action: action | btn | btn := PluggableButtonMorph on: self getState: nil action: action. btn color: Color transparent; hResizing: #shrinkWrap; vResizing: #spaceFill; label: labelText; setBalloonText: balloon; onColor: Color transparent offColor: Color transparent. ^ btn! ! !SMLoaderPlus methodsFor: 'interface' stamp: 'btr 12/5/2006 06:56'! buildCategoriesListWith: aBuilder "Create the hierarchical list holding the category tree." ^ aBuilder pluggableTreeSpec new model: self; roots: #categoryList; getSelectedPath: #selectedCategoryPath; getChildren: #categoryChildren:; hasChildren: #categoryHasChildren:; setSelected: #selectedCategory:; menu: #categoriesMenu:; label: #categoryLabel:; autoDeselect: true; wantsDrop: true; name: #categoriesList; yourself! ! !SMLoaderPlus methodsFor: 'interface' stamp: 'btr 12/5/2006 06:57'! buildPackagePaneWith: aBuilder "Create the text area to the right in the loader." ^ aBuilder pluggableTextSpec new model: self; getText: #itemDescription; name: #packagePane; yourself! ! !SMLoaderPlus methodsFor: 'interface' stamp: 'btr 12/5/2006 06:57'! buildPackagesListWith: aBuilder "Create the hierarchical list holding the packages and releases." ^ aBuilder pluggableTreeSpec new model: self; roots: #packageList; getSelectedPath: #selectedItemPath; setSelected: #selectedItem:; menu: #packagesMenu:; label: #itemLabel:; getChildren: #itemChildren:; hasChildren: #itemHasChildren:; autoDeselect: true; wantsDrop: true; name: #packagesList; yourself! ! !SMLoaderPlus methodsFor: 'interface' stamp: 'btr 12/5/2006 06:57'! buildSearchPaneWith: aBuilder ^ aBuilder pluggableInputFieldSpec new model: self; selection: #searchSelection; getText: #searchText; setText: #findPackage:notifying:; name: #search; yourself! ! !SMLoaderPlus methodsFor: 'interface' stamp: 'btr 12/5/2006 06:54'! buildWith: aBuilder "Create the package loader window." | buttonBarHeight vertDivide horizDivide | buttonBarHeight := 0.07. vertDivide := 0.6. horizDivide := 0.3. builder := aBuilder. window := builder build: (builder pluggableWindowSpec new model: self; label: #label; children: (OrderedCollection new add: ((self buildButtonBarWith: builder) frame: (0 @ 0 corner: 1 @ buttonBarHeight)); add: ((self buildSearchPaneWith: builder) frame: (0 @ buttonBarHeight corner: horizDivide @ (buttonBarHeight * 2))); add: ((self buildPackagesListWith: builder) frame: (0 @ (buttonBarHeight * 2) corner: horizDivide @ vertDivide)); add: ((self buildCategoriesListWith: builder) frame: (0 @ vertDivide corner: horizDivide @ 1)); add: ((self buildPackagePaneWith: builder) frame: (horizDivide @ buttonBarHeight corner: 1 @ 1)); yourself); yourself). window on: #mouseEnter send: #paneTransition: to: window. window on: #mouseLeave send: #paneTransition: to: window. window extent: self initialExtent. ^ window! ! !SMLoaderPlus methodsFor: 'actions' stamp: 'btr 12/1/2006 01:38'! cachePackageReleaseAndOfferToCopy "Cache package release, then offer to copy it somewhere. Answer the chosen file's location after copy, or the cache location if no directory was chosen." | release installer newDir newName newFile oldFile oldName | release := self selectedPackageOrRelease. release isPackageRelease ifFalse: [ self error: 'Should be a package release!!']. installer := SMInstaller forPackageRelease: release. [UIManager default informUser: 'Caching ' , release asString during: [installer cache]] on: Error do: [:ex | | msg | msg := ex messageText ifNil: [ex asString]. self informException: ex msg: ('Error occurred during download:\', msg, '\') withCRs. ^nil ]. installer isCached ifFalse: [self inform: 'Download failed, see transcript for details'. ^nil]. oldName := installer fullFileName. newDir := FileList2 modalFolderSelector: installer directory. newDir ifNil: [ ^oldName ]. newDir = installer directory ifTrue: [ ^oldName ]. newName := newDir fullNameFor: installer fileName. newFile := FileStream newFileNamed: newName. newFile ifNil: [ ^oldName ]. newFile binary. oldFile := FileStream readOnlyFileNamed: oldName. oldFile ifNil: [ ^nil ]. oldFile binary. [[ newDir copyFile: oldFile toFile: newFile ] ensure: [ oldFile close. newFile close ]] on: Error do: [ :ex | ^oldName ]. ^newName! ! !SMLoaderPlus methodsFor: 'menus' stamp: 'btr 11/22/2006 15:02'! categoriesMenu: aMenu "Answer the categories-list menu." self selectedCategory ifNotNil: [aMenu addList: self categorySpecificOptions; addLine]. aMenu addList: self generalOptions. self addFiltersToMenu: aMenu. ^aMenu! ! !SMLoaderPlus methodsFor: 'interface' stamp: 'btr 11/24/2006 14:44'! categoryChildren: aCategory ^ aCategory subCategories! ! !SMLoaderPlus methodsFor: 'interface' stamp: 'btr 11/24/2006 14:45'! categoryHasChildren: aCategory ^ aCategory hasSubCategories! ! !SMLoaderPlus methodsFor: 'interface' stamp: 'btr 11/24/2006 14:46'! categoryLabel: aCategory ^ aCategory name! ! !SMLoaderPlus methodsFor: 'lists' stamp: 'btr 11/30/2006 21:01'! categoryList "Create the category list for the hierarchical list. We sort the categories by name but ensure that 'Squeak versions' is first if it exists." | list first | list := (map categories select: [:each | each parent isNil]) asArray sort: [:c1 :c2 | c1 name <= c2 name]. first := list detect: [:any | any name = 'Squeak versions'] ifNone: []. first ifNotNil: [list := list copyWithout: first. list := {first} , list]. ^ list! ! !SMLoaderPlus methodsFor: 'menus' stamp: 'btr 11/22/2006 15:02'! categorySpecificOptions | choices | choices := OrderedCollection new. (categoriesToFilterIds includes: self selectedCategory id) ifTrue: [ choices add: #('Remove filter' #removeSelectedCategoryAsFilter 'Remove the filter for the selected category.')] ifFalse: [ choices add: #('Add as filter' #addSelectedCategoryAsFilter 'Add the selection as a filter to hide unrelated packages.')]. categoriesToFilterIds isEmpty ifFalse: [ choices add: #('Remove all filters' #removeCategoryFilters 'Remove all category filters.')]. ^ choices! ! !SMLoaderPlus methodsFor: 'accessing' stamp: 'btr 11/22/2006 15:02'! changeFilters: anObject "Update my selection." | oldItem index | oldItem := self selectedPackageOrRelease. filters := anObject. self packagesListIndex: ((index := self packageList indexOf: oldItem) ifNil: [0] ifNotNil: [index]). self noteChanged! ! !SMLoaderPlus methodsFor: 'menus' stamp: 'btr 11/22/2006 18:01'! commandSpecFor: selector ^ self commandSpecs detect: [:spec | spec second = selector]! ! !SMLoaderPlus methodsFor: 'menus' stamp: 'btr 11/22/2006 18:00'! commandSpecs ^ #(('Install' installPackageRelease 'Install the latest version from the server.' (item all)) ('Email' emailPackageMaintainers 'Open an editor to send an email to the owner and co-maintainers of this package.' (item all)) ('Browse cache' browseCacheDirectory 'Browse cache directory of the selection.' (item all)) ('Copy from cache' cachePackageReleaseAndOfferToCopy 'Download selected release into cache first if needed, and then offer to copy it somewhere else.' (item)) ('Force download into cache' downloadPackageRelease 'Force a download of the selected release into the cache.' (item)) ('Update' loadUpdates 'Update the package index from the servers.' (all)) ('Upgrade All' upgradeInstalledPackagesConfirm 'Upgrade all installed packages (conf8irming each).' (all)) ('Upgrade all installed packages' upgradeInstalledPackagesNoConfirm '' (item)) ('Upgrade all installed packages confirming each' upgradeInstalledPackagesConfirm '' (item)) ('Copy list' listInPasteBuffer 'Puts the list as text into the clipboard.' (all)) ('Save filters' saveFiltersAsDefault 'Saves the current filters as default.' (all)) ('Help' help 'What is this?' (all)))! ! !SMLoaderPlus methodsFor: 'interface' stamp: 'btr 11/22/2006 15:02'! defaultButtonPaneHeight "Answer the user's preferred default height for new button panes." ^ Preferences parameterAt: #defaultButtonPaneHeight ifAbsentPut: [25]! ! !SMLoaderPlus methodsFor: 'lists' stamp: 'btr 12/1/2006 01:50'! defaultLabel ^ 'SqueakMap Package Loader'! ! !SMLoaderPlus methodsFor: 'actions' stamp: 'btr 12/1/2006 01:38'! downloadPackageRelease "Force a download of the selected package release into the cache." | release | release := self selectedPackageOrRelease. release isPackageRelease ifFalse: [ self error: 'Should be a package release!!']. [UIManager default informUser: 'Downloading ' , release asString during: [ (SMInstaller forPackageRelease: release) download] ] on: Error do: [:ex | | msg | msg := ex messageText ifNil: [ex asString]. self informException: ex msg: ('Error occurred during download:\', msg, '\') withCRs]! ! !SMLoaderPlus methodsFor: 'actions' stamp: 'btr 11/22/2006 15:02'! emailPackageMaintainers "Send mail to package owner and co-maintainers." | item package toAddresses | item := self selectedPackageOrRelease ifNil: [^ nil]. package := item isPackageRelease ifTrue: [item package] ifFalse: [item]. "(this logic should be moved to MailMessage as soon as it can handle multiple To: addresses)" toAddresses := '<', package owner email, '>'. package maintainers ifNotNil: [ package maintainers do: [:maintainer | toAddresses := toAddresses, ', <', maintainer email, '>']]. SMUtilities sendMailTo: toAddresses regardingPackageRelease: item! ! !SMLoaderPlus methodsFor: 'filter utilities' stamp: 'btr 11/22/2006 15:02'! filterAdd: anObject self changeFilters: (self filters copyWith: anObject) ! ! !SMLoaderPlus methodsFor: 'filters' stamp: 'btr 11/22/2006 15:02'! filterAutoInstall ^[:package | package isInstallable]! ! !SMLoaderPlus methodsFor: 'filters' stamp: 'btr 12/1/2006 01:42'! filterAvailable ^[:package | package isAvailable]! ! !SMLoaderPlus methodsFor: 'filters' stamp: 'btr 11/22/2006 15:02'! filterInstalled ^[:package | package isInstalled]! ! !SMLoaderPlus methodsFor: 'filters' stamp: 'btr 11/22/2006 15:02'! filterNotInstalledYet ^[:package | package isInstalled not]! ! !SMLoaderPlus methodsFor: 'filters' stamp: 'btr 12/1/2006 01:42'! filterNotUptoDate ^[:package | package isAvailable]! ! !SMLoaderPlus methodsFor: 'filters' stamp: 'btr 11/22/2006 15:02'! filterPublished ^[:package | package isPublished]! ! !SMLoaderPlus methodsFor: 'filter utilities' stamp: 'btr 11/22/2006 15:02'! filterRemove: anObject self changeFilters: (self filters copyWithout: anObject) ! ! !SMLoaderPlus methodsFor: 'filters' stamp: 'btr 12/1/2006 01:43'! filterSafelyAvailable ^[:package | package isSafelyAvailable]! ! !SMLoaderPlus methodsFor: 'filter utilities' stamp: 'btr 11/30/2006 21:07'! filterSpecs "Return a specification for the filter menu. Is called each time." | specs | specs := #(#('Auto-installable packages' #filterAutoInstall 'display only packages that can be installed automatically') #('New available packages' #filterAvailable 'display only packages that are not installed or that have newer releases available.') #('New safely-available packages' #filterSafelyAvailable 'display only packages that are not installed or that have newer releases available that are safe to install, meaning that they are published and meant for the current version of Squeak.') #('Installed packages' #filterInstalled 'Display only packages that are installed.') #('Published packages' #filterPublished 'Display only packages that have at least one published release.') ) asOrderedCollection. categoriesToFilterIds do: [:catId | specs add: {'Packages in ' , (map object: catId) name. catId. 'Display only packages that are in the category.'}]. ^ specs! ! !SMLoaderPlus methodsFor: 'filters' stamp: 'btr 12/1/2006 01:43'! filterVersion "Ignore spaces in the version string, they're sometimes spurious. Not used anymore." ^[:package | package categories anySatisfy: [:cat | (cat name, '*') match: (Smalltalk version copyWithout: $ ) ]]! ! !SMLoaderPlus methodsFor: 'filter utilities' stamp: 'btr 11/22/2006 15:02'! filters ^filters! ! !SMLoaderPlus methodsFor: 'actions' stamp: 'btr 11/24/2006 13:49'! findPackage: aString notifying: aView "Search and select a package with the given (sub) string in the name or description. " | index list match descriptions | match := aString asString asLowercase. index := self packagesListIndex. list := self packageNameList. list isEmpty ifTrue: [^ self]. descriptions := self packageList collect: [:e | e description]. index + 1 to: list size do: [:i | (((list at: i) includesSubstring: match caseSensitive: false) or: [(descriptions at: i) includesSubstring: match caseSensitive: false]) ifTrue: [^ self packagesListIndex: i]]. "wrap around" 1 to: index do: [:i | (((list at: i) includesSubstring: match caseSensitive: false) or: [(descriptions at: i) includesSubstring: match caseSensitive: false]) ifTrue: [^ self packagesListIndex: i]]. self inform: 'No package matching ' , aString asString! ! !SMLoaderPlus methodsFor: 'menus' stamp: 'btr 11/22/2006 15:02'! generalOptions ^#( #('Upgrade all installed packages' upgradeInstalledPackagesNoConfirm) #('Upgrade all installed packages confirming each' upgradeInstalledPackagesConfirm) #('Put list in paste buffer' listInPasteBuffer) #('Save filters as default' saveFiltersAsDefault) #- ) ! ! !SMLoaderPlus methodsFor: 'private' stamp: 'btr 11/22/2006 18:36'! hasSelectedItem ^ self selectedPackageOrRelease notNil! ! !SMLoaderPlus methodsFor: 'interface' stamp: 'btr 12/1/2006 01:44'! help "Present help text. If there is a web server available, offer to open it. Use the WebBrowser registry if possible, or Scamper if available." | message browserClass | message := 'Welcome to the SqueakMap package loader. The names of packages are followed by versions: (installed -> latest). If there is no arrow, your installed version of the package is the latest. Bold packages and releases have been installed. The checkbox menu items modify which packages you''ll see. Take a look at them - only some packages are shown initially. The options available for a package depend on how it was packaged. Comment on a package by emailing the author or the squeak list.'. browserClass := Smalltalk at: #WebBrowser ifPresent: [ :registry | registry default ]. browserClass := browserClass ifNil: [ Smalltalk at: #Scamper ifAbsent: [ ^self inform: message ]]. (self confirm: message, ' Would you like to view more detailed help on the SqueakMap swiki page?') ifTrue: [ browserClass openOnUrl: 'http://wiki.squeak.org/2726' asUrl]! ! !SMLoaderPlus methodsFor: 'private' stamp: 'btr 11/22/2006 15:02'! informException: ex msg: msg "Tell the user that an error has occurred. Offer to open debug notifier." (self confirm: msg, 'Would you like to open a debugger?') ifTrue: [ex pass]! ! !SMLoaderPlus methodsFor: 'interface' stamp: 'btr 12/5/2006 05:28'! initialExtent ^500 at 400! ! !SMLoaderPlus methodsFor: 'actions' stamp: 'btr 11/22/2006 15:02'! installPackageRelease "Install selected package or release. The cache is used." | item release | item := self selectedPackageOrRelease ifNil: [^ nil]. item isPackageRelease ifTrue: [ (item isPublished or: [self confirm: 'Selected release is not published yet, install anyway?']) ifTrue: [^self installPackageRelease: item]] ifFalse: [ release := item lastPublishedReleaseForCurrentSystemVersion. release ifNil: [ (self confirm: 'The package has no published release for your Squeak version, try releases for any Squeak version?') ifTrue: [ release := item lastPublishedRelease. release ifNil: [ (self confirm: 'The package has no published release at all, take the latest of the unpublished releases?') ifTrue: [release := item lastRelease]]]]. release ifNotNil: [^self installPackageRelease: release]]! ! !SMLoaderPlus methodsFor: 'private' stamp: 'btr 12/1/2006 01:53'! installPackageRelease: aRelease "Install a package release. The cache is used." | myRelease installer | aRelease isCompatibleWithCurrentSystemVersion ifFalse: [(self confirm: 'The package you are about to install is not listed as being compatible with your image version (', SystemVersion current majorMinorVersion, '), so the package may not work properly. Do you still want to proceed with the install?') ifFalse: [^ self]]. myRelease := self installedReleaseOfMe. installer := SMInstaller forPackageRelease: aRelease. [UIManager default informUser: 'Downloading ' , aRelease asString during: [installer download]. UIManager default informUser: 'Installing ' , aRelease asString during: [ installer install. myRelease = self installedReleaseOfMe ifFalse: [self reOpen] ifTrue: [self noteChanged]] ] on: Error do: [:ex | | msg | msg := ex messageText ifNil:[ex asString]. self informException: ex msg: ('Error occurred during install:\', msg, '\') withCRs].! ! !SMLoaderPlus methodsFor: 'private' stamp: 'btr 11/22/2006 15:02'! installedReleaseOfMe "Return the release of the installed package loader." ^SMSqueakMap default installedReleaseOf: (SMSqueakMap default packageWithId: '941c0108-4039-4071-9863-a8d7d2b3d4a3').! ! !SMLoaderPlus methodsFor: 'interface' stamp: 'btr 11/24/2006 14:44'! itemChildren: anItem ^ anItem isPackage ifTrue: [anItem releases] ifFalse: [#()]! ! !SMLoaderPlus methodsFor: 'private' stamp: 'btr 11/22/2006 19:56'! itemDescription ^ self selectedPackageOrRelease ifNil: [''] ifNotNilDo: [:item | item fullDescription]! ! !SMLoaderPlus methodsFor: 'interface' stamp: 'btr 11/24/2006 14:45'! itemHasChildren: anItem ^ anItem isPackage and: [anItem releases notEmpty]! ! !SMLoaderPlus methodsFor: 'interface' stamp: 'btr 12/1/2006 01:44'! itemLabel: anItem | label | label := anItem isPackage ifTrue: [anItem name , (anItem versionLabel ifEmpty: [''] ifNotEmptyDo: [:lbl | ' (' , anItem versionLabel , ')'])] ifFalse: [anItem smartVersion]. ^ anItem isInstalled ifTrue: [label asText allBold] ifFalse: [label]! ! !SMLoaderPlus methodsFor: 'lists' stamp: 'btr 11/24/2006 17:17'! label ^ self labelForShown: (packagesList ifNil: [self packageList])! ! !SMLoaderPlus methodsFor: 'filter utilities' stamp: 'btr 11/22/2006 15:02'! labelForFilter: aFilterSymbol ^(self filterSpecs detect: [:fs | fs second = aFilterSymbol]) first! ! !SMLoaderPlus methodsFor: 'lists' stamp: 'btr 12/1/2006 01:50'! labelForShown: packagesShown "Update the label of the window." ^ self defaultLabel , ' (', (packagesShown size < map packages size ifTrue: [packagesShown size printString, ' shown out of '] ifFalse: ['']) , map packages size printString, ' packages)'! ! !SMLoaderPlus methodsFor: 'actions' stamp: 'btr 11/22/2006 15:02'! listInPasteBuffer "Useful when talking with people etc. Uses the map to produce a nice String." Clipboard clipboardText: (String streamContents: [:s | packagesList do: [:p | s nextPutAll: p nameWithVersionLabel; cr ]]) asText! ! !SMLoaderPlus methodsFor: 'actions' stamp: 'btr 12/1/2006 01:31'! loadUpdates [UIManager default informUser: 'Loading Updates' during: [ map loadUpdates. self noteChanged ] ] on: Error do: [:ex | self informException: ex msg: ('Error occurred when updating map:\', ex messageText, '\') withCRs]! ! !SMLoaderPlus methodsFor: 'private' stamp: 'btr 11/24/2006 14:05'! noteChanged filters ifNil: [^ self reOpen]. map ifNotNil: [packagesList := nil. selectedCategory := nil. self changed: #categoryList. self changed: #packageList. self changed: #packagesListIndex. "update my selection" self contentsChanged]! ! !SMLoaderPlus methodsFor: 'initialization' stamp: 'btr 11/22/2006 16:11'! on: aSqueakMap "Initialize instance." map := aSqueakMap. map synchWithDisk. filters := DefaultFilters copy. categoriesToFilterIds := DefaultCategoriesToFilterIds copy. self askToLoadUpdates! ! !SMLoaderPlus methodsFor: 'filter utilities' stamp: 'btr 11/22/2006 15:02'! package: aPackage filteredByCategory: aCategory "Answer true if the package should be shown if we filter on . It should be shown if itself or any of its releases has the category." | releases | releases := aPackage releases. ^(aPackage hasCategoryOrSubCategoryOf: aCategory) or: [ releases anySatisfy: [:rel | rel hasCategoryOrSubCategoryOf: aCategory]]! ! !SMLoaderPlus methodsFor: 'lists' stamp: 'btr 12/1/2006 01:49'! packageList "Return a list of the SMPackages that should be visible by applying all the filters. Also filter based on the currently selected category - if any." | list | list := packagesList ifNil: [packagesList := self packageListCalculated]. selectedCategory ifNotNil: [ list := list select: [:each | self package: each filteredByCategory: selectedCategory]]. self updateLabel: list. ^ list! ! !SMLoaderPlus methodsFor: 'lists' stamp: 'btr 12/1/2006 01:49'! packageListCalculated "Return a list of the SMPackages that should be visible by applying all the filters. Also filter based on the currently selected category - if any." ^ self packages select: [:p | filters allSatisfy: [:currFilter | currFilter isSymbol ifTrue: [(self perform: currFilter) value: p] ifFalse: [self package: p filteredByCategory: (map object: currFilter)]]]! ! !SMLoaderPlus methodsFor: 'lists' stamp: 'btr 12/1/2006 01:50'! packageNameList ^ self packageList collect: [:e | e name]! ! !SMLoaderPlus methodsFor: 'menus' stamp: 'btr 11/22/2006 18:30'! packageSpecificOptions | choices packageOrRelease | packageOrRelease := self selectedPackageOrRelease. choices := OrderedCollection new. packageOrRelease isInstallable ifTrue: [ choices add: (self commandSpecFor: #installPackageRelease)]. (packageOrRelease isDownloadable and: [packageOrRelease isCached]) ifTrue: [ choices add: (self commandSpecFor: #browseCacheDirectory)]. (packageOrRelease isPackageRelease and: [packageOrRelease isDownloadable]) ifTrue: [ choices add: (self commandSpecFor: #cachePackageReleaseAndOfferToCopy). choices add: (self commandSpecFor: #downloadPackageRelease)]. choices add: (self commandSpecFor: #emailPackageMaintainers). ^ choices! ! !SMLoaderPlus methodsFor: 'private' stamp: 'btr 11/22/2006 16:11'! packages "We request the packages as sorted by name by default." ^map packagesByName asArray ! ! !SMLoaderPlus methodsFor: 'accessing' stamp: 'btr 11/24/2006 14:01'! packagesListIndex ^ self packageList indexOf: self selectedItem! ! !SMLoaderPlus methodsFor: 'accessing' stamp: 'btr 11/24/2006 14:01'! packagesListIndex: anObject self selectedItem: (anObject = 0 ifFalse: [self packageList at: anObject])! ! !SMLoaderPlus methodsFor: 'menus' stamp: 'btr 11/22/2006 15:02'! packagesMenu: aMenu "Answer the packages-list menu." self selectedPackageOrRelease ifNotNil: [aMenu addList: self packageSpecificOptions; addLine]. aMenu addList: self generalOptions. self addFiltersToMenu: aMenu. ^aMenu! ! !SMLoaderPlus methodsFor: 'interface' stamp: 'btr 12/1/2006 01:45'! perform: selector orSendTo: otherTarget "Selector was just chosen from a menu by a user. If can respond, then perform it on myself. If not, send it to otherTarget, presumably the editPane from which the menu was invoked." ^ (self respondsTo: selector) ifTrue: [self perform: selector] ifFalse: [super perform: selector orSendTo: otherTarget]! ! !SMLoaderPlus methodsFor: 'private' stamp: 'btr 11/26/2006 23:22'! reOpen "Close this package loader, probably because it has been updated, and open a new one." self inform: 'This package loader has been upgraded and will be closed and reopened to avoid strange side effects.'. window delete. (Smalltalk at: self class name) open! ! !SMLoaderPlus methodsFor: 'actions' stamp: 'btr 11/22/2006 15:02'! removeCategoryFilters "Remove all category filters." categoriesToFilterIds := OrderedCollection new! ! !SMLoaderPlus methodsFor: 'actions' stamp: 'btr 11/22/2006 15:02'! removeSelectedCategoryAsFilter "Remove the filter that filters on the currently selected category." categoriesToFilterIds remove: self selectedCategory id! ! !SMLoaderPlus methodsFor: 'actions' stamp: 'btr 11/22/2006 15:02'! saveFiltersAsDefault "Save the current filters as default so that they are selected the next time the loader is opened." DefaultFilters := filters copy. DefaultCategoriesToFilterIds := categoriesToFilterIds copy! ! !SMLoaderPlus methodsFor: 'interface' stamp: 'btr 11/24/2006 14:35'! searchSelection "Selects all of the default search text so that a type-in overwrites it." ^ {1. self searchText size}! ! !SMLoaderPlus methodsFor: 'interface' stamp: 'btr 11/24/2006 14:35'! searchText "A dummy default search text so that the field describes its purpose." ^ 'Search packages'! ! !SMLoaderPlus methodsFor: 'accessing' stamp: 'btr 11/24/2006 14:02'! selectedCategory "Return selected category." ^ selectedCategory! ! !SMLoaderPlus methodsFor: 'accessing' stamp: 'btr 12/1/2006 16:37'! selectedCategory: anSMCategory "Change the selected category." selectedCategory := anSMCategory. selectedCategory ifNotNil: [(selectedCategory objects includes: self selectedItem) ifFalse: [self selectedItem: nil]]. self changed: #selectedCategory. self changed: #packageList! ! !SMLoaderPlus methodsFor: 'accessing' stamp: 'btr 11/24/2006 14:52'! selectedCategoryPath "Return selected category's path." | path | path := #(). selectedCategory ifNotNil: [selectedCategory parent ifNotNilDo: [:p | path := path copyWith: p]. path := path copyWith: selectedCategory]. ^ path collect: [:cat | self categoryLabel: cat]! ! !SMLoaderPlus methodsFor: 'accessing' stamp: 'btr 11/24/2006 14:02'! selectedItem ^ selectedItem! ! !SMLoaderPlus methodsFor: 'accessing' stamp: 'btr 12/1/2006 16:27'! selectedItem: anItem "This == workaround protects us from recursion since ToolBuilder's tree widgets will always tell us that the selection has been updated when we tell it that the selection path has been updated. Cleaner solutions invited." anItem == selectedItem ifFalse: [ selectedItem := anItem. self changed: #selectedItemPath. self changed: #itemDescription. self changed: #hasSelectedItem]! ! !SMLoaderPlus methodsFor: 'accessing' stamp: 'btr 12/1/2006 16:16'! selectedItemPath | path | path := #(). (selectedItem isKindOf: SMPackageRelease) ifTrue: [path := path copyWith: selectedItem package]. selectedItem ifNotNil: [path := path copyWith: selectedItem]. ^ path! ! !SMLoaderPlus methodsFor: 'accessing' stamp: 'btr 11/24/2006 14:03'! selectedPackageOrRelease "Return selected package or package release." ^ selectedItem! ! !SMLoaderPlus methodsFor: 'filter utilities' stamp: 'btr 11/22/2006 15:02'! showFilterString: aFilterSymbol ^(self stateForFilter: aFilterSymbol), (self labelForFilter: aFilterSymbol)! ! !SMLoaderPlus methodsFor: 'filter utilities' stamp: 'btr 11/22/2006 15:02'! stateForFilter: aFilterSymbol ^(self filters includes: aFilterSymbol) ifTrue: [''] ifFalse: [''] ! ! !SMLoaderPlus methodsFor: 'filter utilities' stamp: 'btr 11/22/2006 15:02'! toggleFilterState: aFilterSymbol ^(self filters includes: (aFilterSymbol)) ifTrue: [self filterRemove: aFilterSymbol] ifFalse: [self filterAdd: aFilterSymbol]! ! !SMLoaderPlus methodsFor: 'actions' stamp: 'btr 11/22/2006 15:02'! uncheckFilters "Uncheck all filters." filters := OrderedCollection new. self noteChanged! ! !SMLoaderPlus methodsFor: 'lists' stamp: 'btr 12/1/2006 01:50'! updateLabel: packagesShown "Update the label of the window." window ifNotNilDo: [:w | w setLabel: (self labelForShown: packagesShown)]! ! !SMLoaderPlus methodsFor: 'actions' stamp: 'btr 12/1/2006 01:29'! upgradeInstalledPackages "Tries to upgrade all installed packages to the latest published release for this version of Squeak. So this is a conservative approach." | installed old myRelease toUpgrade info | installed := map installedPackages. old := map oldPackages. old isEmpty ifTrue: [ ^self inform: 'All ', installed size printString, ' installed packages are up to date.']. toUpgrade := map upgradeableAndOldPackages. toUpgrade isEmpty ifTrue: [ ^self inform: 'None of the ', old size printString, ' old packages of the ', installed size printString, ' installed can be automatically upgraded. You need to upgrade them manually.']. info := old size < toUpgrade size ifTrue: [ 'Of the ', old size printString, ' old packages only ', toUpgrade size printString, ' can be upgraded. The following packages will not be upgraded: ', (String streamContents: [:s | (old removeAll: toUpgrade; yourself) do: [:p | s nextPutAll: p nameWithVersionLabel; cr]])] ifFalse: ['All old packages upgradeable.']. (self confirm: info, ' About to upgrade the following packages: ', (String streamContents: [:s | toUpgrade do: [:p | s nextPutAll: p nameWithVersionLabel; cr]]), 'Proceed?') ifTrue: [ myRelease := self installedReleaseOfMe. [UIManager default informUser: 'Upgrading Installed Packages' during: [ map upgradeOldPackages. self inform: toUpgrade size printString, ' packages successfully upgraded.'. myRelease = self installedReleaseOfMe ifFalse: [self reOpen] ifTrue: [self noteChanged]] ] on: Error do: [:ex | self informException: ex msg: ('Error occurred when upgrading old packages:\', ex messageText, '\') withCRs]]! ! !SMLoaderPlus methodsFor: 'actions' stamp: 'btr 11/22/2006 15:02'! upgradeInstalledPackagesConfirm "Tries to upgrade all installed packages to the latest published release for this version of Squeak. Confirms on each upgrade." ^ self upgradeInstalledPackagesConfirm: true! ! !SMLoaderPlus methodsFor: 'private' stamp: 'btr 12/1/2006 01:29'! upgradeInstalledPackagesConfirm: confirmEach "Tries to upgrade all installed packages to the latest published release for this version of Squeak. If confirmEach is true we ask for every upgrade. " | installed old myRelease toUpgrade info | installed := map installedPackages. old := map oldPackages. old isEmpty ifTrue: [^ self inform: 'All ' , installed size printString , ' installed packages are up to date.']. toUpgrade := map upgradeableAndOldPackages. toUpgrade isEmpty ifTrue: [^ self inform: 'None of the ' , old size printString , ' old packages of the ' , installed size printString , ' installed can be automatically upgraded. You need to upgrade them manually.']. info := old size < toUpgrade size ifTrue: ['Of the ' , old size printString , ' old packages only ' , toUpgrade size printString , ' can be upgraded. The following packages will not be upgraded: ' , (String streamContents: [:s | (old removeAll: toUpgrade; yourself) do: [:p | s nextPutAll: p nameWithVersionLabel; cr]])] ifFalse: ['All old packages upgradeable.']. (self confirm: info , ' About to upgrade the following packages: ' , (String streamContents: [:s | toUpgrade do: [:p | s nextPutAll: p nameWithVersionLabel; cr]]) , 'Proceed?') ifTrue: [myRelease := self installedReleaseOfMe. [UIManager default informUser: 'Upgrading Installed Packages' during: [confirmEach ifTrue: [map upgradeOldPackagesConfirmBlock: [:p | self confirm: 'Upgrade ' , p installedRelease packageNameWithVersion , ' to ' , (p lastPublishedReleaseForCurrentSystemVersionNewerThan: p installedRelease) listName , '?']] ifFalse: [map upgradeOldPackages]. self inform: toUpgrade size printString , ' packages successfully processed.'. myRelease = self installedReleaseOfMe ifTrue: [self noteChanged] ifFalse: [self reOpen]]] on: Error do: [:ex | self informException: ex msg: ('Error occurred when upgrading old packages:\' , ex messageText , '\') withCRs]]! ! !SMLoaderPlus methodsFor: 'actions' stamp: 'btr 11/22/2006 15:02'! upgradeInstalledPackagesNoConfirm "Tries to upgrade all installed packages to the latest published release for this version of Squeak. No confirmation on each upgrade." ^ self upgradeInstalledPackagesConfirm: false! ! !SMPackageWrapper methodsFor: 'comparing' stamp: 'dvf 9/21/2003 16:25' prior: 27998626! = anObject ^self withoutListWrapper = anObject withoutListWrapper! ! !SMPackageWrapper methodsFor: 'converting' stamp: 'btr 11/22/2006 00:54' prior: 27998778! asString | string | string := item name, ' (', item versionLabel, ')'. item isInstalled ifTrue: [string := string asText allBold]. "(string includesSubString: '->') ifTrue: [string := string asText color: Color green]." ^ string! ! !SMPackageWrapper methodsFor: 'accessing' stamp: 'dvf 10/14/2003 18:58' prior: 27998902! contents ^item releases reversed collect: [:e | SMPackageReleaseWrapper with: e]! ! !SMPackageWrapper methodsFor: 'testing' stamp: 'dvf 9/21/2003 16:25' prior: 27999070! hash ^self withoutListWrapper hash! ! !SMPackageWrapper methodsFor: 'accessing' stamp: 'btr 11/22/2006 16:55'! help ^ 'This shows all packages with their releases that should be displayed according the current filter.'! ! !SMPackageWrapper methodsFor: 'accessing' stamp: 'btr 11/22/2006 16:49'! label ^ self asString! ! !SMPackageWrapper methodsFor: 'printing' stamp: 'dvf 9/21/2003 16:22' prior: 27999192! printOn: aStream aStream nextPutAll: 'wrapper for: ', item printString! ! !SMCategoryWrapper methodsFor: 'comparing' stamp: 'ar 2/9/2004 02:13' prior: 27849043! = anObject ^self withoutListWrapper = anObject withoutListWrapper! ! !SMCategoryWrapper methodsFor: 'converting' stamp: 'btr 11/30/2006 18:53' prior: 27849195! asString ^ item name , ' (' , self numberOfObjects printString , ')'! ! !SMCategoryWrapper methodsFor: 'accessing' stamp: 'ar 2/9/2004 02:35' prior: 27849301! category ^item! ! !SMCategoryWrapper methodsFor: 'accessing' stamp: 'btr 11/30/2006 21:02' prior: 27849402! contents ^ item subCategories collect: [:n | self class with: n model: n]! ! !SMCategoryWrapper methodsFor: 'model access' stamp: 'btr 11/30/2006 21:02'! getList ^ Array with: (self class with: self contents model: model)! ! !SMCategoryWrapper methodsFor: 'testing' stamp: 'btr 11/30/2006 18:53'! hasContents ^ item hasSubCategories! ! !SMCategoryWrapper methodsFor: 'comparing' stamp: 'ar 2/9/2004 02:13' prior: 27849700! hash ^self withoutListWrapper hash! ! !SMCategoryWrapper methodsFor: 'accessing' stamp: 'btr 11/22/2006 16:56'! help ^ 'The categories are structured in a tree. Packages and package releases belong to several categories. You can add one or more categories as filters and enable them in the menu.'! ! !SMCategoryWrapper methodsFor: 'accessing' stamp: 'BJP 11/22/2002 14:17'! model ^model! ! !SMCategoryWrapper methodsFor: 'accessing' stamp: 'btr 11/30/2006 18:53'! numberOfObjects " | total | total _ 0. model allCategoriesDo: [:c | total _ total + c objects size]. ^total" ^item objects size! ! !SMPackageReleaseWrapper methodsFor: 'converting' stamp: 'btr 11/30/2006 21:30' prior: 27997393! asString "Show installed releases with a trailing asterisk." | string | string := item smartVersion. "Older SMBase versions don't have isInstalled.'" (item respondsTo: #isInstalled) ifTrue: [item isInstalled ifTrue: [string := (string , ' *') asText allBold]]. ^ string! ! !SMPackageReleaseWrapper methodsFor: 'accessing' stamp: 'btr 11/22/2006 17:14'! contents ^ #()! ! !SMPackageReleaseWrapper methodsFor: 'accessing' stamp: 'btr 11/22/2006 16:49'! label ^ self asString ! ! !SMLoader class methodsFor: 'class initialization' stamp: 'btr 12/1/2006 15:47' prior: 27944626! initialize "Hook us up in the world menu." "self initialize" Smalltalk at: #ToolBuilder ifAbsent: [self registerInFlapsRegistry. (Preferences windowColorFor: #SMLoader) = Color white ifTrue: ["not set" Preferences setWindowColorFor: #SMLoader to: (Color colorFrom: self windowColorSpecification brightColor)]. (TheWorldMenu respondsTo: #registerOpenCommand:) ifTrue: [| oldCmds | oldCmds := TheWorldMenu registry select: [:cmd | cmd first includesSubString: 'Package Loader']. oldCmds do: [:cmd | TheWorldMenu unregisterOpenCommand: cmd first]. TheWorldMenu registerOpenCommand: {self openMenuString. {self. #open}}]]. DefaultFilters := OrderedCollection new. DefaultCategoriesToFilterIds := OrderedCollection new! ! !SMLoader class methodsFor: 'class initialization' stamp: 'btr 11/30/2006 21:52'! openMenuString ^ 'SqueakMap Catalog'! ! !SMLoader class methodsFor: 'class initialization' stamp: 'btr 11/30/2006 21:52' prior: 27945298! unload (TheWorldMenu respondsTo: #registerOpenCommand:) ifTrue: [TheWorldMenu unregisterOpenCommand: self openMenuString]. self environment at: #Flaps ifPresent: [:cl | cl unregisterQuadsWithReceiver: self] ! ! !SMLoader methodsFor: 'menus' stamp: 'btr 11/21/2006 16:08' prior: 54331069! addFiltersToMenu: aMenu | filterSymbol help | self filterSpecs do: [:filterArray | filterSymbol := filterArray second. help := filterArray third. aMenu addUpdating: #showFilterString: target: self selector: #toggleFilterState: argumentList: (Array with: filterSymbol). aMenu balloonTextForLastItem: help]. aMenu addLine; addList: #(('Clear all filters' uncheckFilters 'Unchecks all filters to list all packages')) ! ! !SMLoader methodsFor: 'interface' stamp: 'btr 11/22/2006 01:15' prior: 27927912! browseCacheDirectory "Open a FileList2 on the directory for the package or release." | item dir win | item := self selectedPackageOrRelease ifNil: [^ nil]. item ifNil: [^nil]. dir := item isPackage ifTrue: [model cache directoryForPackage: item] ifFalse: [model cache directoryForPackageRelease: item]. win := FileList2 morphicViewOnDirectory: dir. " withLabel: item name, ' cache directory'." win openInWorld ! ! !SMLoader methodsFor: 'interface' stamp: 'btr 11/22/2006 14:52'! buildButtonBar | aRow btn | aRow := AlignmentMorph newRow beSticky. aRow color: Color transparent; clipSubmorphs: true. self buttonSpecs do: [:spec | btn := self buildButtonNamed: spec first helpText: spec third action: spec second. aRow addMorphBack: btn] separatedBy: [aRow addTransparentSpacerOfSize: 3 at 0]. ^ aRow! ! !SMLoader methodsFor: 'interface' stamp: 'btr 11/22/2006 01:27'! buildButtonNamed: labelText helpText: balloon action: action | btn | btn := PluggableButtonMorph on: self getState: nil action: action. btn color: Color transparent; hResizing: #shrinkWrap; vResizing: #spaceFill; label: labelText; setBalloonText: balloon; onColor: Color transparent offColor: Color transparent. ^ btn! ! !SMLoader methodsFor: 'interface' stamp: 'btr 11/30/2006 19:04' prior: 27928394! buildMorphicCategoriesList "Create the hierarchical list holding the category tree." | list | list := (SimpleHierarchicalListMorph on: self list: #categoryWrapperList selected: #selectedCategoryWrapper changeSelected: #selectedCategoryWrapper: menu: #categoriesMenu: keystroke: nil) autoDeselect: true; enableDrag: false; enableDrop: true; yourself. list setBalloonText: 'The categories are structured in a tree. Packages and package releases belong to several categories. You can add one or more categories as filters and enable them in the menu.'. "list scroller submorphs do:[:each| list expandAll: each]." list adjustSubmorphPositions. ^ list! ! !SMLoader methodsFor: 'interface' stamp: 'btr 11/22/2006 00:22' prior: 27929139! buildMorphicPackagesList "Create the hierarchical list holding the packages and releases." ^(SimpleHierarchicalListMorph on: self list: #packageWrapperList selected: #selectedItemWrapper changeSelected: #selectedItemWrapper: menu: #packagesMenu: keystroke: nil) autoDeselect: false; enableDrag: false; enableDrop: true; setBalloonText: 'This shows all packages with their releases that should be displayed according the current filter.'; yourself! ! !SMLoader methodsFor: 'interface' stamp: 'btr 11/30/2006 21:13'! buildPackageButtonBar | aRow | "Somewhat patterned after IRCe's buttonRow method." aRow := AlignmentMorph newRow beSticky. aRow color: Color transparent; clipSubmorphs: true. ^ aRow! ! !SMLoader methodsFor: 'interface' stamp: 'gk 5/5/2006 02:05' prior: 27929686! buildPackagePane "Create the text area to the right in the loader." | ptm | ptm := PluggableTextMorph on: self text: #contents accept: nil readSelection: nil "#packageSelection " menu: nil. ptm setBalloonText: 'This is where the selected package or package release is displayed.'. ptm lock. ^ptm! ! !SMLoader methodsFor: 'interface' stamp: 'btr 11/30/2006 21:08' prior: 27930070! buildSearchPane "Cribbed from MessageNames>>inMorphicWindowWithInitialSearchString:" | typeInView searchButton typeInPane | typeInView := PluggableTextMorph on: self text: nil accept: #findPackage:notifying: readSelection: nil menu: nil. typeInView acceptOnCR: true; vResizing: #spaceFill; hResizing: #spaceFill; setTextMorphToSelectAllOnMouseEnter; askBeforeDiscardingEdits: false; setProperty: #alwaysAccept toValue: true. (typeInView respondsTo: #hideScrollBarsIndefinitely) ifTrue: [typeInView hideScrollBarsIndefinitely] ifFalse: [typeInView hideScrollBarIndefinitely]. searchButton := SimpleButtonMorph new target: typeInView; color: Color white; label: 'Search'; actionSelector: #accept; arguments: #(); yourself. typeInPane := AlignmentMorph newRow. typeInPane vResizing: #shrinkWrap; hResizing: #shrinkWrap; listDirection: #leftToRight; addMorphFront: searchButton; addTransparentSpacerOfSize: 6 @ 0; addMorphBack: typeInView; setBalloonText: 'Type into the pane, then press Search (or hit RETURN) to visit the next package matching what you typed.'. ^ typeInPane! ! !SMLoader methodsFor: 'interface' stamp: 'btr 11/22/2006 14:24'! buttonSpecs ^ #(('Install' installPackageRelease 'Install the latest version from the server.') ('Email' emailPackageMaintainers 'Open an editor to send an email to the owner and co-maintainers of this package.') ('Browse cache' browseCacheDirectory 'Browse cache directory of the selection.') ('Update' loadUpdates 'Update the package index from the servers.') ('Upgrade All' upgradeInstalledPackagesConfirm 'Upgrade all installed packages (confirming each).') ('Help' help 'What is this?'))! ! !SMLoader methodsFor: 'menus' stamp: 'btr 11/21/2006 16:11' prior: 27936393! categorySpecificOptions | choices | choices := OrderedCollection new. (categoriesToFilterIds includes: self selectedCategory id) ifTrue: [ choices add: #('Remove filter' #removeSelectedCategoryAsFilter 'Remove the filter for the selected category.')] ifFalse: [ choices add: #('Add as filter' #addSelectedCategoryAsFilter 'Add the selection as a filter to hide unrelated packages.')]. categoriesToFilterIds isEmpty ifFalse: [ choices add: #('Remove all filters' #removeCategoryFilters 'Remove all category filters.')]. ^ choices! ! !SMLoader methodsFor: 'lists' stamp: 'btr 11/30/2006 21:01' prior: 27933585! categoryWrapperList "Create the wrapper list for the hierarchical list. We sort the categories by name but ensure that 'Squeak versions' is first if it exists." | list first | list := (model categories select: [:each | each parent isNil]) asArray sort: [:c1 :c2 | c1 name <= c2 name]. first := list detect: [:any | any name = 'Squeak versions'] ifNone: []. first ifNotNil: [list := list copyWithout: first. list := {first} , list]. ^ list collect: [:cat | SMCategoryWrapper with: cat model: self]! ! !SMLoader methodsFor: 'filter utilities' stamp: 'gk 7/10/2004 15:45' prior: 27913226! changeFilters: anObject "Update my selection." | oldItem index | oldItem := self selectedPackageOrRelease. filters := anObject. self packagesListIndex: ((index := self packageList indexOf: oldItem) ifNil: [0] ifNotNil: [index]). self noteChanged! ! !SMLoader methodsFor: 'interface' stamp: 'btr 11/30/2006 17:30' prior: 27930584! createWindow | buttonBarHeight searchHeight vertDivide horizDivide | buttonBarHeight := 0.07. searchHeight := 0.07. vertDivide := 0.3. horizDivide := 0.6. self addMorph: (self buildButtonBar borderWidth: 0) frame: (0.0 @ 0.0 corner: 1.0 @ buttonBarHeight). self addMorph: (self buildSearchPane borderWidth: 0) frame: (0.0 @ buttonBarHeight corner: vertDivide @ searchHeight). self addMorph: (self buildMorphicPackagesList borderWidth: 0) frame: (0.0 @ (buttonBarHeight + searchHeight) corner: vertDivide @ horizDivide). self addMorph: (self buildMorphicCategoriesList borderWidth: 0) frame: (0.0 @ horizDivide corner: vertDivide @ 1.0). self addMorph: (self buildPackagePane borderWidth: 0) frame: (vertDivide @ buttonBarHeight corner: 1.0 @ 1.0). self on: #mouseEnter send: #paneTransition: to: self. self on: #mouseLeave send: #paneTransition: to: self! ! !SMLoader methodsFor: 'interface' stamp: 'gk 7/12/2004 11:14' prior: 27931214! defaultButtonPaneHeight "Answer the user's preferred default height for new button panes." ^ Preferences parameterAt: #defaultButtonPaneHeight ifAbsentPut: [25]! ! !SMLoader methodsFor: 'interface' stamp: 'btr 12/1/2006 02:01'! defaultLabel ^'SqueakMap Package Loader'! ! !SMLoader methodsFor: 'actions' stamp: 'btr 11/22/2006 01:14' prior: 27917579! emailPackageMaintainers From noreply at buildbot.pypy.org Mon Apr 29 19:22:00 2013 From: noreply at buildbot.pypy.org (bivab) Date: Mon, 29 Apr 2013 19:22:00 +0200 (CEST) Subject: [pypy-commit] buildbot buildbot-0.8.7: adapt to new interfaces Message-ID: <20130429172200.7A3511C026F@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: buildbot-0.8.7 Changeset: r812:43a1e6b1687c Date: 2013-04-29 17:05 +0200 http://bitbucket.org/pypy/buildbot/changeset/43a1e6b1687c/ Log: adapt to new interfaces diff --git a/bot2/pypybuildbot/test/test_summary.py b/bot2/pypybuildbot/test/test_summary.py --- a/bot2/pypybuildbot/test/test_summary.py +++ b/bot2/pypybuildbot/test/test_summary.py @@ -401,7 +401,7 @@ def __init__(self, builders, args={}): master = FakeMaster(builders) - status = status_builder.Status(master) + status = status_builder.Status(master, builders) self.args = args self.site = FakeSite(status) @@ -444,7 +444,7 @@ n = getattr(builder, 'nextBuildNumber', 0) t = 1000 for rev, reslog in builds: - build = status_builder.BuildStatus(builder, n) + build = status_builder.BuildStatus(builder, builder.master, n) build.started = time.time() build.setProperty('got_revision', str(rev), None) step = build.addStepWithName('pytest') @@ -463,6 +463,7 @@ def setup_method(self, meth): summary.outcome_set_cache.clear() + self.master = FakeMaster([]) def test_sanity(self): s = summary.Summary() @@ -474,9 +475,9 @@ assert cat_branch == {} def test_one_build_no_rev(self): - builder = status_builder.BuilderStatus('builder0') - build = status_builder.BuildStatus(builder, 0) - build.started = time.time() + builder = status_builder.BuilderStatus('builder0', '', self.master) + build = status_builder.BuildStatus(builder, self.master, 0) + builder.buildStarted(build) build.buildFinished() builder.touchBuildCache(build) builder.nextBuildNumber = len(builder.buildCache) @@ -490,8 +491,8 @@ assert cat_branch == {(None, None): ({}, [build])} def test_one_build_no_logs(self): - builder = status_builder.BuilderStatus('builder0') - build = status_builder.BuildStatus(builder, 0) + builder = status_builder.BuilderStatus('builder0', '', self.master) + build = status_builder.BuildStatus(None, builder, 0) build.started = time.time() build.setProperty('got_revision', '50000', None) build.buildFinished() @@ -510,7 +511,7 @@ assert '<run>' in out def test_one_build_no_logs_failure(self): - builder = status_builder.BuilderStatus('builder0') + builder = status_builder.BuilderStatus('builder0', '', self.master) build = status_builder.BuildStatus(builder, 0) build.started = time.time() build.setProperty('got_revision', '50000', None) @@ -537,7 +538,7 @@ assert 'other borken' not in out def test_one_build(self): - builder = status_builder.BuilderStatus('builder0') + builder = status_builder.BuilderStatus('builder0', '', self.master) add_builds(builder, [(60000, "F TEST1\n. b")]) s = summary.Summary() @@ -555,7 +556,7 @@ assert 'TEST1' in out def test_two_builds(self): - builder = status_builder.BuilderStatus('builder0') + builder = status_builder.BuilderStatus('builder0', '', self.master) add_builds(builder, [('60000', "F TEST1\n. b"), ('60001', ". TEST1\n. b")]) @@ -585,7 +586,7 @@ assert '\n - + success' in out def test_two_builds_samerev(self): - builder = status_builder.BuilderStatus('builder0') + builder = status_builder.BuilderStatus('builder0', '', self.master) add_builds(builder, [('60000', "F TEST1\n. b"), ('60000', "F TEST1\n. b")]) @@ -604,7 +605,7 @@ assert 'TEST1' in out def test_two_builds_recentrev(self): - builder = status_builder.BuilderStatus('builder0') + builder = status_builder.BuilderStatus('builder0', '', self.master) add_builds(builder, [('60000', "F TEST1\n. b"), ('60001', "F TEST1\n. b")]) @@ -624,7 +625,7 @@ assert 'TEST1' in out def test_many_builds_query_builder(self): - builder = status_builder.BuilderStatus('builder0') + builder = status_builder.BuilderStatus('builder0', '', self.master) add_builds(builder, [('60000', "F TEST1\n. b"), ('60000', ". a\n. b"), ('60001', "F TEST1\n. b")]) @@ -660,7 +661,7 @@ def test_many_builds_query_builder_builds(self): - builder = status_builder.BuilderStatus('builder0') + builder = status_builder.BuilderStatus('builder0', '', self.master) add_builds(builder, [('60000', "F TEST1\n. b"), ('60000', ". a\n. b"), ('60001', "F TEST1\n. b")]) @@ -692,7 +693,7 @@ assert 'TEST1' in out def test_many_pytestLogs(self): - builder = status_builder.BuilderStatus('builder1') + builder = status_builder.BuilderStatus('builder1', '', self.master) build = status_builder.BuildStatus(builder, 0) build.started = time.time() build.setProperty('got_revision', '70000', None) @@ -719,7 +720,7 @@ assert 'pytest2 aborted' in out def test_subtle_failures(self): - builder = status_builder.BuilderStatus('builder1') + builder = status_builder.BuilderStatus('builder1', '', self.master) build = status_builder.BuildStatus(builder, 0) build.started = time.time() build.setProperty('got_revision', '70000', None) @@ -767,12 +768,9 @@ assert res == (2, '', 4, 'what') def test_builders_with_categories(self): - builder1 = status_builder.BuilderStatus('builder_foo') - builder1.category = 'foo' - builder2 = status_builder.BuilderStatus('builder_bar') - builder2.category = 'bar' - builder3 = status_builder.BuilderStatus('builder_') - builder3.category = '' + builder1 = status_builder.BuilderStatus('builder_foo', 'foo', self.master) + builder2 = status_builder.BuilderStatus('builder_bar', 'bar', self.master) + builder3 = status_builder.BuilderStatus('builder_', '', self.master) add_builds(builder1, [('60000', "F TEST1\n")]) add_builds(builder2, [('60000', "F TEST2\n")]) @@ -792,7 +790,7 @@ assert "{bar}" in out def test_two_builds_different_rev_digits(self): - builder = status_builder.BuilderStatus('builder0') + builder = status_builder.BuilderStatus('builder0', '', self.master) add_builds(builder, [(999, "F TEST1\n. b"), (1000, "F TEST1\n. b")]) @@ -806,8 +804,8 @@ assert p999builder0-p999 == p1000builder0-p1000+1 def test_build_times_and_filtering(self): - builder1 = status_builder.BuilderStatus('builder1') - builder2 = status_builder.BuilderStatus('builder2') + builder1 = status_builder.BuilderStatus('builder1', '', self.master) + builder2 = status_builder.BuilderStatus('builder2', '', self.master) add_builds(builder1, [('60000', "F TEST1\n")]) add_builds(builder2, [('50000', ". TEST2\n")]) From noreply at buildbot.pypy.org Mon Apr 29 19:22:01 2013 From: noreply at buildbot.pypy.org (bivab) Date: Mon, 29 Apr 2013 19:22:01 +0200 (CEST) Subject: [pypy-commit] buildbot buildbot-0.8.7: use the builtin mercurial support Message-ID: <20130429172201.9C3A21C026F@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: buildbot-0.8.7 Changeset: r813:9f8ceeb704d5 Date: 2013-04-29 19:21 +0200 http://bitbucket.org/pypy/buildbot/changeset/9f8ceeb704d5/ Log: use the builtin mercurial support diff --git a/bot2/pypybuildbot/builds.py b/bot2/pypybuildbot/builds.py --- a/bot2/pypybuildbot/builds.py +++ b/bot2/pypybuildbot/builds.py @@ -1,3 +1,4 @@ +from buildbot.steps.source.mercurial import Mercurial from buildbot.process import factory from buildbot.steps import shell, transfer from buildbot.steps.trigger import Trigger @@ -59,8 +60,8 @@ if not os.path.exists(masterdest): os.makedirs(masterdest) # - assert '%(final_file_name)s' in self.basename - symname = self.basename.replace('%(final_file_name)s', 'latest') + assert '%(got_revision)s' in self.basename + symname = self.basename.replace('%(got_revision)s', 'latest') assert '%' not in symname self.symlinkname = os.path.join(masterdest, symname) # @@ -178,92 +179,18 @@ # _______________________________________________________________ -class UpdateCheckout(ShellCmd): - description = 'hg update' - command = 'UNKNOWN' - - def __init__(self, workdir=None, haltOnFailure=True, force_branch=None, - **kwargs): - ShellCmd.__init__(self, workdir=workdir, haltOnFailure=haltOnFailure, - **kwargs) - self.force_branch = force_branch - self.addFactoryArguments(force_branch=force_branch) - - def start(self): - if self.force_branch is not None: - branch = self.force_branch - # Note: We could add a warning to the output if we - # ignore the branch set by the user. - else: - properties = self.build.getProperties() - branch = properties['branch'] or 'default' - command = ["hg", "update", "--clean", "-r", branch] - self.setCommand(command) - ShellCmd.start(self) - - -class CheckGotRevision(ShellCmd): - description = 'got_revision' - command = ['hg', 'parents', '--template', 'got_revision:{rev}:{node}'] - - def commandComplete(self, cmd): - if cmd.rc == 0: - got_revision = cmd.logs['stdio'].getText() - got_revision = got_revision.split('got_revision:')[-1] - # manually get the effect of {node|short} without using a - # '|' in the command-line, because it doesn't work on Windows - num = got_revision.find(':') - if num > 0: - got_revision = got_revision[:num + 13] - # - final_file_name = got_revision.replace(':', '-') - # ':' should not be part of filenames --- too many issues - self.build.setProperty('got_revision', got_revision, - 'got_revision') - self.build.setProperty('final_file_name', final_file_name, - 'got_revision') - - def update_hg(platform, factory, repourl, workdir, use_branch, force_branch=None): - if platform == 'win32': - command = "if not exist .hg rmdir /q /s ." - else: - command = "if [ ! -d .hg ]; then rm -fr * .[a-z]*; fi" - factory.addStep(ShellCmd(description="rmdir?", - command=command, - workdir=workdir, - haltOnFailure=False)) - # - if platform == "win32": - command = "if not exist .hg %s" - else: - command = "if [ ! -d .hg ]; then %s; fi" - command = command % ("hg clone -U " + repourl + " .") - factory.addStep(ShellCmd(description="hg clone", - command=command, - workdir=workdir, - timeout=3600, - haltOnFailure=True)) - # factory.addStep( - ShellCmd(description="hg purge", - command="hg --config extensions.purge= purge --all", - workdir=workdir, - haltOnFailure=True)) - # - factory.addStep(ShellCmd(description="hg pull", - command="hg pull", - workdir=workdir)) - # - if use_branch or force_branch: - factory.addStep(UpdateCheckout(workdir=workdir, - haltOnFailure=True, - force_branch=force_branch)) - else: - factory.addStep(ShellCmd(description="hg update", - command=WithProperties("hg update --clean %(revision)s"), - workdir=workdir)) + Mercurial( + repourl=repourl, + mode='incremental', + method='fresh', + defaultBranch=force_branch, + branchType='inrepo', + clobberOnBranchChange=False, + workdir=workdir, + logEnviron=False)) def setup_steps(platform, factory, workdir=None, @@ -278,11 +205,11 @@ update_hg(platform, factory, repourl, workdir, use_branch=True, force_branch=force_branch) # - factory.addStep(CheckGotRevision(workdir=workdir)) + def build_name(platform, jit=False, flags=[], placeholder=None): if placeholder is None: - placeholder = '%(final_file_name)s' + placeholder = '%(got_revision)s' if jit or '-Ojit' in flags: kind = 'jit' else: From noreply at buildbot.pypy.org Mon Apr 29 19:39:51 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Mon, 29 Apr 2013 19:39:51 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: fixed typo Message-ID: <20130429173951.99D9C1C01C2@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r351:5878891e9deb Date: 2013-04-29 19:39 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/5878891e9deb/ Log: fixed typo calling get_commitid only once changed template because the day information is also recorded by the speedcenter diff --git a/benchmarks.py b/benchmarks.py --- a/benchmarks.py +++ b/benchmarks.py @@ -21,7 +21,7 @@ def build_data(executable, benchmark, result): # Mandatory fields return { - 'commitid': get_commitid(), + 'commitid': COMMIT_ID, 'branch': 'default', 'project': 'lang-smalltalk', 'executable': executable, @@ -92,7 +92,7 @@ def get_commitid(): try: pipe = subprocess.Popen( - ["hg", "log", "-l", "1", "--template", "{branch}-{rev} {date|shortdate}"], + ["hg", "log", "-l", "1", "--template", "{branch}-{rev}"], stdout=subprocess.PIPE ) if pipe.wait() == 0: @@ -110,6 +110,8 @@ pass raise Exception("commitid not found. not a git or hg repo") +COMMIT_ID = get_commitid() + def add(executable, benchmark, result): print "Saving result %s for executable %s, benchmark %s" % ( @@ -133,7 +135,7 @@ with open('update.st', 'w') as f: f.write('''Smalltalk snapshot: true andQuit: true.''') pipe = subprocess.Popen( - ['cogmtlinux/squeak%s images/%s ../update.st' % (suffix, SqueakImage)], + ['coglinux/squeak%s images/%s ../update.st' % (suffix, SqueakImage)], shell=True) pipe.wait() os.remove('update.st') From noreply at buildbot.pypy.org Mon Apr 29 20:07:59 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Mon, 29 Apr 2013 20:07:59 +0200 (CEST) Subject: [pypy-commit] pypy py3k: merge default Message-ID: <20130429180759.A6ED91C1000@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63755:832759b67482 Date: 2013-04-29 11:07 -0700 http://bitbucket.org/pypy/pypy/changeset/832759b67482/ Log: merge default diff --git a/lib-python/2.7/pydoc.py b/lib-python/2.7/pydoc.py --- a/lib-python/2.7/pydoc.py +++ b/lib-python/2.7/pydoc.py @@ -1953,7 +1953,11 @@ if key is None: callback(None, modname, '') else: - desc = split(__import__(modname).__doc__ or '', '\n')[0] + try: + module_doc = __import__(modname).__doc__ + except ImportError: + module_doc = None + desc = split(module_doc or '', '\n')[0] if find(lower(modname + ' - ' + desc), key) >= 0: callback(None, modname, desc) diff --git a/py/_path/local.py b/py/_path/local.py --- a/py/_path/local.py +++ b/py/_path/local.py @@ -655,7 +655,8 @@ mkdtemp = classmethod(mkdtemp) def make_numbered_dir(cls, prefix='session-', rootdir=None, keep=3, - lock_timeout = 172800): # two days + lock_timeout = 172800, # two days + min_timeout = 300): # five minutes """ return unique directory with a number greater than the current maximum one. The number is assumed to start directly after prefix. if keep is true directories with a number less than (maxnum-keep) @@ -723,6 +724,20 @@ for path in rootdir.listdir(): num = parse_num(path) if num is not None and num <= (maxnum - keep): + if min_timeout: + # NB: doing this is needed to prevent (or reduce + # a lot the chance of) the following situation: + # 'keep+1' processes call make_numbered_dir() at + # the same time, they create dirs, but then the + # last process notices the first dir doesn't have + # (yet) a .lock in it and kills it. + try: + t1 = path.lstat().mtime + t2 = lockfile.lstat().mtime + if abs(t2-t1) < min_timeout: + continue # skip directories too recent + except py.error.Error: + continue # failure to get a time, better skip lf = path.join('.lock') try: t1 = lf.lstat().mtime diff --git a/pypy/doc/getting-started-python.rst b/pypy/doc/getting-started-python.rst --- a/pypy/doc/getting-started-python.rst +++ b/pypy/doc/getting-started-python.rst @@ -46,7 +46,7 @@ 2. Install build-time dependencies. On a Debian box these are:: [user at debian-box ~]$ sudo apt-get install \ - gcc make python-dev libffi-dev lib-sqlite3-dev pkg-config \ + gcc make python-dev libffi-dev libsqlite3-dev pkg-config \ libz-dev libbz2-dev libncurses-dev libexpat1-dev \ libssl-dev libgc-dev python-sphinx python-greenlet diff --git a/rpython/annotator/builtin.py b/rpython/annotator/builtin.py --- a/rpython/annotator/builtin.py +++ b/rpython/annotator/builtin.py @@ -89,9 +89,15 @@ builtin_xrange = builtin_range # xxx for now allow it + def builtin_enumerate(s_obj): return SomeIterator(s_obj, "enumerate") + +def builtin_reversed(s_obj): + return SomeIterator(s_obj, "reversed") + + def builtin_bool(s_obj): return s_obj.is_true() diff --git a/rpython/annotator/test/test_annrpython.py b/rpython/annotator/test/test_annrpython.py --- a/rpython/annotator/test/test_annrpython.py +++ b/rpython/annotator/test/test_annrpython.py @@ -3837,6 +3837,16 @@ s = a.build_types(fn, [int]) assert isinstance(s, annmodel.SomeInteger) + def test_reversed(self): + def fn(n): + for elem in reversed([1, 2, 3, 4, 5]): + return elem + return n + + a = self.RPythonAnnotator() + s = a.build_types(fn, [int]) + assert isinstance(s, annmodel.SomeInteger) + def test_no_attr_on_common_exception_classes(self): for cls in [ValueError, Exception]: def fn(): diff --git a/rpython/annotator/unaryop.py b/rpython/annotator/unaryop.py --- a/rpython/annotator/unaryop.py +++ b/rpython/annotator/unaryop.py @@ -616,7 +616,10 @@ if itr.variant == ("enumerate",): s_item = itr.s_container.getanyitem() return SomeTuple((SomeInteger(nonneg=True), s_item)) - return itr.s_container.getanyitem(*itr.variant) + variant = itr.variant + if variant == ("reversed",): + variant = () + return itr.s_container.getanyitem(*variant) next.can_only_throw = _can_only_throw method_next = next diff --git a/rpython/rtyper/lltypesystem/rlist.py b/rpython/rtyper/lltypesystem/rlist.py --- a/rpython/rtyper/lltypesystem/rlist.py +++ b/rpython/rtyper/lltypesystem/rlist.py @@ -52,8 +52,13 @@ def get_eqfunc(self): return inputconst(Void, self.item_repr.get_ll_eq_function()) - def make_iterator_repr(self): - return ListIteratorRepr(self) + def make_iterator_repr(self, *variant): + if not variant: + return ListIteratorRepr(self) + elif variant == ("reversed",): + return ReversedListIteratorRepr(self) + else: + raise NotImplementedError(variant) def get_itemarray_lowleveltype(self): ITEM = self.item_repr.lowleveltype @@ -432,6 +437,7 @@ self.ll_listnext = ll_listnext self.ll_getnextindex = ll_getnextindex + def ll_listiter(ITERPTR, lst): iter = malloc(ITERPTR.TO) iter.list = lst @@ -457,3 +463,30 @@ def ll_getnextindex(iter): return iter.index + + +class ReversedListIteratorRepr(AbstractListIteratorRepr): + def __init__(self, r_list): + self.r_list = r_list + self.lowleveltype = Ptr(GcStruct('revlistiter', + ('list', r_list.lowleveltype), + ('index', Signed), + )) + self.ll_listnext = ll_revlistnext + self.ll_listiter = ll_revlistiter + + +def ll_revlistiter(ITERPTR, lst): + iter = malloc(ITERPTR.TO) + iter.list = lst + iter.index = lst.ll_length() - 1 + return iter + + +def ll_revlistnext(iter): + l = iter.list + index = iter.index + if index < 0: + raise StopIteration + iter.index -= 1 + return l.ll_getitem_fast(index) diff --git a/rpython/rtyper/rbuiltin.py b/rpython/rtyper/rbuiltin.py --- a/rpython/rtyper/rbuiltin.py +++ b/rpython/rtyper/rbuiltin.py @@ -261,6 +261,12 @@ hop.exception_cannot_occur() return hop.gendirectcall(ll_max, v1, v2) + +def rtype_builtin_reversed(hop): + hop.exception_cannot_occur() + return hop.r_result.newiter(hop) + + def ll_max(i1, i2): if i1 > i2: return i1 diff --git a/rpython/rtyper/test/test_rlist.py b/rpython/rtyper/test/test_rlist.py --- a/rpython/rtyper/test/test_rlist.py +++ b/rpython/rtyper/test/test_rlist.py @@ -510,6 +510,17 @@ res = self.interpret(dummyfn, ()) assert res == 235 + def test_reversed(self): + klist = [1, 2, 3] + + def fn(): + res = [] + for elem in reversed(klist): + res.append(elem) + return res[0] * 100 + res[1] * 10 + res[2] + res = self.interpret(fn, []) + assert res == fn() + def test_prebuilt_list(self): klist = [6, 7, 8, 9] def dummyfn(n): @@ -1604,3 +1615,6 @@ class TestOOtype(BaseTestRlist, OORtypeMixin): rlist = oo_rlist type_system = 'ootype' + + def test_reversed(self): + py.test.skip("unsupported") diff --git a/rpython/rtyper/test/test_runicode.py b/rpython/rtyper/test/test_runicode.py --- a/rpython/rtyper/test/test_runicode.py +++ b/rpython/rtyper/test/test_runicode.py @@ -274,6 +274,7 @@ test_char_isxxx = unsupported test_isdigit = unsupported test_str_isalpha = unsupported + test_str_isalnum = unsupported test_upper = unsupported test_lower = unsupported test_splitlines = unsupported diff --git a/rpython/rtyper/tool/rffi_platform.py b/rpython/rtyper/tool/rffi_platform.py --- a/rpython/rtyper/tool/rffi_platform.py +++ b/rpython/rtyper/tool/rffi_platform.py @@ -721,6 +721,8 @@ eci = eci.convert_sources_to_files() files = [filepath] output = build_executable_cache(files, eci, ignore_errors=ignore_errors) + if not output.startswith('-+- '): + raise Exception("run_example_code failed!\nlocals = %r" % (locals(),)) section = None for line in output.splitlines(): line = line.strip() diff --git a/rpython/tool/gcc_cache.py b/rpython/tool/gcc_cache.py --- a/rpython/tool/gcc_cache.py +++ b/rpython/tool/gcc_cache.py @@ -1,7 +1,7 @@ from rpython.translator.platform import CompilationError from rpython.conftest import cache_dir from hashlib import md5 -import py +import py, os cache_dir_root = py.path.local(cache_dir).ensure(dir=1) @@ -35,37 +35,45 @@ # compare equal to another instance without it if platform.log_errors != _previous: platform.log_errors = _previous - path.write(result.out) + try_atomic_write(path, result.out) return result.out +def try_atomic_write(path, data): + path = str(path) + tmppath = '%s~%d' % (path, os.getpid()) + f = open(tmppath, 'wb') + f.write(data) + f.close() + try: + os.rename(tmppath, path) + except OSError: + try: + os.unlink(tmppath) + except OSError: + pass + def try_compile_cache(c_files, eci): - "Try to compile a program; caches the result (starts with 'True' or 'FAIL')" + "Try to compile a program. If it works, caches this fact." # Import 'platform' every time, the compiler may have been changed from rpython.translator.platform import platform path = cache_file_path(c_files, eci, 'try_compile_cache') try: data = path.read() + if data == 'True': + return True except py.error.Error: - data = '' - if not (data.startswith('True') or data.startswith('FAIL\n')): - try: - _previous = platform.log_errors - try: - platform.log_errors = False - platform.compile(c_files, eci) - finally: - del platform.log_errors - # ^^^remove from the instance --- needed so that it can - # compare equal to another instance without it - if platform.log_errors != _previous: - platform.log_errors = _previous - data = 'True' - path.write(data) - except CompilationError, e: - data = 'FAIL\n%s\n' % (e,) - if data.startswith('True'): - return True - else: - assert data.startswith('FAIL\n') - msg = data[len('FAIL\n'):] - raise CompilationError(msg.strip(), '') + pass + # + _previous = platform.log_errors + try: + platform.log_errors = False + platform.compile(c_files, eci) + # ^^^ may raise CompilationError. We don't cache such results. + finally: + del platform.log_errors + # ^^^remove from the instance --- needed so that it can + # compare equal to another instance without it + if platform.log_errors != _previous: + platform.log_errors = _previous + path.write('True') + return True diff --git a/rpython/translator/platform/openbsd.py b/rpython/translator/platform/openbsd.py --- a/rpython/translator/platform/openbsd.py +++ b/rpython/translator/platform/openbsd.py @@ -2,9 +2,10 @@ import os -from pypy.translator.platform.bsd import BSD +from rpython.translator.platform.bsd import BSD class OpenBSD(BSD): + DEFAULT_CC = "cc" name = "openbsd" link_flags = os.environ.get("LDFLAGS", '-pthread').split() diff --git a/tddium.yml b/tddium.yml --- a/tddium.yml +++ b/tddium.yml @@ -13,7 +13,6 @@ - exclude: rpython/jit/backend/cli/** # bitrotted AFAICT - exclude: rpython/jit/backend/llvm/** # bitrotted AFAICT # and things requiring a fix in Tddium, omitted to avoid confusion: - - exclude: pypy/tool/pytest/** # we're running upstream pytest - exclude: rpython/rlib/unicodedata/test/test_ucd.py # need wide build - exclude: rpython/rlib/test/test_runicode.py # need wide build - exclude: rpython/rlib/test/test_rsocket.py # not clear why fails From noreply at buildbot.pypy.org Mon Apr 29 20:13:16 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Mon, 29 Apr 2013 20:13:16 +0200 (CEST) Subject: [pypy-commit] pypy py3k: adjust per 0aea4b24a65c Message-ID: <20130429181316.88E9F1C0246@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63756:c45852ae0b8c Date: 2013-04-29 11:12 -0700 http://bitbucket.org/pypy/pypy/changeset/c45852ae0b8c/ Log: adjust per 0aea4b24a65c diff --git a/pypy/objspace/fake/test/test_checkmodule.py b/pypy/objspace/fake/test/test_checkmodule.py --- a/pypy/objspace/fake/test/test_checkmodule.py +++ b/pypy/objspace/fake/test/test_checkmodule.py @@ -17,10 +17,10 @@ def test_wrap_interp2app(): see, check = make_checker() space = FakeObjSpace() - assert len(space._seen_extras) == 0 + assert len(space._seen_extras) == 1 assert len(check) == 0 space.wrap(interp2app(lambda space: see())) - assert len(space._seen_extras) == 1 + assert len(space._seen_extras) == 2 assert len(check) == 0 space.translates() assert len(check) == 1 From noreply at buildbot.pypy.org Mon Apr 29 23:36:46 2013 From: noreply at buildbot.pypy.org (arigo) Date: Mon, 29 Apr 2013 23:36:46 +0200 (CEST) Subject: [pypy-commit] cffi default: Add a few lines in a test Message-ID: <20130429213646.8306E1C034A@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r1247:4602333ca746 Date: 2013-04-29 23:35 +0200 http://bitbucket.org/cffi/cffi/changeset/4602333ca746/ Log: Add a few lines in a test diff --git a/c/test_c.py b/c/test_c.py --- a/c/test_c.py +++ b/c/test_c.py @@ -2115,6 +2115,9 @@ py.test.raises(ValueError, 'buf[:] = b"this is much too long!"') buf[4:2] = b"" # no effect, but should work assert buf[:] == b"hi there\x00" + buf[:2] = b"HI" + assert buf[:] == b"HI there\x00" + buf[:2] = b"hi" expected = list(map(bitem2bchr, b"hi there\x00")) x = 0 for i in range(-12, 12): From noreply at buildbot.pypy.org Mon Apr 29 23:37:48 2013 From: noreply at buildbot.pypy.org (arigo) Date: Mon, 29 Apr 2013 23:37:48 +0200 (CEST) Subject: [pypy-commit] pypy default: Update to cffi/4602333ca746 Message-ID: <20130429213748.B89001C034A@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63757:c213bfc270cf Date: 2013-04-29 23:37 +0200 http://bitbucket.org/pypy/pypy/changeset/c213bfc270cf/ Log: Update to cffi/4602333ca746 diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py --- a/pypy/module/_cffi_backend/test/_backend_test_c.py +++ b/pypy/module/_cffi_backend/test/_backend_test_c.py @@ -2104,6 +2104,9 @@ py.test.raises(ValueError, 'buf[:] = b"this is much too long!"') buf[4:2] = b"" # no effect, but should work assert buf[:] == b"hi there\x00" + buf[:2] = b"HI" + assert buf[:] == b"HI there\x00" + buf[:2] = b"hi" expected = list(map(bitem2bchr, b"hi there\x00")) x = 0 for i in range(-12, 12): From noreply at buildbot.pypy.org Tue Apr 30 02:43:02 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Tue, 30 Apr 2013 02:43:02 +0200 (CEST) Subject: [pypy-commit] pypy py3k: skip these under appdirect Message-ID: <20130430004302.869111C0246@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63759:92e51c381429 Date: 2013-04-29 17:42 -0700 http://bitbucket.org/pypy/pypy/changeset/92e51c381429/ Log: skip these under appdirect diff --git a/pypy/module/_ffi/test/test_funcptr.py b/pypy/module/_ffi/test/test_funcptr.py --- a/pypy/module/_ffi/test/test_funcptr.py +++ b/pypy/module/_ffi/test/test_funcptr.py @@ -84,12 +84,14 @@ pow = libm.getfunc('pow', [types.double, types.double], types.double) assert pow(2, 3) == 8 + @py.test.mark.skipif("py.test.config.option.runappdirect") def test_getaddr(self): from _ffi import CDLL, types libm = CDLL(self.libm_name) pow = libm.getfunc('pow', [types.double, types.double], types.double) assert pow.getaddr() == self.pow_addr + @py.test.mark.skipif("py.test.config.option.runappdirect") def test_getaddressindll(self): import sys from _ffi import CDLL diff --git a/pypy/module/gc/test/test_referents.py b/pypy/module/gc/test/test_referents.py --- a/pypy/module/gc/test/test_referents.py +++ b/pypy/module/gc/test/test_referents.py @@ -119,4 +119,5 @@ if x is l7t: break # found else: - assert 0, "the tuple (7,) is not found as gc.get_referrers(7)" + if i7 is self.ALL_ROOTS[3][0]: # not the case under runappdirect + assert 0, "the tuple (7,) is not found as gc.get_referrers(7)" From noreply at buildbot.pypy.org Tue Apr 30 02:43:01 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Tue, 30 Apr 2013 02:43:01 +0200 (CEST) Subject: [pypy-commit] pypy py3k: generate the test_pyc bits under the host python when appdirect Message-ID: <20130430004301.35DE91C00BD@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63758:153e509bad15 Date: 2013-04-29 17:39 -0700 http://bitbucket.org/pypy/pypy/changeset/153e509bad15/ Log: generate the test_pyc bits under the host python when appdirect diff --git a/pypy/module/zipimport/test/test_zipimport.py b/pypy/module/zipimport/test/test_zipimport.py --- a/pypy/module/zipimport/test/test_zipimport.py +++ b/pypy/module/zipimport/test/test_zipimport.py @@ -1,12 +1,10 @@ -import py, os +import inspect +import os import time -import struct -from pypy.module.imp.importing import get_pyc_magic, _w_long +from zipfile import ZIP_STORED + from pypy.module.imp.test.support import BaseImportTest -from StringIO import StringIO - from rpython.tool.udir import udir -from zipfile import ZIP_STORED, ZIP_DEFLATED class AppTestZipimport(BaseImportTest): @@ -20,49 +18,25 @@ pathsep = os.path.sep @classmethod - def make_pyc(cls, space, w_co, mtime): - w_data = space.call_method(space.getbuiltinmodule('marshal'), - 'dumps', w_co) - data = space.bytes_w(w_data) - if type(mtime) is type(0.0): - # Mac mtimes need a bit of special casing - if mtime < 0x7fffffff: - mtime = int(mtime) - else: - mtime = int(-0x100000000L + long(mtime)) - s = StringIO() - try: - _w_long(s, get_pyc_magic(space)) - except AttributeError: - import imp - s.write(imp.get_magic()) - pyc = s.getvalue() + struct.pack(" Author: Philip Jenvey Branch: py3k Changeset: r63760:dc67b5d68c34 Date: 2013-04-29 17:44 -0700 http://bitbucket.org/pypy/pypy/changeset/dc67b5d68c34/ Log: merge default diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py --- a/pypy/module/_cffi_backend/test/_backend_test_c.py +++ b/pypy/module/_cffi_backend/test/_backend_test_c.py @@ -2104,6 +2104,9 @@ py.test.raises(ValueError, 'buf[:] = b"this is much too long!"') buf[4:2] = b"" # no effect, but should work assert buf[:] == b"hi there\x00" + buf[:2] = b"HI" + assert buf[:] == b"HI there\x00" + buf[:2] = b"hi" expected = list(map(bitem2bchr, b"hi there\x00")) x = 0 for i in range(-12, 12): From noreply at buildbot.pypy.org Tue Apr 30 02:59:26 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Tue, 30 Apr 2013 02:59:26 +0200 (CEST) Subject: [pypy-commit] pypy py3k: 2.6 compat Message-ID: <20130430005926.CFE911C0FF8@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63761:55f31f3a5d68 Date: 2013-04-29 17:58 -0700 http://bitbucket.org/pypy/pypy/changeset/55f31f3a5d68/ Log: 2.6 compat diff --git a/pypy/objspace/std/test/test_setobject.py b/pypy/objspace/std/test/test_setobject.py --- a/pypy/objspace/std/test/test_setobject.py +++ b/pypy/objspace/std/test/test_setobject.py @@ -969,13 +969,13 @@ def test_unicodestrategy(self): s = 'àèìòù' - myset = {s} + myset = set([s]) s2 = myset.pop() assert s2 == s def test_preserve_identity_of_strings(self): s = 'hello' - myset = {s} + myset = set([s]) s2 = myset.pop() assert s2 == s assert s2 is s From noreply at buildbot.pypy.org Tue Apr 30 03:53:42 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Tue, 30 Apr 2013 03:53:42 +0200 (CEST) Subject: [pypy-commit] pypy default: add a DefinedConstantString helper Message-ID: <20130430015342.066FB1C01C2@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: Changeset: r63762:754de53974f9 Date: 2013-04-29 18:52 -0700 http://bitbucket.org/pypy/pypy/changeset/754de53974f9/ Log: add a DefinedConstantString helper diff --git a/rpython/rtyper/tool/rffi_platform.py b/rpython/rtyper/tool/rffi_platform.py --- a/rpython/rtyper/tool/rffi_platform.py +++ b/rpython/rtyper/tool/rffi_platform.py @@ -61,6 +61,12 @@ DEFINED = DefinedConstantInteger(macro) return configure(CConfig)['DEFINED'] +def getdefinedstring(macro, c_header_source): + class CConfig: + _compilation_info_ = eci_from_header(c_header_source) + DEFINED = DefinedConstantString(macro) + return configure(CConfig)['DEFINED'] + def getintegerfunctionresult(function, args=None, c_header_source='', includes=[]): class CConfig: _compilation_info_ = eci_from_header(c_header_source) diff --git a/rpython/rtyper/tool/test/test_rffi_platform.py b/rpython/rtyper/tool/test/test_rffi_platform.py --- a/rpython/rtyper/tool/test/test_rffi_platform.py +++ b/rpython/rtyper/tool/test/test_rffi_platform.py @@ -126,6 +126,13 @@ value = rffi_platform.getdefineddouble('BLAH', '#define BLAH (double)0/0') assert isnan(value) +def test_defined_constant_string(): + value = rffi_platform.getdefinedstring('MCDONC', '') + assert value is None + value = rffi_platform.getdefinedstring('RAYDEO', + '#define RAYDEO "Michael Merickel"') + assert value == 'Michael Merickel' + def test_getintegerfunctionresult(): func = 'int sum(int a, int b) {return a + b;}' value = rffi_platform.getintegerfunctionresult('sum', [6, 7], func) From noreply at buildbot.pypy.org Tue Apr 30 03:53:43 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Tue, 30 Apr 2013 03:53:43 +0200 (CEST) Subject: [pypy-commit] pypy default: grab gcc and also clang info from their __VERSION__ macro Message-ID: <20130430015343.456E61C01C2@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: Changeset: r63763:c7f8dea181b6 Date: 2013-04-29 18:53 -0700 http://bitbucket.org/pypy/pypy/changeset/c7f8dea181b6/ Log: grab gcc and also clang info from their __VERSION__ macro diff --git a/pypy/module/sys/version.py b/pypy/module/sys/version.py --- a/pypy/module/sys/version.py +++ b/pypy/module/sys/version.py @@ -15,13 +15,9 @@ if platform.name == 'msvc': COMPILER_INFO = 'MSC v.%d 32 bit' % (platform.version * 10 + 600) -elif platform.cc is not None and platform.cc.startswith('gcc'): - out = platform.execute(platform.cc, '--version').out - match = re.search(' (\d+\.\d+(\.\d+)*)', out) - if match: - COMPILER_INFO = "GCC " + match.group(1) - else: - COMPILER_INFO = "GCC" +elif platform.cc is not None and platform.cc.startswith(('gcc', 'clang')): + from rpython.rtyper.tool import rffi_platform + COMPILER_INFO = 'GCC ' + rffi_platform.getdefinedstring('__VERSION__', '') else: COMPILER_INFO = "" From noreply at buildbot.pypy.org Tue Apr 30 06:38:32 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Tue, 30 Apr 2013 06:38:32 +0200 (CEST) Subject: [pypy-commit] pypy py3k: merge default Message-ID: <20130430043832.59C811C034A@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63764:d3a9a3b856c4 Date: 2013-04-29 21:37 -0700 http://bitbucket.org/pypy/pypy/changeset/d3a9a3b856c4/ Log: merge default diff --git a/pypy/module/sys/version.py b/pypy/module/sys/version.py --- a/pypy/module/sys/version.py +++ b/pypy/module/sys/version.py @@ -15,13 +15,9 @@ if platform.name == 'msvc': COMPILER_INFO = 'MSC v.%d 32 bit' % (platform.version * 10 + 600) -elif platform.cc is not None and platform.cc.startswith('gcc'): - out = platform.execute(platform.cc, '--version').out - match = re.search(' (\d+\.\d+(\.\d+)*)', out) - if match: - COMPILER_INFO = "GCC " + match.group(1) - else: - COMPILER_INFO = "GCC" +elif platform.cc is not None and platform.cc.startswith(('gcc', 'clang')): + from rpython.rtyper.tool import rffi_platform + COMPILER_INFO = 'GCC ' + rffi_platform.getdefinedstring('__VERSION__', '') else: COMPILER_INFO = "" diff --git a/rpython/rtyper/tool/rffi_platform.py b/rpython/rtyper/tool/rffi_platform.py --- a/rpython/rtyper/tool/rffi_platform.py +++ b/rpython/rtyper/tool/rffi_platform.py @@ -61,6 +61,12 @@ DEFINED = DefinedConstantInteger(macro) return configure(CConfig)['DEFINED'] +def getdefinedstring(macro, c_header_source): + class CConfig: + _compilation_info_ = eci_from_header(c_header_source) + DEFINED = DefinedConstantString(macro) + return configure(CConfig)['DEFINED'] + def getintegerfunctionresult(function, args=None, c_header_source='', includes=[]): class CConfig: _compilation_info_ = eci_from_header(c_header_source) diff --git a/rpython/rtyper/tool/test/test_rffi_platform.py b/rpython/rtyper/tool/test/test_rffi_platform.py --- a/rpython/rtyper/tool/test/test_rffi_platform.py +++ b/rpython/rtyper/tool/test/test_rffi_platform.py @@ -126,6 +126,13 @@ value = rffi_platform.getdefineddouble('BLAH', '#define BLAH (double)0/0') assert isnan(value) +def test_defined_constant_string(): + value = rffi_platform.getdefinedstring('MCDONC', '') + assert value is None + value = rffi_platform.getdefinedstring('RAYDEO', + '#define RAYDEO "Michael Merickel"') + assert value == 'Michael Merickel' + def test_getintegerfunctionresult(): func = 'int sum(int a, int b) {return a + b;}' value = rffi_platform.getintegerfunctionresult('sum', [6, 7], func) From noreply at buildbot.pypy.org Tue Apr 30 09:42:42 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Tue, 30 Apr 2013 09:42:42 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: added headless option to cog-calls in (vain) hope to succeed running on CI Message-ID: <20130430074242.7F46F1C0334@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r352:9b6429ace28b Date: 2013-04-30 09:42 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/9b6429ace28b/ Log: added headless option to cog-calls in (vain) hope to succeed running on CI diff --git a/benchmarks.py b/benchmarks.py --- a/benchmarks.py +++ b/benchmarks.py @@ -16,7 +16,9 @@ executables = ["targetimageloadingsmalltalk-c", "coglinux/squeak"] # Arguments (inserted between executable and benchmark) -executable_arguments = [["images/%s.image" % SqueakImage, '-m', 'runSPyBenchmarks'], ["images/%s.image" % SqueakImage, '../benchmarks.st']] +executable_arguments = [ + ["images/%s.image" % SqueakImage, '-m', 'runSPyBenchmarks'], + ['-vm-display-X11', '-headless', "images/%s.image" % SqueakImage, '../benchmarks.st']] def build_data(executable, benchmark, result): # Mandatory fields @@ -110,12 +112,14 @@ pass raise Exception("commitid not found. not a git or hg repo") -COMMIT_ID = get_commitid() +COMMIT_ID = None def add(executable, benchmark, result): print "Saving result %s for executable %s, benchmark %s" % ( result, executable, benchmark) + if COMMIT_ID is None: + COMMIT_ID = get_commitid() data = build_data(executable, benchmark, result) params = urllib.urlencode(data) response = "None" @@ -135,7 +139,7 @@ with open('update.st', 'w') as f: f.write('''Smalltalk snapshot: true andQuit: true.''') pipe = subprocess.Popen( - ['coglinux/squeak%s images/%s ../update.st' % (suffix, SqueakImage)], + ['coglinux/squeak%s -vm-display-X11 -headless images/%s ../update.st' % (suffix, SqueakImage)], shell=True) pipe.wait() os.remove('update.st') @@ -153,8 +157,8 @@ ) out, err = pipe.communicate() errcode = pipe.wait() + print out benchmarks = out.split('\n') - print out for s in benchmarks: if ';' in s: name, time = s.split(';') From noreply at buildbot.pypy.org Tue Apr 30 10:08:54 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Tue, 30 Apr 2013 10:08:54 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: fixed visibility bug Message-ID: <20130430080854.7176A1C0246@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r353:55fb742e4097 Date: 2013-04-30 10:08 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/55fb742e4097/ Log: fixed visibility bug diff --git a/benchmarks.py b/benchmarks.py --- a/benchmarks.py +++ b/benchmarks.py @@ -118,6 +118,7 @@ def add(executable, benchmark, result): print "Saving result %s for executable %s, benchmark %s" % ( result, executable, benchmark) + global COMMIT_ID if COMMIT_ID is None: COMMIT_ID = get_commitid() data = build_data(executable, benchmark, result) From noreply at buildbot.pypy.org Tue Apr 30 10:51:02 2013 From: noreply at buildbot.pypy.org (bivab) Date: Tue, 30 Apr 2013 10:51:02 +0200 (CEST) Subject: [pypy-commit] pypy default: fix library dir inclusion for cross compilation builds Message-ID: <20130430085102.AC4481C0334@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63765:22402f1ba4ea Date: 2013-04-30 08:41 +0000 http://bitbucket.org/pypy/pypy/changeset/22402f1ba4ea/ Log: fix library dir inclusion for cross compilation builds diff --git a/rpython/translator/platform/arm.py b/rpython/translator/platform/arm.py --- a/rpython/translator/platform/arm.py +++ b/rpython/translator/platform/arm.py @@ -18,9 +18,13 @@ class ARM(Linux): name = "arm" - available_includedirs = (SB2 + '/usr/include', '/tmp') + available_librarydirs = [SB2 + '/usr/lib/arm-linux-gnueabi/', + SB2 + '/usr/lib/arm-linux-gnueabihf/'] + available_includedirs = [SB2 + '/usr/include/arm-linux-gnueabi/', + SB2 + '/usr/include/arm-linux-gnueabihf/'] copied_cache = {} + def _invent_new_name(self, basepath, base): pth = basepath.join(base) num = 0 @@ -47,12 +51,13 @@ return ExecutionResult(returncode, stdout, stderr) def include_dirs_for_libffi(self): - return [SB2 + '/usr/include/arm-linux-gnueabi/', - SB2 + '/usr/include/arm-linux-gnueabihf/'] + return self.available_includedirs def library_dirs_for_libffi(self): - return [SB2 + '/usr/lib/arm-linux-gnueabi/', - SB2 + '/usr/lib/arm-linux-gnueabihf/'] + return self.available_librarydirs + + def _preprocess_library_dirs(self, library_dirs): + return list(library_dirs) + self.available_librarydirs def execute_makefile(self, path_to_makefile, extra_opts=[]): if isinstance(path_to_makefile, GnuMakefile): From noreply at buildbot.pypy.org Tue Apr 30 10:51:08 2013 From: noreply at buildbot.pypy.org (bivab) Date: Tue, 30 Apr 2013 10:51:08 +0200 (CEST) Subject: [pypy-commit] pypy default: merge heads Message-ID: <20130430085108.78A3C1C0334@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63766:c770cb4118f9 Date: 2013-04-30 08:46 +0000 http://bitbucket.org/pypy/pypy/changeset/c770cb4118f9/ Log: merge heads diff too long, truncating to 2000 out of 24414 lines diff --git a/Makefile b/Makefile new file mode 100644 --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ + +all: pypy-c + +pypy-c: + @echo "Building PyPy with JIT, it'll take about 40 minutes and 4G of RAM" + @sleep 3 + rpython/bin/rpython -Ojit pypy/goal/targetpypystandalone.py diff --git a/README.rst b/README.rst --- a/README.rst +++ b/README.rst @@ -13,12 +13,25 @@ http://pypy.org/ -The getting-started document will help guide you: +If you want to help developing PyPy, this document might help you: - http://doc.pypy.org/en/latest/getting-started.html + http://doc.pypy.org/ It will also point you to the rest of the documentation which is generated from files in the pypy/doc directory within the source repositories. Enjoy and send us feedback! the pypy-dev team + +Building +======== + +build with:: + + rpython/bin/rpython -Ojit pypy/goal/targetpypystandalone.py + +This ends up with ``pypy-c`` binary in the main pypy directory. We suggest +to use virtualenv with the resulting pypy-c as the interpreter, you can +find more details about various installation schemes here: + +http://doc.pypy.org/en/latest/getting-started.html#installing-pypy diff --git a/lib-python/2.7/json/decoder.py b/lib-python/2.7/json/decoder.py --- a/lib-python/2.7/json/decoder.py +++ b/lib-python/2.7/json/decoder.py @@ -162,7 +162,7 @@ if nextchar == '}': if object_pairs_hook is not None: result = object_pairs_hook(pairs) - return result, end + return result, end + 1 pairs = {} if object_hook is not None: pairs = object_hook(pairs) diff --git a/lib-python/2.7/json/tests/test_decode.py b/lib-python/2.7/json/tests/test_decode.py --- a/lib-python/2.7/json/tests/test_decode.py +++ b/lib-python/2.7/json/tests/test_decode.py @@ -44,6 +44,7 @@ object_pairs_hook=OrderedDict, object_hook=lambda x: None), OrderedDict(p)) + self.assertEqual(self.loads("{}", object_pairs_hook=list), []) class TestPyDecode(TestDecode, PyTest): pass diff --git a/lib-python/2.7/pydoc.py b/lib-python/2.7/pydoc.py --- a/lib-python/2.7/pydoc.py +++ b/lib-python/2.7/pydoc.py @@ -1953,7 +1953,11 @@ if key is None: callback(None, modname, '') else: - desc = split(__import__(modname).__doc__ or '', '\n')[0] + try: + module_doc = __import__(modname).__doc__ + except ImportError: + module_doc = None + desc = split(module_doc or '', '\n')[0] if find(lower(modname + ' - ' + desc), key) >= 0: callback(None, modname, desc) diff --git a/lib-python/2.7/test/test_descr.py b/lib-python/2.7/test/test_descr.py --- a/lib-python/2.7/test/test_descr.py +++ b/lib-python/2.7/test/test_descr.py @@ -3592,6 +3592,9 @@ list.__init__(a, sequence=[0, 1, 2]) self.assertEqual(a, [0, 1, 2]) + @unittest.skipIf(test_support.check_impl_detail(pypy=True) and + sys.platform == 'win32', + "XXX: https://bugs.pypy.org/issue1461") def test_recursive_call(self): # Testing recursive __call__() by setting to instance of class... class A(object): diff --git a/lib-python/2.7/test/test_fileio.py b/lib-python/2.7/test/test_fileio.py --- a/lib-python/2.7/test/test_fileio.py +++ b/lib-python/2.7/test/test_fileio.py @@ -318,7 +318,6 @@ self.assertRaises(ValueError, _FileIO, -10) self.assertRaises(OSError, _FileIO, make_bad_fd()) if sys.platform == 'win32': - raise unittest.SkipTest('Set _invalid_parameter_handler for low level io') import msvcrt self.assertRaises(IOError, msvcrt.get_osfhandle, make_bad_fd()) diff --git a/lib_pypy/_curses.py b/lib_pypy/_curses.py --- a/lib_pypy/_curses.py +++ b/lib_pypy/_curses.py @@ -364,7 +364,9 @@ key_n = ffi.string(key_n) if key_n == b"UNKNOWN KEY": continue - key_n = key_n.decode().replace('(', '').replace(')', '') + if not isinstance(key_n, str): # python 3 + key_n = key_n.decode() + key_n = key_n.replace('(', '').replace(')', '') globals()[key_n] = key _setup() diff --git a/lib_pypy/_functools.py b/lib_pypy/_functools.py --- a/lib_pypy/_functools.py +++ b/lib_pypy/_functools.py @@ -20,3 +20,16 @@ if self.keywords is not None: fkeywords = dict(self.keywords, **fkeywords) return self.func(*(self.args + fargs), **fkeywords) + + def __reduce__(self): + d = dict((k, v) for k, v in self.__dict__.iteritems() if k not in + ('func', 'args', 'keywords')) + if len(d) == 0: + d = None + return (type(self), (self.func,), + (self.func, self.args, self.keywords, d)) + + def __setstate__(self, state): + self.func, self.args, self.keywords, d = state + if d is not None: + self.__dict__.update(d) diff --git a/lib_pypy/_pypy_interact.py b/lib_pypy/_pypy_interact.py --- a/lib_pypy/_pypy_interact.py +++ b/lib_pypy/_pypy_interact.py @@ -44,7 +44,7 @@ import code if mainmodule is None: import __main__ as mainmodule - console = code.InteractiveConsole(mainmodule.__dict__) + console = code.InteractiveConsole(mainmodule.__dict__, filename='') # some parts of code.py are copied here because it seems to be impossible # to start an interactive console without printing at least one line # of banner diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -256,7 +256,13 @@ typedef ... sqlite3; int sqlite3_enable_load_extension(sqlite3 *db, int onoff); """) - unverified_lib = unverified_ffi.dlopen('sqlite3') + libname = 'sqlite3' + if sys.platform == 'win32': + import os + _libname = os.path.join(os.path.dirname(sys.executable), libname) + if os.path.exists(_libname + '.dll'): + libname = _libname + unverified_lib = unverified_ffi.dlopen(libname) return hasattr(unverified_lib, 'sqlite3_enable_load_extension') if _has_load_extension(): @@ -759,9 +765,9 @@ if isinstance(name, unicode): name = name.encode('utf-8') ret = _lib.sqlite3_create_collation(self._db, name, - _lib.SQLITE_UTF8, - _ffi.NULL, - collation_callback) + _lib.SQLITE_UTF8, + _ffi.NULL, + collation_callback) if ret != _lib.SQLITE_OK: raise self._get_exception(ret) @@ -780,9 +786,7 @@ return _lib.SQLITE_DENY self.__func_cache[callback] = authorizer - ret = _lib.sqlite3_set_authorizer(self._db, - authorizer, - _ffi.NULL) + ret = _lib.sqlite3_set_authorizer(self._db, authorizer, _ffi.NULL) if ret != _lib.SQLITE_OK: raise self._get_exception(ret) @@ -798,15 +802,13 @@ @_ffi.callback("int(void*)") def progress_handler(userdata): try: - ret = callable() - return bool(ret) + return bool(callable()) except Exception: # abort query if error occurred return 1 self.__func_cache[callable] = progress_handler - _lib.sqlite3_progress_handler(self._db, nsteps, - progress_handler, - _ffi.NULL) + _lib.sqlite3_progress_handler(self._db, nsteps, progress_handler, + _ffi.NULL) if sys.version_info[0] >= 3: def __get_in_transaction(self): @@ -888,8 +890,8 @@ def __check_reset(self): if self._reset: raise InterfaceError( - "Cursor needed to be reset because of commit/rollback " - "and can no longer be fetched from.") + "Cursor needed to be reset because of commit/rollback " + "and can no longer be fetched from.") def __build_row_cast_map(self): if not self.__connection._detect_types: @@ -996,17 +998,18 @@ # Actually execute the SQL statement ret = _lib.sqlite3_step(self.__statement._statement) - if ret not in (_lib.SQLITE_DONE, _lib.SQLITE_ROW): - self.__statement._reset() - raise self.__connection._get_exception(ret) if ret == _lib.SQLITE_ROW: if multiple: raise ProgrammingError("executemany() can only execute DML statements.") self.__build_row_cast_map() self.__next_row = self.__fetch_one_row() - elif ret == _lib.SQLITE_DONE and not multiple: + elif ret == _lib.SQLITE_DONE: + if not multiple: + self.__statement._reset() + else: self.__statement._reset() + raise self.__connection._get_exception(ret) if self.__statement._type in ("UPDATE", "DELETE", "INSERT", "REPLACE"): if self.__rowcount == -1: @@ -1087,7 +1090,6 @@ try: next_row = self.__next_row except AttributeError: - self.__statement._reset() raise StopIteration del self.__next_row @@ -1095,11 +1097,12 @@ next_row = self.row_factory(self, next_row) ret = _lib.sqlite3_step(self.__statement._statement) - if ret not in (_lib.SQLITE_DONE, _lib.SQLITE_ROW): + if ret == _lib.SQLITE_ROW: + self.__next_row = self.__fetch_one_row() + else: self.__statement._reset() - raise self.__connection._get_exception(ret) - elif ret == _lib.SQLITE_ROW: - self.__next_row = self.__fetch_one_row() + if ret != _lib.SQLITE_DONE: + raise self.__connection._get_exception(ret) return next_row if sys.version_info[0] < 3: diff --git a/lib_pypy/cffi/api.py b/lib_pypy/cffi/api.py --- a/lib_pypy/cffi/api.py +++ b/lib_pypy/cffi/api.py @@ -370,7 +370,10 @@ if key in ffi._parser._declarations: tp = ffi._parser._declarations[key] BType = ffi._get_cached_btype(tp) - value = backendlib.load_function(BType, name) + try: + value = backendlib.load_function(BType, name) + except KeyError: + raise AttributeError(name) library.__dict__[name] = value return # diff --git a/lib_pypy/msvcrt.py b/lib_pypy/msvcrt.py --- a/lib_pypy/msvcrt.py +++ b/lib_pypy/msvcrt.py @@ -8,25 +8,37 @@ # PAC: 2010/08 added MS locking for Whoosh import ctypes +import errno from ctypes_support import standard_c_lib as _c from ctypes_support import get_errno -import errno try: open_osfhandle = _c._open_osfhandle except AttributeError: # we are not on windows raise ImportError -try: from __pypy__ import builtinify -except ImportError: builtinify = lambda f: f +try: from __pypy__ import builtinify, validate_fd +except ImportError: builtinify = validate_fd = lambda f: f 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 +_get_osfhandle = _c._get_osfhandle +_get_osfhandle.argtypes = [ctypes.c_int] +_get_osfhandle.restype = ctypes.c_int + + at builtinify +def get_osfhandle(fd): + """"get_osfhandle(fd) -> file handle + + Return the file handle for the file descriptor fd. Raises IOError if + fd is not recognized.""" + try: + validate_fd(fd) + except OSError as e: + raise IOError(*e.args) + return _get_osfhandle(fd) setmode = _c._setmode setmode.argtypes = [ctypes.c_int, ctypes.c_int] diff --git a/lib_pypy/pyrepl/python_reader.py b/lib_pypy/pyrepl/python_reader.py --- a/lib_pypy/pyrepl/python_reader.py +++ b/lib_pypy/pyrepl/python_reader.py @@ -171,11 +171,11 @@ def execute(self, text): try: - # ooh, look at the hack: + # ooh, look at the hack: code = self.compile("# coding:utf8\n"+text.encode('utf-8'), - '', 'single') + '', 'single') except (OverflowError, SyntaxError, ValueError): - self.showsyntaxerror("") + self.showsyntaxerror('') else: self.runcode(code) if sys.stdout and not sys.stdout.closed: diff --git a/lib_pypy/pyrepl/simple_interact.py b/lib_pypy/pyrepl/simple_interact.py --- a/lib_pypy/pyrepl/simple_interact.py +++ b/lib_pypy/pyrepl/simple_interact.py @@ -37,13 +37,13 @@ import code if mainmodule is None: import __main__ as mainmodule - console = code.InteractiveConsole(mainmodule.__dict__) + console = code.InteractiveConsole(mainmodule.__dict__, filename='') def more_lines(unicodetext): # ooh, look at the hack: src = "#coding:utf-8\n"+unicodetext.encode('utf-8') try: - code = console.compile(src, '', 'single') + code = console.compile(src, '', 'single') except (OverflowError, SyntaxError, ValueError): return False else: diff --git a/py/_path/local.py b/py/_path/local.py --- a/py/_path/local.py +++ b/py/_path/local.py @@ -655,7 +655,8 @@ mkdtemp = classmethod(mkdtemp) def make_numbered_dir(cls, prefix='session-', rootdir=None, keep=3, - lock_timeout = 172800): # two days + lock_timeout = 172800, # two days + min_timeout = 300): # five minutes """ return unique directory with a number greater than the current maximum one. The number is assumed to start directly after prefix. if keep is true directories with a number less than (maxnum-keep) @@ -723,6 +724,20 @@ for path in rootdir.listdir(): num = parse_num(path) if num is not None and num <= (maxnum - keep): + if min_timeout: + # NB: doing this is needed to prevent (or reduce + # a lot the chance of) the following situation: + # 'keep+1' processes call make_numbered_dir() at + # the same time, they create dirs, but then the + # last process notices the first dir doesn't have + # (yet) a .lock in it and kills it. + try: + t1 = path.lstat().mtime + t2 = lockfile.lstat().mtime + if abs(t2-t1) < min_timeout: + continue # skip directories too recent + except py.error.Error: + continue # failure to get a time, better skip lf = path.join('.lock') try: t1 = lf.lstat().mtime diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py --- a/pypy/config/pypyoption.py +++ b/pypy/config/pypyoption.py @@ -35,7 +35,7 @@ "thread", "itertools", "pyexpat", "_ssl", "cpyext", "array", "binascii", "_multiprocessing", '_warnings', "_collections", "_multibytecodec", "micronumpy", "_ffi", - "_continuation", "_cffi_backend", "_csv"] + "_continuation", "_cffi_backend", "_csv", "cppyy"] )) translation_modules = default_modules.copy() @@ -64,6 +64,8 @@ del working_modules["termios"] del working_modules["_minimal_curses"] + del working_modules["cppyy"] # not tested on win32 + # The _locale module is needed by site.py on Windows default_modules["_locale"] = None @@ -75,7 +77,7 @@ del working_modules["_minimal_curses"] del working_modules["termios"] del working_modules["_multiprocessing"] # depends on rctime - + del working_modules["cppyy"] # depends on ctypes module_dependencies = { diff --git a/pypy/doc/arm.rst b/pypy/doc/arm.rst --- a/pypy/doc/arm.rst +++ b/pypy/doc/arm.rst @@ -153,7 +153,7 @@ :: - pypy /rpython/bin/rpython -Ojit --platform=arm --gcrootfinder=shadowstack --jit-backend=armv7 targetpypystandalone.py + pypy /rpython/bin/rpython -Ojit --platform=arm --gcrootfinder=shadowstack --jit-backend=arm targetpypystandalone.py The gcrootfinder option is needed to work around `issue 1377`_ and the jit-backend works around `issue 1376`_ diff --git a/pypy/doc/config/translation.gcrootfinder.txt b/pypy/doc/config/translation.gcrootfinder.txt --- a/pypy/doc/config/translation.gcrootfinder.txt +++ b/pypy/doc/config/translation.gcrootfinder.txt @@ -9,7 +9,9 @@ - ``--gcrootfinder=asmgcc``: use assembler hackery to find the roots directly from the normal stack. This is a bit faster, but platform specific. It works so far with GCC or MSVC, - on i386 and x86-64. + on i386 and x86-64. It is tested only on Linux (where it is + the default) so other platforms (as well as MSVC) may need + various fixes before they can be used. You may have to force the use of the shadowstack root finder if you are running into troubles or if you insist on translating diff --git a/pypy/doc/cppyy.rst b/pypy/doc/cppyy.rst --- a/pypy/doc/cppyy.rst +++ b/pypy/doc/cppyy.rst @@ -2,94 +2,128 @@ cppyy: C++ bindings for PyPy ============================ -The cppyy module provides C++ bindings for PyPy by using the reflection -information extracted from C++ header files by means of the -`Reflex package`_. -For this to work, you have to both install Reflex and build PyPy from source, -as the cppyy module is not enabled by default. -Note that the development version of cppyy lives in the reflex-support -branch. -As indicated by this being a branch, support for Reflex is still -experimental. -However, it is functional enough to put it in the hands of those who want -to give it a try. -In the medium term, cppyy will move away from Reflex and instead use -`cling`_ as its backend, which is based on `llvm`_. -Although that will change the logistics on the generation of reflection -information, it will not change the python-side interface. +The cppyy module creates, at run-time, Python-side classes and functions for +C++, by querying a C++ reflection system. +The default system used is `Reflex`_, which extracts the needed information +from C++ header files. +Another current backend is based on `CINT`_, and yet another, more important +one for the medium- to long-term will be based on `cling`_. +The latter sits on top of `llvm`_'s `clang`_, and will therefore allow the use +of C++11. +The work on the cling backend has so far been done only for CPython, but +bringing it to PyPy is a lot less work than developing it in the first place. -.. _`Reflex package`: http://root.cern.ch/drupal/content/reflex +.. _`Reflex`: http://root.cern.ch/drupal/content/reflex +.. _`CINT`: http://root.cern.ch/drupal/content/cint .. _`cling`: http://root.cern.ch/drupal/content/cling .. _`llvm`: http://llvm.org/ +.. _`clang`: http://clang.llvm.org/ + +This document describes the version of cppyy that lives in the main branch of +PyPy. +The development of cppyy happens in the "reflex-support" branch. Motivation ========== -The cppyy module offers two unique features, which result in great -performance as well as better functionality and cross-language integration -than would otherwise be possible. -First, cppyy is written in RPython and therefore open to optimizations by the -JIT up until the actual point of call into C++. -This means that there are no conversions necessary between a garbage collected -and a reference counted environment, as is needed for the use of existing -extension modules written or generated for CPython. -It also means that if variables are already unboxed by the JIT, they can be -passed through directly to C++. -Second, Reflex (and cling far more so) adds dynamic features to C++, thus -greatly reducing impedance mismatches between the two languages. -In fact, Reflex is dynamic enough that you could write the runtime bindings +To provide bindings to another language in CPython, you program to a +generic C-API that exposes many of the interpreter features. +With PyPy, however, there is no such generic C-API, because several of the +interpreter features (e.g. the memory model) are pluggable and therefore +subject to change. +Furthermore, a generic API does not allow any assumptions about the calls +into another language, forcing the JIT to behave conservatively around these +calls and with the objects that cross language boundaries. +In contrast, cppyy does not expose an API, but expects one to be implemented +by a backend. +It makes strong assumptions about the semantics of the API that it uses and +that in turn allows the JIT to make equally strong assumptions. +This is possible, because the expected API is only for providing C++ language +bindings, and does not provide generic programmability. + +The cppyy module further offers two features, which result in improved +performance as well as better functionality and cross-language integration. +First, cppyy itself is written in RPython and therefore open to optimizations +by the JIT up until the actual point of call into C++. +This means for example, that if variables are already unboxed by the JIT, they +can be passed through directly to C++. +Second, a backend such as Reflex (and cling far more so) adds dynamic features +to C++, thus greatly reducing impedance mismatches between the two languages. +For example, Reflex is dynamic enough to allow writing runtime bindings generation in python (as opposed to RPython) and this is used to create very natural "pythonizations" of the bound code. +As another example, cling allows automatic instantiations of templates. + +See this description of the `cppyy architecture`_ for further details. + +.. _`cppyy architecture`: http://morepypy.blogspot.com/2012/06/architecture-of-cppyy.html Installation ============ -For now, the easiest way of getting the latest version of Reflex, is by -installing the ROOT package. -Besides getting the latest version of Reflex, another advantage is that with -the full ROOT package, you can also use your Reflex-bound code on `CPython`_. -`Download`_ a binary or install from `source`_. -Some Linux and Mac systems may have ROOT provided in the list of scientific -software of their packager. -If, however, you prefer a standalone version of Reflex, the best is to get -this `recent snapshot`_, and install like so:: +There are two ways of using cppyy, and the choice depends on how pypy-c was +built: the backend can be builtin, or dynamically loadable. +The former has the disadvantage of requiring pypy-c to be linked with external +C++ libraries (e.g. libReflex.so), but has the advantage of being faster in +some cases. +That advantage will disappear over time, however, with improvements in the +JIT. +Therefore, this document assumes that the dynamically loadable backend is +chosen (it is, by default). +See the `backend documentation`_. - $ tar jxf reflex-2012-05-02.tar.bz2 - $ cd reflex-2012-05-02 - $ build/autogen +.. _`backend documentation`: cppyy_backend.html + +A standalone version of Reflex that also provides the dynamically loadable +backend is available for `download`_. +That version, as well as any other distribution of Reflex (e.g. the one that +comes with `ROOT`_, which may be part of your Linux distribution as part of +the selection of scientific software) will also work for a build with the +builtin backend. + +.. _`download`: http://cern.ch/wlav/reflex-2013-04-23.tar.bz2 +.. _`ROOT`: http://root.cern.ch/ + +Besides Reflex, you probably need a version of `gccxml`_ installed, which is +most easily provided by the packager of your system. +If you read up on gccxml, you will probably notice that it is no longer being +developed and hence will not provide C++11 support. +That's why the medium term plan is to move to cling. +Note that gccxml is only needed to generate reflection libraries. +It is not needed to use them. + +.. _`gccxml`: http://www.gccxml.org + +To install the standalone version of Reflex, after download:: + + $ tar jxf reflex-2013-04-23.tar.bz2 + $ cd reflex-2013-04-23 + $ ./build/autogen $ ./configure $ make && make install -Also, make sure you have a version of `gccxml`_ installed, which is most -easily provided by the packager of your system. -If you read up on gccxml, you'll probably notice that it is no longer being -developed and hence will not provide C++11 support. -That's why the medium term plan is to move to `cling`_. +The usual rules apply: /bin needs to be added to the ``PATH`` and +/lib to the ``LD_LIBRARY_PATH`` environment variable. +For convenience, this document will assume that there is a ``REFLEXHOME`` +variable that points to . +If you downloaded or built the whole of ROOT, ``REFLEXHOME`` should be equal +to ``ROOTSYS``. -.. _`Download`: http://root.cern.ch/drupal/content/downloading-root -.. _`source`: http://root.cern.ch/drupal/content/installing-root-source -.. _`recent snapshot`: http://cern.ch/wlav/reflex-2012-05-02.tar.bz2 -.. _`gccxml`: http://www.gccxml.org +The following is optional, and is only to show how pypy-c can be build +`from source`_, for example to get at the main development branch of cppyy. +The `backend documentation`_ has more details on the backend-specific +prerequisites. -Next, get the `PyPy sources`_, optionally select the reflex-support branch, -and build it. -For the build to succeed, the ``$ROOTSYS`` environment variable must point to -the location of your ROOT (or standalone Reflex) installation, or the -``root-config`` utility must be accessible through ``PATH`` (e.g. by adding -``$ROOTSYS/bin`` to ``PATH``). -In case of the former, include files are expected under ``$ROOTSYS/include`` -and libraries under ``$ROOTSYS/lib``. Then run the translation to build ``pypy-c``:: $ hg clone https://bitbucket.org/pypy/pypy $ cd pypy $ hg up reflex-support # optional - $ cd pypy/goal # This example shows python, but using pypy-c is faster and uses less memory - $ python ../../rpython/bin/rpython.py -O jit --gcrootfinder=shadowstack targetpypystandalone.py --withmod-cppyy + $ python rpython/translator/goal/translate.py --opt=jit pypy/goal/targetpypystandalone --withmod-cppyy This will build a ``pypy-c`` that includes the cppyy module, and through that, Reflex support. @@ -98,12 +132,12 @@ If not, you may want `to obtain a binary distribution`_ to speed up the translation step. -.. _`PyPy sources`: https://bitbucket.org/pypy/pypy/overview +.. _`from source`: https://bitbucket.org/pypy/pypy/overview .. _`to obtain a binary distribution`: http://doc.pypy.org/en/latest/getting-started.html#download-a-pre-built-pypy -Basic example -============= +Basic bindings example +====================== Now test with a trivial example whether all packages are properly installed and functional. @@ -127,7 +161,7 @@ code:: $ genreflex MyClass.h - $ g++ -fPIC -rdynamic -O2 -shared -I$ROOTSYS/include MyClass_rflx.cpp -o libMyClassDict.so -L$ROOTSYS/lib -lReflex + $ g++ -fPIC -rdynamic -O2 -shared -I$REFLEXHOME/include MyClass_rflx.cpp -o libMyClassDict.so -L$REFLEXHOME/lib -lReflex Now you're ready to use the bindings. Since the bindings are designed to look pythonistic, it should be @@ -176,7 +210,7 @@ For example:: $ genreflex MyClass.h --rootmap=libMyClassDict.rootmap --rootmap-lib=libMyClassDict.so - $ g++ -fPIC -rdynamic -O2 -shared -I$ROOTSYS/include MyClass_rflx.cpp -o libMyClassDict.so -L$ROOTSYS/lib -lReflex + $ g++ -fPIC -rdynamic -O2 -shared -I$REFLEXHOME/include MyClass_rflx.cpp -o libMyClassDict.so -L$REFLEXHOME/lib -lReflex where the first option (``--rootmap``) specifies the output file name, and the second option (``--rootmap-lib``) the name of the reflection library where @@ -277,7 +311,7 @@ Now the reflection info can be generated and compiled:: $ genreflex MyAdvanced.h --selection=MyAdvanced.xml - $ g++ -fPIC -rdynamic -O2 -shared -I$ROOTSYS/include MyAdvanced_rflx.cpp -o libAdvExDict.so -L$ROOTSYS/lib -lReflex + $ g++ -fPIC -rdynamic -O2 -shared -I$REFLEXHOME/include MyAdvanced_rflx.cpp -o libAdvExDict.so -L$REFLEXHOME/lib -lReflex and subsequently be used from PyPy:: @@ -336,7 +370,7 @@ bound using:: $ genreflex example.h --deep --rootmap=libexampleDict.rootmap --rootmap-lib=libexampleDict.so - $ g++ -fPIC -rdynamic -O2 -shared -I$ROOTSYS/include example_rflx.cpp -o libexampleDict.so -L$ROOTSYS/lib -lReflex + $ g++ -fPIC -rdynamic -O2 -shared -I$REFLEXHOME/include example_rflx.cpp -o libexampleDict.so -L$REFLEXHOME/lib -lReflex .. _`example code`: cppyy_example.html @@ -595,6 +629,16 @@ All template classes must already exist in the loaded reflection info, they do not work (yet) with the class loader. + For compatibility with other bindings generators, use of square brackets + instead of parenthesis to instantiate templates is supported as well. + +* **templated functions**: Automatically participate in overloading and are + used in the same way as other global functions. + +* **templated methods**: For now, require an explicit selection of the + template parameters. + This will be changed to allow them to participate in overloads as expected. + * **typedefs**: Are simple python references to the actual classes to which they refer. @@ -692,7 +736,7 @@ Run the normal ``genreflex`` and compilation steps:: $ genreflex MyTemplate.h --selection=MyTemplate.xml - $ g++ -fPIC -rdynamic -O2 -shared -I$ROOTSYS/include MyTemplate_rflx.cpp -o libTemplateDict.so -L$ROOTSYS/lib -lReflex + $ g++ -fPIC -rdynamic -O2 -shared -I$REFLEXHOME/include MyTemplate_rflx.cpp -o libTemplateDict.so -L$REFLEXHOME/lib -lReflex Note: this is a dirty corner that clearly could do with some automation, even if the macro already helps. @@ -727,18 +771,18 @@ The fast lane ============= -The following is an experimental feature of cppyy, and that makes it doubly -experimental, so caveat emptor. +The following is an experimental feature of cppyy. +It mostly works, but there are some known issues (e.g. with return-by-value). +Soon it should be the default mode, however. + With a slight modification of Reflex, it can provide function pointers for C++ methods, and hence allow PyPy to call those pointers directly, rather than calling C++ through a Reflex stub. -This results in a rather significant speed-up. -Mind you, the normal stub path is not exactly slow, so for now only use this -out of curiosity or if you really need it. -To install this patch of Reflex, locate the file genreflex-methptrgetter.patch -in pypy/module/cppyy and apply it to the genreflex python scripts found in -``$ROOTSYS/lib``:: +The standalone version of Reflex `provided`_ has been patched, but if you get +Reflex from another source (most likely with a ROOT distribution), locate the +file `genreflex-methptrgetter.patch`_ in pypy/module/cppyy and apply it to +the genreflex python scripts found in ``$ROOTSYS/lib``:: $ cd $ROOTSYS/lib $ patch -p2 < genreflex-methptrgetter.patch @@ -749,8 +793,10 @@ ``-Wno-pmf-conversions`` option to ``g++`` when compiling. The rest works the same way: the fast path will be used transparently (which also means that you can't actually find out whether it is in use, other than -by running a micro-benchmark). +by running a micro-benchmark or a JIT test). +.. _`provided`: http://cern.ch/wlav/reflex-2013-04-23.tar.bz2 +.. _`genreflex-methptrgetter.patch`: https://bitbucket.org/pypy/pypy/src/default/pypy/module/cppyy/genreflex-methptrgetter.patch CPython ======= diff --git a/pypy/doc/cppyy_backend.rst b/pypy/doc/cppyy_backend.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/cppyy_backend.rst @@ -0,0 +1,53 @@ +================== +Backends for cppyy +================== + +The cppyy module needs a backend to provide the C++ reflection information on +which the Python bindings are build. +The backend is called through a C-API, which can be found in the PyPy sources +in: `pypy/module/cppyy/include/capi.h`_. +There are two kinds of API calls: querying about reflection information, which +are used during the creation of Python-side constructs, and making the actual +calls into C++. +The objects passed around are all opaque: cppyy does not make any assumptions +about them, other than that the opaque handles can be copied. +Their definition, however, appears in two places: in the C code (in capi.h), +and on the RPython side (in `capi_types.py`_), so if they are changed, they +need to be changed on both sides. + +.. _`pypy/module/cppyy/include/capi.h`: https://bitbucket.org/pypy/pypy/src/default/pypy/module/cppyy/include/capi.h +.. _`capi_types.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/module/cppyy/capi/capi_types.py + +There are two places where selections in the RPython code affect the choice +(and use) of the backend. +The first is in `pypy/module/cppyy/capi/__init__.py`_:: + + # choose C-API access method: + from pypy.module.cppyy.capi.loadable_capi import * + #from pypy.module.cppyy.capi.builtin_capi import * + +The default is the loadable C-API. +Comment it and uncomment the builtin C-API line, to use the builtin version. + +.. _`pypy/module/cppyy/capi/__init__.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/module/cppyy/capi/__init__.py + +Next, if the builtin C-API is chosen, the specific backend needs to be set as +well (default is Reflex). +This second choice is in `pypy/module/cppyy/capi/builtin_capi.py`_:: + + import reflex_capi as backend + #import cint_capi as backend + +After those choices have been made, built pypy-c as usual. + +.. _`pypy/module/cppyy/capi/builtin_capi.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/module/cppyy/capi/builtin_capi.py + +When building pypy-c from source, keep the following in mind. +If the loadable_capi is chosen, no further prerequisites are needed. +However, for the build of the builtin_capi to succeed, the ``ROOTSYS`` +environment variable must point to the location of your ROOT (or standalone +Reflex in the case of the Reflex backend) installation, or the ``root-config`` +utility must be accessible through ``$PATH`` (e.g. by adding ``$ROOTSYS/bin`` +to ``PATH``). +In case of the former, include files are expected under ``$ROOTSYS/include`` +and libraries under ``$ROOTSYS/lib``. diff --git a/pypy/doc/dir-reference.rst b/pypy/doc/dir-reference.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/dir-reference.rst @@ -0,0 +1,140 @@ +PyPy directory cross-reference +------------------------------ + +Here is a fully referenced alphabetical two-level deep +directory overview of PyPy: + +================================= ============================================ +Directory explanation/links +================================= ============================================ +`pypy/bin/`_ command-line scripts, mainly + `pypy/bin/pyinteractive.py`_ + +`pypy/config/`_ handles the numerous options for building + and running PyPy + +`pypy/doc/`_ text versions of PyPy developer + documentation + +`pypy/doc/config/`_ documentation for the numerous translation + options + +`pypy/doc/discussion/`_ drafts of ideas and documentation + +``doc/*/`` other specific documentation topics or tools + +`pypy/interpreter/`_ `bytecode interpreter`_ and related objects + (frames, functions, modules,...) + +`pypy/interpreter/pyparser/`_ interpreter-level Python source parser + +`pypy/interpreter/astcompiler/`_ interpreter-level bytecode compiler, + via an AST representation + +`pypy/module/`_ contains `mixed modules`_ + implementing core modules with + both application and interpreter level code. + Not all are finished and working. Use + the ``--withmod-xxx`` + or ``--allworkingmodules`` translation + options. + +`pypy/objspace/`_ `object space`_ implementations + +`pypy/objspace/std/`_ the StdObjSpace_ implementing CPython's + objects and types + +`pypy/tool/`_ various utilities and hacks used + from various places + +`pypy/tool/algo/`_ general-purpose algorithmic and mathematic + tools + +`pypy/tool/pytest/`_ support code for our `testing methods`_ + + +`rpython/annotator/`_ `type inferencing code`_ for + `RPython`_ programs + +`rpython/config/`_ handles the numerous options for RPython + + +`rpython/flowspace/`_ the FlowObjSpace_ implementing + `abstract interpretation`_ + +`rpython/rlib/`_ a `"standard library"`_ for RPython_ + programs + +`rpython/rtyper/`_ the `RPython Typer`_ + +`rpython/rtyper/lltypesystem/`_ the `low-level type system`_ for + C-like backends + +`rpython/rtyper/ootypesystem/`_ the `object-oriented type system`_ + for OO backends + +`rpython/memory/`_ the `garbage collector`_ construction + framework + +`rpython/translator/`_ translation_ backends and support code + +`rpython/translator/backendopt/`_ general optimizations that run before a + backend generates code + +`rpython/translator/c/`_ the `GenC backend`_, producing C code + from an + RPython program (generally via the rtyper_) + +`rpython/translator/cli/`_ the `CLI backend`_ for `.NET`_ + (Microsoft CLR or Mono_) + +`pypy/goal/`_ our `main PyPy-translation scripts`_ + live here + +`rpython/translator/jvm/`_ the Java backend + +`rpython/translator/tool/`_ helper tools for translation + +`dotviewer/`_ `graph viewer`_ + +``*/test/`` many directories have a test subdirectory + containing test + modules (see `Testing in PyPy`_) + +``_cache/`` holds cache files from various purposes +================================= ============================================ + +.. _`bytecode interpreter`: interpreter.html +.. _`Testing in PyPy`: coding-guide.html#testing-in-pypy +.. _`mixed modules`: coding-guide.html#mixed-modules +.. _`modules`: coding-guide.html#modules +.. _`basil`: http://people.cs.uchicago.edu/~jriehl/BasilTalk.pdf +.. _`object space`: objspace.html +.. _FlowObjSpace: objspace.html#the-flow-object-space +.. _`transparent proxies`: objspace-proxies.html#tproxy +.. _`Differences between PyPy and CPython`: cpython_differences.html +.. _`What PyPy can do for your objects`: objspace-proxies.html +.. _`Continulets and greenlets`: stackless.html +.. _StdObjSpace: objspace.html#the-standard-object-space +.. _`abstract interpretation`: http://en.wikipedia.org/wiki/Abstract_interpretation +.. _`rpython`: coding-guide.html#rpython +.. _`type inferencing code`: translation.html#the-annotation-pass +.. _`RPython Typer`: translation.html#rpython-typer +.. _`testing methods`: coding-guide.html#testing-in-pypy +.. _`translation`: translation.html +.. _`GenC backend`: translation.html#genc +.. _`CLI backend`: cli-backend.html +.. _`py.py`: getting-started-python.html#the-py.py-interpreter +.. _`translatorshell.py`: getting-started-dev.html#try-out-the-translator +.. _JIT: jit/index.html +.. _`JIT Generation in PyPy`: jit/index.html +.. _`just-in-time compiler generator`: jit/index.html +.. _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 +.. _`main PyPy-translation scripts`: getting-started-python.html#translating-the-pypy-python-interpreter +.. _`.NET`: http://www.microsoft.com/net/ +.. _Mono: http://www.mono-project.com/ +.. _`"standard library"`: rlib.html +.. _`graph viewer`: getting-started-dev.html#try-out-the-translator diff --git a/pypy/doc/getting-started-dev.rst b/pypy/doc/getting-started-dev.rst --- a/pypy/doc/getting-started-dev.rst +++ b/pypy/doc/getting-started-dev.rst @@ -1,13 +1,58 @@ -=============================================================================== -Getting Started with the Translation Toolchain and Development Process -=============================================================================== +============================ +Getting Started with RPython +============================ .. contents:: +RPython is a subset of Python that can be statically compiled. The PyPy +interpreter is written mostly in RPython (with pieces in Python), while +the RPython compiler is written in Python. The hard to understand part +is that Python is a meta-programming language for RPython, that is, +RPython is considered from live objects **after** the imports are done. +This might require more explanation. You start writing RPython from +``entry_point``, a good starting point is +``rpython/translator/goal/targetnopstandalone.py``. This does not do all that +much, but is a start. Now if code analyzed (in this case ``entry_point``) +calls some functions, those calls will be followed. Those followed calls +have to be RPython themselves (and everything they call etc.), however not +entire module files. To show how you can use metaprogramming, we can do +a silly example (note that closures are not RPython):: + + def generator(operation): + if operation == 'add': + def f(a, b): + return a + b + else: + def f(a, b): + return a - b + return f + + add = generator('add') + sub = generator('sub') + + def entry_point(argv): + print add(sub(int(argv[1]), 3) 4) + return 0 + +In this example ``entry_point`` is RPython, ``add`` and ``sub`` are RPython, +however, ``generator`` is not. + +A good introductory level articles are available: + +* Laurence Tratt -- `Fast Enough VMs in Fast Enough Time`_. + +* `How to write interpreters in RPython`_ and `part 2`_ by Andrew Brown. + +.. _`Fast Enough VMs in Fast Enough Time`: http://tratt.net/laurie/tech_articles/articles/fast_enough_vms_in_fast_enough_time + +.. _`How to write interpreters in RPython`: http://morepypy.blogspot.com/2011/04/tutorial-writing-interpreter-with-pypy.html + +.. _`part 2`: http://morepypy.blogspot.com/2011/04/tutorial-part-2-adding-jit.html + .. _`try out the translator`: Trying out the translator -------------------------- +------------------------- The translator is a tool based on the PyPy interpreter which can translate sufficiently static RPython programs into low-level code (in particular it can @@ -28,7 +73,7 @@ >>> t = Translation(snippet.is_perfect_number, [int]) >>> t.view() - + After that, the graph viewer pops up, that lets you interactively inspect the flow graph. To move around, click on something that you want to inspect. To get help about how to use it, press 'H'. To close it again, press 'Q'. @@ -83,10 +128,10 @@ The object returned by ``compile_cli`` or ``compile_jvm`` is a wrapper around the real executable: the parameters are passed as command line arguments, and -the returned value is read from the standard output. +the returned value is read from the standard output. Once you have compiled the snippet, you can also try to launch the -executable directly from the shell. You will find the +executable directly from the shell. You will find the executable in one of the ``/tmp/usession-*`` directories:: # For CLI: diff --git a/pypy/doc/getting-started-python.rst b/pypy/doc/getting-started-python.rst --- a/pypy/doc/getting-started-python.rst +++ b/pypy/doc/getting-started-python.rst @@ -6,7 +6,7 @@ PyPy's Python interpreter is a very compliant Python -interpreter implemented in Python. When translated to C, it passes most of +interpreter implemented in RPython. When compiled, it passes most of `CPythons core language regression tests`_ and comes with many of the extension modules included in the standard library including ``ctypes``. It can run large libraries such as Django_ and Twisted_. There are some small behavioral @@ -46,7 +46,7 @@ 2. Install build-time dependencies. On a Debian box these are:: [user at debian-box ~]$ sudo apt-get install \ - gcc make python-dev libffi-dev lib-sqlite3-dev pkg-config \ + gcc make python-dev libffi-dev libsqlite3-dev pkg-config \ libz-dev libbz2-dev libncurses-dev libexpat1-dev \ libssl-dev libgc-dev python-sphinx python-greenlet @@ -147,6 +147,8 @@ Translating using the CLI backend +++++++++++++++++++++++++++++++++ +**Note: the CLI backend is no longer maintained** + To create a standalone .NET executable using the `CLI backend`_:: ./translate.py --backend=cli targetpypystandalone.py diff --git a/pypy/doc/how-to-contribute.rst b/pypy/doc/how-to-contribute.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/how-to-contribute.rst @@ -0,0 +1,78 @@ +How to contribute to PyPy +------------------------- + +This page describes how to contribute to the PyPy project. The first thing +to remember is that PyPy project is very different than most projects out there. +It's also different from a classic compiler project, so academic courses +about compilers often don't apply or lead in the wrong direction. + +Don't just hack +--------------- + +The first and most important rule how not to contribute to PyPy is +"just hacking". This won't work. There are two major reasons why not +-- build times are large and PyPy has very thick layer separation which +make it harder to "just hack a feature". + +Test driven development +----------------------- + +Instead, we practice a lot of test driven development. This is partly because +of very high quality requirements for compilers and partly because there is +simply no other way to get around such complex project, that will keep you sane. +There are probably people out there who are smart enough not to need it, we're +not one of those. You may consider familiarizing yourself with `pytest`_, +since this is a tool we use for tests. +This leads to the next issue: + +Layers +------ + +PyPy has layers. Those layers help us keep the respective parts separated enough +to be worked on independently and make the complexity manageable. This is, +again, just a sanity requirement for such a complex project. For example writing +a new optimization for the JIT usually does **not** involve touching a Python +interpreter at all or the JIT assembler backend or the garbage collector. +Instead it requires writing small tests in +``rpython/jit/metainterp/optimizeopt/test/test_*`` and fixing files there. +After that, you can just compile PyPy and things should just work. + +The short list of layers for further reading. For each of those layers, a good +entry point is a test subdirectory in respective directories. It usually +describes (better or worse) the interfaces between the submodules. For the +``pypy`` subdirectory, most tests are small snippets of python programs that +check for correctness (calls ``AppTestXxx``) that will call the appropriate +part of the interpreter. For the ``rpython`` directory, most tests are small +RPython interpreters that perform certain tasks. To see how they translate +to low-level graphs, run them with ``--view``. To see small interpreters +with a JIT compiler, use ``--viewloops`` option. + +* **python interpreter** - it's the part implemented in the ``pypy/`` directory. + It's implemented in RPython, which is a high level static language with + classes, garbage collection, just-in-time compiler generation and the ability + to call C. A cool part about it is that it can be run untranslated, so all + the tests are runnable without translating PyPy. + + **interpreter** contains the interpreter core + + **objspace** contains implementations of various objects exported to + the Python layer + + **module** directory contains extension modules written in RPython + +* **rpython compiler** that resides in ``rpython/annotator`` and + ``rpython/rtyper`` directories. Consult `introduction to RPython`_ for + further reading + +* **JIT generator** lives in ``rpython/jit`` directory. optimizations live + in ``rpython/jit/metainterp/optimizeopt``, the main JIT in + ``rpython/jit/metainterp`` (runtime part) and + ``rpython/jit/codewriter`` (translation-time part). Backends live in + ``rpython/jit/backend``. + +* **garbage collection** lives in ``rpython/memory`` + +The rest of directories serve specific niche goal and are unlikely a good +entry point. + +.. _`introduction to RPython`: getting-started-dev.rst diff --git a/pypy/doc/index.rst b/pypy/doc/index.rst --- a/pypy/doc/index.rst +++ b/pypy/doc/index.rst @@ -1,15 +1,40 @@ -Welcome to PyPy Development -============================================= +Welcome to PyPy +=============== -The PyPy project aims at producing a flexible and fast Python_ -implementation. The guiding idea is to translate a Python-level -description of the Python language itself to lower level languages. -Rumors have it that the secret goal is being faster-than-C which is -nonsense, isn't it? `more...`_ +The PyPy project aims to produce a flexible and fast Python_ +implementation. This page documents the development of the PyPy +project itself. If you don't know what PyPy is, consult the `PyPy +website`_. If you just want to use PyPy, consult the `download`_ page +and the `getting started with pypy`_ documents. If you want to help +develop PyPy -- keep reading! -Getting into PyPy ... -============================================= +PyPy is written in a language called `RPython`_, which is suitable for +writing dynamic language interpreters (and not much else). RPython is +a subset of Python and is itself written in Python. If you'd like to +learn more about RPython, `Starting with RPython`_ should provide a +reasonable overview. + +**If you would like to contribute to PyPy**, please read `how to +contribute`_ first. PyPy's development style is somewhat different to +that of many other software projects and it often surprises +newcomers. What is **not** necessary is an academic background from +university in writing compilers -- much of it does not apply to PyPy +any way. + +All of the documentation and source code is available under the MIT license, +unless otherwise specified. Consult `LICENSE`_ + +.. _`download`: http://pypy.org/download.html +.. _`getting started with pypy`: getting-started-python.html +.. _`RPython`: coding-guide.html#RPython +.. _`Starting with RPython`: getting-started-dev.html +.. _`how to contribute`: how-to-contribute.html +.. _`PyPy website`: http://pypy.org +.. _`LICENSE`: https://bitbucket.org/pypy/pypy/src/default/LICENSE + +Index of various topics: +======================== * `Getting started`_: how to install and run the PyPy Python interpreter @@ -25,20 +50,30 @@ * `potential project ideas`_: In case you want to get your feet wet... +* `more stuff`_: this is a collection of documentation that's there, but not + particularly organized + Documentation for the PyPy Python Interpreter -=============================================== +============================================= New features of PyPy's Python Interpreter and Translation Framework: * `Differences between PyPy and CPython`_ - * `What PyPy can do for your objects`_ - * `Continulets and greenlets`_ + * `What PyPy can do for your objects`_ - transparent proxy documentation + * `Continulets and greenlets`_ - documentation about stackless features * `JIT Generation in PyPy`_ + * `JIT hooks`_ * `Sandboxing Python code`_ + * `Garbage collection environment variables`_ -Status_ of the project. - +.. _`Differences between PyPy and CPython`: cpython_differences.html +.. _`What PyPy can do for your objects`: objspace-proxies.html +.. _`Continulets and greenlets`: stackless.html +.. _`JIT Generation in PyPy`: jit/index.html +.. _`JIT hooks`: jit-hooks.html +.. _`Sandboxing Python code`: sandbox.html +.. _`Garbage collection environment variables`: gc_info.html Mailing lists, bug tracker, IRC channel ============================================= @@ -79,354 +114,6 @@ .. _`speed.pypy.org`: http://speed.pypy.org .. _`RPython toolchain`: translation.html .. _`potential project ideas`: project-ideas.html - -Project Documentation -===================================== - -PyPy was funded by the EU for several years. See the `web site of the EU -project`_ for more details. - -.. _`web site of the EU project`: http://pypy.org - -architecture_ gives a complete view of PyPy's basic design. - -`coding guide`_ helps you to write code for PyPy (especially also describes -coding in RPython a bit). - -`sprint reports`_ lists reports written at most of our sprints, from -2003 to the present. - -`papers, talks and related projects`_ lists presentations -and related projects as well as our published papers. - -`PyPy video documentation`_ is a page linking to the videos (e.g. of talks and -introductions) that are available. - -`Technical reports`_ is a page that contains links to the -reports that we submitted to the European Union. - -`development methodology`_ describes our sprint-driven approach. - -`LICENSE`_ contains licensing details (basically a straight MIT-license). - -`Glossary`_ of PyPy words to help you align your inner self with -the PyPy universe. - - -Status -=================================== - -PyPy can be used to run Python programs on Linux, OS/X, -Windows, on top of .NET, and on top of Java. -To dig into PyPy it is recommended to try out the current -Mercurial default branch, which is always working or mostly working, -instead of the latest release, which is `2.0 beta1`__. - -.. __: release-2.0.0-beta1.html - -PyPy is mainly developed on Linux and Mac OS X. Windows is supported, -but platform-specific bugs tend to take longer before we notice and fix -them. Linux 64-bit machines are supported (though it may also take some -time before we notice and fix bugs). - -PyPy's own tests `summary`_, daily updated, run through BuildBot infrastructure. -You can also find CPython's compliance tests run with compiled ``pypy-c`` -executables there. - - -Source Code Documentation -=============================================== - -`object spaces`_ discusses the object space interface -and several implementations. - -`bytecode interpreter`_ explains the basic mechanisms -of the bytecode interpreter and virtual machine. - -`interpreter optimizations`_ describes our various strategies for -improving the performance of our interpreter, including alternative -object implementations (for strings, dictionaries and lists) in the -standard object space. - -`translation`_ is a detailed overview of our translation process. The -rtyper_ is the largest component of our translation process. - -`dynamic-language translation`_ is a paper that describes -the translation process, especially the flow object space -and the annotator in detail. (This document is one -of the `EU reports`_.) - -`low-level encapsulation`_ describes how our approach hides -away a lot of low level details. This document is also part -of the `EU reports`_. - -`translation aspects`_ describes how we weave different -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. - -`rlib`_ describes some modules that can be used when implementing programs in -RPython. - -`configuration documentation`_ describes the various configuration options that -allow you to customize PyPy. - -`CLI backend`_ describes the details of the .NET backend. - -`JIT Generation in PyPy`_ describes how we produce the Python Just-in-time Compiler -from our Python interpreter. - - - -.. _`FAQ`: faq.html -.. _Glossary: glossary.html -.. _`PyPy video documentation`: video-index.html -.. _parser: parser.html -.. _`development methodology`: dev_method.html -.. _`sprint reports`: sprint-reports.html -.. _`papers, talks and related projects`: extradoc.html -.. _`object spaces`: objspace.html -.. _`interpreter optimizations`: interpreter-optimizations.html -.. _`translation`: translation.html -.. _`dynamic-language translation`: https://bitbucket.org/pypy/extradoc/raw/tip/eu-report/D05.1_Publish_on_translating_a_very-high-level_description.pdf -.. _`low-level encapsulation`: low-level-encapsulation.html -.. _`translation aspects`: translation-aspects.html -.. _`configuration documentation`: config/ -.. _`coding guide`: coding-guide.html -.. _`architecture`: architecture.html -.. _`getting started`: getting-started.html -.. _`bytecode interpreter`: interpreter.html -.. _`EU reports`: index-report.html -.. _`Technical reports`: index-report.html -.. _`summary`: http://buildbot.pypy.org/summary -.. _`ideas for PyPy related projects`: project-ideas.html -.. _`Nightly builds and benchmarks`: http://tuatara.cs.uni-duesseldorf.de/benchmark.html -.. _`directory reference`: -.. _`rlib`: rlib.html -.. _`Sandboxing Python code`: sandbox.html -.. _`LICENSE`: https://bitbucket.org/pypy/pypy/src/default/LICENSE - -PyPy directory cross-reference ------------------------------- - -Here is a fully referenced alphabetical two-level deep -directory overview of PyPy: - -================================= ============================================ -Directory explanation/links -================================= ============================================ -`pypy/bin/`_ command-line scripts, mainly - `pypy/bin/pyinteractive.py`_ - -`pypy/config/`_ handles the numerous options for building - and running PyPy - -`pypy/doc/`_ text versions of PyPy developer - documentation - -`pypy/doc/config/`_ documentation for the numerous translation - options - -`pypy/doc/discussion/`_ drafts of ideas and documentation - -``doc/*/`` other specific documentation topics or tools - -`pypy/interpreter/`_ `bytecode interpreter`_ and related objects - (frames, functions, modules,...) - -`pypy/interpreter/pyparser/`_ interpreter-level Python source parser - -`pypy/interpreter/astcompiler/`_ interpreter-level bytecode compiler, - via an AST representation - -`pypy/module/`_ contains `mixed modules`_ - implementing core modules with - both application and interpreter level code. - Not all are finished and working. Use - the ``--withmod-xxx`` - or ``--allworkingmodules`` translation - options. - -`pypy/objspace/`_ `object space`_ implementations - -`pypy/objspace/std/`_ the StdObjSpace_ implementing CPython's - objects and types - -`pypy/tool/`_ various utilities and hacks used - from various places - -`pypy/tool/algo/`_ general-purpose algorithmic and mathematic - tools - -`pypy/tool/pytest/`_ support code for our `testing methods`_ - - -`rpython/annotator/`_ `type inferencing code`_ for - `RPython`_ programs - -`rpython/config/`_ handles the numerous options for RPython - - -`rpython/flowspace/`_ the FlowObjSpace_ implementing - `abstract interpretation`_ - -`rpython/rlib/`_ a `"standard library"`_ for RPython_ - programs - -`rpython/rtyper/`_ the `RPython Typer`_ - -`rpython/rtyper/lltypesystem/`_ the `low-level type system`_ for - C-like backends - -`rpython/rtyper/ootypesystem/`_ the `object-oriented type system`_ - for OO backends - -`rpython/memory/`_ the `garbage collector`_ construction - framework - -`rpython/translator/`_ translation_ backends and support code - -`rpython/translator/backendopt/`_ general optimizations that run before a - backend generates code - -`rpython/translator/c/`_ the `GenC backend`_, producing C code - from an - RPython program (generally via the rtyper_) - -`rpython/translator/cli/`_ the `CLI backend`_ for `.NET`_ - (Microsoft CLR or Mono_) - -`pypy/goal/`_ our `main PyPy-translation scripts`_ - live here - -`rpython/translator/jvm/`_ the Java backend - -`rpython/translator/tool/`_ helper tools for translation - -`dotviewer/`_ `graph viewer`_ - -``*/test/`` many directories have a test subdirectory - containing test - modules (see `Testing in PyPy`_) - -``_cache/`` holds cache files from various purposes -================================= ============================================ - -.. _`bytecode interpreter`: interpreter.html -.. _`Testing in PyPy`: coding-guide.html#testing-in-pypy -.. _`mixed modules`: coding-guide.html#mixed-modules -.. _`modules`: coding-guide.html#modules -.. _`basil`: http://people.cs.uchicago.edu/~jriehl/BasilTalk.pdf -.. _`object space`: objspace.html -.. _FlowObjSpace: objspace.html#the-flow-object-space -.. _`transparent proxies`: objspace-proxies.html#tproxy -.. _`Differences between PyPy and CPython`: cpython_differences.html -.. _`What PyPy can do for your objects`: objspace-proxies.html -.. _`Continulets and greenlets`: stackless.html -.. _StdObjSpace: objspace.html#the-standard-object-space -.. _`abstract interpretation`: http://en.wikipedia.org/wiki/Abstract_interpretation -.. _`rpython`: coding-guide.html#rpython -.. _`type inferencing code`: translation.html#the-annotation-pass -.. _`RPython Typer`: translation.html#rpython-typer -.. _`testing methods`: coding-guide.html#testing-in-pypy -.. _`translation`: translation.html -.. _`GenC backend`: translation.html#genc -.. _`CLI backend`: cli-backend.html -.. _`py.py`: getting-started-python.html#the-py.py-interpreter -.. _`translatorshell.py`: getting-started-dev.html#try-out-the-translator -.. _JIT: jit/index.html -.. _`JIT Generation in PyPy`: jit/index.html -.. _`just-in-time compiler generator`: jit/index.html -.. _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 -.. _`main PyPy-translation scripts`: getting-started-python.html#translating-the-pypy-python-interpreter -.. _`.NET`: http://www.microsoft.com/net/ -.. _Mono: http://www.mono-project.com/ -.. _`"standard library"`: rlib.html -.. _`graph viewer`: getting-started-dev.html#try-out-the-translator - - -.. The following documentation is important and reasonably up-to-date: - -.. extradoc: should this be integrated one level up: dcolish? - - -.. toctree:: - :maxdepth: 1 - :hidden: - - getting-started.rst - getting-started-python.rst - getting-started-dev.rst - windows.rst - faq.rst - commandline_ref.rst - architecture.rst - coding-guide.rst - cpython_differences.rst - garbage_collection.rst - gc_info.rst - interpreter.rst - objspace.rst - __pypy__-module.rst - objspace-proxies.rst - config/index.rst - - dev_method.rst - extending.rst - - extradoc.rst - video-index.rst - - glossary.rst - - contributor.rst - - interpreter-optimizations.rst - configuration.rst - parser.rst - rlib.rst - rtyper.rst - rffi.rst - - translation.rst - jit/index.rst - jit/overview.rst - jit/pyjitpl5.rst - - index-of-release-notes.rst - - ctypes-implementation.rst - - how-to-release.rst - - index-report.rst - - stackless.rst - sandbox.rst - - discussions.rst - - cleanup.rst - - sprint-reports.rst - - eventhistory.rst - statistic/index.rst - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`search` -* :ref:`glossary` - +.. _`more stuff`: project-documentation.html .. include:: _ref.txt diff --git a/pypy/doc/needswork.txt b/pypy/doc/needswork.txt deleted file mode 100644 --- a/pypy/doc/needswork.txt +++ /dev/null @@ -1,3 +0,0 @@ -.. warning:: - - This documentation needs work (as discussed during the Gothenburg sprint in 2011) diff --git a/pypy/doc/objspace-proxies.rst b/pypy/doc/objspace-proxies.rst --- a/pypy/doc/objspace-proxies.rst +++ b/pypy/doc/objspace-proxies.rst @@ -5,7 +5,6 @@ .. contents:: - Thanks to the `Object Space`_ architecture, any feature that is based on proxying, extending, changing or otherwise controlling the behavior of all objects in a running program is easy to implement on diff --git a/pypy/doc/project-documentation.rst b/pypy/doc/project-documentation.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/project-documentation.rst @@ -0,0 +1,177 @@ + +Project Documentation +===================================== + +`architecture`_ gives a complete view of PyPy's basic design. + +`coding guide`_ helps you to write code for PyPy (especially also describes +coding in RPython a bit). + +`sprint reports`_ lists reports written at most of our sprints, from +2003 to the present. + +`papers, talks and related projects`_ lists presentations +and related projects as well as our published papers. + +`PyPy video documentation`_ is a page linking to the videos (e.g. of talks and +introductions) that are available. + +`Technical reports`_ is a page that contains links to the +reports that we submitted to the European Union. + +`development methodology`_ describes our sprint-driven approach. + +`LICENSE`_ contains licensing details (basically a straight MIT-license). + +`Glossary`_ of PyPy words to help you align your inner self with +the PyPy universe. + +Source Code Documentation +=============================================== + +`object spaces`_ discusses the object space interface +and several implementations. + +`bytecode interpreter`_ explains the basic mechanisms +of the bytecode interpreter and virtual machine. + +`interpreter optimizations`_ describes our various strategies for +improving the performance of our interpreter, including alternative +object implementations (for strings, dictionaries and lists) in the +standard object space. + +`translation`_ is a detailed overview of our translation process. The +rtyper_ is the largest component of our translation process. + +`dynamic-language translation`_ is a paper that describes +the translation process, especially the flow object space +and the annotator in detail. (This document is one +of the `EU reports`_.) + +`low-level encapsulation`_ describes how our approach hides +away a lot of low level details. This document is also part +of the `EU reports`_. + +`translation aspects`_ describes how we weave different +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. + +`rlib`_ describes some modules that can be used when implementing programs in +RPython. + +`configuration documentation`_ describes the various configuration options that +allow you to customize PyPy. + +`pypy on windows`_ + +`command line reference`_ + +`CLI backend`_ describes the details of the .NET backend. + +`JIT Generation in PyPy`_ describes how we produce the Python Just-in-time Compiler +from our Python interpreter. + +`directory cross-reference`_ + +.. _`garbage collector`: garbage_collection.html +.. _`directory cross-reference`: dir-reference.html +.. _`pypy on windows`: windows.html +.. _`command line reference`: commandline_ref.html +.. _`FAQ`: faq.html +.. _Glossary: glossary.html +.. _`PyPy video documentation`: video-index.html +.. _parser: parser.html +.. _`development methodology`: dev_method.html +.. _`sprint reports`: sprint-reports.html +.. _`papers, talks and related projects`: extradoc.html +.. _`object spaces`: objspace.html +.. _`interpreter optimizations`: interpreter-optimizations.html +.. _`translation`: translation.html +.. _`dynamic-language translation`: https://bitbucket.org/pypy/extradoc/raw/tip/eu-report/D05.1_Publish_on_translating_a_very-high-level_description.pdf +.. _`low-level encapsulation`: low-level-encapsulation.html +.. _`translation aspects`: translation-aspects.html +.. _`configuration documentation`: config/ +.. _`coding guide`: coding-guide.html +.. _`Architecture`: architecture.html +.. _`getting started`: getting-started.html +.. _`bytecode interpreter`: interpreter.html +.. _`EU reports`: index-report.html +.. _`Technical reports`: index-report.html +.. _`summary`: http://buildbot.pypy.org/summary +.. _`ideas for PyPy related projects`: project-ideas.html +.. _`Nightly builds and benchmarks`: http://tuatara.cs.uni-duesseldorf.de/benchmark.html +.. _`directory reference`: +.. _`rlib`: rlib.html +.. _`Sandboxing Python code`: sandbox.html +.. _`LICENSE`: https://bitbucket.org/pypy/pypy/src/default/LICENSE + +.. The following documentation is important and reasonably up-to-date: + +.. extradoc: should this be integrated one level up: dcolish? + +.. toctree:: + :maxdepth: 1 + :hidden: + + interpreter.rst + objspace.rst + __pypy__-module.rst + objspace-proxies.rst + config/index.rst + + dev_method.rst + extending.rst + + extradoc.rst + video-index.rst + + glossary.rst + + contributor.rst + + interpreter-optimizations.rst + configuration.rst + parser.rst + rlib.rst + rtyper.rst + rffi.rst + + translation.rst + jit/index.rst + jit/overview.rst + jit/pyjitpl5.rst + + index-of-release-notes.rst + + ctypes-implementation.rst + + how-to-release.rst + + index-report.rst + + stackless.rst + sandbox.rst + + discussions.rst + + cleanup.rst + + sprint-reports.rst + + eventhistory.rst + statistic/index.rst + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`search` +* :ref:`glossary` + +.. include:: _ref.txt diff --git a/pypy/doc/release-2.0.0-beta2.rst b/pypy/doc/release-2.0.0-beta2.rst --- a/pypy/doc/release-2.0.0-beta2.rst +++ b/pypy/doc/release-2.0.0-beta2.rst @@ -82,3 +82,13 @@ * we now have special strategies for ``dict``/``set``/``list`` which contain unicode strings, which means that now such collections will be both faster and more compact. + +.. _`eventlet`: http://eventlet.net/ +.. _`gevent`: http://www.gevent.org/ +.. _`cffi`: http://cffi.readthedocs.org/en/release-0.6/ +.. _`JIT hooks`: http://doc.pypy.org/en/latest/jit-hooks.html +.. _`pypycore`: https://github.com/gevent-on-pypy/pypycore +.. _`pypy-hacks`: https://github.com/schmir/gevent/tree/pypy-hacks +.. _`_curses.py`: https://bitbucket.org/pypy/pypy/src/aefddd47f224e3c12e2ea74f5c796d76f4355bdb/lib_pypy/_curses.py?at=default +.. _`_sqlite3.py`: https://bitbucket.org/pypy/pypy/src/aefddd47f224e3c12e2ea74f5c796d76f4355bdb/lib_pypy/_sqlite3.py?at=default + diff --git a/pypy/doc/stackless.rst b/pypy/doc/stackless.rst --- a/pypy/doc/stackless.rst +++ b/pypy/doc/stackless.rst @@ -17,8 +17,8 @@ Continulets can be directly used by application code, or it is possible to write (entirely at app-level) more user-friendly interfaces. -Currently PyPy implements greenlets_ on top of continulets. It would be -easy to implement tasklets and channels as well, emulating the model +Currently PyPy implements greenlets_ on top of continulets. It also +implements (an approximation of) tasklets and channels, emulating the model of `Stackless Python`_. Continulets are extremely light-weight, which means that PyPy should be diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -43,12 +43,26 @@ Rudimentary support for bytearray in RPython .. branch: refactor-call_release_gil -Fix a bug which casused cffi to return the wrong result when calling a C +Fix a bug which caused cffi to return the wrong result when calling a C function which calls a Python callback which forces the frames +.. branch: virtual-raw-mallocs +JIT optimizations which make cffi calls even faster, by removing the need to +allocate a temporary buffer where to store the arguments. + +.. branch: improve-docs-2 +Improve documents and straighten out links + +.. branch: fast-newarray +Inline the fast path of newarray in the assembler. +Disabled on ARM until we fix issues. + +.. branch: reflex-support +Allow dynamic loading of a (Reflex) backend that implements the C-API needed +to provide reflection information + .. branches we don't care about .. branch: autoreds -.. branch: reflex-support .. branch: kill-faking .. branch: improved_ebnfparse_error .. branch: task-decorator @@ -121,3 +135,6 @@ cffi implementation of sqlite3 .. branch: release-2.0-beta2 +.. branch: unbreak-freebsd + +.. branch: virtualref-virtualizable diff --git a/pypy/goal/getnightly.py b/pypy/goal/getnightly.py --- a/pypy/goal/getnightly.py +++ b/pypy/goal/getnightly.py @@ -13,8 +13,13 @@ if sys.maxint == 2**63 - 1: arch += '64' +hg = py.path.local.sysfind('hg') +branch = hg.sysexec('branch').strip() +if branch == 'default': + branch = 'trunk' + filename = 'pypy-c-jit-latest-%s.tar.bz2' % arch -url = 'http://buildbot.pypy.org/nightly/trunk/%s' % filename +url = 'http://buildbot.pypy.org/nightly/%s/%s' % (branch, filename) tmp = py.path.local.mkdtemp() mydir = tmp.chdir() print 'Downloading pypy to', tmp diff --git a/pypy/interpreter/astcompiler/consts.py b/pypy/interpreter/astcompiler/consts.py --- a/pypy/interpreter/astcompiler/consts.py +++ b/pypy/interpreter/astcompiler/consts.py @@ -15,8 +15,6 @@ CO_FUTURE_WITH_STATEMENT = 0x8000 CO_FUTURE_PRINT_FUNCTION = 0x10000 CO_FUTURE_UNICODE_LITERALS = 0x20000 -CO_CONTAINSGLOBALS = 0x80000 # pypy-specific: need to check that it's not used - # by any other flag PyCF_SOURCE_IS_UTF8 = 0x0100 PyCF_DONT_IMPLY_DEDENT = 0x0200 diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py --- a/pypy/interpreter/baseobjspace.py +++ b/pypy/interpreter/baseobjspace.py @@ -709,6 +709,8 @@ def new_interned_w_str(self, w_s): s = self.str_w(w_s) + if not we_are_translated(): + assert type(s) is str try: return self.interned_strings[s] except KeyError: @@ -717,6 +719,8 @@ return w_s def new_interned_str(self, s): + if not we_are_translated(): + assert type(s) is str try: return self.interned_strings[s] except KeyError: diff --git a/pypy/interpreter/pycode.py b/pypy/interpreter/pycode.py --- a/pypy/interpreter/pycode.py +++ b/pypy/interpreter/pycode.py @@ -12,7 +12,7 @@ from pypy.interpreter.gateway import unwrap_spec from pypy.interpreter.astcompiler.consts import ( CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS, CO_NESTED, - CO_GENERATOR, CO_CONTAINSGLOBALS) + CO_GENERATOR) from pypy.tool.stdlib_opcode import opcodedesc, HAVE_ARGUMENT from rpython.rlib.rarithmetic import intmask from rpython.rlib.objectmodel import compute_hash @@ -88,8 +88,6 @@ self._initialize() def _initialize(self): - self._init_flags() - if self.co_cellvars: argcount = self.co_argcount assert argcount >= 0 # annotator hint @@ -134,22 +132,6 @@ '__pypy__' not in sys.builtin_module_names): raise Exception("CPython host codes should not be rendered") - def _init_flags(self): - co_code = self.co_code - next_instr = 0 - while next_instr < len(co_code): - opcode = ord(co_code[next_instr]) - next_instr += 1 - if opcode >= HAVE_ARGUMENT: - next_instr += 2 - while opcode == opcodedesc.EXTENDED_ARG.index: - opcode = ord(co_code[next_instr]) - next_instr += 3 - if opcode == opcodedesc.LOAD_GLOBAL.index: - self.co_flags |= CO_CONTAINSGLOBALS - elif opcode == opcodedesc.LOAD_NAME.index: - self.co_flags |= CO_CONTAINSGLOBALS - co_names = property(lambda self: [self.space.unwrap(w_name) for w_name in self.co_names_w]) # for trace def signature(self): diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py --- a/pypy/interpreter/pyopcode.py +++ b/pypy/interpreter/pyopcode.py @@ -255,19 +255,7 @@ "code=%d, name=%s" % (self.last_instr, opcode, methodname)) - try: - res = meth(oparg, next_instr) - except Exception: - if 0: - import dis, sys - print "*** %s at offset %d (%s)" % (sys.exc_info()[0], - self.last_instr, - methodname) From noreply at buildbot.pypy.org Tue Apr 30 11:08:05 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Tue, 30 Apr 2013 11:08:05 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: commit just to kick off the CI Message-ID: <20130430090805.DF50B1C07F7@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r354:c1db68c509c6 Date: 2013-04-30 11:07 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/c1db68c509c6/ Log: commit just to kick off the CI diff --git a/.hgignore b/.hgignore --- a/.hgignore +++ b/.hgignore @@ -5,3 +5,6 @@ images/Squeak* targetimageloadingsmalltalk-c images/package-cache +versions +coglinux + From noreply at buildbot.pypy.org Tue Apr 30 11:15:05 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Tue, 30 Apr 2013 11:15:05 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: added vmdebugging plugin allowing squeak code to start tracing and halting (when interpreted) Message-ID: <20130430091505.7F0B31C07F7@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r355:00e92c2f5b1c Date: 2013-04-30 11:14 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/00e92c2f5b1c/ Log: added vmdebugging plugin allowing squeak code to start tracing and halting (when interpreted) diff --git a/spyvm/plugins/vmdebugging.py b/spyvm/plugins/vmdebugging.py new file mode 100644 --- /dev/null +++ b/spyvm/plugins/vmdebugging.py @@ -0,0 +1,29 @@ +from spyvm import model, error +from spyvm.plugins.plugin import Plugin + + +DebuggingPlugin = Plugin() + + + at DebuggingPlugin.expose_primitive(unwrap_spec=[object]) +def trace(interp, s_frame, w_rcvr): + interp.trace = True + return w_rcvr + + at DebuggingPlugin.expose_primitive(unwrap_spec=[object]) +def untrace(interp, s_frame, w_rcvr): + interp.trace = False + return w_rcvr + + at DebuggingPlugin.expose_primitive(unwrap_spec=[object]) +def halt(interp, s_frame, w_rcvr): + from rpython.rlib.objectmodel import we_are_translated + from spyvm.error import Exit + + if not we_are_translated(): + import pdb; pdb.set_trace() + else: + print s_frame.print_stack()[1] + print s_frame + raise Exit('Halt is not well defined when translated.') + return w_rcvr diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -816,8 +816,6 @@ @expose_primitive(EXTERNAL_CALL, clean_stack=False, no_result=True, compiled_method=True) def func(interp, s_frame, argcount, s_method): - from spyvm.plugins.socket import SocketPlugin - space = interp.space w_description = s_method.w_self().literalat0(space, 1) if not isinstance(w_description, model.W_PointersObject) or w_description.size() < 2: @@ -832,7 +830,11 @@ if signature == ('BitBltPlugin', 'primitiveCopyBits'): return prim_holder.prim_table[BITBLT_COPY_BITS](interp, s_frame, argcount, s_method) elif signature[0] == "SocketPlugin": + from spyvm.plugins.socket import SocketPlugin return SocketPlugin.call(signature[1], interp, s_frame, argcount, s_method) + elif signature[0] == "VMDebugging": + from spyvm.plugins.vmdebugging import DebuggingPlugin + return DebuggingPlugin.call(signature[1], interp, s_frame, argcount, s_method) raise PrimitiveFailedError # ___________________________________________________________________________ From noreply at buildbot.pypy.org Tue Apr 30 11:25:42 2013 From: noreply at buildbot.pypy.org (arigo) Date: Tue, 30 Apr 2013 11:25:42 +0200 (CEST) Subject: [pypy-commit] pypy default: Fix for translating a sandbox Message-ID: <20130430092542.2725B1C1260@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63767:5af6563cf284 Date: 2013-04-30 11:28 +0200 http://bitbucket.org/pypy/pypy/changeset/5af6563cf284/ Log: Fix for translating a sandbox diff --git a/rpython/rlib/types.py b/rpython/rlib/types.py --- a/rpython/rlib/types.py +++ b/rpython/rlib/types.py @@ -7,6 +7,10 @@ return model.s_None +def impossible(): + return model.s_ImpossibleValue + + def float(): return model.SomeFloat() diff --git a/rpython/translator/sandbox/rsandbox.py b/rpython/translator/sandbox/rsandbox.py --- a/rpython/translator/sandbox/rsandbox.py +++ b/rpython/translator/sandbox/rsandbox.py @@ -100,7 +100,7 @@ else: raise RuntimeError - at signature(types.str(), returns=types.none()) + at signature(types.str(), returns=types.impossible()) def not_implemented_stub(msg): STDERR = 2 buf = rffi.str2charp(msg + '\n') From noreply at buildbot.pypy.org Tue Apr 30 11:35:16 2013 From: noreply at buildbot.pypy.org (fijal) Date: Tue, 30 Apr 2013 11:35:16 +0200 (CEST) Subject: [pypy-commit] pypy default: skip those tests Message-ID: <20130430093516.E04131C12A2@cobra.cs.uni-duesseldorf.de> Author: Maciej Fijalkowski Branch: Changeset: r63768:33bd2dbd04b2 Date: 2013-04-30 11:34 +0200 http://bitbucket.org/pypy/pypy/changeset/33bd2dbd04b2/ Log: skip those tests diff --git a/rpython/translator/cli/test/test_list.py b/rpython/translator/cli/test/test_list.py --- a/rpython/translator/cli/test/test_list.py +++ b/rpython/translator/cli/test/test_list.py @@ -13,6 +13,9 @@ def test_getitem_exc_2(self): py.test.skip('fixme!') + def test_reversed(self): + py.test.skip("unsupported") + def test_list_unsigned(self): def fn(x): lst = [r_uint(0), r_uint(1)] diff --git a/rpython/translator/jvm/test/test_list.py b/rpython/translator/jvm/test/test_list.py --- a/rpython/translator/jvm/test/test_list.py +++ b/rpython/translator/jvm/test/test_list.py @@ -15,6 +15,9 @@ def test_r_short_list(self): py.test.skip('fixme!') + def test_reversed(self): + py.test.skip("unsupported") + def test_zeroed_list(self): def fn(): lst = [0] * 16 diff --git a/rpython/translator/oosupport/test/test_treebuilder.py b/rpython/translator/oosupport/test/test_treebuilder.py --- a/rpython/translator/oosupport/test/test_treebuilder.py +++ b/rpython/translator/oosupport/test/test_treebuilder.py @@ -13,7 +13,7 @@ t = TranslationContext() t.buildannotator().build_types(func, argtypes) t.buildrtyper(type_system='ootype').specialize() - + if backendopt: backend_optimizations(t, merge_if_blocks=True) return t @@ -121,4 +121,5 @@ return interp.eval_graph(graph, args) class TestBuildTreeList(BuildTreeRtypingTest, BaseTestRlist): - pass + def test_reversed(self): + py.test.skip("unsupported on ootype") From noreply at buildbot.pypy.org Tue Apr 30 13:36:20 2013 From: noreply at buildbot.pypy.org (arigo) Date: Tue, 30 Apr 2013 13:36:20 +0200 (CEST) Subject: [pypy-commit] pypy default: Use only uints as keys in the jit_cells dict, rather than Message-ID: <20130430113620.68D581C13D5@cobra.cs.uni-duesseldorf.de> Author: Armin Rigo Branch: Changeset: r63769:2c3d5d1a6245 Date: 2013-04-30 13:38 +0200 http://bitbucket.org/pypy/pypy/changeset/2c3d5d1a6245/ Log: Use only uints as keys in the jit_cells dict, rather than a tuple (next_instr, is_being_profiled). Kill a deprecated method ("return False" is the default). diff --git a/pypy/module/pypyjit/interp_jit.py b/pypy/module/pypyjit/interp_jit.py --- a/pypy/module/pypyjit/interp_jit.py +++ b/pypy/module/pypyjit/interp_jit.py @@ -33,15 +33,16 @@ return '%s #%d %s' % (bytecode.get_repr(), next_instr, name) def get_jitcell_at(next_instr, is_being_profiled, bytecode): - return bytecode.jit_cells.get((next_instr, is_being_profiled), None) + # use only uints as keys in the jit_cells dict, rather than + # a tuple (next_instr, is_being_profiled) + key = (next_instr << 1) | r_uint(intmask(is_being_profiled)) + return bytecode.jit_cells.get(key, None) def set_jitcell_at(newcell, next_instr, is_being_profiled, bytecode): - bytecode.jit_cells[next_instr, is_being_profiled] = newcell + key = (next_instr << 1) | r_uint(intmask(is_being_profiled)) + bytecode.jit_cells[key] = newcell -def can_never_inline(next_instr, is_being_profiled, bytecode): - return False - def should_unroll_one_iteration(next_instr, is_being_profiled, bytecode): return (bytecode.co_flags & CO_GENERATOR) != 0 @@ -53,7 +54,6 @@ pypyjitdriver = PyPyJitDriver(get_printable_location = get_printable_location, get_jitcell_at = get_jitcell_at, set_jitcell_at = set_jitcell_at, - can_never_inline = can_never_inline, should_unroll_one_iteration = should_unroll_one_iteration, name='pypyjit') From noreply at buildbot.pypy.org Tue Apr 30 15:43:35 2013 From: noreply at buildbot.pypy.org (timfel) Date: Tue, 30 Apr 2013 15:43:35 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: FRAMEWORK ALL THE THINGS (related to codespeed and benchmarks) Message-ID: <20130430134335.754101C12A2@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: Changeset: r356:37a1dfe0e066 Date: 2013-04-30 15:42 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/37a1dfe0e066/ Log: FRAMEWORK ALL THE THINGS (related to codespeed and benchmarks) diff --git a/benchmarks.py b/benchmarks.py --- a/benchmarks.py +++ b/benchmarks.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- import os +import shutil import socket import subprocess import sys @@ -12,159 +13,201 @@ # You need to enter the real URL and have the server running CODESPEED_URL = 'http://speed.bithug.org/' -# Executables (assumed to be in the local directory) -executables = ["targetimageloadingsmalltalk-c", "coglinux/squeak"] -# Arguments (inserted between executable and benchmark) -executable_arguments = [ - ["images/%s.image" % SqueakImage, '-m', 'runSPyBenchmarks'], - ['-vm-display-X11', '-headless', "images/%s.image" % SqueakImage, '../benchmarks.st']] +class Project(object): + def __init__(self, name, executables={}, arguments="", commitid=None): + self.commitid = commitid if commitid else self.get_commitid() + self.name = name + self.executables = executables + self.arguments = arguments -def build_data(executable, benchmark, result): - # Mandatory fields - return { - 'commitid': COMMIT_ID, - 'branch': 'default', - 'project': 'lang-smalltalk', - 'executable': executable, - 'benchmark': benchmark, - 'environment': socket.gethostname(), - 'result_value': str(result), - } - # Optional fields - # { - # 'std_dev': 1.11111, # Optional. Default is blank - # 'max': 4001.6, # Optional. Default is blank - # 'min': 3995.1, # Optional. Default is blank - # } + def run(self): + for executable in self.executables: + yield executable.name, executable.run(self.arguments) + def post_results(self): + for executable, output in self.run(): + benchmarks = output.split('\n') + for s in benchmarks: + if ';' in s: + name, time = s.split(';') + self.add(executable, name, time) -def ungzip(url, name, target): - import gzip - zip_contents = urllib2.urlopen(url).read() - with open(name, "w") as f: - f.write(zip_contents) - f = gzip.open(name) - with open(target, "w") as s: - s.write(f.read()) + def add(self, executable, benchmark, result): + print "Saving result %s for executable %s, benchmark %s" % ( + result, executable, benchmark) + data = self.build_data(executable, benchmark, result) + params = urllib.urlencode(data) + response = "None" + print "Saving result for executable %s, revision %s, benchmark %s" % ( + data['executable'], data['commitid'], data['benchmark']) + try: + f = urllib2.urlopen(CODESPEED_URL + 'result/add/', params) + except urllib2.HTTPError as e: + print str(e) + print e.read() + return + response = f.read() + f.close() + print "Server (%s) response: %s\n" % (CODESPEED_URL, response) -def untar(name, target): - import tarfile - try: - f = tarfile.open(name) - f.extractall(target) - finally: - f.close() - -def download_prerequesites(): - clean_workspace() - print 'Downloading', - download_cog() - print 'done' - -def download_cog(): - if sys.platform == "win32": - url = "http://www.mirandabanda.org/files/Cog/VM/VM.r2714/cogwin-13.13.2714.zip" - unzip(url, 'cogwin.zip', '.') - else: - url = "http://www.mirandabanda.org/files/Cog/VM/VM.r2714/coglinux-13.13.2714.tgz" - print '.', - ungzip(url, 'coglinux.tgz', 'coglinux.tar') - print '.', - untar('coglinux.tar', '.') - -def clean_workspace(): - print 'Cleaning workspace', - for f in ["image.tgz", "image.tar", - 'coglinux.tgz', 'coglinux.tar', - 'cogwin.zip']: + def get_commitid(self): try: - os.remove(f) + pipe = subprocess.Popen( + ["hg", "log", "-l", "1", "--template", "{rev}:{node}"], + stdout=subprocess.PIPE + ) + if pipe.wait() == 0: + return pipe.stdout.read() except: pass - print '.', - for d in ['coglinux', 'cogwin']: try: - shutil.rmtree(d) + pipe = subprocess.Popen( + ["git", "log", "-1", "--pretty=%H"], + stdout=subprocess.PIPE + ) + if pipe.wait() == 0: + return pipe.stdout.read() except: pass - print '.', - print 'done' + raise Exception("commitid not found. not a git or hg repo") -def get_commitid(): - try: - pipe = subprocess.Popen( - ["hg", "log", "-l", "1", "--template", "{branch}-{rev}"], - stdout=subprocess.PIPE - ) - if pipe.wait() == 0: - return pipe.stdout.read() - except: - pass - try: - pipe = subprocess.Popen( - ["git", "log", "-1", "--pretty=%H"], - stdout=subprocess.PIPE - ) - if pipe.wait() == 0: - return pipe.stdout.read() - except: - pass - raise Exception("commitid not found. not a git or hg repo") + def build_data(self, executable, benchmark, result): + # Mandatory fields + return { + 'commitid': self.commitid, + 'branch': 'default', + 'project': self.name, + 'executable': executable, + 'benchmark': benchmark, + 'environment': socket.gethostname(), + 'result_value': str(result), + } + # Optional fields + # { + # 'std_dev': 1.11111, # Optional. Default is blank + # 'max': 4001.6, # Optional. Default is blank + # 'min': 3995.1, # Optional. Default is blank + # } -COMMIT_ID = None +class Archive(object): + def __init__(self, filename, target, func): + self.filename = filename + self.func = func + self.target = target -def add(executable, benchmark, result): - print "Saving result %s for executable %s, benchmark %s" % ( - result, executable, benchmark) - global COMMIT_ID - if COMMIT_ID is None: - COMMIT_ID = get_commitid() - data = build_data(executable, benchmark, result) - params = urllib.urlencode(data) - response = "None" - print "Saving result for executable %s, revision %s, benchmark %s" % ( - data['executable'], data['commitid'], data['benchmark']) - try: - f = urllib2.urlopen(CODESPEED_URL + 'result/add/', params) - except urllib2.HTTPError as e: - print str(e) - print e.read() - return - response = f.read() - f.close() - print "Server (%s) response: %s\n" % (CODESPEED_URL, response) + def extract(self): + self.func(self.filename, self.target) -def update_image(suffix): - with open('update.st', 'w') as f: - f.write('''Smalltalk snapshot: true andQuit: true.''') - pipe = subprocess.Popen( - ['coglinux/squeak%s -vm-display-X11 -headless images/%s ../update.st' % (suffix, SqueakImage)], - shell=True) - pipe.wait() - os.remove('update.st') + def __enter__(self): + self.extract() + def __exit__(self, *_): + if os.path.exists(self.target) and os.path.isfile(self.target): + os.remove(self.target) -def run(): - suffix = ".exe" if sys.platform == "win32" else "" - update_image(suffix) - for i, executable in enumerate(executables): +class Executable(object): + def __init__(self, name, path, url=None, callback=None): + self.name = name + self.path = path + if url: + self.download(url, callback=callback) + + def ungzip(self, source, target): + import gzip + contents = gzip.open(source).read() + with open(target, "w") as t: + t.write(contents) + + def untar(self, source, target): + import tarfile + try: + f = tarfile.open(source) + f.extractall(target) + finally: + f.close() + + def download(self, url, callback=None): + if os.path.exists(self.path): + shutil.rmtree(os.path.dirname(self.path)) + filename = url.rsplit("/", 1)[1] + if os.path.exists(filename): + os.remove(filename) + print "Downloading from", url + with open(filename, "w") as f: + f.write(urllib2.urlopen(url).read()) + try: + print "Extracting", filename + if filename.endswith(".tar.gz") or filename.endswith(".tgz"): + tarfile = os.path.basename(filename) + ".tar" + with Archive(filename, tarfile, self.ungzip): + Archive(tarfile, ".", self.untar).extract() + elif filename.endswith(".tar"): + Archive(filename, ".", self.untar).extract() + else: + raise NotImplementedError + finally: + os.remove(filename) + if callback: + callback(self) + + def run(self, args): print 'Calling %s ...' % executable pipe = subprocess.Popen( - ["./%s%s" % (executable, suffix)] + executable_arguments[i], + ["%s" % executable.path] + args, stdout=subprocess.PIPE ) out, err = pipe.communicate() errcode = pipe.wait() print out - benchmarks = out.split('\n') - for s in benchmarks: - if ';' in s: - name, time = s.split(';') - add(executable, name, time) + return out + + +# XXX: Find a better place to put this +def update_image(executable): + print "Updating image ..." + with open('update.st', 'w') as f: + f.write('''Smalltalk snapshot: true andQuit: true.''') + print executable.run(["-vm-display-X11", "-headless", "images/%s" % SqueakImage, "../update.st"]) + os.remove('update.st') + + +def find_cog_url(): + baseurl = "http://www.mirandabanda.org/files/Cog/VM/" + r = urllib2.urlopen(baseurl) + ver = r.read().rsplit("VM.r", 1)[1].split("/", 1)[0] + vmfolder = "%s/VM.r%s/" % (baseurl, ver) + r = urllib2.urlopen(vmfolder).read() + off = r.find("coglinux") + filename = r[off:r.find(".tgz", off)] + ".tgz" + return ver, vmfolder + filename +cogid, cogurl = find_cog_url() + + +Cog = Project( + "squeak", + executables=[ + Executable( + "cogvm", + "coglinux/squeak", + cogurl, + callback=update_image + ) + ], + arguments=['-vm-display-X11', '-headless', "images/%s.image" % SqueakImage, '../benchmarks.st'], + commitid=cogid +) +RSqueakVM = Project( + "lang-smalltalk", + executables=[ + Executable("targetimageloadingsmalltalk-c", "./targetimageloadingsmalltalk-c") + ], + arguments=["images/%s.image" % SqueakImage, '-m', 'runSPyBenchmarks'] +) + if __name__ == "__main__": - download_prerequesites() - run() + for project in [Cog, RSqueakVM]: + project.post_results() From noreply at buildbot.pypy.org Tue Apr 30 16:08:59 2013 From: noreply at buildbot.pypy.org (timfel) Date: Tue, 30 Apr 2013 16:08:59 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: fix benchmark script Message-ID: <20130430140859.B2B271C13E0@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: Changeset: r357:c9d95a10ca3c Date: 2013-04-30 16:08 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/c9d95a10ca3c/ Log: fix benchmark script diff --git a/benchmarks.py b/benchmarks.py --- a/benchmarks.py +++ b/benchmarks.py @@ -154,9 +154,9 @@ callback(self) def run(self, args): - print 'Calling %s ...' % executable + print 'Calling %s ...' % self.name pipe = subprocess.Popen( - ["%s" % executable.path] + args, + ["%s" % self.path] + args, stdout=subprocess.PIPE ) out, err = pipe.communicate() From noreply at buildbot.pypy.org Tue Apr 30 16:44:13 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Tue, 30 Apr 2013 16:44:13 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: added the StackVM, without automatically looking for new versions Message-ID: <20130430144413.AD9791C13D5@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r358:813b6f270b6c Date: 2013-04-30 16:42 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/813b6f270b6c/ Log: added the StackVM, without automatically looking for new versions diff --git a/benchmarks.py b/benchmarks.py --- a/benchmarks.py +++ b/benchmarks.py @@ -194,6 +194,12 @@ "coglinux/squeak", cogurl, callback=update_image + ), + Executable( + "stackvm", + "stackvm/bin/squeak", + "http://squeakvm.org/unix/release/Squeak-4.10.2.2614-linux_i386.tar.gz", + callback=(lambda x: subprocess.Popen(["mv", "Squeak-4.10.2.2614-linux_i386", "stackvm"]).wait()) ) ], arguments=['-vm-display-X11', '-headless', "images/%s.image" % SqueakImage, '../benchmarks.st'], From noreply at buildbot.pypy.org Tue Apr 30 16:44:15 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Tue, 30 Apr 2013 16:44:15 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: merge with tip Message-ID: <20130430144415.065BC1C13D5@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r359:60891eda87e3 Date: 2013-04-30 16:43 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/60891eda87e3/ Log: merge with tip diff --git a/benchmarks.py b/benchmarks.py --- a/benchmarks.py +++ b/benchmarks.py @@ -154,9 +154,9 @@ callback(self) def run(self, args): - print 'Calling %s ...' % executable + print 'Calling %s ...' % self.name pipe = subprocess.Popen( - ["%s" % executable.path] + args, + ["%s" % self.path] + args, stdout=subprocess.PIPE ) out, err = pipe.communicate() From noreply at buildbot.pypy.org Tue Apr 30 16:46:19 2013 From: noreply at buildbot.pypy.org (timfel) Date: Tue, 30 Apr 2013 16:46:19 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: short hash Message-ID: <20130430144619.4DB821C13D5@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: Changeset: r360:c46a4d25f6ea Date: 2013-04-30 16:44 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/c46a4d25f6ea/ Log: short hash diff --git a/benchmarks.py b/benchmarks.py --- a/benchmarks.py +++ b/benchmarks.py @@ -54,7 +54,7 @@ def get_commitid(self): try: pipe = subprocess.Popen( - ["hg", "log", "-l", "1", "--template", "{rev}:{node}"], + ["hg", "log", "-l", "1", "--template", "{rev}:{node|short}"], stdout=subprocess.PIPE ) if pipe.wait() == 0: From noreply at buildbot.pypy.org Tue Apr 30 16:46:20 2013 From: noreply at buildbot.pypy.org (timfel) Date: Tue, 30 Apr 2013 16:46:20 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: merge default Message-ID: <20130430144620.7BDF61C13D5@cobra.cs.uni-duesseldorf.de> Author: Tim Felgentreff Branch: Changeset: r361:d8c5396941c4 Date: 2013-04-30 16:45 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/d8c5396941c4/ Log: merge default diff --git a/benchmarks.py b/benchmarks.py --- a/benchmarks.py +++ b/benchmarks.py @@ -194,6 +194,12 @@ "coglinux/squeak", cogurl, callback=update_image + ), + Executable( + "stackvm", + "stackvm/bin/squeak", + "http://squeakvm.org/unix/release/Squeak-4.10.2.2614-linux_i386.tar.gz", + callback=(lambda x: subprocess.Popen(["mv", "Squeak-4.10.2.2614-linux_i386", "stackvm"]).wait()) ) ], arguments=['-vm-display-X11', '-headless', "images/%s.image" % SqueakImage, '../benchmarks.st'], From noreply at buildbot.pypy.org Tue Apr 30 17:29:49 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Tue, 30 Apr 2013 17:29:49 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: added possibilities to output "name; value; min; max\n" from squeak (instead of "name; value\n") thus enabeling tracking of multiple executions for every benchmark Message-ID: <20130430152949.53E711C12A2@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r362:d5d056861228 Date: 2013-04-30 17:28 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/d5d056861228/ Log: added possibilities to output "name;value;min;max\n" from squeak (instead of "name;value\n") thus enabeling tracking of multiple executions for every benchmark diff --git a/benchmarks.py b/benchmarks.py --- a/benchmarks.py +++ b/benchmarks.py @@ -30,13 +30,19 @@ benchmarks = output.split('\n') for s in benchmarks: if ';' in s: - name, time = s.split(';') - self.add(executable, name, time) + results = s.split(';') + if len(results) == 2: + self.add(executable, *results) + elif len(results) == 4: + self.add(executble, *results) - def add(self, executable, benchmark, result): + def add(self, executable, benchmark, result, min=None, max=None): print "Saving result %s for executable %s, benchmark %s" % ( result, executable, benchmark) - data = self.build_data(executable, benchmark, result) + if min is max is None: + data = self.build_data(executable, benchmark, result) + else: + data = self.build_extended_data(executable, benchmark, result, min, max) params = urllib.urlencode(data) response = "None" print "Saving result for executable %s, revision %s, benchmark %s" % ( @@ -89,7 +95,13 @@ # 'max': 4001.6, # Optional. Default is blank # 'min': 3995.1, # Optional. Default is blank # } - + def build_data_extended(self, executable, benchmark, result, min, max): + return dict(self.build_data(executable, benchmark, result), + **{ + 'min': str(min), + 'max': str(max) + } + ) class Archive(object): def __init__(self, filename, target, func): From noreply at buildbot.pypy.org Tue Apr 30 17:29:50 2013 From: noreply at buildbot.pypy.org (lwassermann) Date: Tue, 30 Apr 2013 17:29:50 +0200 (CEST) Subject: [pypy-commit] lang-smalltalk default: merge tip Message-ID: <20130430152950.834B01C13E5@cobra.cs.uni-duesseldorf.de> Author: Lars Wassermann Branch: Changeset: r363:8a6c4d9be439 Date: 2013-04-30 17:29 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/8a6c4d9be439/ Log: merge tip diff --git a/benchmarks.py b/benchmarks.py --- a/benchmarks.py +++ b/benchmarks.py @@ -60,7 +60,7 @@ def get_commitid(self): try: pipe = subprocess.Popen( - ["hg", "log", "-l", "1", "--template", "{rev}:{node}"], + ["hg", "log", "-l", "1", "--template", "{rev}:{node|short}"], stdout=subprocess.PIPE ) if pipe.wait() == 0: From noreply at buildbot.pypy.org Tue Apr 30 17:43:12 2013 From: noreply at buildbot.pypy.org (bivab) Date: Tue, 30 Apr 2013 17:43:12 +0200 (CEST) Subject: [pypy-commit] pypy default: get size of long double using rfficache instead of ctypes.sizeof Message-ID: <20130430154312.5D9D11C12A2@cobra.cs.uni-duesseldorf.de> Author: David Schneider Branch: Changeset: r63770:b7810d45dff1 Date: 2013-04-30 17:41 +0200 http://bitbucket.org/pypy/pypy/changeset/b7810d45dff1/ Log: get size of long double using rfficache instead of ctypes.sizeof diff --git a/rpython/rtyper/lltypesystem/rffi.py b/rpython/rtyper/lltypesystem/rffi.py --- a/rpython/rtyper/lltypesystem/rffi.py +++ b/rpython/rtyper/lltypesystem/rffi.py @@ -934,8 +934,8 @@ if tp is lltype.SingleFloat: return 4 if tp is lltype.LongFloat: - import ctypes # :-/ - return ctypes.sizeof(ctypes.c_longdouble) + # :-/ + return sizeof_c_type("long double") assert isinstance(tp, lltype.Number) if tp is lltype.Signed: return LONG_BIT/8 From noreply at buildbot.pypy.org Tue Apr 30 22:37:24 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Tue, 30 Apr 2013 22:37:24 +0200 (CEST) Subject: [pypy-commit] pypy py3k: fix mistaken changes from a609f7a7a5fa Message-ID: <20130430203724.91D071C1260@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63771:22b213574ebb Date: 2013-04-30 11:52 -0700 http://bitbucket.org/pypy/pypy/changeset/22b213574ebb/ Log: fix mistaken changes from a609f7a7a5fa diff --git a/pypy/module/_continuation/test/test_zpickle.py b/pypy/module/_continuation/test/test_zpickle.py --- a/pypy/module/_continuation/test/test_zpickle.py +++ b/pypy/module/_continuation/test/test_zpickle.py @@ -188,7 +188,7 @@ def test_pickle_continulet_real(self): import types, sys - mod = types.ModuleType('test_copy_continulet_real') + mod = types.ModuleType('test_pickle_continulet_real') sys.modules['test_pickle_continulet_real'] = mod mod.version = self.version exec('''if 1: @@ -222,7 +222,7 @@ def test_pickle_continulet_real_subclass(self): import types, sys - mod = types.ModuleType('test_copy_continulet_real_subclass') + mod = types.ModuleType('test_pickle_continulet_real_subclass') sys.modules['test_pickle_continulet_real_subclass'] = mod mod.version = self.version exec('''if 1: From noreply at buildbot.pypy.org Tue Apr 30 22:37:25 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Tue, 30 Apr 2013 22:37:25 +0200 (CEST) Subject: [pypy-commit] pypy py3k: apply the function pickling extras from default, fixes all but 1 of the Message-ID: <20130430203725.E1D361C1260@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63772:0b9904f7bb80 Date: 2013-04-30 11:53 -0700 http://bitbucket.org/pypy/pypy/changeset/0b9904f7bb80/ Log: apply the function pickling extras from default, fixes all but 1 of the outstanding pickle py3k_skips diff --git a/lib-python/3/pickle.py b/lib-python/3/pickle.py --- a/lib-python/3/pickle.py +++ b/lib-python/3/pickle.py @@ -25,7 +25,7 @@ __version__ = "$Revision$" # Code version -from types import FunctionType, BuiltinFunctionType +from types import FunctionType, BuiltinFunctionType, ModuleType from copyreg import dispatch_table from copyreg import _extension_registry, _inverted_registry, _extension_cache import marshal @@ -615,7 +615,27 @@ write(APPEND) # else tmp is empty, and we're done + def _pickle_maybe_moduledict(self, obj): + # save module dictionary as "getattr(module, '__dict__')" + try: + name = obj['__name__'] + if type(name) is not str: + return None + themodule = sys.modules[name] + if type(themodule) is not ModuleType: + return None + if themodule.__dict__ is not obj: + return None + except (AttributeError, KeyError, TypeError): + return None + + return getattr, (themodule, '__dict__') + def save_dict(self, obj): + modict_saver = self._pickle_maybe_moduledict(obj) + if modict_saver is not None: + return self.save_reduce(*modict_saver) + write = self.write if self.bin: @@ -666,6 +686,35 @@ write(SETITEM) # else tmp is empty, and we're done + def save_function(self, obj): + lasterr = None + try: + return self.save_global(obj) + except PicklingError as e: + lasterr = e + try: + # Check copy_reg.dispatch_table + reduce = dispatch_table.get(type(obj)) + if reduce: + rv = reduce(obj) + else: + # Check for a __reduce_ex__ method, fall back to + # __reduce__ + reduce = getattr(obj, "__reduce_ex__", None) + if reduce: + rv = reduce(self.proto) + else: + reduce = getattr(obj, "__reduce__", None) + if reduce: + rv = reduce() + else: + raise last_exc + return self.save_reduce(obj=obj, *rv) + finally: + if lasterr is not None: + del lasterr + dispatch[FunctionType] = save_function + def save_global(self, obj, name=None, pack=struct.pack): write = self.write memo = self.memo @@ -722,7 +771,6 @@ self.memoize(obj) - dispatch[FunctionType] = save_global dispatch[BuiltinFunctionType] = save_global dispatch[type] = save_global diff --git a/pypy/interpreter/test/test_zzpickle_and_slow.py b/pypy/interpreter/test/test_zzpickle_and_slow.py --- a/pypy/interpreter/test/test_zzpickle_and_slow.py +++ b/pypy/interpreter/test/test_zzpickle_and_slow.py @@ -125,7 +125,6 @@ assert map is result def test_pickle_non_top_reachable_func(self): - py3k_skip("not supported yet") def func(): return 42 global a @@ -157,7 +156,6 @@ assert not (cell != result) def test_pickle_frame(self): - py3k_skip("not supported yet") #import sys # avoid creating a closure for now def f(): @@ -189,7 +187,6 @@ assert f1.f_trace is f2.f_trace def test_pickle_frame_with_exc(self): - py3k_skip("not supported yet") #import sys # avoid creating a closure for now self = None @@ -211,7 +208,6 @@ assert read_exc_type(f2) is ValueError def test_pickle_frame_clos(self): - py3k_skip("not supported yet") # similar to above, therefore skipping the asserts. # we just want to see that the closure works import sys # this is the difference! @@ -229,7 +225,6 @@ f2 = pickle.loads(pckl) def test_pickle_traceback(self): - py3k_skip("not supported yet") def f(): try: raise Exception() @@ -258,7 +253,6 @@ assert mod is result def test_pickle_moduledict(self): - py3k_skip("not supported yet") import pickle moddict = pickle.__dict__ pckl = pickle.dumps(moddict) @@ -289,7 +283,6 @@ assert a == result def test_pickle_method(self): - py3k_skip("not supported yet") class myclass(object): def f(self): return 42 @@ -311,7 +304,6 @@ del sys.modules['mod'] def test_pickle_staticmethod(self): - py3k_skip("not supported yet") class myclass(object): def f(): return 42 @@ -323,7 +315,6 @@ assert method() == result() def test_pickle_classmethod(self): - py3k_skip("not supported yet") class myclass(object): def f(cls): return cls @@ -404,9 +395,8 @@ assert list(e) == list(result) def test_pickle_xrangeiter(self): - py3k_skip("not supported yet") import pickle - riter = iter(xrange(5)) + riter = iter(range(5)) next(riter) next(riter) pckl = pickle.dumps(riter) @@ -415,7 +405,6 @@ assert list(result) == [2,3,4] def test_pickle_generator(self): - py3k_skip("not supported yet") import types mod = types.ModuleType('mod') import sys @@ -439,7 +428,6 @@ del sys.modules['mod'] def test_pickle_generator_blk(self): - py3k_skip("not supported yet") # same as above but with the generator inside a block import types mod = types.ModuleType('mod') diff --git a/pypy/module/_continuation/test/test_zpickle.py b/pypy/module/_continuation/test/test_zpickle.py --- a/pypy/module/_continuation/test/test_zpickle.py +++ b/pypy/module/_continuation/test/test_zpickle.py @@ -6,9 +6,6 @@ continuation=True, CALL_METHOD=True) - def setup_class(cls): - py.test.py3k_skip("_continuation not supported yet") - def test_basic_setup(self): from _continuation import continulet lst = [4] @@ -113,7 +110,6 @@ } def setup_class(cls): - py.test.py3k_skip("_continuation not supported yet") cls.space.appexec([], """(): global continulet, A, __name__ From noreply at buildbot.pypy.org Tue Apr 30 22:37:27 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Tue, 30 Apr 2013 22:37:27 +0200 (CEST) Subject: [pypy-commit] pypy py3k: skip the rest of the strategy tests for now Message-ID: <20130430203727.7BB611C1260@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63773:2db1e0a806e2 Date: 2013-04-30 13:33 -0700 http://bitbucket.org/pypy/pypy/changeset/2db1e0a806e2/ Log: skip the rest of the strategy tests for now diff --git a/pypy/module/__pypy__/test/test_special.py b/pypy/module/__pypy__/test/test_special.py --- a/pypy/module/__pypy__/test/test_special.py +++ b/pypy/module/__pypy__/test/test_special.py @@ -75,6 +75,7 @@ assert x == 42 def test_list_strategy(self): + py3k_skip("XXX: strategies are currently broken") from __pypy__ import list_strategy l = [1, 2, 3] diff --git a/pypy/objspace/std/test/test_dictmultiobject.py b/pypy/objspace/std/test/test_dictmultiobject.py --- a/pypy/objspace/std/test/test_dictmultiobject.py +++ b/pypy/objspace/std/test/test_dictmultiobject.py @@ -126,6 +126,7 @@ assert self.space.eq_w(space.call_function(get, w("33"), w(44)), w(44)) def test_fromkeys_fastpath(self): + py.test.py3k_skip("XXX: strategies are currently broken") space = self.space w = space.wrap wb = space.wrapbytes @@ -138,6 +139,7 @@ assert space.eq_w(w_d.getitem_str("b"), space.w_None) def test_listview_str_dict(self): + py.test.py3k_skip("XXX: strategies are currently broken") w = self.space.wrap wb = self.space.wrapbytes w_d = self.space.newdict() @@ -158,6 +160,7 @@ assert self.space.listview_int(w_d) == [1, 2] def test_keys_on_string_unicode_int_dict(self, monkeypatch): + py.test.py3k_skip("XXX: strategies are currently broken") w = self.space.wrap wb = self.space.wrapbytes @@ -1292,6 +1295,7 @@ assert s.unwrapped def test_view_as_kwargs(self): + py.test.py3k_skip("XXX: strategies are currently broken") self.fill_impl() assert self.fakespace.view_as_kwargs(self.impl) == (["fish", "fish2"], [1000, 2000]) @@ -1312,6 +1316,7 @@ def test_module_uses_strdict(): + py.test.py3k_skip("XXX: strategies are currently broken") fakespace = FakeSpace() d = fakespace.newdict(module=True) assert type(d.strategy) is StringDictStrategy diff --git a/pypy/objspace/std/test/test_identitydict.py b/pypy/objspace/std/test/test_identitydict.py --- a/pypy/objspace/std/test/test_identitydict.py +++ b/pypy/objspace/std/test/test_identitydict.py @@ -1,6 +1,8 @@ import py from pypy.interpreter.gateway import interp2app +py.test.py3k_skip("XXX: strategies are currently broken") + class AppTestComparesByIdentity: spaceconfig = {"objspace.std.withidentitydict": True} diff --git a/pypy/objspace/std/test/test_kwargsdict.py b/pypy/objspace/std/test/test_kwargsdict.py --- a/pypy/objspace/std/test/test_kwargsdict.py +++ b/pypy/objspace/std/test/test_kwargsdict.py @@ -149,6 +149,7 @@ assert sorted(f(a=2, b=3).itervalues()) == [2, 3] def test_setdefault(self): + py3k_skip("XXX: strategies are currently broken") def f(**args): return args d = f(a=1, b=2) diff --git a/pypy/objspace/std/test/test_listobject.py b/pypy/objspace/std/test/test_listobject.py --- a/pypy/objspace/std/test/test_listobject.py +++ b/pypy/objspace/std/test/test_listobject.py @@ -401,6 +401,7 @@ self.space.w_True) def test_sizehint(self): + py.test.py3k_skip("XXX: strategies are currently broken") space = self.space w_l = space.newlist([], sizehint=10) assert isinstance(w_l.strategy, SizeListStrategy) @@ -417,6 +418,7 @@ assert w_lst.strategy.sizehint == 13 def test_find_fast_on_intlist(self, monkeypatch): + py.test.py3k_skip("XXX: strategies are currently broken") monkeypatch.setattr(self.space, "eq_w", None) w = self.space.wrap intlist = W_ListObject(self.space, [w(1),w(2),w(3),w(4),w(5),w(6),w(7)]) diff --git a/pypy/objspace/std/test/test_liststrategies.py b/pypy/objspace/std/test/test_liststrategies.py --- a/pypy/objspace/std/test/test_liststrategies.py +++ b/pypy/objspace/std/test/test_liststrategies.py @@ -4,6 +4,8 @@ from pypy.objspace.std import listobject from pypy.objspace.std.test.test_listobject import TestW_ListObject +py.test.py3k_skip("XXX: strategies are currently broken") + class TestW_ListStrategies(TestW_ListObject): def test_check_strategy(self): diff --git a/pypy/objspace/std/test/test_setobject.py b/pypy/objspace/std/test/test_setobject.py --- a/pypy/objspace/std/test/test_setobject.py +++ b/pypy/objspace/std/test/test_setobject.py @@ -87,6 +87,7 @@ assert space.is_true(self.space.eq(result, W_SetObject(space, self.space.wrap("")))) def test_create_set_from_list(self): + py.test.py3k_skip("XXX: strategies are currently broken") from pypy.objspace.std.setobject import ObjectSetStrategy, UnicodeSetStrategy from pypy.objspace.std.floatobject import W_FloatObject from pypy.objspace.std.model import W_Object @@ -133,7 +134,7 @@ intstr.get_storage_from_list = tmp_func def test_listview_str_int_on_set(self): - py.test.skip("listview_str not supported for py3k strings (i.e., unicode)") + py.test.py3k_skip("XXX: strategies are currently broken") w = self.space.wrap w_a = W_SetObject(self.space) diff --git a/pypy/objspace/std/test/test_setstrategies.py b/pypy/objspace/std/test/test_setstrategies.py --- a/pypy/objspace/std/test/test_setstrategies.py +++ b/pypy/objspace/std/test/test_setstrategies.py @@ -7,6 +7,9 @@ UnicodeIteratorImplementation) from pypy.objspace.std.listobject import W_ListObject +import py +py.test.py3k_skip("XXX: strategies are currently broken") + class TestW_SetStrategies: def wrapped(self, l, bytes=False): From noreply at buildbot.pypy.org Tue Apr 30 22:50:05 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Tue, 30 Apr 2013 22:50:05 +0200 (CEST) Subject: [pypy-commit] pypy py3k: loosen the str cmp to fix test_methodcache's test_many_names. py3k likely Message-ID: <20130430205005.680471C0334@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63774:25e7ce4956dd Date: 2013-04-30 13:49 -0700 http://bitbucket.org/pypy/pypy/changeset/25e7ce4956dd/ Log: loosen the str cmp to fix test_methodcache's test_many_names. py3k likely doesn't intern the names as often as default since they're originally unicode, but default doesn't always intern every name either IIRC diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py --- a/pypy/objspace/std/typeobject.py +++ b/pypy/objspace/std/typeobject.py @@ -392,7 +392,7 @@ cached_version_tag = cache.versions[method_hash] if cached_version_tag is version_tag: cached_name = cache.names[method_hash] - if cached_name is name: + if cached_name == name: tup = cache.lookup_where[method_hash] if space.config.objspace.std.withmethodcachecounter: cache.hits[name] = cache.hits.get(name, 0) + 1 From noreply at buildbot.pypy.org Tue Apr 30 22:56:44 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Tue, 30 Apr 2013 22:56:44 +0200 (CEST) Subject: [pypy-commit] pypy py3k: test against py3's pow behavior Message-ID: <20130430205644.9A3F81C1260@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63775:c0a21ffcbb97 Date: 2013-04-30 13:55 -0700 http://bitbucket.org/pypy/pypy/changeset/c0a21ffcbb97/ Log: test against py3's pow behavior diff --git a/pypy/objspace/std/test/test_floatobject.py b/pypy/objspace/std/test/test_floatobject.py --- a/pypy/objspace/std/test/test_floatobject.py +++ b/pypy/objspace/std/test/test_floatobject.py @@ -26,10 +26,8 @@ assert v.floatval == x ** y f1 = fobj.W_FloatObject(-1.23) f2 = fobj.W_FloatObject(-4.56) - self.space.raises_w(self.space.w_ValueError, - fobj.pow__Float_Float_ANY, - self.space, f1, f2, - self.space.w_None) + v = fobj.pow__Float_Float_ANY(self.space, f1, f2, self.space.w_None) + assert self.space.isinstance_w(v, self.space.w_complex) x = -10 y = 2.0 f1 = fobj.W_FloatObject(x) @@ -218,7 +216,7 @@ assert espeq(pw(4.0, 0.5), 2.0) assert pw(4.0, 0) == 1.0 assert pw(-4.0, 0) == 1.0 - raises(ValueError, pw, -1.0, 0.5) + assert type(pw(-1.0, 0.5)) == complex assert pw(-1.0, 2.0) == 1.0 assert pw(-1.0, 3.0) == -1.0 assert pw(-1.0, 1e200) == 1.0 From noreply at buildbot.pypy.org Tue Apr 30 23:30:27 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Tue, 30 Apr 2013 23:30:27 +0200 (CEST) Subject: [pypy-commit] pypy py3k: switch to py3 behavior Message-ID: <20130430213027.E15DE1C0246@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63776:49b50e7a7d05 Date: 2013-04-30 14:28 -0700 http://bitbucket.org/pypy/pypy/changeset/49b50e7a7d05/ Log: switch to py3 behavior diff --git a/pypy/module/cmath/test/test_cmath.py b/pypy/module/cmath/test/test_cmath.py --- a/pypy/module/cmath/test/test_cmath.py +++ b/pypy/module/cmath/test/test_cmath.py @@ -21,8 +21,8 @@ import math z = eval("-0j") assert z == -0j - assert math.copysign(1., z.real) == 1. - assert math.copysign(1., z.imag) == -1. + assert math.copysign(1., z.real) == -1.0 + assert math.copysign(1., z.imag) == -1.0 def test_sqrt(self): import cmath, math From noreply at buildbot.pypy.org Tue Apr 30 23:46:48 2013 From: noreply at buildbot.pypy.org (pjenvey) Date: Tue, 30 Apr 2013 23:46:48 +0200 (CEST) Subject: [pypy-commit] pypy py3k: quiet a warning Message-ID: <20130430214648.D74F41C0334@cobra.cs.uni-duesseldorf.de> Author: Philip Jenvey Branch: py3k Changeset: r63777:1640a73b7e8d Date: 2013-04-30 14:42 -0700 http://bitbucket.org/pypy/pypy/changeset/1640a73b7e8d/ Log: quiet a warning diff --git a/pypy/module/_codecs/locale.c b/pypy/module/_codecs/locale.c --- a/pypy/module/_codecs/locale.c +++ b/pypy/module/_codecs/locale.c @@ -4,6 +4,7 @@ /* #include "Python.h" */ +#include #include #include #include