[pypy-svn] r74287 - in pypy/branch/blackhole-improvement/pypy/jit: codewriter codewriter/test metainterp

arigo at codespeak.net arigo at codespeak.net
Fri Apr 30 16:47:04 CEST 2010


Author: arigo
Date: Fri Apr 30 16:47:02 2010
New Revision: 74287

Modified:
   pypy/branch/blackhole-improvement/pypy/jit/codewriter/assembler.py
   pypy/branch/blackhole-improvement/pypy/jit/codewriter/liveness.py
   pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_assembler.py
   pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_codewriter.py
   pypy/branch/blackhole-improvement/pypy/jit/metainterp/blackhole.py
   pypy/branch/blackhole-improvement/pypy/jit/metainterp/pyjitpl.py
   pypy/branch/blackhole-improvement/pypy/jit/metainterp/resume.py
Log:
Stop abusing the last character of the bytecode, and instead
store all three num_regs_X as a single separate integer.
Use it to implement replace_box() efficiently.


Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/assembler.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/assembler.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/assembler.py	Fri Apr 30 16:47:02 2010
@@ -3,6 +3,7 @@
 from pypy.jit.codewriter.flatten import ListOfKind, SwitchDictDescr
 from pypy.objspace.flow.model import Constant
 from pypy.rpython.lltypesystem import lltype, llmemory
+from pypy.rlib.objectmodel import we_are_translated
 
 
 class JitCode(AbstractValue):
@@ -11,31 +12,34 @@
     _empty_f = []
 
     def __init__(self, name, cfnptr=None, calldescr=None, called_from=None,
-                 liveness=None):
+                 liveness=None, assembler=None):
         self.name = name
         #self.cfnptr = cfnptr
         #self.calldescr = calldescr
         #self.called_from = called_from
         self.liveness = liveness
+        self._assembler = assembler
 
     def setup(self, code, constants_i=[], constants_r=[], constants_f=[],
-              num_regs_r=256):
-        # stick an extra char at the end of self.code, which is the
-        # highest 'r' register used in this code.  It default to 255,
-        # which is always correct.  Also, even if no 'r' register is
-        # used it must be set to 0, which means that register %r0 is
-        # always marked as used.
-        self.code = code + chr((num_regs_r or 1)-1)
+              num_regs_i=256, num_regs_r=256, num_regs_f=256):
+        self.code = code
         # if the following lists are empty, use a single shared empty list
         self.constants_i = constants_i or self._empty_i
         self.constants_r = constants_r or self._empty_r
         self.constants_f = constants_f or self._empty_f
+        # encode the three num_regs into a single integer
+        self.num_regs_encoded = ((num_regs_i << 18) |
+                                 (num_regs_r << 9) |
+                                 (num_regs_f << 0))
 
-    def _code(self):
-        return self.code[:-1]   # for testing, without the extra char
+    def num_regs_i(self):
+        return self.num_regs_encoded >> 18
 
-    def highest_r_reg(self):
-        return ord(self.code[-1])
+    def num_regs_r(self):
+        return (self.num_regs_encoded >> 9) & 0x1FF
+
+    def num_regs_f(self):
+        return self.num_regs_encoded & 0x1FF
 
     def enumerate_live_vars(self, pc, callback, arg,
                             registers_i, registers_r, registers_f):
@@ -45,11 +49,23 @@
         # of that instruction which are no longer used afterwards, and
         # also the return value of that instruction.)  More precisely,
         # this invokes 'callback(arg, box)' where 'box' comes from one
-        # of the three lists of registers.
+        # of the three lists of registers.  If the callback returns a
+        # box, then it is stored back.
+        if not we_are_translated() and pc not in self.liveness:
+            self._missing_liveness(pc)
         live_i, live_r, live_f = self.liveness[pc]    # XXX compactify!!
-        for c in live_i: callback(arg, registers_i[ord(c)])
-        for c in live_r: callback(arg, registers_r[ord(c)])
-        for c in live_f: callback(arg, registers_f[ord(c)])
+        for c in live_i:
+            newbox = callback(arg, registers_i[ord(c)])
+            if newbox is not None:
+                registers_i[ord(c)] = newbox
+        for c in live_r:
+            newbox = callback(arg, registers_r[ord(c)])
+            if newbox is not None:
+                registers_r[ord(c)] = newbox
+        for c in live_f:
+            newbox = callback(arg, registers_f[ord(c)])
+            if newbox is not None:
+                registers_f[ord(c)] = newbox
     enumerate_live_vars._annspecialcase_ = 'specialize:arg(2)'
 
     def _live_vars(self, pc):
@@ -67,6 +83,16 @@
         lst.sort()
         return ' '.join(lst)
 
+    def _missing_liveness(self, pc):
+        opcode = ord(self.code[pc])
+        insn = 'insn %d' % opcode
+        if self._assembler is not None:
+            for name, code in self._assembler.insns.items():
+                if code == opcode:
+                    insn = name
+        raise KeyError("missing liveness[%d], corresponding to %r" % (
+            pc, insn))
+
 
 class Assembler(object):
 
@@ -223,10 +249,13 @@
         assert self.count_regs['float'] + len(self.constants_f) <= 256
 
     def make_jitcode(self, name):
-        jitcode = JitCode(name, liveness=self.liveness)
+        jitcode = JitCode(name, liveness=self.liveness,
+                          assembler=self)
         jitcode.setup(''.join(self.code),
                       self.constants_i,
                       self.constants_r,
                       self.constants_f,
-                      self.count_regs['ref'])
+                      self.count_regs['int'],
+                      self.count_regs['ref'],
+                      self.count_regs['float'])
         return jitcode

Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/liveness.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/liveness.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/liveness.py	Fri Apr 30 16:47:02 2010
@@ -12,6 +12,7 @@
 # 'switches_require_liveness' to True.
 DEFAULT_OPNAMES_REQUIRING_LIVENESS = [
     'residual_call_',
+    '(int|ref|float)_guard_value',
     ]
 
 # ____________________________________________________________

Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_assembler.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_assembler.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_assembler.py	Fri Apr 30 16:47:02 2010
@@ -17,10 +17,12 @@
     assembler = Assembler()
     jitcode = assembler.assemble(ssarepr)
     assert jitcode.code == ("\x00\x00\x01\x02"
-                            "\x01\x02"
-                            "\x00")
+                            "\x01\x02")
     assert assembler.insns == {'int_add/iii': 0,
                                'int_return/i': 1}
+    assert jitcode.num_regs_i() == 3
+    assert jitcode.num_regs_r() == 0
+    assert jitcode.num_regs_f() == 0
 
 def test_assemble_consts():
     ssarepr = SSARepr("test")
@@ -37,8 +39,7 @@
                             "\x01\x12"   # use int_return/c for one-byte consts
                             "\x01\xFC"
                             "\x00\xFF"   # use int_return/i for larger consts
-                            "\x00\xFE"
-                            "\x00")      # highest_r_reg
+                            "\x00\xFE")
     assert assembler.insns == {'int_return/i': 0,
                                'int_return/c': 1}
     assert jitcode.constants_i == [128, -129]
@@ -56,8 +57,7 @@
     assert jitcode.code == ("\x00\x0D"
                             "\x00\xFF"
                             "\x00\xFE"
-                            "\x00\xFD"
-                            "\x00")
+                            "\x00\xFD")
     assert assembler.insns == {'float_return/f': 0}
     assert jitcode.constants_f == [18.0, -4.0, 128.1]
 
@@ -78,8 +78,7 @@
     assert jitcode.code == ("\x00\x58"
                             "\x01\xFF"
                             "\x01\xFE"
-                            "\x02\xFF"
-                            "\x00")
+                            "\x02\xFF")
     assert assembler.insns == {'int_return/c': 0,
                                'int_return/i': 1,
                                'ref_return/r': 2}
@@ -106,8 +105,7 @@
                             "\x01\x17\x16\x17"
                             "\x02\x16\x01\x16"
                             "\x03\x00\x00"
-                            "\x04\x17"
-                            "\x00")
+                            "\x04\x17")
     assert assembler.insns == {'goto_if_not_int_gt/Lic': 0,
                                'int_add/iii': 1,
                                'int_sub/ici': 2,
@@ -123,7 +121,7 @@
         ]
     assembler = Assembler()
     jitcode = assembler.assemble(ssarepr)
-    assert jitcode._code() == "\x00\x03\x16\x17\xFF\x00"
+    assert jitcode.code == "\x00\x03\x16\x17\xFF\x00"
     assert assembler.insns == {'foobar/IR': 0}
     assert jitcode.constants_i == [42]
 
@@ -135,21 +133,27 @@
     ssarepr.insns = [('foobar', d) for d in descrs[::-1]]
     assembler = Assembler()
     jitcode = assembler.assemble(ssarepr)
-    assert jitcode._code() == ''.join(["\x00" + struct.pack("<H", i)
+    assert jitcode.code == ''.join(["\x00" + struct.pack("<H", i)
                                        for i in range(300)])
     assert assembler.insns == {'foobar/d': 0}
     assert assembler.descrs == descrs[::-1]
 
-def test_highest_r_reg():
+def test_num_regs():
     assembler = Assembler()
     ssarepr = SSARepr("test")
     ssarepr.insns = []
     jitcode = assembler.assemble(ssarepr)
-    assert jitcode.highest_r_reg() == 0
-    ssarepr = SSARepr("test")
-    ssarepr.insns = [('foobar', Register('int', 51), Register('ref', 27))]
-    jitcode = assembler.assemble(ssarepr)
-    assert jitcode.highest_r_reg() == 27
+    assert jitcode.num_regs_i() == 0
+    assert jitcode.num_regs_r() == 0
+    assert jitcode.num_regs_f() == 0
+    ssarepr = SSARepr("test")
+    ssarepr.insns = [('foobar', Register('int', 51),
+                                Register('ref', 27),
+                                Register('int', 12))]
+    jitcode = assembler.assemble(ssarepr)
+    assert jitcode.num_regs_i() == 52
+    assert jitcode.num_regs_r() == 28
+    assert jitcode.num_regs_f() == 0
 
 def test_liveness():
     ssarepr = SSARepr("test")
@@ -170,7 +174,7 @@
         ]
     assembler = Assembler()
     jitcode = assembler.assemble(ssarepr)
-    assert jitcode._code() == ("\x00\x00\x0A\x01"
+    assert jitcode.code == ("\x00\x00\x0A\x01"
                                "\x00\x00\x03\x02"
                                "\x01\x01\x02\x03"
                                "\x00\x00\x06\x04"

Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_codewriter.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_codewriter.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_codewriter.py	Fri Apr 30 16:47:02 2010
@@ -10,18 +10,21 @@
         return b
     cw = CodeWriter()
     jitcode = cw.transform_func_to_jitcode(f, [5, 6])
-    assert jitcode._code() == ("\x00\x10\x00\x00\x00"
-                               "\x01\x01\x00\x01"
-                               "\x02\x00\x01\x00"
-                               "\x03\x00\x00"
-                               "\x04\x01")
+    assert jitcode.code == ("\x00\x10\x00\x00\x00"
+                            "\x01\x01\x00\x01"
+                            "\x02\x00\x01\x00"
+                            "\x03\x00\x00"
+                            "\x04\x01")
     assert cw.assembler.insns == {'goto_if_not_int_gt/Lic': 0,
                                   'int_add/iii': 1,
                                   'int_sub/ici': 2,
                                   'goto/L': 3,
                                   'int_return/i': 4}
+    assert jitcode.num_regs_i() == 2
+    assert jitcode.num_regs_r() == 0
+    assert jitcode.num_regs_f() == 0
     assert jitcode._live_vars(0) == '%i0 %i1'
-    for i in range(1, len(jitcode._code())):
+    for i in range(1, len(jitcode.code)):
         py.test.raises(KeyError, jitcode._live_vars, i)
 
 def test_integration():

Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/blackhole.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/metainterp/blackhole.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/blackhole.py	Fri Apr 30 16:47:02 2010
@@ -217,7 +217,7 @@
         self.dispatch_loop      = builder.dispatch_loop
         self.descrs             = builder.descrs
         self.op_catch_exception = builder.op_catch_exception
-        self.cleanup_required_in_registers_r = -1
+        self.cleanup_required_in_registers_r = 0
         #
         if we_are_translated():
             default_i = 0
@@ -247,7 +247,7 @@
         code = jitcode.code
         self.cleanup_required_in_registers_r = max(
             self.cleanup_required_in_registers_r,
-            ord(code[-1]))
+            jitcode.num_regs_r())
         while True:
             try:
                 self.dispatch_loop(self, code, position)
@@ -286,11 +286,9 @@
         # To avoid keeping references alive, this cleans up the registers_r.
         # It does not clear the references set by copy_constants(), but
         # these are all prebuilt constants anyway.
-        i = self.cleanup_required_in_registers_r
-        self.cleanup_required_in_registers_r = -1
-        while i >= 0:
+        for i in range(self.cleanup_required_in_registers_r):
             self.registers_r[i] = NULL
-            i -= 1
+        self.cleanup_required_in_registers_r = 0
         self.tmpreg_r = NULL
         self.exception_last_value = None
 

Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/metainterp/pyjitpl.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/pyjitpl.py	Fri Apr 30 16:47:02 2010
@@ -93,77 +93,36 @@
             outvalue[startindex+i] = reg
     prepare_list_of_boxes._annspecialcase_ = 'specialize:arg(4)'
 
-    def load_int(self):
-        pc = self.pc
-        result = ord(self.bytecode[pc])
-        self.pc = pc + 1
-        if result > 0x7F:
-            result = self._load_larger_int(result)
-        return result
-
-    def _load_larger_int(self, result):    # slow path
-        result = result & 0x7F
-        shift = 7
-        pc = self.pc
-        while 1:
-            byte = ord(self.bytecode[pc])
-            pc += 1
-            result += (byte & 0x7F) << shift
-            shift += 7
-            if not byte & 0x80:
-                break
-        self.pc = pc
-        return intmask(result)
-    _load_larger_int._dont_inline_ = True
-
-    def load_3byte(self):
-        pc = self.pc
-        result = (((ord(self.bytecode[pc + 0])) << 16) |
-                  ((ord(self.bytecode[pc + 1])) <<  8) |
-                  ((ord(self.bytecode[pc + 2])) <<  0))
-        self.pc = pc + 3
-        return result
-
-    def load_bool(self):
-        pc = self.pc
-        result = ord(self.bytecode[pc])
-        self.pc = pc + 1
-        return bool(result)
-
-    def getenv(self, i):
-        assert i >= 0
-        j = i >> 1
-        if i & 1:
-            return self.constants[j]
-        else:
-            assert j < len(self.env)
-            return self.env[j]
-
-    def load_arg(self):
-        return self.getenv(self.load_int())
-
-    def load_const_arg(self):
-        return self.constants[self.load_int()]
-
-    def load_varargs(self):
-        count = self.load_int()
-        return [self.load_arg() for i in range(count)]
-
-    def load_constargs(self):
-        count = self.load_int()
-        return [self.load_const_arg() for i in range(count)]
-
-    def ignore_varargs(self):
-        count = self.load_int()
+    def get_list_of_active_boxes(self):
+        # XXX find a way to avoid needing the temporary 'env' as a
+        # variable-sized list
+        env = []
+        self.jitcode.enumerate_live_vars(
+            self.pc, MIFrame._store_in_env, env,
+            self.registers_i, self.registers_r, self.registers_f)
+        return env[:]
+
+    @staticmethod
+    def _store_in_env(env, box):
+        env.append(box)
+
+    def replace_active_box_in_frame(self, oldbox, newbox):
+        if isinstance(oldbox, history.BoxInt):
+            count = self.jitcode.num_regs_i()
+            registers = self.registers_i
+        elif isinstance(oldbox, history.BoxPtr):
+            count = self.jitcode.num_regs_r()
+            registers = self.registers_r
+        elif isinstance(oldbox, history.BoxFloat):
+            count = self.jitcode.num_regs_f()
+            registers = self.registers_f
+        else:
+            assert 0, repr(oldbox)
         for i in range(count):
-            self.load_int()
-
-    def getvarenv(self, i):
-        return self.env[i]
-
-    def make_result_box(self, box):
-        assert isinstance(box, Box) or isinstance(box, Const)
-        self.env.append(box)
+            if registers[i] is oldbox:
+                registers[i] = newbox
+        if not we_are_translated():
+            assert oldbox not in registers[count:]
 
     # ------------------------------
 
@@ -1999,11 +1958,9 @@
         return boxes
 
     def replace_box(self, oldbox, newbox):
+        assert isinstance(oldbox, Box)
         for frame in self.framestack:
-            boxes = frame.env
-            for i in range(len(boxes)):
-                if boxes[i] is oldbox:
-                    boxes[i] = newbox
+            frame.replace_active_box_in_frame(oldbox, newbox)
         boxes = self.virtualref_boxes
         for i in range(len(boxes)):
             if boxes[i] is oldbox:

Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/resume.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/metainterp/resume.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/resume.py	Fri Apr 30 16:47:02 2010
@@ -21,13 +21,12 @@
         self.boxes = boxes
 
 class FrameInfo(object):
-    __slots__ = ('prev', 'jitcode', 'pc', 'exception_target')
+    __slots__ = ('prev', 'jitcode', 'pc')
 
     def __init__(self, prev, frame):
         self.prev = prev
         self.jitcode = frame.jitcode
         self.pc = frame.pc
-        self.exception_target = frame.exception_target
 
 def _ensure_parent_resumedata(framestack, n):
     target = framestack[n]
@@ -40,7 +39,7 @@
                                          back)
     target.parent_resumedata_snapshot = Snapshot(
                                          back.parent_resumedata_snapshot,
-                                         back.env[:])
+                                         back.get_list_of_active_boxes())
 
 def capture_resumedata(framestack, virtualizable_boxes, virtualref_boxes,
                        storage):
@@ -50,7 +49,8 @@
     frame_info_list = FrameInfo(top.parent_resumedata_frame_info_list,
                                 top)
     storage.rd_frame_info_list = frame_info_list
-    snapshot = Snapshot(top.parent_resumedata_snapshot, top.env[:])
+    snapshot = Snapshot(top.parent_resumedata_snapshot,
+                        top.get_list_of_active_boxes())
     snapshot = Snapshot(snapshot, virtualref_boxes[:]) # xxx for now
     if virtualizable_boxes is not None:
         snapshot = Snapshot(snapshot, virtualizable_boxes[:]) # xxx for now
@@ -576,7 +576,7 @@
             except AttributeError:
                 jitcodename = str(compute_unique_id(frameinfo.jitcode))
             debug_print('\tjitcode/pc', jitcodename,
-                        frameinfo.pc, frameinfo.exception_target,
+                        frameinfo.pc,
                         'at', compute_unique_id(frameinfo))
             frameinfo = frameinfo.prev
         numb = storage.rd_numb



More information about the Pypy-commit mailing list