[pypy-svn] r67082 - pypy/branch/pyjitpl5/pypy/jit/metainterp/doc
benjamin at codespeak.net
benjamin at codespeak.net
Fri Aug 21 17:42:12 CEST 2009
Author: benjamin
Date: Fri Aug 21 17:42:12 2009
New Revision: 67082
Modified:
pypy/branch/pyjitpl5/pypy/jit/metainterp/doc/jitpl5.txt
pypy/branch/pyjitpl5/pypy/jit/metainterp/doc/linking.txt
pypy/branch/pyjitpl5/pypy/jit/metainterp/doc/virtualizables.txt
Log:
update, mostly by deleting things I know aren't true anymore
Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/doc/jitpl5.txt
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/doc/jitpl5.txt (original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/doc/jitpl5.txt Fri Aug 21 17:42:12 2009
@@ -12,20 +12,20 @@
Tracing: executing code and recording what we did, for one loop. This
starts at the app-level JUMP_ABSOLUTE (or equivalent) bytecode that
-closes an app-level loop. Implemented by interpreting the rainbow
+closes an app-level loop. Implemented by interpreting a custom
bytecode that describes the interpreter itself. (Could later be
optimized by removing the rainbow bytecode.)
We pass around BoxInt and BoxPtr objects that have this minimal
content::
- +- BoxPtr ---------+
+ +- BoxInt ---------+
| real value |
+------------------+
-In other words, BoxInt and BoxPtr just record the real value. Each
-operation generates a new BoxInt or BoxPtr (even if it contains the same
-real value as another box).
+In other words, BoxInt and BoxPtr just record the real value. Like
+PyPy's flowgraph, each operation generates a new BoxInt or BoxPtr
+(even if it contains the same real value as another box).
Tracing goes on for exactly one iteration of the app-level loop. As it
handles real values, it makes the real program progress one iteration.
@@ -95,9 +95,11 @@
=============
When a guard fails, we normally fall back to regular interpretation.
-Because the guard failure occurs in the middle of executing an app-level
-bytecode, this requires interpreting the rainbow bytecode with a
-fall-back interpreter until the start of the next app-level bytecode.
+Because the guard failure occurs in the middle of executing an
+app-level bytecode, this requires interpreting the bytecode describing
+the interpreter with a fall-back interpreter (which is actually
+implemented with the same code as the tracer) until the start of the
+next app-level bytecode.
When we decide instead to compile more code for this guard failure, we
take the set of live values and put them back into boxes, and proceed
Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/doc/linking.txt
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/doc/linking.txt (original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/doc/linking.txt Fri Aug 21 17:42:12 2009
@@ -25,33 +25,9 @@
so that it points to the next bytecode to execute */
}
-Initially, for a given frame position, there is no machine code produced
-by the JIT so far. To simplify things, we use the following trick:
-conceptually there is *always* machine code available, but this machine
-code just contains an always-failing guard. So
-lookup_machine_code_for() returns a pointer to machine code that looks
-like this::
-
- setup the frame...
- /* here starts the code for an always- failing guard */
- PUSH info_about_this_guard
- JMP generic_guard_recovery_code
-
-The generic guard recovery code contains the following logic::
-
- REG1 = info_about_this_guard
- REG2 = current_stack_base_pointer
- REG3 = CALL jit_compile(REG1, REG2)
- copy REG3->inputargs[0] to EAX
- copy REG3->inputargs[1] to EBX
- etc.
- JMP REG3->targetaddr
-
-The jit_compile() function comes from RPython sources written in the JIT
-support code. It does tracing and generally ends up compiling an extra
-loop to machine code. It can also patch the failing guard in the
-machine code (above) so that later invocations will jump directly to the
-correct code.
+The jit_compile() function comes from RPython sources written in the
+JIT support code (warmspot.py). It does tracing and generally ends up
+compiling an extra loop to machine code.
Then jit_compile() itself needs to transfer execution to the newly
compiled loop. Instead of calling the loop, jit_compile() returns a
Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/doc/virtualizables.txt
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/doc/virtualizables.txt (original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/doc/virtualizables.txt Fri Aug 21 17:42:12 2009
@@ -57,48 +57,3 @@
We can achieve that by unpacking W_IntObject read from locals before the loop
and carefully rebuilding this for each guard failure, by a small bit of
assembler code.
-
-Problem one: what if we access this from a call or somewhere else?
--------------------------------------------------------------------
-
-This is the general problem with virtualizables, what if one has a reference
-to that object and will choose to use it in place where we have things on
-stack or not allocated at all?
-
-1. We store a small piece of assembler code as a function pointer inside
- a virtualizable. This is, I think, simpler than having complex rebuild
- info kept together along the chain. If someone accesses the frame,
- this code will run and rebuild what is necessary. If this happens, there
- are two possiblities:
-
-2. We check after the call (guard_nonvirtualized, but we need to put it
- a bit differently) that frame was not accessed and if it was, exit the
- jit.
-
-Problem two: what if we grow more elements during bridges?
-----------------------------------------------------------
-
-The problem is for such code:
-
- while i < 10000:
- if i % 2:
- i += a
- else:
- i += b
-
-Now the first loop is compiled and when the second part (a bridge) is compiled,
-we end up with non-matching virtualizables. To avoid that, we need to pass
-more arguments to the loop that usually anticipated. Note that this is not
-a big deal if we're careful enough (for x86) since we can put more stuff on
-the stack if we update esp register. We'll use ebp as a base for stack
-operations, so we're free to change value of esp any time we want.
-So we will end up with things like this:
-
-(%ebp-4), (%ebp-8), (%ebp-c) - original args
-(%ebp-10), %(ebp-14) - temporary values
-(%ebp-18) - additional value
-
-and we'll update esp by +4
-
-This also solves the problem of moving around vars when we need to update
-esp because of jump. good.
More information about the Pypy-commit
mailing list