Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Understanding RPython

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.

Understanding RPython

Avatar for David Beazley

David Beazley

January 13, 2012
Tweet

More Decks by David Beazley

Other Decks in Programming

Transcript

  1. PyPy Project • You've probably heard about PyPy • Python

    implemented in Python • It is apparently quite fast • Smart people seem to work on it • How it works: Magic? Souls of grad students?
  2. Concerns • Honestly, PyPy scares me a little bit •

    Actually, it's the implementation that scares me • Can I make it fit my brain? • Can "normal" programmers understand it? • Can you debug it? • Can you modify it?
  3. Building PyPy from source (at 64x speed) On a machine

    with 8GB RAM Please Explain (and debug)
  4. Premise • I think a big part of Python's success

    is due to the fact that "normal" programmers are easily able to tinker with the implementation • Written in ANSI C • Uses standard tools (make, autoconf, etc.) • Well documented
  5. Why it Matters • People can submit bug reports (with

    patches) • People can make extensions • People can port Python to new environments • People can experiment with it • Everything great about Python has happened because of tinkering
  6. PyPy • An advanced research project • Lots of academic

    papers and tech reports • Many high-level presentations • A fair bit of documentation • A lot of information giving you the "gist"
  7. Detailed Tech Reports To be fair, it's a funded academic

    project in PL. They have no other choice than to write like this.
  8. Detailed Tech Reports To be fair, it's a funded academic

    project in PL. They have no other choice than to write like this. (maybe I'll just read the source code)
  9. This Talk • A tiny bit about how PyPy works

    at an implementation level (e.g., code) • Specifically, rpython • Based on a lot of personal tinkering with it • Mainly, I'm just curious • Is there anything to take away?
  10. Disclaimer • I am not affiliated with PyPy in any

    way • Have not used it for any real project • Have contributed nothing to it except a bug report about bad GIL behavior (sic) • Have general awareness based on various conference presentations, blog posts, etc.
  11. PyPy Overview • PyPy is Python implemented in Python Interpreter

    (ANSI C) Python Program Interpreter (Python) Python Program CPython PyPy • You can run PyPy as a normal Python script
  12. Running py.py • Running as a script... Interpreter (Python) Python

    Program PyPy bash % python py.py [platform:execute] gcc-4.0 -c -arch x86_64 -O3 -fomit-frame-pointer - \ [platform:execute] gcc-4.0 -c -arch x86_64 -O3 -fomit-frame-pointer - \ ... PyPy 1.7.0 in StdObjSpace on top of Python 2.7.2 (startuptime: 34.51 secs) >>>> Interpreter (ANSI C) • Performance is dreadful • Just for testing
  13. rpython • PyPy is actually implemented in "rpython" • rpython

    is not an "interpreter", but a restricted subset of the Python language Python rpython • It can run as valid Python code, but that's about the only similarity
  14. rpython • rpython is a completely different language • Python

    syntax, yes. • Must be compiled (like C, C++, etc.) • Static typing via type inference • If you love Python, you will hate rpython • Closest comparable language I've used: ML
  15. Hello World • Sample rpython Program # hello.py def main(argv):

    print "Hello World" return 0 def target(*args): return main, None • Must have a C-like entry point (main) • Must define target() to identify the entry
  16. Translation (Compilation) • rpython programs must be translated bash %

    pypy/translator/goal/translate.py hello.py [platform:msg] Setting platform to 'host' cc=None [translation:info] Translating target as defined by hello [platform:execute] gcc-4.0 -c -arch x86_64 -O3 - fomit-frame-pointer -mdynamic-no-pic /var/folders/- \ ... lots of additional output ... • Creates a C program and compiles it bash % ./hello-c Hello World bash %
  17. A Real World Example • Fibonacci numbers (of course) #

    fib.py def fib(n): if n < 2: return 1 else: return fib(n-1) + fib(n-2) def main(argv): print fib(int(argv[1])) return 0 def target(*args): return main, None
  18. A Real World Example • Fibonacci numbers (of course) #

    fib.py def fib(n): if n < 2: return 1 else: return fib(n-1) + fib(n-2) def main(argv): print fib(int(argv[1])) return 0 def target(*args): return main, None CPython 2.7 95.4s pypy 17.0s rpython 2.6s ANSI C (-O2) 2.1s Yes, it is fast
  19. Type Inference • Type inference illustrated # fib.py def fib(n):

    if n < 2: return 1 else: return fib(n-1) + fib(n-2) def main(argv): print fib(int(argv[1])) return 0 def target(*args): return main, None
  20. Type Inference • Type inference illustrated # fib.py def fib(n):

    if n < 2: return 1 else: return fib(n-1) + fib(n-2) def main(argv): print fib(int(argv[1])) return 0 def target(*args): return main, None int
  21. Type Inference • Type inference illustrated # fib.py def fib(n):

    if n < 2: return 1 else: return fib(n-1) + fib(n-2) def main(argv): print fib(int(argv[1])) return 0 def target(*args): return main, None int int
  22. Type Inference • Type inference illustrated # fib.py def fib(n):

    if n < 2: return 1 else: return fib(n-1) + fib(n-2) def main(argv): print fib(int(argv[1])) return 0 def target(*args): return main, None int int int
  23. Type Inference • Type inference illustrated # fib.py def fib(n):

    if n < 2: return 1 else: return fib(n-1) + fib(n-2) def main(argv): print fib(int(argv[1])) return 0 def target(*args): return main, None int int int int
  24. Type Inference • Type inference illustrated # fib.py def fib(n):

    if n < 2: return 1 else: return fib(n-1) + fib(n-2) def main(argv): print fib(int(argv[1])) return 0 def target(*args): return main, None int int int int It's fast because types are attached to everything (like C) Resulting code is stripped of all "dynamic" features
  25. R is for Restricted • rpython allows no dynamic typing

    def add(x,y): return x+y def main(argv): r1 = add(2,3) # Ok r2 = add("Hello","World") # Error return 0 • Functions can only have one type signature • Determined on first use
  26. Sample Error Message [translation:ERROR] raise AnnotatorError(msgstr) [translation:ERROR] AnnotatorError': annotation of

    'union' degenerated to SomeObje [translation:ERROR] Simple call of incompatible family: [translation:ERROR] (KeyError getting at the binding!) [translation:ERROR] [translation:ERROR] In <FunctionGraph of (func:4)main at 0x181c7d8>: [translation:ERROR] Happened at file func.py line 6 [translation:ERROR] [translation:ERROR] r1 = add(2,3) [translation:ERROR] ==> r2 = add("Hello","World") [translation:ERROR] [translation:ERROR] Previous annotation: [translation:ERROR] (none) [translation:ERROR] .. v8 = simple_call((function add), ('Hello'), ('World')) [translation:ERROR] .. '(func:4)main' [translation:ERROR] Processing block: [translation:ERROR] block@9 is a <class 'pypy.objspace.flow.flowcontext.SpamBlock' [translation:ERROR] in (func:4)main [translation:ERROR] containing the following operations: [translation:ERROR] v3 = simple_call((function add), (2), (3)) [translation:ERROR] v8 = simple_call((function add), ('Hello'), ('World')) [translation:ERROR] --end--
  27. R is for Restricted • Containers can only have a

    single type numbers = [1,2,3,4,5] # Ok items = [1, "Hello", 3.5] # Error names = { # Ok 'dabeaz' : 'David Beazley', 'gaynor' : 'Alex Gaynor', } record = { # Error 'name' : 'ACME', 'shares' : 100 } • Think C, not Python.
  28. R is for Restricted • Attributes can only be a

    single type class Pair(object): def __init__(self,x,y): self.x = x self.y = y a = Pair(2,3) # OK (first use) b = Pair("Hello","World") # Error • Again, think C
  29. R is for Restricted • Mixing datatypes requires boxing/unboxing class

    SomeValue(object): pass class IntValue(SomeValue): def __init__(self,value): self.value = value def getint(self): return self.value class StrValue(SomeValue): def __init__(self,value): self.value = value def getstr(self): return self.value # Error record = { 'name' : 'Dave', 'clout' : 13 } # OK record = { 'name' : StrValue('Dave'), 'clout' : IntValue(13) } print record['name'].getstr() print record['clout'].getint() • All objects are of type "SomeValue"
  30. R is for Restricted • PyPy developers seem to indicate

    that end- users shouldn't mess around with rpython • I agree • It's not the python that you know • Trades speed for annoyance • Missing a lot of features (e.g., generators)
  31. rpython Translation • The really interesting part of rpython is

    the translation process • rpython takes your Python program and turns it into C code which is then compiled • This is done without "parsing" your program or doing anything that looks like the operation of traditional compiler
  32. rpython Translation • Translation process works on a live imported

    version of your code in a standard Python interpreter • Driven entirely through introspection of the underlying bytecode • Let's peel back the covers....
  33. rpython Translation # Some Python code def ctest(a,b,c): d =

    a + b if d < c: e = d - c else: e = d + c return e >>> dis.dis(ctest) 4 0 LOAD_FAST 0 (a) 3 LOAD_FAST 1 (b) 6 BINARY_ADD 7 STORE_FAST 3 (d) 5 10 LOAD_FAST 3 (d) 13 LOAD_FAST 2 (c) 16 COMPARE_OP 0 (<) 19 JUMP_IF_FALSE 14 (to 36) 22 POP_TOP 6 23 LOAD_FAST 3 (d) 26 LOAD_FAST 2 (c) 29 BINARY_SUBTRACT 30 STORE_FAST 4 (e) 33 JUMP_FORWARD 11 (to 47) >> 36 POP_TOP 8 37 LOAD_FAST 3 (d) 40 LOAD_FAST 2 (c) 43 BINARY_ADD 44 STORE_FAST 4 (e) 9 >> 47 LOAD_FAST 4 (e) 50 RETURN_VALUE • All Python code is compiled to bytecode
  34. rpython Translation >>> ctest.__code__ <code object ctest at 0x33a968, file

    "ctest.py", line 3> >>> ctest.__code__.co_code '|\x00\x00|\x01\x00\x17}\x03\x00|\x03\x00|\x02\x00j\x00\x00o\n\x \x03\x00}\x04\x00n\x07\x00\x01|\x02\x00}\x04\x00|\x04\x00S' >>> ctest.__code__.co_varnames ('a', 'b', 'c', 'd', 'e') >>> ctest.__code__.co_argcount 3 >>> ctest.__code__.co_nlocals 5 >>> • Compiled code held in code objects • rpython operates entirely from this (not source)!
  35. Bytecode Interpretation • A core part of PyPy consists of

    a Python bytecode interpreter (remember, it's Python implemented in Python) • A modular design that allows different backends (object spaces) to be plugged into it bytecode interpreter object space (implementation of the bytecodes)
  36. Abstract Interpretation • rpython takes Python code objects from CPython

    and interprets them using the pypy byte code interpreter (head explodes) • A special "flow space" monitors and records the actual operations that get performed • Assembles the operations into a flow graph describing the program
  37. Abstract Interpretation 0 LOAD_FAST 0 (a) 3 LOAD_FAST 1 (b)

    6 BINARY_ADD 7 STORE_FAST 3 (d) 10 LOAD_FAST 3 (d) 13 LOAD_FAST 2 (c) 16 COMPARE_OP 0 (<) 19 JUMP_IF_FALSE 14 (to 36) 22 POP_TOP 23 LOAD_FAST 3 (d) 26 LOAD_FAST 2 (c) 29 BINARY_SUBTRACT 30 STORE_FAST 4 (e) 33 JUMP_FORWARD 11 (to 47) 36 POP_TOP 37 LOAD_FAST 3 (d) 40 LOAD_FAST 2 (c) 43 BINARY_ADD 44 STORE_FAST 4 (e) 47 LOAD_FAST 4 (e) 50 RETURN_VALUE Instruction stream is "executed" in the abstract
  38. Abstract Interpretation 0 LOAD_FAST 0 (a) 3 LOAD_FAST 1 (b)

    6 BINARY_ADD 7 STORE_FAST 3 (d) 10 LOAD_FAST 3 (d) 13 LOAD_FAST 2 (c) 16 COMPARE_OP 0 (<) 19 JUMP_IF_FALSE 14 (to 36) 22 POP_TOP 23 LOAD_FAST 3 (d) 26 LOAD_FAST 2 (c) 29 BINARY_SUBTRACT 30 STORE_FAST 4 (e) 33 JUMP_FORWARD 11 (to 47) 36 POP_TOP 37 LOAD_FAST 3 (d) 40 LOAD_FAST 2 (c) 43 BINARY_ADD 44 STORE_FAST 4 (e) 47 LOAD_FAST 4 (e) 50 RETURN_VALUE Start block is created. Inputs are initial stack frame Inputs: [a_0, b_0, c_0, None, None, None, None]
  39. Abstract Interpretation 0 LOAD_FAST 0 (a) 3 LOAD_FAST 1 (b)

    6 BINARY_ADD 7 STORE_FAST 3 (d) 10 LOAD_FAST 3 (d) 13 LOAD_FAST 2 (c) 16 COMPARE_OP 0 (<) 19 JUMP_IF_FALSE 14 (to 36) 22 POP_TOP 23 LOAD_FAST 3 (d) 26 LOAD_FAST 2 (c) 29 BINARY_SUBTRACT 30 STORE_FAST 4 (e) 33 JUMP_FORWARD 11 (to 47) 36 POP_TOP 37 LOAD_FAST 3 (d) 40 LOAD_FAST 2 (c) 43 BINARY_ADD 44 STORE_FAST 4 (e) 47 LOAD_FAST 4 (e) 50 RETURN_VALUE Inputs: [a_0, b_0, c_0, None, None, None, None] Start executing instructions and updating the frame [a_0, b_0, c_0, None, None, a_0, None]
  40. Abstract Interpretation 0 LOAD_FAST 0 (a) 3 LOAD_FAST 1 (b)

    6 BINARY_ADD 7 STORE_FAST 3 (d) 10 LOAD_FAST 3 (d) 13 LOAD_FAST 2 (c) 16 COMPARE_OP 0 (<) 19 JUMP_IF_FALSE 14 (to 36) 22 POP_TOP 23 LOAD_FAST 3 (d) 26 LOAD_FAST 2 (c) 29 BINARY_SUBTRACT 30 STORE_FAST 4 (e) 33 JUMP_FORWARD 11 (to 47) 36 POP_TOP 37 LOAD_FAST 3 (d) 40 LOAD_FAST 2 (c) 43 BINARY_ADD 44 STORE_FAST 4 (e) 47 LOAD_FAST 4 (e) 50 RETURN_VALUE Inputs: [a_0, b_0, c_0, None, None, None, None] [a_0, b_0, c_0, None, None, a_0, None] [a_0, b_0, c_0, None, None, a_0, b_0] Start executing instructions and updating the frame
  41. Abstract Interpretation 0 LOAD_FAST 0 (a) 3 LOAD_FAST 1 (b)

    6 BINARY_ADD 7 STORE_FAST 3 (d) 10 LOAD_FAST 3 (d) 13 LOAD_FAST 2 (c) 16 COMPARE_OP 0 (<) 19 JUMP_IF_FALSE 14 (to 36) 22 POP_TOP 23 LOAD_FAST 3 (d) 26 LOAD_FAST 2 (c) 29 BINARY_SUBTRACT 30 STORE_FAST 4 (e) 33 JUMP_FORWARD 11 (to 47) 36 POP_TOP 37 LOAD_FAST 3 (d) 40 LOAD_FAST 2 (c) 43 BINARY_ADD 44 STORE_FAST 4 (e) 47 LOAD_FAST 4 (e) 50 RETURN_VALUE Inputs: [a_0, b_0, c_0, None, None, None, None] Notice how the stack is getting updated (keeps track of where things are) [a_0, b_0, c_0, None, None, a_0, None] [a_0, b_0, c_0, None, None, a_0, b_0]
  42. Abstract Interpretation 0 LOAD_FAST 0 (a) 3 LOAD_FAST 1 (b)

    6 BINARY_ADD 7 STORE_FAST 3 (d) 10 LOAD_FAST 3 (d) 13 LOAD_FAST 2 (c) 16 COMPARE_OP 0 (<) 19 JUMP_IF_FALSE 14 (to 36) 22 POP_TOP 23 LOAD_FAST 3 (d) 26 LOAD_FAST 2 (c) 29 BINARY_SUBTRACT 30 STORE_FAST 4 (e) 33 JUMP_FORWARD 11 (to 47) 36 POP_TOP 37 LOAD_FAST 3 (d) 40 LOAD_FAST 2 (c) 43 BINARY_ADD 44 STORE_FAST 4 (e) 47 LOAD_FAST 4 (e) 50 RETURN_VALUE Inputs: [a_0, b_0, c_0, None, None, None, None] Operation causes the creation of a new block (inputs represent stack state) [a_0, b_0, c_0, None, None, a_0, None] [a_0, b_0, c_0, None, None, a_0, b_0] Inputs: [a_1, b_1, c_1, None, None, v6, v7] [a_1, b_1, c_1, None, None, v8, None] v8=add(v6,v7)
  43. Abstract Interpretation 0 LOAD_FAST 0 (a) 3 LOAD_FAST 1 (b)

    6 BINARY_ADD 7 STORE_FAST 3 (d) 10 LOAD_FAST 3 (d) 13 LOAD_FAST 2 (c) 16 COMPARE_OP 0 (<) 19 JUMP_IF_FALSE 14 (to 36) 22 POP_TOP 23 LOAD_FAST 3 (d) 26 LOAD_FAST 2 (c) 29 BINARY_SUBTRACT 30 STORE_FAST 4 (e) 33 JUMP_FORWARD 11 (to 47) 36 POP_TOP 37 LOAD_FAST 3 (d) 40 LOAD_FAST 2 (c) 43 BINARY_ADD 44 STORE_FAST 4 (e) 47 LOAD_FAST 4 (e) 50 RETURN_VALUE Inputs: [a_0, b_0, c_0, None, None, None, None] Keep updating the frame [a_0, b_0, c_0, None, None, a_0, None] [a_0, b_0, c_0, None, None, a_0, b_0] Inputs: [a_1, b_1, c_1, None, None, v6, v7] [a_1, b_1, c_1, None, None, v8, None] [a_1, b_1, c_1, v8, None, None, None] v8=add(v6,v7)
  44. Abstract Interpretation 0 LOAD_FAST 0 (a) 3 LOAD_FAST 1 (b)

    6 BINARY_ADD 7 STORE_FAST 3 (d) 10 LOAD_FAST 3 (d) 13 LOAD_FAST 2 (c) 16 COMPARE_OP 0 (<) 19 JUMP_IF_FALSE 14 (to 36) 22 POP_TOP 23 LOAD_FAST 3 (d) 26 LOAD_FAST 2 (c) 29 BINARY_SUBTRACT 30 STORE_FAST 4 (e) 33 JUMP_FORWARD 11 (to 47) 36 POP_TOP 37 LOAD_FAST 3 (d) 40 LOAD_FAST 2 (c) 43 BINARY_ADD 44 STORE_FAST 4 (e) 47 LOAD_FAST 4 (e) 50 RETURN_VALUE Inputs: [a_0, b_0, c_0, None, None, None, None] Keep updating the frame [a_0, b_0, c_0, None, None, a_0, None] [a_0, b_0, c_0, None, None, a_0, b_0] Inputs: [a_1, b_1, c_1, None, None, v6, v7] [a_1, b_1, c_1, None, None, v8, None] [a_1, b_1, c_1, v8, None, None, None] [a_1, b_1, c_1, v8, None, v8, None] v8=add(v6,v7)
  45. Abstract Interpretation 0 LOAD_FAST 0 (a) 3 LOAD_FAST 1 (b)

    6 BINARY_ADD 7 STORE_FAST 3 (d) 10 LOAD_FAST 3 (d) 13 LOAD_FAST 2 (c) 16 COMPARE_OP 0 (<) 19 JUMP_IF_FALSE 14 (to 36) 22 POP_TOP 23 LOAD_FAST 3 (d) 26 LOAD_FAST 2 (c) 29 BINARY_SUBTRACT 30 STORE_FAST 4 (e) 33 JUMP_FORWARD 11 (to 47) 36 POP_TOP 37 LOAD_FAST 3 (d) 40 LOAD_FAST 2 (c) 43 BINARY_ADD 44 STORE_FAST 4 (e) 47 LOAD_FAST 4 (e) 50 RETURN_VALUE Inputs: [a_0, b_0, c_0, None, None, None, None] Keep updating the frame [a_0, b_0, c_0, None, None, a_0, None] [a_0, b_0, c_0, None, None, a_0, b_0] Inputs: [a_1, b_1, c_1, None, None, v6, v7] [a_1, b_1, c_1, None, None, v8, None] [a_1, b_1, c_1, v8, None, None, None] [a_1, b_1, c_1, v8, None, v8, None] [a_1, b_1, c_1, v8, None, v8, c_1 ] v8=add(v6,v7)
  46. Abstract Interpretation 0 LOAD_FAST 0 (a) 3 LOAD_FAST 1 (b)

    6 BINARY_ADD 7 STORE_FAST 3 (d) 10 LOAD_FAST 3 (d) 13 LOAD_FAST 2 (c) 16 COMPARE_OP 0 (<) 19 JUMP_IF_FALSE 14 (to 36) 22 POP_TOP 23 LOAD_FAST 3 (d) 26 LOAD_FAST 2 (c) 29 BINARY_SUBTRACT 30 STORE_FAST 4 (e) 33 JUMP_FORWARD 11 (to 47) 36 POP_TOP 37 LOAD_FAST 3 (d) 40 LOAD_FAST 2 (c) 43 BINARY_ADD 44 STORE_FAST 4 (e) 47 LOAD_FAST 4 (e) 50 RETURN_VALUE Inputs: [a_0, b_0, c_0, None, None, None, None] Operation means a new block [a_0, b_0, c_0, None, None, a_0, None] [a_0, b_0, c_0, None, None, a_0, b_0] Inputs: [a_1, b_1, c_1, None, None, v6, v7] [a_1, b_1, c_1, None, None, v8, None] [a_1, b_1, c_1, v8, None, None, None] [a_1, b_1, c_1, v8, None, v8, None] [a_1, b_1, c_1, v8, None, v8, c_1 ] v8=add(v6,v7) Inputs: [a_2, b_2, c_2, d_0, None, v13, v14] [a_2, b_2, c_2, d_0, None, v15, None] v15=lt(v13, v14)
  47. Abstract Interpretation 0 LOAD_FAST 0 (a) 3 LOAD_FAST 1 (b)

    6 BINARY_ADD 7 STORE_FAST 3 (d) 10 LOAD_FAST 3 (d) 13 LOAD_FAST 2 (c) 16 COMPARE_OP 0 (<) 19 JUMP_IF_FALSE 14 (to 36) 22 POP_TOP 23 LOAD_FAST 3 (d) 26 LOAD_FAST 2 (c) 29 BINARY_SUBTRACT 30 STORE_FAST 4 (e) 33 JUMP_FORWARD 11 (to 47) 36 POP_TOP 37 LOAD_FAST 3 (d) 40 LOAD_FAST 2 (c) 43 BINARY_ADD 44 STORE_FAST 4 (e) 47 LOAD_FAST 4 (e) 50 RETURN_VALUE Inputs: [a_0, b_0, c_0, None, None, None, None] [a_0, b_0, c_0, None, None, a_0, None] [a_0, b_0, c_0, None, None, a_0, b_0] Inputs: [a_1, b_1, c_1, None, None, v6, v7] [a_1, b_1, c_1, None, None, v8, None] [a_1, b_1, c_1, v8, None, None, None] [a_1, b_1, c_1, v8, None, v8, None] [a_1, b_1, c_1, v8, None, v8, c_1 ] v8=add(v6,v7) Inputs: [a_2, b_2, c_2, d_0, None, v13, v14] [a_2, b_2, c_2, d_0, None, v15, None] v15=lt(v13, v14) Critical: Each operation lives in its own block
  48. Abstract Interpretation 0 LOAD_FAST 0 (a) 3 LOAD_FAST 1 (b)

    6 BINARY_ADD 7 STORE_FAST 3 (d) 10 LOAD_FAST 3 (d) 13 LOAD_FAST 2 (c) 16 COMPARE_OP 0 (<) 19 JUMP_IF_FALSE 14 (to 36) 22 POP_TOP 23 LOAD_FAST 3 (d) 26 LOAD_FAST 2 (c) 29 BINARY_SUBTRACT 30 STORE_FAST 4 (e) 33 JUMP_FORWARD 11 (to 47) 36 POP_TOP 37 LOAD_FAST 3 (d) 40 LOAD_FAST 2 (c) 43 BINARY_ADD 44 STORE_FAST 4 (e) 47 LOAD_FAST 4 (e) 50 RETURN_VALUE Inputs: [a_2, b_2, c_2, d_0, None, v13, v14] [a_2, b_2, c_2, d_0, None, v15, None] v15=lt(v13, v14) [a_3, b_3, c_3, d_1, None, v21, None] v21=is_true(v20) Inputs: [a_3, b_3, c_3, d_1, None, v20, None]
  49. Abstract Interpretation 0 LOAD_FAST 0 (a) 3 LOAD_FAST 1 (b)

    6 BINARY_ADD 7 STORE_FAST 3 (d) 10 LOAD_FAST 3 (d) 13 LOAD_FAST 2 (c) 16 COMPARE_OP 0 (<) 19 JUMP_IF_FALSE 14 (to 36) 22 POP_TOP 23 LOAD_FAST 3 (d) 26 LOAD_FAST 2 (c) 29 BINARY_SUBTRACT 30 STORE_FAST 4 (e) 33 JUMP_FORWARD 11 (to 47) 36 POP_TOP 37 LOAD_FAST 3 (d) 40 LOAD_FAST 2 (c) 43 BINARY_ADD 44 STORE_FAST 4 (e) 47 LOAD_FAST 4 (e) 50 RETURN_VALUE Inputs: [a_2, b_2, c_2, d_0, None, v13, v14] [a_2, b_2, c_2, d_0, None, v15, None] v15=lt(v13, v14) [a_3, b_3, c_3, d_1, None, v21, None] v21=is_true(v20) Inputs: [a_3, b_3, c_3, d_1, None, v20, None] Let's talk branches: Must explore both the true/false branches
  50. Abstract Interpretation 0 LOAD_FAST 0 (a) 3 LOAD_FAST 1 (b)

    6 BINARY_ADD 7 STORE_FAST 3 (d) 10 LOAD_FAST 3 (d) 13 LOAD_FAST 2 (c) 16 COMPARE_OP 0 (<) 19 JUMP_IF_FALSE 14 (to 36) 22 POP_TOP 23 LOAD_FAST 3 (d) 26 LOAD_FAST 2 (c) 29 BINARY_SUBTRACT 30 STORE_FAST 4 (e) 33 JUMP_FORWARD 11 (to 47) 36 POP_TOP 37 LOAD_FAST 3 (d) 40 LOAD_FAST 2 (c) 43 BINARY_ADD 44 STORE_FAST 4 (e) 47 LOAD_FAST 4 (e) 50 RETURN_VALUE Inputs: [a_2, b_2, c_2, d_0, None, v13, v14] [a_2, b_2, c_2, d_0, None, v15, None] v15=lt(v13, v14) [a_3, b_3, c_3, d_1, None, v21, None] v21=is_true(v20) Inputs: [a_3, b_3, c_3, d_1, None, v20, None] [a_3, b_3, c_3, d_1, None, None, None] v21=is_true(v20) Inputs: [a_3, b_3, c_3, d_1, None, v21, None] false
  51. Abstract Interpretation 0 LOAD_FAST 0 (a) 3 LOAD_FAST 1 (b)

    6 BINARY_ADD 7 STORE_FAST 3 (d) 10 LOAD_FAST 3 (d) 13 LOAD_FAST 2 (c) 16 COMPARE_OP 0 (<) 19 JUMP_IF_FALSE 14 (to 36) 22 POP_TOP 23 LOAD_FAST 3 (d) 26 LOAD_FAST 2 (c) 29 BINARY_SUBTRACT 30 STORE_FAST 4 (e) 33 JUMP_FORWARD 11 (to 47) 36 POP_TOP 37 LOAD_FAST 3 (d) 40 LOAD_FAST 2 (c) 43 BINARY_ADD 44 STORE_FAST 4 (e) 47 LOAD_FAST 4 (e) 50 RETURN_VALUE Inputs: [a_2, b_2, c_2, d_0, None, v13, v14] [a_2, b_2, c_2, d_0, None, v15, None] v15=lt(v13, v14) [a_3, b_3, c_3, d_1, None, v21, None] v21=is_true(v20) Inputs: [a_3, b_3, c_3, d_1, None, v20, None] [a_3, b_3, c_3, d_1, None, None, None] [a_3, b_3, c_3, d_1, None, d_1, None] v21=is_true(v20) Inputs: [a_3, b_3, c_3, d_1, None, v21, None] false
  52. Abstract Interpretation 0 LOAD_FAST 0 (a) 3 LOAD_FAST 1 (b)

    6 BINARY_ADD 7 STORE_FAST 3 (d) 10 LOAD_FAST 3 (d) 13 LOAD_FAST 2 (c) 16 COMPARE_OP 0 (<) 19 JUMP_IF_FALSE 14 (to 36) 22 POP_TOP 23 LOAD_FAST 3 (d) 26 LOAD_FAST 2 (c) 29 BINARY_SUBTRACT 30 STORE_FAST 4 (e) 33 JUMP_FORWARD 11 (to 47) 36 POP_TOP 37 LOAD_FAST 3 (d) 40 LOAD_FAST 2 (c) 43 BINARY_ADD 44 STORE_FAST 4 (e) 47 LOAD_FAST 4 (e) 50 RETURN_VALUE Inputs: [a_2, b_2, c_2, d_0, None, v13, v14] [a_2, b_2, c_2, d_0, None, v15, None] v15=lt(v13, v14) [a_3, b_3, c_3, d_1, None, v21, None] v21=is_true(v20) Inputs: [a_3, b_3, c_3, d_1, None, v20, None] [a_3, b_3, c_3, d_1, None, None, None] [a_3, b_3, c_3, d_1, None, d_1, None] [a_3, b_3, c_3, d_1, None, d_1, c_3 ] v21=is_true(v20) Inputs: [a_3, b_3, c_3, d_1, None, v21, None] false
  53. Abstract Interpretation 0 LOAD_FAST 0 (a) 3 LOAD_FAST 1 (b)

    6 BINARY_ADD 7 STORE_FAST 3 (d) 10 LOAD_FAST 3 (d) 13 LOAD_FAST 2 (c) 16 COMPARE_OP 0 (<) 19 JUMP_IF_FALSE 14 (to 36) 22 POP_TOP 23 LOAD_FAST 3 (d) 26 LOAD_FAST 2 (c) 29 BINARY_SUBTRACT 30 STORE_FAST 4 (e) 33 JUMP_FORWARD 11 (to 47) 36 POP_TOP 37 LOAD_FAST 3 (d) 40 LOAD_FAST 2 (c) 43 BINARY_ADD 44 STORE_FAST 4 (e) 47 LOAD_FAST 4 (e) 50 RETURN_VALUE Inputs: [a_2, b_2, c_2, d_0, None, v13, v14] [a_2, b_2, c_2, d_0, None, v15, None] v15=lt(v13, v14) [a_3, b_3, c_3, d_1, None, v21, None] v21=is_true(v20) Inputs: [a_3, b_3, c_3, d_1, None, v20, None] [a_3, b_3, c_3, d_1, None, None, None] [a_3, b_3, c_3, d_1, None, d_1, None] [a_3, b_3, c_3, d_1, None, d_1, c_3 ] v21=is_true(v20) Inputs: [a_3, b_3, c_3, d_1, None, v21, None] false [a_3, b_3, c_3, d_1, None, None, None] v21=is_true(v20) Inputs: [a_3, b_3, c_3, d_1, None, v21, None] true
  54. Abstract Interpretation 0 LOAD_FAST 0 (a) 3 LOAD_FAST 1 (b)

    6 BINARY_ADD 7 STORE_FAST 3 (d) 10 LOAD_FAST 3 (d) 13 LOAD_FAST 2 (c) 16 COMPARE_OP 0 (<) 19 JUMP_IF_FALSE 14 (to 36) 22 POP_TOP 23 LOAD_FAST 3 (d) 26 LOAD_FAST 2 (c) 29 BINARY_SUBTRACT 30 STORE_FAST 4 (e) 33 JUMP_FORWARD 11 (to 47) 36 POP_TOP 37 LOAD_FAST 3 (d) 40 LOAD_FAST 2 (c) 43 BINARY_ADD 44 STORE_FAST 4 (e) 47 LOAD_FAST 4 (e) 50 RETURN_VALUE Inputs: [a_2, b_2, c_2, d_0, None, v13, v14] [a_2, b_2, c_2, d_0, None, v15, None] v15=lt(v13, v14) [a_3, b_3, c_3, d_1, None, v21, None] v21=is_true(v20) Inputs: [a_3, b_3, c_3, d_1, None, v20, None] [a_3, b_3, c_3, d_1, None, None, None] [a_3, b_3, c_3, d_1, None, d_1, None] [a_3, b_3, c_3, d_1, None, d_1, c_3 ] v21=is_true(v20) Inputs: [a_3, b_3, c_3, d_1, None, v21, None] false [a_3, b_3, c_3, d_1, None, None, None] [a_3, b_3, c_3, d_1, None, d_1, None] v21=is_true(v20) Inputs: [a_3, b_3, c_3, d_1, None, v21, None] true
  55. Abstract Interpretation 0 LOAD_FAST 0 (a) 3 LOAD_FAST 1 (b)

    6 BINARY_ADD 7 STORE_FAST 3 (d) 10 LOAD_FAST 3 (d) 13 LOAD_FAST 2 (c) 16 COMPARE_OP 0 (<) 19 JUMP_IF_FALSE 14 (to 36) 22 POP_TOP 23 LOAD_FAST 3 (d) 26 LOAD_FAST 2 (c) 29 BINARY_SUBTRACT 30 STORE_FAST 4 (e) 33 JUMP_FORWARD 11 (to 47) 36 POP_TOP 37 LOAD_FAST 3 (d) 40 LOAD_FAST 2 (c) 43 BINARY_ADD 44 STORE_FAST 4 (e) 47 LOAD_FAST 4 (e) 50 RETURN_VALUE Inputs: [a_2, b_2, c_2, d_0, None, v13, v14] [a_2, b_2, c_2, d_0, None, v15, None] v15=lt(v13, v14) [a_3, b_3, c_3, d_1, None, v21, None] v21=is_true(v20) Inputs: [a_3, b_3, c_3, d_1, None, v20, None] [a_3, b_3, c_3, d_1, None, None, None] [a_3, b_3, c_3, d_1, None, d_1, None] [a_3, b_3, c_3, d_1, None, d_1, c_3 ] v21=is_true(v20) Inputs: [a_3, b_3, c_3, d_1, None, v21, None] false [a_3, b_3, c_3, d_1, None, None, None] [a_3, b_3, c_3, d_1, None, d_1, None] [a_3, b_3, c_3, d_1, None, d_1, c_3 ] v21=is_true(v20) Inputs: [a_3, b_3, c_3, d_1, None, v21, None] true
  56. Abstract Interpretation 0 LOAD_FAST 0 (a) 3 LOAD_FAST 1 (b)

    6 BINARY_ADD 7 STORE_FAST 3 (d) 10 LOAD_FAST 3 (d) 13 LOAD_FAST 2 (c) 16 COMPARE_OP 0 (<) 19 JUMP_IF_FALSE 14 (to 36) 22 POP_TOP 23 LOAD_FAST 3 (d) 26 LOAD_FAST 2 (c) 29 BINARY_SUBTRACT 30 STORE_FAST 4 (e) 33 JUMP_FORWARD 11 (to 47) 36 POP_TOP 37 LOAD_FAST 3 (d) 40 LOAD_FAST 2 (c) 43 BINARY_ADD 44 STORE_FAST 4 (e) 47 LOAD_FAST 4 (e) 50 RETURN_VALUE [a_3, b_3, c_3, d_1, None, None, None] [a_3, b_3, c_3, d_1, None, d_1, None] [a_3, b_3, c_3, d_1, None, d_1, c_3 ] v21=is_true(v20) Inputs: [a_3, b_3, c_3, d_1, None, v21, None] [a_3, b_3, c_3, d_1, None, None, None] [a_3, b_3, c_3, d_1, None, d_1, None] [a_3, b_3, c_3, d_1, None, d_1, c_3 ] v21=is_true(v20) Inputs: [a_3, b_3, c_3, d_1, None, v21, None] false true [a_4, b_4, c_4, d_2, None, v28, None] Inputs: [a_4, b_4, c_4, d_2, None, v26, v27 ] v28 = add(v26, v27)
  57. Abstract Interpretation 0 LOAD_FAST 0 (a) 3 LOAD_FAST 1 (b)

    6 BINARY_ADD 7 STORE_FAST 3 (d) 10 LOAD_FAST 3 (d) 13 LOAD_FAST 2 (c) 16 COMPARE_OP 0 (<) 19 JUMP_IF_FALSE 14 (to 36) 22 POP_TOP 23 LOAD_FAST 3 (d) 26 LOAD_FAST 2 (c) 29 BINARY_SUBTRACT 30 STORE_FAST 4 (e) 33 JUMP_FORWARD 11 (to 47) 36 POP_TOP 37 LOAD_FAST 3 (d) 40 LOAD_FAST 2 (c) 43 BINARY_ADD 44 STORE_FAST 4 (e) 47 LOAD_FAST 4 (e) 50 RETURN_VALUE [a_3, b_3, c_3, d_1, None, None, None] [a_3, b_3, c_3, d_1, None, d_1, None] [a_3, b_3, c_3, d_1, None, d_1, c_3 ] v21=is_true(v20) Inputs: [a_3, b_3, c_3, d_1, None, v21, None] [a_3, b_3, c_3, d_1, None, None, None] [a_3, b_3, c_3, d_1, None, d_1, None] [a_3, b_3, c_3, d_1, None, d_1, c_3 ] v21=is_true(v20) Inputs: [a_3, b_3, c_3, d_1, None, v21, None] false true [a_4, b_4, c_4, d_2, None, v28, None] [a_4, b_4, c_4, d_2, v28, None, None] Inputs: [a_4, b_4, c_4, d_2, None, v26, v27 ] v28 = add(v26, v27)
  58. Abstract Interpretation 0 LOAD_FAST 0 (a) 3 LOAD_FAST 1 (b)

    6 BINARY_ADD 7 STORE_FAST 3 (d) 10 LOAD_FAST 3 (d) 13 LOAD_FAST 2 (c) 16 COMPARE_OP 0 (<) 19 JUMP_IF_FALSE 14 (to 36) 22 POP_TOP 23 LOAD_FAST 3 (d) 26 LOAD_FAST 2 (c) 29 BINARY_SUBTRACT 30 STORE_FAST 4 (e) 33 JUMP_FORWARD 11 (to 47) 36 POP_TOP 37 LOAD_FAST 3 (d) 40 LOAD_FAST 2 (c) 43 BINARY_ADD 44 STORE_FAST 4 (e) 47 LOAD_FAST 4 (e) 50 RETURN_VALUE [a_3, b_3, c_3, d_1, None, None, None] [a_3, b_3, c_3, d_1, None, d_1, None] [a_3, b_3, c_3, d_1, None, d_1, c_3 ] v21=is_true(v20) Inputs: [a_3, b_3, c_3, d_1, None, v21, None] [a_3, b_3, c_3, d_1, None, None, None] [a_3, b_3, c_3, d_1, None, d_1, None] [a_3, b_3, c_3, d_1, None, d_1, c_3 ] v21=is_true(v20) Inputs: [a_3, b_3, c_3, d_1, None, v21, None] false true [a_4, b_4, c_4, d_2, None, v28, None] [a_4, b_4, c_4, d_2, v28, None, None] Inputs: [a_4, b_4, c_4, d_2, None, v26, v27 ] v28 = add(v26, v27) [a_5, b_5, c_5, d_3, None, v31, None] Inputs: [a_5, b_5, c_5, d_3, None, v29, v30 ] v31 = sub(v29, v30)
  59. Abstract Interpretation 0 LOAD_FAST 0 (a) 3 LOAD_FAST 1 (b)

    6 BINARY_ADD 7 STORE_FAST 3 (d) 10 LOAD_FAST 3 (d) 13 LOAD_FAST 2 (c) 16 COMPARE_OP 0 (<) 19 JUMP_IF_FALSE 14 (to 36) 22 POP_TOP 23 LOAD_FAST 3 (d) 26 LOAD_FAST 2 (c) 29 BINARY_SUBTRACT 30 STORE_FAST 4 (e) 33 JUMP_FORWARD 11 (to 47) 36 POP_TOP 37 LOAD_FAST 3 (d) 40 LOAD_FAST 2 (c) 43 BINARY_ADD 44 STORE_FAST 4 (e) 47 LOAD_FAST 4 (e) 50 RETURN_VALUE [a_3, b_3, c_3, d_1, None, None, None] [a_3, b_3, c_3, d_1, None, d_1, None] [a_3, b_3, c_3, d_1, None, d_1, c_3 ] v21=is_true(v20) Inputs: [a_3, b_3, c_3, d_1, None, v21, None] [a_3, b_3, c_3, d_1, None, None, None] [a_3, b_3, c_3, d_1, None, d_1, None] [a_3, b_3, c_3, d_1, None, d_1, c_3 ] v21=is_true(v20) Inputs: [a_3, b_3, c_3, d_1, None, v21, None] false true [a_4, b_4, c_4, d_2, None, v28, None] [a_4, b_4, c_4, d_2, v28, None, None] Inputs: [a_4, b_4, c_4, d_2, None, v26, v27 ] v28 = add(v26, v27) [a_5, b_5, c_5, d_3, None, v31, None] [a_5, b_5, c_5, d_3, v31, None, None] Inputs: [a_5, b_5, c_5, d_3, None, v29, v30 ] v31 = sub(v29, v30)
  60. Annotation and Discovery • After flow graph of entry point

    is created, rpython starts annotating it • Flow graph is scanned and types are attached • If new functions are discovered, their flow graphs are created and they are annotated • This continues recursively, eventually reaching all corners of your program.
  61. Final Comments • None really • Still trying to wrap

    my brain around some of the later stages of translation (time issue) • Extremely challenging (maybe I've missed some documentation?)
  62. One Challenge • Everything is Python • PyPy interprets Python

    • PyPy is written in python (rpython) • rpython is implemented in Python • Parts of rpython use PyPy code • Boom! • Challenging to sort out what you're looking at