churchyard pushed to pypy3 (master). "1.7 (..more)"

notifications at fedoraproject.org notifications at fedoraproject.org
Sun May 10 14:23:49 UTC 2015


From 4ef3f10721000d632a9dcfcfca05c7cde0f91b95 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm at redhat.com>
Date: Tue, 22 Nov 2011 11:30:49 -0500
Subject: 1.7

* Mon Nov 21 2011 David Malcolm <dmalcolm at redhat.com> - 1.7-1
- 1.7: refresh patch 0 (configuration) and patch 4 (readability of generated
code)

diff --git a/.gitignore b/.gitignore
index ecd135f..99af398 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
 /pypy-1.4.1-src.tar.bz2
 /pypy-1.5-src.tar.bz2
 /release-1.6.tar.bz2
+/release-1.7.tar.bz2
diff --git a/config.patch b/config.patch
new file mode 100644
index 0000000..afd7a7d
--- /dev/null
+++ b/config.patch
@@ -0,0 +1,49 @@
+diff -up pypy-pypy-release-1.7/pypy/translator/platform/linux.py.configure-fedora pypy-pypy-release-1.7/pypy/translator/platform/linux.py
+--- pypy-pypy-release-1.7/pypy/translator/platform/linux.py.configure-fedora	2011-11-19 02:44:54.000000000 -0500
++++ pypy-pypy-release-1.7/pypy/translator/platform/linux.py	2011-11-21 13:07:03.454240019 -0500
+@@ -1,15 +1,21 @@
+ """Support for Linux."""
+ 
++import os
+ import sys
+ from pypy.translator.platform.posix import BasePosix
+ 
++CFLAGS = ['-O3', '-pthread', '-fomit-frame-pointer',
++          '-Wall', '-Wno-unused']
++if os.environ.get('CFLAGS', None):
++    CFLAGS.extend(os.environ['CFLAGS'].split())
++CFLAGS = tuple(CFLAGS)
++
+ class BaseLinux(BasePosix):
+     name = "linux"
+     
+     link_flags = ('-pthread',)
+     extra_libs = ('-lrt',)
+-    cflags = ('-O3', '-pthread', '-fomit-frame-pointer',
+-              '-Wall', '-Wno-unused')
++    cflags = CFLAGS
+     standalone_only = ()
+     shared_only = ('-fPIC',)
+     so_ext = 'so'
+@@ -26,13 +32,14 @@ class BaseLinux(BasePosix):
+         return self._pkg_config("libffi", "--libs-only-L",
+                                 ['/usr/lib/libffi'])
+ 
+-    def library_dirs_for_libffi_a(self):
+-        # places where we need to look for libffi.a
+-        # XXX obscuuure!  only look for libffi.a if run with translate.py
+-        if 'translate' in sys.modules:
+-            return self.library_dirs_for_libffi() + ['/usr/lib']
+-        else:
+-            return []
++    # Fedora, at least, has the shared version but not the static:
++    #def library_dirs_for_libffi_a(self):
++    #    # places where we need to look for libffi.a
++    #    # XXX obscuuure!  only look for libffi.a if run with translate.py
++    #    if 'translate' in sys.modules:
++    #        return self.library_dirs_for_libffi() + ['/usr/lib']
++    #    else:
++    #        return []
+ 
+ 
+ class Linux(BaseLinux):
diff --git a/more-readable-c-code.patch b/more-readable-c-code.patch
new file mode 100644
index 0000000..92d340f
--- /dev/null
+++ b/more-readable-c-code.patch
@@ -0,0 +1,693 @@
+diff -up pypy-pypy-release-1.7/pypy/interpreter/pycode.py.more-readable-c-code pypy-pypy-release-1.7/pypy/interpreter/pycode.py
+--- pypy-pypy-release-1.7/pypy/interpreter/pycode.py.more-readable-c-code	2011-11-19 02:44:54.000000000 -0500
++++ pypy-pypy-release-1.7/pypy/interpreter/pycode.py	2011-11-21 16:16:15.673463780 -0500
+@@ -13,6 +13,7 @@ from pypy.interpreter.gateway import Non
+ from pypy.interpreter.astcompiler.consts import (
+     CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS, CO_NESTED,
+     CO_GENERATOR, CO_CONTAINSGLOBALS)
++from pypy.interpreter.pytraceback import offset2lineno
+ from pypy.rlib.rarithmetic import intmask
+ from pypy.rlib.debug import make_sure_not_resized
+ from pypy.rlib import jit
+@@ -81,6 +82,7 @@ class PyCode(eval.Code):
+         self.hidden_applevel = hidden_applevel
+         self.magic = magic
+         self._signature = cpython_code_signature(self)
++        self._cached_source = None
+         self._initialize()
+ 
+     def _initialize(self):
+@@ -397,3 +399,23 @@ class PyCode(eval.Code):
+ 
+     def repr(self, space):
+         return space.wrap(self.get_repr())
++
++    def get_linenum_for_offset(self, offset):
++        # Given a bytecode offset, return a 1-based index into the lines of the
++        # source code
++        return offset2lineno(self, offset)
++
++    def _ensure_source(self):
++        # Lazily grab the source lines into self._cached_source (or raise
++        # an IOError)
++        if not self._cached_source:
++            f = open(self.co_filename, 'r')
++            source = [line.rstrip() for line in f.readlines()]
++            f.close()
++            self._cached_source = source
++    
++    def get_source_text(self, linenum):
++        # Given a 1-based index, get the corresponding line of source code (or
++        # raise an IOError)
++        self._ensure_source()
++        return self._cached_source[linenum - 1]
+diff -up pypy-pypy-release-1.7/pypy/objspace/flow/model.py.more-readable-c-code pypy-pypy-release-1.7/pypy/objspace/flow/model.py
+--- pypy-pypy-release-1.7/pypy/objspace/flow/model.py.more-readable-c-code	2011-11-19 02:44:54.000000000 -0500
++++ pypy-pypy-release-1.7/pypy/objspace/flow/model.py	2011-11-21 16:15:36.599466455 -0500
+@@ -31,6 +31,120 @@ from pypy.tool.identity_dict import iden
+ 
+ __metaclass__ = type
+ 
++class SourceLoc(object):
++    # A srcloc is a specific location within the RPython source code,
++    # intended for human display
++    __slots__ = ('code', # code object
++                 'linenum' # 1-based index, as displayed to a user
++                 )
++    def __init__(self, code, linenum):
++        self.code = code
++        self.linenum = linenum
++
++    def get_text(self):
++        # Get the actual source text of this line
++        return self.code.get_source_text(self.linenum)
++
++    def __eq__(self, other):
++        return self.code == other.code and self.linenum == other.linenum
++
++    def __ne__(self, other):
++        if other:
++            return self.code != other.code or self.linenum != other.linenum
++        else:
++            return True
++
++class CodeLoc(object):
++    # A codeloc is a specific location within the RPython bytecode
++    __slots__ = ('code', # code object
++                 'offset' # int index into bytecode, or -1
++                 )
++
++    def __init__(self, code, offset):
++        self.code = code
++        self.offset = offset
++
++    def __str__(self):
++        if self.offset >= 0:
++            return "%s@%d" % (self.code.co_name, self.offset)
++        else:
++            return ""
++
++    def __ne__(self, other):
++        if other:
++            return self.code != other.code or self.offset != other.offset
++        else:
++            return True
++
++    def __cmp__(self, other):
++        # Partial ordering, for those locations that have an offset:
++        if other:
++            if self.offset >= 0 and other.offset >= 0:
++                return self.offset - other.offset
++        return 0
++
++    def get_source_loc(self):
++        # Convert to a SourceLoc:
++        return SourceLoc(self.code, self.code.get_linenum_for_offset(self.offset))
++
++class OperationLoc(object):
++    # An oploc is the location within the RPython source code of a given
++    # operation
++    # 
++    # This is a list consisting of CodeLoc instances, some of which may be None
++    #
++    # For the simple case, this is list of length 1 with a single CodeLoc
++    #
++    # For an operation inside an inlined callsite, we have a list of length 2:
++    #    [codeloc of callsite,
++    #     codeloc of operation within inlined body]
++    #
++    # For more interesting inlined cases, we have a chain of source locations:
++    #    [codeloc of callsite,
++    #     codeloc of inner callsite,
++    #     ... ,
++    #     codeloc of innermost inlined callsite,
++    #     codeloc of operation within inlined body]
++    #
++
++    __slots__ = ('codelocs', )
++
++    def __init__(self, codelocs):
++        self.codelocs = codelocs
++
++    def __str__(self):
++        return '[' + ' > '.join(str(codeloc) for codeloc in self.codelocs) + ']'
++
++    def __cmp__(self, other):
++        return cmp(self.codelocs, other.codelocs)
++
++def block_comparator(blk0, blk1):
++    '''
++    Sort function for blocks, putting them in an ordering that attempts to
++    maximize readability of the generated C code
++    '''
++    # print 'comparing %r and %r' % (blk0, blk1)
++    # Put the start/end block at the top/bottom:
++    if blk0.isstartblock:
++        return -1
++
++    if blk1.isstartblock:
++        return 1
++
++    # Order blocks by the offset, where present:
++    if blk0.operations:
++        if blk1.operations:
++            return cmp(blk0.operations[0].oploc, blk1.operations[0].oploc)
++        else:
++            return -1
++    else:
++        if blk1.operations:
++            return 1
++        else:
++            return 0
++
++def edge_comparator(edge0, edge1):
++    return block_comparator(edge0.target, edge1.target)
+ 
+ class FunctionGraph(object):
+     __slots__ = ['startblock', 'returnblock', 'exceptblock', '__dict__']
+@@ -94,6 +208,21 @@ class FunctionGraph(object):
+                 seen[block] = True
+                 stack += block.exits[::-1]
+ 
++    def iterblocks_by_source(self):
++        # Try to preserve logical source ordering in the blocks
++        block = self.startblock
++        yield block
++        seen = {block: True}
++        stack = list(block.exits[::-1])
++        stack.sort(edge_comparator)
++        while stack:
++            block = stack.pop().target
++            if block not in seen:
++                yield block
++                seen[block] = True
++                stack += block.exits[::-1]
++                stack.sort(edge_comparator)
++
+     def iterlinks(self):
+         block = self.startblock
+         seen = {block: True}
+@@ -183,14 +312,14 @@ class Block(object):
+         self.exits      = []              # list of Link(s)
+ 
+     def at(self):
+-        if self.operations and self.operations[0].offset >= 0:
+-            return "@%d" % self.operations[0].offset
++        if self.operations:
++            return str(self.operations[0].oploc)
+         else:
+             return ""
+ 
+     def __str__(self):
+         if self.operations:
+-            txt = "block@%d" % self.operations[0].offset
++            txt = "block%s" % self.operations[0].oploc
+         else:
+             if (not self.exits) and len(self.inputargs) == 1:
+                 txt = "return block"
+@@ -245,6 +374,21 @@ class Block(object):
+         from pypy.translator.tool.graphpage import try_show
+         try_show(self)
+ 
++    def isreturnblock(self):
++        return (not self.operations) and (not self.exits) and len(self.inputargs) == 1
++
++    def get_base_label(self, blocknum):
++        # Generate a more friendly C label for this block
++        if self.operations:
++            txt = "block"
++        elif (not self.exits) and len(self.inputargs) == 1:
++            txt = "return_block"
++        elif (not self.exits) and len(self.inputargs) == 2:
++            txt = "raise_block"
++        else:
++            txt = "codeless_block"
++        return '%s%d' % (txt, blocknum)
++
+ 
+ class Variable(object):
+     __slots__ = ["_name", "_nr", "concretetype"]
+@@ -331,13 +475,15 @@ class WrapException(Exception):
+ 
+ 
+ class SpaceOperation(object):
+-    __slots__ = "opname args result offset".split()
++    __slots__ = "opname args result oploc".split()
+ 
+-    def __init__(self, opname, args, result, offset=-1):
++    def __init__(self, opname, args, result, oploc=None):
+         self.opname = intern(opname)      # operation name
+         self.args   = list(args)  # mixed list of var/const
+         self.result = result      # either Variable or Constant instance
+-        self.offset = offset      # offset in code string
++        if oploc is None:
++            oploc = OperationLoc([None])
++        self.oploc = oploc
+ 
+     def __eq__(self, other):
+         return (self.__class__ is other.__class__ and 
+@@ -352,8 +498,9 @@ class SpaceOperation(object):
+         return hash((self.opname,tuple(self.args),self.result))
+ 
+     def __repr__(self):
+-        return "%r = %s(%s)" % (self.result, self.opname,
+-                                ", ".join(map(repr, self.args)))
++        return "%r = %s(%s) (%s)" % (self.result, self.opname,
++                                     ", ".join(map(repr, self.args)),
++                                     self.oploc)
+ 
+ class Atom(object):
+     def __init__(self, name):
+@@ -427,8 +574,7 @@ def copygraph(graph, shallow=False, varm
+                 for op in oplist:
+                     copyop = SpaceOperation(op.opname,
+                                             [copyvar(v) for v in op.args],
+-                                            copyvar(op.result), op.offset)
+-                    #copyop.offset = op.offset
++                                            copyvar(op.result), op.oploc)
+                     result.append(copyop)
+                 return result
+             newblock.operations = copyoplist(block.operations)
+diff -up pypy-pypy-release-1.7/pypy/objspace/flow/objspace.py.more-readable-c-code pypy-pypy-release-1.7/pypy/objspace/flow/objspace.py
+--- pypy-pypy-release-1.7/pypy/objspace/flow/objspace.py.more-readable-c-code	2011-11-19 02:44:54.000000000 -0500
++++ pypy-pypy-release-1.7/pypy/objspace/flow/objspace.py	2011-11-21 16:15:36.600466455 -0500
+@@ -315,7 +315,9 @@ class FlowObjSpace(ObjSpace):
+     def do_operation(self, name, *args_w):
+         spaceop = SpaceOperation(name, args_w, Variable())
+         if hasattr(self, 'executioncontext'):  # not here during bootstrapping
+-            spaceop.offset = self.executioncontext.crnt_offset
++            codeloc = CodeLoc(self.executioncontext.code,
++                              self.executioncontext.crnt_offset)
++            spaceop.oploc = OperationLoc([codeloc])
+             self.executioncontext.recorder.append(spaceop)
+         return spaceop.result
+ 
+diff -up pypy-pypy-release-1.7/pypy/objspace/flow/test/test_model.py.more-readable-c-code pypy-pypy-release-1.7/pypy/objspace/flow/test/test_model.py
+--- pypy-pypy-release-1.7/pypy/objspace/flow/test/test_model.py.more-readable-c-code	2011-11-19 02:44:54.000000000 -0500
++++ pypy-pypy-release-1.7/pypy/objspace/flow/test/test_model.py	2011-11-21 16:15:36.600466455 -0500
+@@ -119,3 +119,25 @@ def test_variable():
+     assert v2.renamed
+     assert v2.name.startswith("foobar_") and v2.name != v.name
+     assert v2.name.split('_', 1)[1].isdigit()
++
++def test_source_locations():
++    # Invent some random offsets into the code:
++    co = sample_function.__code__
++    codelocA = CodeLoc(co, 42)
++    codelocB = CodeLoc(co, 87)
++
++    assert str(codelocA) == 'sample_function at 42'
++    assert str(codelocB) == 'sample_function at 87'
++
++    assert cmp(codelocA, codelocB) < 0
++    assert cmp(codelocB, codelocA) > 0
++    
++    oplocA = OperationLoc([codelocA])
++    oplocB = OperationLoc([codelocB])
++
++    assert str(oplocA) == '[sample_function at 42]'
++    assert str(oplocB) == '[sample_function at 87]'
++
++    assert cmp(oplocA, oplocB) < 0
++    assert cmp(oplocB, oplocA) > 0
++
+diff -up pypy-pypy-release-1.7/pypy/rpython/rtyper.py.more-readable-c-code pypy-pypy-release-1.7/pypy/rpython/rtyper.py
+--- pypy-pypy-release-1.7/pypy/rpython/rtyper.py.more-readable-c-code	2011-11-19 02:44:54.000000000 -0500
++++ pypy-pypy-release-1.7/pypy/rpython/rtyper.py	2011-11-21 16:15:36.601466455 -0500
+@@ -800,7 +800,7 @@ class HighLevelOp(object):
+         return vars
+ 
+     def genop(self, opname, args_v, resulttype=None):
+-        return self.llops.genop(opname, args_v, resulttype)
++        return self.llops.genop(opname, args_v, resulttype, self.spaceop.oploc)
+ 
+     def gendirectcall(self, ll_function, *args_v):
+         return self.llops.gendirectcall(ll_function, *args_v)
+@@ -935,7 +935,7 @@ class LowLevelOpList(list):
+                                                     v.concretetype))
+         return v
+ 
+-    def genop(self, opname, args_v, resulttype=None):
++    def genop(self, opname, args_v, resulttype=None, oploc=None):
+         try:
+             for v in args_v:
+                 v.concretetype
+@@ -944,7 +944,7 @@ class LowLevelOpList(list):
+                                  " and pass its result to genop(),"
+                                  " never hop.args_v directly.")
+         vresult = Variable()
+-        self.append(SpaceOperation(opname, args_v, vresult))
++        self.append(SpaceOperation(opname, args_v, vresult, oploc))
+         if resulttype is None:
+             vresult.concretetype = Void
+             return None
+diff -up pypy-pypy-release-1.7/pypy/translator/backendopt/inline.py.more-readable-c-code pypy-pypy-release-1.7/pypy/translator/backendopt/inline.py
+--- pypy-pypy-release-1.7/pypy/translator/backendopt/inline.py.more-readable-c-code	2011-11-19 02:44:54.000000000 -0500
++++ pypy-pypy-release-1.7/pypy/translator/backendopt/inline.py	2011-11-21 16:15:36.601466455 -0500
+@@ -4,6 +4,7 @@ from pypy.translator.simplify import get
+ from pypy.translator.unsimplify import copyvar
+ from pypy.objspace.flow.model import Variable, Constant, Block, Link
+ from pypy.objspace.flow.model import SpaceOperation, c_last_exception
++from pypy.objspace.flow.model import OperationLoc
+ from pypy.objspace.flow.model import FunctionGraph
+ from pypy.objspace.flow.model import mkentrymap, checkgraph
+ from pypy.annotation import model as annmodel
+@@ -231,6 +232,7 @@ class BaseInliner(object):
+         self.varmap = {}
+         self._copied_blocks = {}
+         self.op = block.operations[index_operation]
++        self.callsite_oploc = self.op.oploc
+         self.graph_to_inline = self.get_graph_from_op(self.op)
+         self.exception_guarded = False
+         if (block.exitswitch == c_last_exception and
+@@ -290,7 +292,9 @@ class BaseInliner(object):
+         
+     def copy_operation(self, op):
+         args = [self.get_new_name(arg) for arg in op.args]
+-        result = SpaceOperation(op.opname, args, self.get_new_name(op.result))
++        new_oploc = OperationLoc(self.callsite_oploc.codelocs[:] + op.oploc.codelocs[:])
++        result = SpaceOperation(op.opname, args, self.get_new_name(op.result), 
++                                new_oploc)
+         return result
+ 
+     def copy_block(self, block):
+diff -up pypy-pypy-release-1.7/pypy/translator/c/funcgen.py.more-readable-c-code pypy-pypy-release-1.7/pypy/translator/c/funcgen.py
+--- pypy-pypy-release-1.7/pypy/translator/c/funcgen.py.more-readable-c-code	2011-11-19 02:44:54.000000000 -0500
++++ pypy-pypy-release-1.7/pypy/translator/c/funcgen.py	2011-11-21 16:15:36.602466455 -0500
+@@ -1,4 +1,6 @@
+ import sys
++import inspect
++import dis
+ from pypy.translator.c.support import USESLOTS # set to False if necessary while refactoring
+ from pypy.translator.c.support import cdecl
+ from pypy.translator.c.support import llvalue_from_constant, gen_assignments
+@@ -22,6 +24,38 @@ LOCALVAR = 'l_%s'
+ 
+ KEEP_INLINED_GRAPHS = False
+ 
++def block_comparator(blk0, blk1):
++    '''
++    Sort function for blocks, putting them in an ordering that attempts to
++    maximize readability of the generated C code
++    '''
++    # print 'comparing %r and %r' % (blk0, blk1)
++    # Put the start/end block at the top/bottom:
++    if blk0.isstartblock:
++        return -1
++
++    if blk1.isstartblock:
++        return 1
++
++    # Order blocks by the offset, where present:
++    if blk0.operations:
++        if blk1.operations:
++            return cmp(blk0.operations[0].oploc, blk1.operations[0].oploc)
++        else:
++            return -1
++    else:
++        if blk1.operations:
++            return 1
++        else:
++            return 0
++
++def escape_c_comments(py_src):
++    # Escape C comments within RPython source, to avoid generating bogus
++    # comments in our generated C source:
++    py_src = py_src.replace('/*', '')
++    py_src = py_src.replace('*/', '')
++    return py_src
++
+ class FunctionCodeGenerator(object):
+     """
+     Collects information about a function which we have to generate
+@@ -207,14 +241,57 @@ class FunctionCodeGenerator(object):
+ 
+     def cfunction_body(self):
+         graph = self.graph
+-        yield 'goto block0;'    # to avoid a warning "this label is not used"
++        # Try to print python source code:
++        if hasattr(graph, 'func'):
++            filename = inspect.getfile(graph.func)
++            #yield '/* name: %r */' % filename
++            try:
++                src, startline = inspect.getsourcelines(graph.func)
++            except IOError:
++                pass # No source found
++            except IndexError:
++                pass # Bulletproofing
++            else:
++                yield '/* Python source %r' % filename
++                for i, line in enumerate(src):
++                    line = line.rstrip()
++                    line = escape_c_comments(line)
++                    # FuncNode.funcgen_implementation treats lines ending in ':'
++                    # as C blocks, which messes up the formatting.
++                    # Work around this:
++                    if line.endswith(':'):
++                        line += ' '
++                    yield ' * %4d : %s' % (startline + i, line)
++                yield ' */'
++
++        label = graph.startblock.get_base_label(self.blocknum[graph.startblock])
++        yield 'goto %s;' % label # to avoid a warning "this label is not used"
++
++        # Sort the blocks into a (hopefully) readable order:
++        blocks = list(graph.iterblocks_by_source())
++        blocks.sort(block_comparator)
+ 
+         # generate the body of each block
+-        for block in graph.iterblocks():
++        for block in blocks:
++            cursrcloc = None
+             myblocknum = self.blocknum[block]
+             yield ''
+-            yield 'block%d:' % myblocknum
++            yield '%s:' % block.get_base_label(myblocknum)
++            #yield "/* repr(block): %r */" % (block, )
++            #yield "/* type(block): %r */" % (type(block), )
+             for i, op in enumerate(block.operations):
++                #yield "/* type(op): %r */" % (type(op), )
++                #yield "/* op.oploc: %s */" % (op.oploc, )
++                codeloc = op.oploc.codelocs[-1]
++                if codeloc:
++                    srcloc = codeloc.get_source_loc()
++                    if srcloc != cursrcloc:
++                        try:
++                            yield "/* %s:%d : %s */" % (codeloc.code.co_name, srcloc.linenum, escape_c_comments(srcloc.get_text()))
++                            cursrcloc = srcloc
++                        except IOError:
++                            pass
++
+                 for line in self.gen_op(op):
+                     yield line
+             if len(block.exits) == 0:
+@@ -306,7 +383,7 @@ class FunctionCodeGenerator(object):
+             assignments.append((a2typename, dest, src))
+         for line in gen_assignments(assignments):
+             yield line
+-        label = 'block%d' % self.blocknum[link.target]
++        label = link.target.get_base_label(self.blocknum[link.target])
+         if link.target in self.innerloops:
+             loop = self.innerloops[link.target]
+             if link is loop.links[-1]:   # link that ends a loop
+diff -up pypy-pypy-release-1.7/pypy/translator/c/test/test_genc.py.more-readable-c-code pypy-pypy-release-1.7/pypy/translator/c/test/test_genc.py
+--- pypy-pypy-release-1.7/pypy/translator/c/test/test_genc.py.more-readable-c-code	2011-11-19 02:44:54.000000000 -0500
++++ pypy-pypy-release-1.7/pypy/translator/c/test/test_genc.py	2011-11-21 16:15:36.602466455 -0500
+@@ -1,4 +1,5 @@
+ import autopath, sys, os, py
++import re
+ from pypy.rpython.lltypesystem.lltype import *
+ from pypy.annotation import model as annmodel
+ from pypy.translator.translator import TranslationContext
+@@ -532,3 +533,130 @@ def test_inhibit_tail_call():
+     else:
+         assert 0, "the call was not found in the C source"
+     assert 'PYPY_INHIBIT_TAIL_CALL();' in lines[i+1]
++
++def get_generated_c_source(fn, types):
++    # Return a (optimized fn, c source code, c source filename) 3-tuple
++    t = Translation(fn)
++    t.annotate(types)
++    c_filename_path = t.source_c()
++    h = c_filename_path.open()
++    src = h.read()
++    h.close()
++    c_fn = t.compile_c()
++    return (c_fn, src, c_filename_path)
++
++def extract_c_function(c_src, fname):
++    # Extract the source for a given C function out of a the given src string
++    # Makes assumptions about the layout of the source
++    pattern = '^(.+) \**%s\(.*\) {$' % fname
++    within_fn = False
++    result = ''
++    for line in c_src.splitlines():
++        if within_fn:
++            result += line + '\n'
++            if line.startswith('}'):
++                return result
++        else:
++            m = re.match(pattern, line)
++            if m:
++                within_fn = True
++                result += line + '\n'
++    return result
++    
++    
++
++def test_generated_c_source():
++    # Verify that generate C source "looks good"
++    # We'll use is_perfect_number, as it contains a loop and a conditional
++
++    # Generate C source code
++    from pypy.translator.test.snippet import is_perfect_number
++    c_fn, c_src, c_filename_path = get_generated_c_source(is_perfect_number,
++                                                        [int])
++
++    # Locate the C source for the type-specialized function:
++    c_fn_src = extract_c_function(c_src, 'pypy_g_is_perfect_number')
++    
++    # Verify that the C source contains embedded comments containing the lines
++    # of the python source:
++    expected_comment_lines = [
++        '/* is_perfect_number:31 :     while div < n: */',
++        '/* is_perfect_number:32 :         if n % div == 0: */',
++        '/* is_perfect_number:33 :             sum += div */',
++        '/* is_perfect_number:34 :         div += 1 */',
++        '/* is_perfect_number:35 :     return n == sum */']
++    for exp_line in expected_comment_lines:
++        assert exp_line in c_fn_src
++        
++    # Verify that the lines occur in the correct order
++    # ...we do this by filtering the function's generated C source to just
++    # those lines containing our comments (and dropping whitespace):
++    lines = c_fn_src.splitlines()
++    lines = [line.strip()
++             for line in lines
++             if '/* is_perfect_number:' in line]
++
++    # ...we should now have exact equality: the ordering should be as expected,
++    # and each comment should appear exactly once:
++    assert lines == expected_comment_lines
++
++    # Ensure that the generated C function does the right thing:
++    assert c_fn(5) == False
++    assert c_fn(6) == True
++    assert c_fn(7) == False
++
++    assert c_fn(5.0) == False
++    assert c_fn(6.0) == True
++    assert c_fn(7.0) == False
++
++    assert c_fn(5L) == False
++    assert c_fn(6L) == True
++    assert c_fn(7L) == False
++
++    try:
++        c_fn('hello world')
++    except:
++        pass
++    else:
++        raise 'Was expected exception'
++    
++def test_escaping_c_comments():
++    # Ensure that c comments within RPython code get escaped when we generate
++    # our .c code (to avoid generating bogus C)
++    # See e.g. pypy.module.cpyext.dictobject's PyDict_Next, which has a
++    # docstring embedding a C comment
++    def c_style_comment(a, b):
++        '''Here is a C-style comment within an RPython docstring:
++                /* hello world */
++        '''
++        # and here's one in a string literal:
++        return '/* hello world a:%s b:%s */' % (a, b)
++
++    def cplusplus_style_comment(a, b):
++        '''Here is a C++-style comment within an RPython docstring:
++                // hello world
++        '''
++        # and here are some in string literals, and one as the floor division
++        # operator:
++        return '// hello world: a // b = %s' % (a // b)
++
++    for fn_name, exp_output in [('c_style_comment',
++                                 '/* hello world a:6 b:3 */'),
++                                ('cplusplus_style_comment',
++                                 '// hello world: a // b = 2')]:
++        fn = locals()[fn_name]
++
++        c_fn, c_src, c_filename_path = get_generated_c_source(fn, [int, int])
++        # If the above survived, then the C compiler managed to handle
++        # the generated C code
++
++        # Verify that the generated code works (i.e. that we didn't
++        # accidentally change the meaning):
++        assert c_fn(6, 3) == exp_output
++
++        # Ensure that at least part of the docstrings made it into the C
++        # code:
++        c_fn_src = extract_c_function(c_src, 'pypy_g_' + fn_name)
++        assert 'Here is a ' in c_fn_src
++        assert 'style comment within an RPython docstring' in c_fn_src
++        
+diff -up pypy-pypy-release-1.7/pypy/translator/driver.py.more-readable-c-code pypy-pypy-release-1.7/pypy/translator/driver.py
+--- pypy-pypy-release-1.7/pypy/translator/driver.py.more-readable-c-code	2011-11-19 02:44:54.000000000 -0500
++++ pypy-pypy-release-1.7/pypy/translator/driver.py	2011-11-21 16:15:36.603466455 -0500
+@@ -535,6 +535,7 @@ class TranslationDriver(SimpleTaskEngine
+             dstname = self.compute_exe_name() + '.staticdata.info'
+             shutil.copy(str(fname), str(dstname))
+             self.log.info('Static data info written to %s' % dstname)
++        return c_source_filename
+ 
+     #
+     task_source_c = taskdef(task_source_c, ['database_c'], "Generating c source")
+diff -up pypy-pypy-release-1.7/pypy/translator/gensupp.py.more-readable-c-code pypy-pypy-release-1.7/pypy/translator/gensupp.py
+--- pypy-pypy-release-1.7/pypy/translator/gensupp.py.more-readable-c-code	2011-11-19 02:44:54.000000000 -0500
++++ pypy-pypy-release-1.7/pypy/translator/gensupp.py	2011-11-21 16:15:36.603466455 -0500
+@@ -14,8 +14,8 @@ def ordered_blocks(graph):
+     allblocks = []
+     for block in graph.iterblocks():
+             # first we order by offset in the code string
+-            if block.operations:
+-                ofs = block.operations[0].offset
++            if block.operations and block.operations[0].oploc.codelocs[0]:
++                ofs = block.operations[0].oploc.codelocs[0].offset
+             else:
+                 ofs = sys.maxint
+             # then we order by input variable name or value
+diff -up pypy-pypy-release-1.7/pypy/translator/interactive.py.more-readable-c-code pypy-pypy-release-1.7/pypy/translator/interactive.py
+--- pypy-pypy-release-1.7/pypy/translator/interactive.py.more-readable-c-code	2011-11-19 02:44:54.000000000 -0500
++++ pypy-pypy-release-1.7/pypy/translator/interactive.py	2011-11-21 16:15:36.604466454 -0500
+@@ -138,7 +138,7 @@ class Translation(object):
+     def source_c(self, argtypes=None, **kwds):
+         self.update_options(argtypes, kwds)
+         self.ensure_backend('c')
+-        self.driver.source_c()
++        return self.driver.source_c()
+ 
+     def source_cl(self, argtypes=None, **kwds):
+         self.update_options(argtypes, kwds)
+diff -up pypy-pypy-release-1.7/pypy/translator/llsupport/wrapper.py.more-readable-c-code pypy-pypy-release-1.7/pypy/translator/llsupport/wrapper.py
+--- pypy-pypy-release-1.7/pypy/translator/llsupport/wrapper.py.more-readable-c-code	2011-11-19 02:44:54.000000000 -0500
++++ pypy-pypy-release-1.7/pypy/translator/llsupport/wrapper.py	2011-11-21 16:15:36.604466454 -0500
+@@ -59,6 +59,8 @@ def new_wrapper(func, translator, newnam
+     # "return result"
+     block = Block(wrapper_inputargs)
+     wgraph = FunctionGraph('pyfn_' + (newname or func.func_name), block)
++    if hasattr(graph, 'func'):
++        wgraph.func = graph.func
+     translator.update_call_graph(wgraph, graph, object())
+     translator.graphs.append(wgraph)
+     block.operations[:] = newops
+diff -up pypy-pypy-release-1.7/pypy/translator/simplify.py.more-readable-c-code pypy-pypy-release-1.7/pypy/translator/simplify.py
+--- pypy-pypy-release-1.7/pypy/translator/simplify.py.more-readable-c-code	2011-11-19 02:44:54.000000000 -0500
++++ pypy-pypy-release-1.7/pypy/translator/simplify.py	2011-11-21 16:15:36.605466454 -0500
+@@ -292,7 +292,7 @@ def join_blocks(graph):
+                 return renaming.get(v, v)
+             def rename_op(op):
+                 args = [rename(a) for a in op.args]
+-                op = SpaceOperation(op.opname, args, rename(op.result), op.offset)
++                op = SpaceOperation(op.opname, args, rename(op.result), op.oploc)
+                 # special case...
+                 if op.opname == 'indirect_call':
+                     if isinstance(op.args[0], Constant):
diff --git a/pypy-1.5-config.patch b/pypy-1.5-config.patch
deleted file mode 100644
index 82d8fc9..0000000
--- a/pypy-1.5-config.patch
+++ /dev/null
@@ -1,39 +0,0 @@
-diff -up pypy-1.5-src/pypy/translator/platform/linux.py.configure-fedora pypy-1.5-src/pypy/translator/platform/linux.py
---- pypy-1.5-src/pypy/translator/platform/linux.py.configure-fedora	2011-04-30 10:18:50.000000000 -0400
-+++ pypy-1.5-src/pypy/translator/platform/linux.py	2011-04-30 18:59:24.041160978 -0400
-@@ -1,13 +1,18 @@
- """Support for Linux."""
--
-+import os
- from pypy.translator.platform.posix import BasePosix
- 
-+CFLAGS = ['-O3', '-pthread', '-fomit-frame-pointer',
-+          '-Wall', '-Wno-unused']
-+if os.environ.get('CFLAGS', None):
-+    CFLAGS.extend(os.environ['CFLAGS'].split())
-+CFLAGS = tuple(CFLAGS)
-+
- class BaseLinux(BasePosix):
-     name = "linux"
-     
-     link_flags = ('-pthread', '-lrt')
--    cflags = ('-O3', '-pthread', '-fomit-frame-pointer',
--              '-Wall', '-Wno-unused')
-+    cflags = CFLAGS
-     standalone_only = ()
-     shared_only = ('-fPIC',)
-     so_ext = 'so'
-@@ -29,9 +34,10 @@ class Linux(BaseLinux):
-     shared_only = ()    # it seems that on 32-bit linux, compiling with -fPIC
-                         # gives assembler that asmgcc is not happy about.
- 
--    def library_dirs_for_libffi_a(self):
--        # places where we need to look for libffi.a
--        return self.library_dirs_for_libffi() + ['/usr/lib']
-+    # Fedora Linux, at least, has the shared version but not the static
-+    #def library_dirs_for_libffi_a(self):
-+    #    # places where we need to look for libffi.a
-+    #    return self.library_dirs_for_libffi() + ['/usr/lib']
- 
- 
- class Linux64(BaseLinux):
diff --git a/pypy-1.5-more-readable-c-code.patch b/pypy-1.5-more-readable-c-code.patch
deleted file mode 100644
index b7103e2..0000000
--- a/pypy-1.5-more-readable-c-code.patch
+++ /dev/null
@@ -1,693 +0,0 @@
-diff -up pypy-1.5-src/pypy/interpreter/pycode.py.more-readable-c-code pypy-1.5-src/pypy/interpreter/pycode.py
---- pypy-1.5-src/pypy/interpreter/pycode.py.more-readable-c-code	2011-04-30 10:18:50.000000000 -0400
-+++ pypy-1.5-src/pypy/interpreter/pycode.py	2011-05-02 14:28:33.942161002 -0400
-@@ -13,6 +13,7 @@ from pypy.interpreter.gateway import Non
- from pypy.interpreter.astcompiler.consts import (CO_OPTIMIZED,
-     CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS, CO_NESTED,
-     CO_GENERATOR, CO_CONTAINSGLOBALS)
-+from pypy.interpreter.pytraceback import offset2lineno
- from pypy.rlib.rarithmetic import intmask
- from pypy.rlib.debug import make_sure_not_resized
- from pypy.rlib import jit
-@@ -80,6 +81,7 @@ class PyCode(eval.Code):
-         self.hidden_applevel = hidden_applevel
-         self.magic = magic
-         self._signature = cpython_code_signature(self)
-+        self._cached_source = None
-         self._initialize()
- 
-     def _initialize(self):
-@@ -396,3 +398,23 @@ class PyCode(eval.Code):
- 
-     def repr(self, space):
-         return space.wrap(self.get_repr())
-+
-+    def get_linenum_for_offset(self, offset):
-+        # Given a bytecode offset, return a 1-based index into the lines of the
-+        # source code
-+        return offset2lineno(self, offset)
-+
-+    def _ensure_source(self):
-+        # Lazily grab the source lines into self._cached_source (or raise
-+        # an IOError)
-+        if not self._cached_source:
-+            f = open(self.co_filename, 'r')
-+            source = [line.rstrip() for line in f.readlines()]
-+            f.close()
-+            self._cached_source = source
-+    
-+    def get_source_text(self, linenum):
-+        # Given a 1-based index, get the corresponding line of source code (or
-+        # raise an IOError)
-+        self._ensure_source()
-+        return self._cached_source[linenum - 1]
-diff -up pypy-1.5-src/pypy/objspace/flow/model.py.more-readable-c-code pypy-1.5-src/pypy/objspace/flow/model.py
---- pypy-1.5-src/pypy/objspace/flow/model.py.more-readable-c-code	2011-04-30 10:18:50.000000000 -0400
-+++ pypy-1.5-src/pypy/objspace/flow/model.py	2011-05-02 14:28:33.942161002 -0400
-@@ -31,6 +31,120 @@ from pypy.tool.identity_dict import iden
- 
- __metaclass__ = type
- 
-+class SourceLoc(object):
-+    # A srcloc is a specific location within the RPython source code,
-+    # intended for human display
-+    __slots__ = ('code', # code object
-+                 'linenum' # 1-based index, as displayed to a user
-+                 )
-+    def __init__(self, code, linenum):
-+        self.code = code
-+        self.linenum = linenum
-+
-+    def get_text(self):
-+        # Get the actual source text of this line
-+        return self.code.get_source_text(self.linenum)
-+
-+    def __eq__(self, other):
-+        return self.code == other.code and self.linenum == other.linenum
-+
-+    def __ne__(self, other):
-+        if other:
-+            return self.code != other.code or self.linenum != other.linenum
-+        else:
-+            return True
-+
-+class CodeLoc(object):
-+    # A codeloc is a specific location within the RPython bytecode
-+    __slots__ = ('code', # code object
-+                 'offset' # int index into bytecode, or -1
-+                 )
-+
-+    def __init__(self, code, offset):
-+        self.code = code
-+        self.offset = offset
-+
-+    def __str__(self):
-+        if self.offset >= 0:
-+            return "%s@%d" % (self.code.co_name, self.offset)
-+        else:
-+            return ""
-+
-+    def __ne__(self, other):
-+        if other:
-+            return self.code != other.code or self.offset != other.offset
-+        else:
-+            return True
-+
-+    def __cmp__(self, other):
-+        # Partial ordering, for those locations that have an offset:
-+        if other:
-+            if self.offset >= 0 and other.offset >= 0:
-+                return self.offset - other.offset
-+        return 0
-+
-+    def get_source_loc(self):
-+        # Convert to a SourceLoc:
-+        return SourceLoc(self.code, self.code.get_linenum_for_offset(self.offset))
-+
-+class OperationLoc(object):
-+    # An oploc is the location within the RPython source code of a given
-+    # operation
-+    # 
-+    # This is a list consisting of CodeLoc instances, some of which may be None
-+    #
-+    # For the simple case, this is list of length 1 with a single CodeLoc
-+    #
-+    # For an operation inside an inlined callsite, we have a list of length 2:
-+    #    [codeloc of callsite,
-+    #     codeloc of operation within inlined body]
-+    #
-+    # For more interesting inlined cases, we have a chain of source locations:
-+    #    [codeloc of callsite,
-+    #     codeloc of inner callsite,
-+    #     ... ,
-+    #     codeloc of innermost inlined callsite,
-+    #     codeloc of operation within inlined body]
-+    #
-+
-+    __slots__ = ('codelocs', )
-+
-+    def __init__(self, codelocs):
-+        self.codelocs = codelocs
-+
-+    def __str__(self):
-+        return '[' + ' > '.join(str(codeloc) for codeloc in self.codelocs) + ']'
-+
-+    def __cmp__(self, other):
-+        return cmp(self.codelocs, other.codelocs)
-+
-+def block_comparator(blk0, blk1):
-+    '''
-+    Sort function for blocks, putting them in an ordering that attempts to
-+    maximize readability of the generated C code
-+    '''
-+    # print 'comparing %r and %r' % (blk0, blk1)
-+    # Put the start/end block at the top/bottom:
-+    if blk0.isstartblock:
-+        return -1
-+
-+    if blk1.isstartblock:
-+        return 1
-+
-+    # Order blocks by the offset, where present:
-+    if blk0.operations:
-+        if blk1.operations:
-+            return cmp(blk0.operations[0].oploc, blk1.operations[0].oploc)
-+        else:
-+            return -1
-+    else:
-+        if blk1.operations:
-+            return 1
-+        else:
-+            return 0
-+
-+def edge_comparator(edge0, edge1):
-+    return block_comparator(edge0.target, edge1.target)
- 
- class FunctionGraph(object):
-     __slots__ = ['startblock', 'returnblock', 'exceptblock', '__dict__']
-@@ -94,6 +208,21 @@ class FunctionGraph(object):
-                 seen[block] = True
-                 stack += block.exits[::-1]
- 
-+    def iterblocks_by_source(self):
-+        # Try to preserve logical source ordering in the blocks
-+        block = self.startblock
-+        yield block
-+        seen = {block: True}
-+        stack = list(block.exits[::-1])
-+        stack.sort(edge_comparator)
-+        while stack:
-+            block = stack.pop().target
-+            if block not in seen:
-+                yield block
-+                seen[block] = True
-+                stack += block.exits[::-1]
-+                stack.sort(edge_comparator)
-+
-     def iterlinks(self):
-         block = self.startblock
-         seen = {block: True}
-@@ -183,14 +312,14 @@ class Block(object):
-         self.exits      = []              # list of Link(s)
- 
-     def at(self):
--        if self.operations and self.operations[0].offset >= 0:
--            return "@%d" % self.operations[0].offset
-+        if self.operations:
-+            return str(self.operations[0].oploc)
-         else:
-             return ""
- 
-     def __str__(self):
-         if self.operations:
--            txt = "block@%d" % self.operations[0].offset
-+            txt = "block%s" % self.operations[0].oploc
-         else:
-             if (not self.exits) and len(self.inputargs) == 1:
-                 txt = "return block"
-@@ -245,6 +374,21 @@ class Block(object):
-         from pypy.translator.tool.graphpage import try_show
-         try_show(self)
- 
-+    def isreturnblock(self):
-+        return (not self.operations) and (not self.exits) and len(self.inputargs) == 1
-+
-+    def get_base_label(self, blocknum):
-+        # Generate a more friendly C label for this block
-+        if self.operations:
-+            txt = "block"
-+        elif (not self.exits) and len(self.inputargs) == 1:
-+            txt = "return_block"
-+        elif (not self.exits) and len(self.inputargs) == 2:
-+            txt = "raise_block"
-+        else:
-+            txt = "codeless_block"
-+        return '%s%d' % (txt, blocknum)
-+
- 
- class Variable(object):
-     __slots__ = ["_name", "_nr", "concretetype"]
-@@ -331,13 +475,15 @@ class WrapException(Exception):
- 
- 
- class SpaceOperation(object):
--    __slots__ = "opname args result offset".split()
-+    __slots__ = "opname args result oploc".split()
- 
--    def __init__(self, opname, args, result, offset=-1):
-+    def __init__(self, opname, args, result, oploc=None):
-         self.opname = intern(opname)      # operation name
-         self.args   = list(args)  # mixed list of var/const
-         self.result = result      # either Variable or Constant instance
--        self.offset = offset      # offset in code string
-+        if oploc is None:
-+            oploc = OperationLoc([None])
-+        self.oploc = oploc
- 
-     def __eq__(self, other):
-         return (self.__class__ is other.__class__ and 
-@@ -352,8 +498,9 @@ class SpaceOperation(object):
-         return hash((self.opname,tuple(self.args),self.result))
- 
-     def __repr__(self):
--        return "%r = %s(%s)" % (self.result, self.opname,
--                                ", ".join(map(repr, self.args)))
-+        return "%r = %s(%s) (%s)" % (self.result, self.opname,
-+                                     ", ".join(map(repr, self.args)),
-+                                     self.oploc)
- 
- class Atom(object):
-     def __init__(self, name):
-@@ -427,8 +574,7 @@ def copygraph(graph, shallow=False, varm
-                 for op in oplist:
-                     copyop = SpaceOperation(op.opname,
-                                             [copyvar(v) for v in op.args],
--                                            copyvar(op.result), op.offset)
--                    #copyop.offset = op.offset
-+                                            copyvar(op.result), op.oploc)
-                     result.append(copyop)
-                 return result
-             newblock.operations = copyoplist(block.operations)
-diff -up pypy-1.5-src/pypy/objspace/flow/objspace.py.more-readable-c-code pypy-1.5-src/pypy/objspace/flow/objspace.py
---- pypy-1.5-src/pypy/objspace/flow/objspace.py.more-readable-c-code	2011-04-30 10:18:50.000000000 -0400
-+++ pypy-1.5-src/pypy/objspace/flow/objspace.py	2011-05-02 14:28:33.943161001 -0400
-@@ -313,7 +313,9 @@ class FlowObjSpace(ObjSpace):
-     def do_operation(self, name, *args_w):
-         spaceop = SpaceOperation(name, args_w, Variable())
-         if hasattr(self, 'executioncontext'):  # not here during bootstrapping
--            spaceop.offset = self.executioncontext.crnt_offset
-+            codeloc = CodeLoc(self.executioncontext.code,
-+                              self.executioncontext.crnt_offset)
-+            spaceop.oploc = OperationLoc([codeloc])
-             self.executioncontext.recorder.append(spaceop)
-         return spaceop.result
- 
-diff -up pypy-1.5-src/pypy/objspace/flow/test/test_model.py.more-readable-c-code pypy-1.5-src/pypy/objspace/flow/test/test_model.py
---- pypy-1.5-src/pypy/objspace/flow/test/test_model.py.more-readable-c-code	2011-04-30 10:18:50.000000000 -0400
-+++ pypy-1.5-src/pypy/objspace/flow/test/test_model.py	2011-05-02 14:28:33.943161001 -0400
-@@ -119,3 +119,25 @@ def test_variable():
-     assert v2.renamed
-     assert v2.name.startswith("foobar_") and v2.name != v.name
-     assert v2.name.split('_', 1)[1].isdigit()
-+
-+def test_source_locations():
-+    # Invent some random offsets into the code:
-+    co = sample_function.__code__
-+    codelocA = CodeLoc(co, 42)
-+    codelocB = CodeLoc(co, 87)
-+
-+    assert str(codelocA) == 'sample_function at 42'
-+    assert str(codelocB) == 'sample_function at 87'
-+
-+    assert cmp(codelocA, codelocB) < 0
-+    assert cmp(codelocB, codelocA) > 0
-+    
-+    oplocA = OperationLoc([codelocA])
-+    oplocB = OperationLoc([codelocB])
-+
-+    assert str(oplocA) == '[sample_function at 42]'
-+    assert str(oplocB) == '[sample_function at 87]'
-+
-+    assert cmp(oplocA, oplocB) < 0
-+    assert cmp(oplocB, oplocA) > 0
-+
-diff -up pypy-1.5-src/pypy/rpython/rtyper.py.more-readable-c-code pypy-1.5-src/pypy/rpython/rtyper.py
---- pypy-1.5-src/pypy/rpython/rtyper.py.more-readable-c-code	2011-04-30 10:18:50.000000000 -0400
-+++ pypy-1.5-src/pypy/rpython/rtyper.py	2011-05-02 14:28:33.943161001 -0400
-@@ -800,7 +800,7 @@ class HighLevelOp(object):
-         return vars
- 
-     def genop(self, opname, args_v, resulttype=None):
--        return self.llops.genop(opname, args_v, resulttype)
-+        return self.llops.genop(opname, args_v, resulttype, self.spaceop.oploc)
- 
-     def gendirectcall(self, ll_function, *args_v):
-         return self.llops.gendirectcall(ll_function, *args_v)
-@@ -935,7 +935,7 @@ class LowLevelOpList(list):
-                                                     v.concretetype))
-         return v
- 
--    def genop(self, opname, args_v, resulttype=None):
-+    def genop(self, opname, args_v, resulttype=None, oploc=None):
-         try:
-             for v in args_v:
-                 v.concretetype
-@@ -944,7 +944,7 @@ class LowLevelOpList(list):
-                                  " and pass its result to genop(),"
-                                  " never hop.args_v directly.")
-         vresult = Variable()
--        self.append(SpaceOperation(opname, args_v, vresult))
-+        self.append(SpaceOperation(opname, args_v, vresult, oploc))
-         if resulttype is None:
-             vresult.concretetype = Void
-             return None
-diff -up pypy-1.5-src/pypy/translator/backendopt/inline.py.more-readable-c-code pypy-1.5-src/pypy/translator/backendopt/inline.py
---- pypy-1.5-src/pypy/translator/backendopt/inline.py.more-readable-c-code	2011-04-30 10:18:50.000000000 -0400
-+++ pypy-1.5-src/pypy/translator/backendopt/inline.py	2011-05-02 14:32:26.975161005 -0400
-@@ -4,6 +4,7 @@ from pypy.translator.simplify import get
- from pypy.translator.unsimplify import copyvar
- from pypy.objspace.flow.model import Variable, Constant, Block, Link
- from pypy.objspace.flow.model import SpaceOperation, c_last_exception
-+from pypy.objspace.flow.model import OperationLoc
- from pypy.objspace.flow.model import FunctionGraph
- from pypy.objspace.flow.model import mkentrymap, checkgraph
- from pypy.annotation import model as annmodel
-@@ -231,6 +232,7 @@ class BaseInliner(object):
-         self.varmap = {}
-         self._copied_blocks = {}
-         self.op = block.operations[index_operation]
-+        self.callsite_oploc = self.op.oploc
-         self.graph_to_inline = self.get_graph_from_op(self.op)
-         self.exception_guarded = False
-         if (block.exitswitch == c_last_exception and
-@@ -290,7 +292,9 @@ class BaseInliner(object):
-         
-     def copy_operation(self, op):
-         args = [self.get_new_name(arg) for arg in op.args]
--        result = SpaceOperation(op.opname, args, self.get_new_name(op.result))
-+        new_oploc = OperationLoc(self.callsite_oploc.codelocs[:] + op.oploc.codelocs[:])
-+        result = SpaceOperation(op.opname, args, self.get_new_name(op.result), 
-+                                new_oploc)
-         return result
- 
-     def copy_block(self, block):
-diff -up pypy-1.5-src/pypy/translator/c/funcgen.py.more-readable-c-code pypy-1.5-src/pypy/translator/c/funcgen.py
---- pypy-1.5-src/pypy/translator/c/funcgen.py.more-readable-c-code	2011-04-30 10:18:50.000000000 -0400
-+++ pypy-1.5-src/pypy/translator/c/funcgen.py	2011-05-02 14:28:33.944161001 -0400
-@@ -1,4 +1,6 @@
- import sys
-+import inspect
-+import dis
- from pypy.translator.c.support import USESLOTS # set to False if necessary while refactoring
- from pypy.translator.c.support import cdecl
- from pypy.translator.c.support import llvalue_from_constant, gen_assignments
-@@ -22,6 +24,38 @@ LOCALVAR = 'l_%s'
- 
- KEEP_INLINED_GRAPHS = False
- 
-+def block_comparator(blk0, blk1):
-+    '''
-+    Sort function for blocks, putting them in an ordering that attempts to
-+    maximize readability of the generated C code
-+    '''
-+    # print 'comparing %r and %r' % (blk0, blk1)
-+    # Put the start/end block at the top/bottom:
-+    if blk0.isstartblock:
-+        return -1
-+
-+    if blk1.isstartblock:
-+        return 1
-+
-+    # Order blocks by the offset, where present:
-+    if blk0.operations:
-+        if blk1.operations:
-+            return cmp(blk0.operations[0].oploc, blk1.operations[0].oploc)
-+        else:
-+            return -1
-+    else:
-+        if blk1.operations:
-+            return 1
-+        else:
-+            return 0
-+
-+def escape_c_comments(py_src):
-+    # Escape C comments within RPython source, to avoid generating bogus
-+    # comments in our generated C source:
-+    py_src = py_src.replace('/*', '')
-+    py_src = py_src.replace('*/', '')
-+    return py_src
-+
- class FunctionCodeGenerator(object):
-     """
-     Collects information about a function which we have to generate
-@@ -210,14 +244,57 @@ class FunctionCodeGenerator(object):
- 
-     def cfunction_body(self):
-         graph = self.graph
--        yield 'goto block0;'    # to avoid a warning "this label is not used"
-+        # Try to print python source code:
-+        if hasattr(graph, 'func'):
-+            filename = inspect.getfile(graph.func)
-+            #yield '/* name: %r */' % filename
-+            try:
-+                src, startline = inspect.getsourcelines(graph.func)
-+            except IOError:
-+                pass # No source found
-+            except IndexError:
-+                pass # Bulletproofing
-+            else:
-+                yield '/* Python source %r' % filename
-+                for i, line in enumerate(src):
-+                    line = line.rstrip()
-+                    line = escape_c_comments(line)
-+                    # FuncNode.funcgen_implementation treats lines ending in ':'
-+                    # as C blocks, which messes up the formatting.
-+                    # Work around this:
-+                    if line.endswith(':'):
-+                        line += ' '
-+                    yield ' * %4d : %s' % (startline + i, line)
-+                yield ' */'
-+
-+        label = graph.startblock.get_base_label(self.blocknum[graph.startblock])
-+        yield 'goto %s;' % label # to avoid a warning "this label is not used"
-+
-+        # Sort the blocks into a (hopefully) readable order:
-+        blocks = list(graph.iterblocks_by_source())
-+        blocks.sort(block_comparator)
- 
-         # generate the body of each block
--        for block in graph.iterblocks():
-+        for block in blocks:
-+            cursrcloc = None
-             myblocknum = self.blocknum[block]
-             yield ''
--            yield 'block%d:' % myblocknum
-+            yield '%s:' % block.get_base_label(myblocknum)
-+            #yield "/* repr(block): %r */" % (block, )
-+            #yield "/* type(block): %r */" % (type(block), )
-             for i, op in enumerate(block.operations):
-+                #yield "/* type(op): %r */" % (type(op), )
-+                #yield "/* op.oploc: %s */" % (op.oploc, )
-+                codeloc = op.oploc.codelocs[-1]
-+                if codeloc:
-+                    srcloc = codeloc.get_source_loc()
-+                    if srcloc != cursrcloc:
-+                        try:
-+                            yield "/* %s:%d : %s */" % (codeloc.code.co_name, srcloc.linenum, escape_c_comments(srcloc.get_text()))
-+                            cursrcloc = srcloc
-+                        except IOError:
-+                            pass
-+
-                 for line in self.gen_op(op):
-                     yield line
-             if len(block.exits) == 0:
-@@ -309,7 +386,7 @@ class FunctionCodeGenerator(object):
-             assignments.append((a2typename, dest, src))
-         for line in gen_assignments(assignments):
-             yield line
--        label = 'block%d' % self.blocknum[link.target]
-+        label = link.target.get_base_label(self.blocknum[link.target])
-         if link.target in self.innerloops:
-             loop = self.innerloops[link.target]
-             if link is loop.links[-1]:   # link that ends a loop
-diff -up pypy-1.5-src/pypy/translator/c/test/test_genc.py.more-readable-c-code pypy-1.5-src/pypy/translator/c/test/test_genc.py
---- pypy-1.5-src/pypy/translator/c/test/test_genc.py.more-readable-c-code	2011-04-30 10:18:50.000000000 -0400
-+++ pypy-1.5-src/pypy/translator/c/test/test_genc.py	2011-05-02 14:28:33.945161001 -0400
-@@ -1,4 +1,5 @@
- import autopath, sys, os, py
-+import re
- from pypy.rpython.lltypesystem.lltype import *
- from pypy.annotation import model as annmodel
- from pypy.translator.translator import TranslationContext
-@@ -515,3 +516,130 @@ def test_inhibit_tail_call():
-     else:
-         assert 0, "the call was not found in the C source"
-     assert 'PYPY_INHIBIT_TAIL_CALL();' in lines[i+1]
-+
-+def get_generated_c_source(fn, types):
-+    # Return a (optimized fn, c source code, c source filename) 3-tuple
-+    t = Translation(fn)
-+    t.annotate(types)
-+    c_filename_path = t.source_c()
-+    h = c_filename_path.open()
-+    src = h.read()
-+    h.close()
-+    c_fn = t.compile_c()
-+    return (c_fn, src, c_filename_path)
-+
-+def extract_c_function(c_src, fname):
-+    # Extract the source for a given C function out of a the given src string
-+    # Makes assumptions about the layout of the source
-+    pattern = '^(.+) \**%s\(.*\) {$' % fname
-+    within_fn = False
-+    result = ''
-+    for line in c_src.splitlines():
-+        if within_fn:
-+            result += line + '\n'
-+            if line.startswith('}'):
-+                return result
-+        else:
-+            m = re.match(pattern, line)
-+            if m:
-+                within_fn = True
-+                result += line + '\n'
-+    return result
-+    
-+    
-+
-+def test_generated_c_source():
-+    # Verify that generate C source "looks good"
-+    # We'll use is_perfect_number, as it contains a loop and a conditional
-+
-+    # Generate C source code
-+    from pypy.translator.test.snippet import is_perfect_number
-+    c_fn, c_src, c_filename_path = get_generated_c_source(is_perfect_number,
-+                                                        [int])
-+
-+    # Locate the C source for the type-specialized function:
-+    c_fn_src = extract_c_function(c_src, 'pypy_g_is_perfect_number')
-+    
-+    # Verify that the C source contains embedded comments containing the lines
-+    # of the python source:
-+    expected_comment_lines = [
-+        '/* is_perfect_number:31 :     while div < n: */',
-+        '/* is_perfect_number:32 :         if n % div == 0: */',
-+        '/* is_perfect_number:33 :             sum += div */',
-+        '/* is_perfect_number:34 :         div += 1 */',
-+        '/* is_perfect_number:35 :     return n == sum */']
-+    for exp_line in expected_comment_lines:
-+        assert exp_line in c_fn_src
-+        
-+    # Verify that the lines occur in the correct order
-+    # ...we do this by filtering the function's generated C source to just
-+    # those lines containing our comments (and dropping whitespace):
-+    lines = c_fn_src.splitlines()
-+    lines = [line.strip()
-+             for line in lines
-+             if '/* is_perfect_number:' in line]
-+
-+    # ...we should now have exact equality: the ordering should be as expected,
-+    # and each comment should appear exactly once:
-+    assert lines == expected_comment_lines
-+
-+    # Ensure that the generated C function does the right thing:
-+    assert c_fn(5) == False
-+    assert c_fn(6) == True
-+    assert c_fn(7) == False
-+
-+    assert c_fn(5.0) == False
-+    assert c_fn(6.0) == True
-+    assert c_fn(7.0) == False
-+
-+    assert c_fn(5L) == False
-+    assert c_fn(6L) == True
-+    assert c_fn(7L) == False
-+
-+    try:
-+        c_fn('hello world')
-+    except:
-+        pass
-+    else:
-+        raise 'Was expected exception'
-+    
-+def test_escaping_c_comments():
-+    # Ensure that c comments within RPython code get escaped when we generate
-+    # our .c code (to avoid generating bogus C)
-+    # See e.g. pypy.module.cpyext.dictobject's PyDict_Next, which has a
-+    # docstring embedding a C comment
-+    def c_style_comment(a, b):
-+        '''Here is a C-style comment within an RPython docstring:
-+                /* hello world */
-+        '''
-+        # and here's one in a string literal:
-+        return '/* hello world a:%s b:%s */' % (a, b)
-+
-+    def cplusplus_style_comment(a, b):
-+        '''Here is a C++-style comment within an RPython docstring:
-+                // hello world
-+        '''
-+        # and here are some in string literals, and one as the floor division
-+        # operator:
-+        return '// hello world: a // b = %s' % (a // b)
-+
-+    for fn_name, exp_output in [('c_style_comment',
-+                                 '/* hello world a:6 b:3 */'),
-+                                ('cplusplus_style_comment',
-+                                 '// hello world: a // b = 2')]:
-+        fn = locals()[fn_name]
-+
-+        c_fn, c_src, c_filename_path = get_generated_c_source(fn, [int, int])
-+        # If the above survived, then the C compiler managed to handle
-+        # the generated C code
-+
-+        # Verify that the generated code works (i.e. that we didn't
-+        # accidentally change the meaning):
-+        assert c_fn(6, 3) == exp_output
-+
-+        # Ensure that at least part of the docstrings made it into the C
-+        # code:
-+        c_fn_src = extract_c_function(c_src, 'pypy_g_' + fn_name)
-+        assert 'Here is a ' in c_fn_src
-+        assert 'style comment within an RPython docstring' in c_fn_src
-+        
-diff -up pypy-1.5-src/pypy/translator/driver.py.more-readable-c-code pypy-1.5-src/pypy/translator/driver.py
---- pypy-1.5-src/pypy/translator/driver.py.more-readable-c-code	2011-04-30 10:18:50.000000000 -0400
-+++ pypy-1.5-src/pypy/translator/driver.py	2011-05-02 14:28:33.945161001 -0400
-@@ -536,6 +536,7 @@ class TranslationDriver(SimpleTaskEngine
-             dstname = self.compute_exe_name() + '.staticdata.info'
-             shutil.copy(str(fname), str(dstname))
-             self.log.info('Static data info written to %s' % dstname)
-+        return c_source_filename
- 
-     #
-     task_source_c = taskdef(task_source_c, ['database_c'], "Generating c source")
-diff -up pypy-1.5-src/pypy/translator/gensupp.py.more-readable-c-code pypy-1.5-src/pypy/translator/gensupp.py
---- pypy-1.5-src/pypy/translator/gensupp.py.more-readable-c-code	2011-04-30 10:18:50.000000000 -0400
-+++ pypy-1.5-src/pypy/translator/gensupp.py	2011-05-02 14:33:31.026161001 -0400
-@@ -14,8 +14,8 @@ def ordered_blocks(graph):
-     allblocks = []
-     for block in graph.iterblocks():
-             # first we order by offset in the code string
--            if block.operations:
--                ofs = block.operations[0].offset
-+            if block.operations and block.operations[0].oploc.codelocs[0]:
-+                ofs = block.operations[0].oploc.codelocs[0].offset
-             else:
-                 ofs = sys.maxint
-             # then we order by input variable name or value
-diff -up pypy-1.5-src/pypy/translator/interactive.py.more-readable-c-code pypy-1.5-src/pypy/translator/interactive.py
---- pypy-1.5-src/pypy/translator/interactive.py.more-readable-c-code	2011-04-30 10:18:50.000000000 -0400
-+++ pypy-1.5-src/pypy/translator/interactive.py	2011-05-02 14:28:33.946161001 -0400
-@@ -138,7 +138,7 @@ class Translation(object):
-     def source_c(self, argtypes=None, **kwds):
-         self.update_options(argtypes, kwds)
-         self.ensure_backend('c')
--        self.driver.source_c()
-+        return self.driver.source_c()
- 
-     def source_cl(self, argtypes=None, **kwds):
-         self.update_options(argtypes, kwds)
-diff -up pypy-1.5-src/pypy/translator/llsupport/wrapper.py.more-readable-c-code pypy-1.5-src/pypy/translator/llsupport/wrapper.py
---- pypy-1.5-src/pypy/translator/llsupport/wrapper.py.more-readable-c-code	2011-04-30 10:18:50.000000000 -0400
-+++ pypy-1.5-src/pypy/translator/llsupport/wrapper.py	2011-05-02 14:28:33.946161001 -0400
-@@ -59,6 +59,8 @@ def new_wrapper(func, translator, newnam
-     # "return result"
-     block = Block(wrapper_inputargs)
-     wgraph = FunctionGraph('pyfn_' + (newname or func.func_name), block)
-+    if hasattr(graph, 'func'):
-+        wgraph.func = graph.func
-     translator.update_call_graph(wgraph, graph, object())
-     translator.graphs.append(wgraph)
-     block.operations[:] = newops
-diff -up pypy-1.5-src/pypy/translator/simplify.py.more-readable-c-code pypy-1.5-src/pypy/translator/simplify.py
---- pypy-1.5-src/pypy/translator/simplify.py.more-readable-c-code	2011-04-30 10:18:50.000000000 -0400
-+++ pypy-1.5-src/pypy/translator/simplify.py	2011-05-02 14:28:33.952161001 -0400
-@@ -298,7 +298,7 @@ def join_blocks(graph):
-                 return renaming.get(v, v)
-             def rename_op(op):
-                 args = [rename(a) for a in op.args]
--                op = SpaceOperation(op.opname, args, rename(op.result), op.offset)
-+                op = SpaceOperation(op.opname, args, rename(op.result), op.oploc)
-                 # special case...
-                 if op.opname == 'indirect_call':
-                     if isinstance(op.args[0], Constant):
diff --git a/pypy.spec b/pypy.spec
index 2579860..1d6b6af 100644
--- a/pypy.spec
+++ b/pypy.spec
@@ -1,6 +1,6 @@
 Name:           pypy
-Version:        1.6
-Release:        7%{?dist}
+Version:        1.7
+Release:        1%{?dist}
 Summary:        Python implementation with a Just-In-Time compiler
 
 Group:          Development/Languages
@@ -126,14 +126,14 @@ BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
   %(echo '%{__os_install_post}' | sed -e 's!/usr/lib[^[:space:]]*/brp-python-bytecompile[[:space:]].*$!!g')
 
 # Source and patches:
-Source0:        https://bitbucket.org/pypy/pypy/get/release-1.6.tar.bz2
+Source0:        https://bitbucket.org/pypy/pypy/get/release-%{version}.tar.bz2
 
 # Supply various useful RPM macros for building python modules against pypy:
 #  __pypy, pypy_sitelib, pypy_sitearch
 Source2:        macros.pypy
 
 # Edit a translator file for linux in order to configure our cflags and dynamic libffi
-Patch0:         pypy-1.5-config.patch
+Patch0:         config.patch
 
 # By default, if built at a tty, the translation process renders a Mandelbrot
 # set to indicate progress.
@@ -163,7 +163,7 @@ Patch3: pypy-1.4.1-add-LIBRARY_INSTALLATION_PATH.patch
 #  http://codespeak.net/pipermail/pypy-dev/2010q4/006532.html
 # TODO: get this into the upstream bug tracker, and finish inlining
 # support (rhbz#666963)
-Patch4: pypy-1.5-more-readable-c-code.patch
+Patch4: more-readable-c-code.patch
 
 # In my koji builds, /root/bin is in the PATH for some reason
 # This leads to test_subprocess.py failing, due to "test_leaking_fds_on_error"
@@ -847,6 +847,10 @@ rm -rf $RPM_BUILD_ROOT
 
 
 %changelog
+* Mon Nov 21 2011 David Malcolm <dmalcolm at redhat.com> - 1.7-1
+- 1.7: refresh patch 0 (configuration) and patch 4 (readability of generated
+code)
+
 * Tue Oct  4 2011 David Malcolm <dmalcolm at redhat.com> - 1.6-7
 - skip test_multiprocessing
 
diff --git a/sources b/sources
index 5660f1e..197491c 100644
--- a/sources
+++ b/sources
@@ -1 +1 @@
-1189352effc5df7df84e6916b3b3eae3  release-1.6.tar.bz2
+fc22184c931ead98bdae9ec3e79595c2  release-1.7.tar.bz2
-- 
cgit v0.10.2


	http://pkgs.fedoraproject.org/cgit/pypy3.git/commit/?h=master&id=4ef3f10721000d632a9dcfcfca05c7cde0f91b95


More information about the scm-commits mailing list