[pypy-commit] pypy arm-backend-2: merge up to 43861

bivab noreply at buildbot.pypy.org
Fri Jun 24 17:39:50 CEST 2011


Author: David Schneider <david.schneider at picle.org>
Branch: arm-backend-2
Changeset: r45103:60ff2d1ca4bb
Date: 2011-06-24 10:00 +0200
http://bitbucket.org/pypy/pypy/changeset/60ff2d1ca4bb/

Log:	merge up to 43861

diff --git a/pypy/doc/discussion/jit-profiler.rst b/pypy/doc/discussion/jit-profiler.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/discussion/jit-profiler.rst
@@ -0,0 +1,79 @@
+A JIT-aware profiler
+====================
+
+Goal: have a profiler which is aware of the PyPy JIT and which shows which
+percentage of the time have been spent in which loops.
+
+Long term goal: integrate the data collected by the profiler with the
+jitviewer.
+
+The idea is record an event in the PYPYLOG everytime we enter and exit a loop
+or a bridge.
+
+Expected output
+----------------
+
+[100] {jit-profile-enter
+loop1      # e.g. an entry bridge
+[101] jit-profile-enter}
+...
+[200] {jit-profile-enter
+loop0      # JUMP from loop1 to loop0
+[201] jit-profile-enter}
+...
+[500] {jit-profile-exit
+loop0      # e.g. because of a failing guard
+[501] jit-profile-exit}
+
+In this example, the exiting from loop1 is implicit because we are entering
+loop0.  So, we spent 200-100=100 ticks in the entry bridge, and 500-200=300
+ticks in the actual loop.
+
+What to do about "inner" bridges?
+----------------------------------
+
+"Inner bridges" are those bridges which jump back to the loop where they
+originate from.  There are two possible ways of dealing with them:
+
+  1. we ignore them: we record when we enter the loop, but not when we jump to
+     a compiled inner bridge.  The exit event will be recorded only in case of
+     a non-compiled guard failure or a JUMP to another loop
+
+  2. we record the enter/exit of each inner bridge
+
+The disadvantage of solution (2) is that there are certain loops which takes
+bridges at everty single iteration.  So, in this case we would record a huge
+number of events, possibly adding a lot of overhead and thus making the
+profiled data useless.
+
+
+Detecting the enter to/exit from a loop
+----------------------------------------
+
+Ways to enter:
+
+    - just after the tracing/compilation
+
+    - from the interpreter, if the loop has already been compiled
+
+    - from another loop, via a JUMP operation
+
+    - from a hot guard failure (which we ignore, in case we choose solution
+      (1) above)
+
+    - XXX: am I missing anything?
+
+Ways to exit:
+
+    - guard failure (entering blackhole)
+
+    - guard failure (jumping to a bridge) (ignored in case of solution (1))
+
+    - jump to another loop
+
+    - XXX: am I missing anything?
+
+
+About call_assembler: I think that at the beginning, we should just ignore
+call_assembler: the time spent inside the call will be accounted to the loop
+calling it.
diff --git a/pypy/jit/backend/test/runner_test.py b/pypy/jit/backend/test/runner_test.py
--- a/pypy/jit/backend/test/runner_test.py
+++ b/pypy/jit/backend/test/runner_test.py
@@ -332,6 +332,30 @@
         fail = self.cpu.execute_token(looptoken)
         assert fail is faildescr
 
+        if self.cpu.supports_floats:
+            looptoken = LoopToken()
+            f0 = BoxFloat()
+            operations = [
+                ResOperation(rop.FINISH, [f0], None, descr=faildescr)
+                ]
+            self.cpu.compile_loop([f0], operations, looptoken)
+            value = longlong.getfloatstorage(-61.25)
+            self.cpu.set_future_value_float(0, value)
+            fail = self.cpu.execute_token(looptoken)
+            assert fail is faildescr
+            res = self.cpu.get_latest_value_float(0)
+            assert longlong.getrealfloat(res) == -61.25
+
+            looptoken = LoopToken()
+            operations = [
+                ResOperation(rop.FINISH, [constfloat(42.5)], None, descr=faildescr)
+                ]
+            self.cpu.compile_loop([], operations, looptoken)
+            fail = self.cpu.execute_token(looptoken)
+            assert fail is faildescr
+            res = self.cpu.get_latest_value_float(0)
+            assert longlong.getrealfloat(res) == 42.5
+
     def test_execute_operations_in_env(self):
         cpu = self.cpu
         x = BoxInt(123)
diff --git a/pypy/jit/backend/x86/assembler.py b/pypy/jit/backend/x86/assembler.py
--- a/pypy/jit/backend/x86/assembler.py
+++ b/pypy/jit/backend/x86/assembler.py
@@ -1843,8 +1843,9 @@
         for i in range(len(locs)):
             loc = locs[i]
             if not isinstance(loc, RegLoc):
-                if isinstance(loc, StackLoc) and loc.type == FLOAT:
-                    self.mc.MOVSD_xb(xmm0.value, loc.value)
+                if ((isinstance(loc, StackLoc) and loc.type == FLOAT) or
+                        isinstance(loc, ConstFloatLoc)):
+                    self.mc.MOVSD(xmm0, loc)
                     adr = self.fail_boxes_float.get_addr_for_num(i)
                     self.mc.MOVSD(heap(adr), xmm0)
                 else:
diff --git a/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py b/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
--- a/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
@@ -1662,3 +1662,20 @@
         assert log.result == 300
         loop, = log.loops_by_filename(self.filepath)
         assert loop.match_by_id('shift', "")  # optimized away
+
+    def test_division_to_rshift(self):
+        def main(b):
+            res = 0
+            a = 0
+            while a < 300:
+                assert a >= 0
+                assert 0 <= b <= 10
+                res = a/b     # ID: div
+                a += 1
+            return res
+        #
+        log = self.run(main, [3], threshold=200)
+        #assert log.result == 149
+        loop, = log.loops_by_filename(self.filepath)
+        import pdb;pdb.set_trace()
+        assert loop.match_by_id('div', "")  # optimized away


More information about the pypy-commit mailing list