[pypy-commit] pypy py3.5: hg merge default
arigo
pypy.commits at gmail.com
Sun Nov 13 04:48:44 EST 2016
Author: Armin Rigo <arigo at tunes.org>
Branch: py3.5
Changeset: r88338:65a37f0d6b93
Date: 2016-11-13 10:47 +0100
http://bitbucket.org/pypy/pypy/changeset/65a37f0d6b93/
Log: hg merge default
diff --git a/pypy/doc/release-pypy2.7-v5.6.0.rst b/pypy/doc/release-pypy2.7-v5.6.0.rst
--- a/pypy/doc/release-pypy2.7-v5.6.0.rst
+++ b/pypy/doc/release-pypy2.7-v5.6.0.rst
@@ -72,7 +72,7 @@
* **s390x** running Linux
.. _`PyPy and CPython 2.7.x`: http://speed.pypy.org
-.. _`dynamic languages`: http://pypyjs.org
+.. _`dynamic languages`: http://rpython.readthedocs.io/en/latest/examples.html
Other Highlights (since 5.4 released Aug 31, 2016)
=========================================================
diff --git a/rpython/doc/examples.rst b/rpython/doc/examples.rst
new file mode 100644
--- /dev/null
+++ b/rpython/doc/examples.rst
@@ -0,0 +1,42 @@
+Projects Using RPython
+======================
+
+A very time-dependent list of interpreters written in RPython. Corrections welcome,
+this list was last curated in
+Nov 2016
+
+Actively Developed:
+
+ * PyPy, Python, very complete and maintained, http://pypy.org
+ * Pydgin, CPU emulation framework, supports ARM well, jitted, active development, https://github.com/cornell-brg/pydgin
+ * RSqueak VM, Smalltalk, core complete, JIT working, graphics etc getting there, in active development https://github.com/HPI-SWA-Lab/RSqueak
+ * Pixie, 'A small, fast, native lisp with "magical" powers', jitted, maintained, https://github.com/pixie-lang/pixie
+ * Monte, 'A dynamic language inspired by Python and E.' has an rpython implementation, in active development, https://github.com/monte-language/typhon
+ * Typhon, 'A virtual machine for Monte', in active development, https://github.com/monte-language/typhon
+ * Tulip, an untyped functional language, in language design mode, maintained, https://github.com/tulip-lang/tulip/
+ * Pycket, a Racket implementation, proof of concept, small language core working, a lot of primitives are missing. Slow development https://github.com/samth/pycket
+ * Lever, a dynamic language with a modifiable grammar, actively developed, https://github.com/cheery/lever
+
+Complete, functioning, but inactive
+
+ * Converge 2, complete, last release version 2.1 in Feb 2015, http://convergepl.org/
+ * Pyrolog, Prolog, core complete, extensions missing, last commit in Nov 2015, http://bitbucket.org/cfbolz/pyrolog
+ * PyPy.js, adds a JavaScript backend to pypy, http://pypyjs.org
+
+Inactive (last reviewed Sept 2015):
+
+ * Topaz, Ruby, major functionality complete, library missing, inactive http://topazruby.com
+ * Rapydo, R, execution semantics complete, most builtins missing, inactive, http://bitbucket.org/cfbolz/rapydo
+ * Hippy, PHP, proof of concept, inactive, http://morepypy.blogspot.de/2012/07/hello-everyone.html
+ * Scheme, no clue about completeness, inactive, http://bitbucket.org/pypy/lang-scheme/
+ * PyGirl, Gameboy emulator, works but there is a bug somewhere, does not use JIT, unmaintained, http://bitbucket.org/pypy/lang-gameboy
+ * Javascript, proof of concept, inactive, http://bitbucket.org/pypy/lang-js
+ * An implementation of Notch's DCPU-16, https://github.com/AlekSi/dcpu16py/tree/pypy-again
+ * Haskell, core of the language works, but not many libraries, inactive http://bitbucket.org/cfbolz/haskell-python
+ * IO, no clue about completeness, inactive https://bitbucket.org/pypy/lang-io
+ * Qoppy, an implementation Qoppa, which is a scheme without special forms: https://github.com/timfel/qoppy
+ * XlispX, a toy Lisp: https://bitbucket.org/rxe/xlispx
+ * RPySOM, an RPython implementation of SOM (Simple Object Model) https://github.com/SOM-st/RPySOM
+ * SQPyte, really experimental implementation of the SQLite bytecode VM, jitted, probably inactive, https://bitbucket.org/softdevteam/sqpyte
+ * Icbink, an implementation of Kernel, core complete, naive, no JIT optimizations yet, on hiatus https://github.com/euccastro/icbink
+
diff --git a/rpython/doc/index.rst b/rpython/doc/index.rst
--- a/rpython/doc/index.rst
+++ b/rpython/doc/index.rst
@@ -25,7 +25,6 @@
architecture
faq
-
User Documentation
------------------
@@ -48,6 +47,7 @@
rpython
rlib
rffi
+ examples
RPython internals
diff --git a/rpython/tool/disassembler.py b/rpython/tool/disassembler.py
--- a/rpython/tool/disassembler.py
+++ b/rpython/tool/disassembler.py
@@ -50,6 +50,9 @@
current_lineno = opcode.lineno
self.source = source.split("\n")
+ def get_opcode_from_info(self, info):
+ return self.map[info.bytecode_no]
+
def _setup():
for opcode in opname:
if not opcode.startswith('<'):
diff --git a/rpython/tool/jitlogparser/parser.py b/rpython/tool/jitlogparser/parser.py
--- a/rpython/tool/jitlogparser/parser.py
+++ b/rpython/tool/jitlogparser/parser.py
@@ -11,15 +11,28 @@
filename = None
bytecode_no = 0
bytecode_name = None
- m = re.search('<code object ([<>\w]+)[\.,] file \'(.+?)\'[\.,] line (\d+)> #(\d+) (\w+)',
- arg)
+ mask = 0
+ # generic format: the numbers are 'startlineno-currentlineno',
+ # and this function returns currentlineno as the value
+ # 'bytecode_no = currentlineno ^ -1': i.e. it abuses bytecode_no,
+ # which doesn't make sense in the generic format, as a negative
+ # number
+ m = re.match(r'(.+?);(.+?):(\d+)-(\d+)~(.*)', arg)
+ if m is not None:
+ mask = -1
+ else:
+ # PyPy2 format: bytecode_no is really a bytecode index,
+ # which must be turned into a real line number by parsing the
+ # source file
+ m = re.search(r'<code object ([<>\w]+)[\.,] file \'(.+?)\'[\.,] '
+ r'line (\d+)> #(\d+) (\w+)', arg)
if m is None:
# a non-code loop, like StrLiteralSearch or something
if arg:
bytecode_name = arg
else:
name, filename, lineno, bytecode_no, bytecode_name = m.groups()
- return name, bytecode_name, filename, int(lineno), int(bytecode_no)
+ return name, bytecode_name, filename, int(lineno), int(bytecode_no) ^ mask
class Op(object):
bridge = None
@@ -195,8 +208,9 @@
self.startlineno, self.bytecode_no) = parsed
self.operations = operations
self.storage = storage
+ generic_format = (self.bytecode_no < 0)
self.code = storage.disassemble_code(self.filename, self.startlineno,
- self.name)
+ self.name, generic_format)
def repr(self):
if self.filename is None:
@@ -213,7 +227,7 @@
def getopcode(self):
if self.code is None:
return None
- return self.code.map[self.bytecode_no]
+ return self.code.get_opcode_from_info(self)
def getlineno(self):
code = self.getopcode()
diff --git a/rpython/tool/jitlogparser/storage.py b/rpython/tool/jitlogparser/storage.py
--- a/rpython/tool/jitlogparser/storage.py
+++ b/rpython/tool/jitlogparser/storage.py
@@ -5,6 +5,7 @@
import py
import os
+import linecache
from rpython.tool.disassembler import dis
from rpython.tool.jitlogparser.module_finder import gather_all_code_objs
@@ -29,7 +30,10 @@
self.codes[fname] = res
return res
- def disassemble_code(self, fname, startlineno, name):
+ def disassemble_code(self, fname, startlineno, name, generic_format=False):
+ # 'generic_format' is False for PyPy2 (returns a
+ # disassembler.CodeRepresentation) or True otherwise (returns a
+ # GenericCode, without attempting any disassembly)
try:
if py.path.local(fname).check(file=False):
return None # cannot find source file
@@ -39,6 +43,10 @@
try:
return self.disassembled_codes[key]
except KeyError:
+ pass
+ if generic_format:
+ res = GenericCode(fname, startlineno, name)
+ else:
codeobjs = self.load_code(fname)
if (startlineno, name) not in codeobjs:
# cannot find the code obj at this line: this can happen for
@@ -50,8 +58,8 @@
return None
code = codeobjs[(startlineno, name)]
res = dis(code)
- self.disassembled_codes[key] = res
- return res
+ self.disassembled_codes[key] = res
+ return res
def reconnect_loops(self, loops):
""" Re-connect loops in a way that entry bridges are filtered out
@@ -80,3 +88,40 @@
res.append(loop)
self.loops = res
return res
+
+
+class GenericCode(object):
+ def __init__(self, fname, startlineno, name):
+ self._fname = fname
+ self._startlineno = startlineno
+ self._name = name
+ self._first_bytecodes = {} # {lineno: info}
+ self._source = None
+
+ def __repr__(self):
+ return 'GenericCode(%r, %r, %r)' % (
+ self._fname, self._startlineno, self._name)
+
+ def get_opcode_from_info(self, info):
+ lineno = ~info.bytecode_no
+ if self._first_bytecodes.setdefault(lineno, info) is info:
+ # this is the first opcode of the line---or, at least,
+ # the first time we ask for an Opcode on that line.
+ line_starts_here = True
+ else:
+ line_starts_here = False
+ return GenericOpcode(lineno, line_starts_here)
+
+ @property
+ def source(self):
+ if self._source is None:
+ src = linecache.getlines(self._fname)
+ if self._startlineno > 0:
+ src = src[self._startlineno - 1:]
+ self._source = [s.rstrip('\n\r') for s in src]
+ return self._source
+
+class GenericOpcode(object):
+ def __init__(self, lineno, line_starts_here):
+ self.lineno = lineno
+ self.line_starts_here = line_starts_here
diff --git a/rpython/tool/jitlogparser/test/test_parser.py b/rpython/tool/jitlogparser/test/test_parser.py
--- a/rpython/tool/jitlogparser/test/test_parser.py
+++ b/rpython/tool/jitlogparser/test/test_parser.py
@@ -2,7 +2,8 @@
Function, adjust_bridges,
import_log, split_trace, Op,
parse_log_counts)
-from rpython.tool.jitlogparser.storage import LoopStorage
+from rpython.tool.jitlogparser.storage import LoopStorage, GenericCode
+from rpython.tool.udir import udir
import py, sys
from rpython.jit.backend.detect_cpu import autodetect
from rpython.jit.backend.tool.viewcode import ObjdumpNotFound
@@ -381,4 +382,58 @@
""")
f = Function.from_operations(loop.operations, LoopStorage())
assert len(f.chunks) == 2
-
+
+def test_embedded_lineno():
+ # debug_merge_point() can have a text that is either:
+ #
+ # * the PyPy2's <code object %s. file '%s'. line %d> #%d %s>
+ # funcname, filename, lineno, bytecode_no, bytecode_name
+ #
+ # * a standard text of the form %s;%s:%d-%d-%d %s
+ # funcname, filename, startlineno, curlineno, endlineno, anything
+ #
+ # * or anything else, which is not specially recognized but shouldn't crash
+ #
+ sourcefile = str(udir.join('test_embedded_lineno.src'))
+ with open(sourcefile, 'w') as f:
+ print >> f, "A#1"
+ print >> f, "B#2"
+ print >> f, "C#3"
+ print >> f, "D#4"
+ print >> f, "E#5"
+ print >> f, "F#6"
+ loop = parse("""
+ []
+ debug_merge_point(0, 0, 'myfunc;%(filename)s:2-2~one')
+ debug_merge_point(0, 0, 'myfunc;%(filename)s:2-2~two')
+ debug_merge_point(0, 0, 'myfunc;%(filename)s:2-4~')
+ debug_merge_point(0, 0, 'myfunc;%(filename)s:2-4~four')
+ """ % {'filename': sourcefile})
+ f = Function.from_operations(loop.operations, LoopStorage())
+
+ expect = [(2, 'one', True),
+ (2, 'two', False),
+ (4, '', True),
+ (4, 'four', False)]
+ assert len(f.chunks) == len(expect)
+
+ code_seen = set()
+ for chunk, (expected_lineno,
+ expected_bytecode_name,
+ expected_line_starts_here) in zip(f.chunks, expect):
+ assert chunk.name == 'myfunc'
+ assert chunk.bytecode_name == expected_bytecode_name
+ assert chunk.filename == sourcefile
+ assert chunk.startlineno == 2
+ assert chunk.bytecode_no == ~expected_lineno # half-abuse
+ assert chunk.has_valid_code()
+ assert chunk.lineno == expected_lineno
+ assert chunk.line_starts_here == expected_line_starts_here
+ code_seen.add(chunk.code)
+
+ assert len(code_seen) == 1
+ code, = code_seen
+ assert code.source[0] == "B#2"
+ assert code.source[1] == "C#3"
+ assert code.source[4] == "F#6"
+ py.test.raises(IndexError, "code.source[5]")
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
@@ -926,6 +926,13 @@
assert lineoffset in (1,2)
return [InsnStackAdjust(-4)]
+ if target.startswith('__x86.get_pc_thunk.'):
+ # special case, found on x86-32: these static functions
+ # contain only a simple load of some non-GC pointer to
+ # a specific register (not necessarily EAX)
+ reg = '%e' + target.split('.')[-1]
+ return [InsnSetLocal(reg)]
+
insns = [InsnCall(target, self.currentlineno),
InsnSetLocal(self.EAX)] # the result is there
if self.format in ('mingw32', 'msvc'):
More information about the pypy-commit
mailing list