[pypy-svn] r63811 - pypy/branch/pyjitpl5-simplify/pypy/jit/backend/x86

fijal at codespeak.net fijal at codespeak.net
Wed Apr 8 01:18:07 CEST 2009


Author: fijal
Date: Wed Apr  8 01:18:05 2009
New Revision: 63811

Modified:
   pypy/branch/pyjitpl5-simplify/pypy/jit/backend/x86/assembler.py
   pypy/branch/pyjitpl5-simplify/pypy/jit/backend/x86/regalloc.py
   pypy/branch/pyjitpl5-simplify/pypy/jit/backend/x86/runner.py
Log:
A very delicate change - compute frame sizes and restore caching of bootstraps.
Tests are passing, but I would not mind having some extra tests for particular
pieces (3 of them)


Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/backend/x86/assembler.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/backend/x86/assembler.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/backend/x86/assembler.py	Wed Apr  8 01:18:05 2009
@@ -8,7 +8,7 @@
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.annotation import model as annmodel
 from pypy.tool.uid import fixid
-from pypy.jit.backend.x86.regalloc import (RegAlloc, FRAMESIZE, WORD, REGS,
+from pypy.jit.backend.x86.regalloc import (RegAlloc, WORD, REGS,
                                       arg_pos, lower_byte, stack_pos)
 from pypy.rlib.objectmodel import we_are_translated, specialize, compute_unique_id
 from pypy.jit.backend.x86 import codebuf
@@ -58,6 +58,7 @@
         return mc
 
     def give_mc_back(self, mc):
+        mc.done()
         assert self.mcstack[self.counter - 1] is mc
         self.counter -= 1
 
@@ -191,10 +192,12 @@
         return max_so_far
 
     def assemble(self, tree):
+        self.places_to_patch_framesize = []
         # the last operation can be 'jump', 'return' or 'guard_pause';
         # a 'jump' can either close a loop, or end a bridge to some
         # previously-compiled code.
         self._compute_longest_fail_op(tree.operations)
+        self.tree = tree
         self.make_sure_mc_exists()
         inputargs = tree.inputargs
         self.eventually_log_operations(tree.inputargs, tree.operations, None,
@@ -206,6 +209,11 @@
         self.sanitize_tree(tree.operations)
         self.mc.done()
         self.mc2.done()
+        tree._x86_stack_depth = regalloc.max_stack_depth
+        for place, offset in self.places_to_patch_framesize:
+            mc = codebuf.InMemoryCodeBuilder(place, 128)
+            mc.ADD(esp, imm32((tree._x86_stack_depth - offset) * WORD))
+            mc.done()
 
     def sanitize_tree(self, operations):
         """ Cleans up all attributes attached by regalloc and backend
@@ -216,11 +224,11 @@
                 op.longevity = None
                 self.sanitize_tree(op.suboperations)
 
-    def assemble_bootstrap_code(self, jumpaddr, arglocs):
+    def assemble_bootstrap_code(self, jumpaddr, arglocs, framesize):
         self.make_sure_mc_exists()
         addr = self.mc.tell()
-        self.mc.SUB(esp, imm(FRAMESIZE))
-        self.mc.MOV(eax, arg_pos(0))
+        self.mc.SUB(esp, imm(framesize * WORD))
+        self.mc.MOV(eax, arg_pos(0, framesize * WORD))
         for i in range(len(arglocs)):
             loc = arglocs[i]
             if not isinstance(loc, REG):
@@ -588,14 +596,20 @@
         #tree.comeback_bootstrap_addr = self.assemble_comeback_bootstrap(pos,
         #                                                locs, stacklocs)
 
-    def patch_jump(self, old_pos, new_pos, oldlocs, newlocs):
+    def patch_jump(self, old_pos, new_pos, oldlocs, newlocs, olddepth, newdepth):
         if len(oldlocs) != len(newlocs):
             # virtualizable mess
             return
         if not we_are_translated():
             assert str(oldlocs) == str(newlocs)
+        mc2 = self.mcstack.next_mc()
+        pos = mc2.tell()
+        mc2.SUB(esp, imm32((newdepth - olddepth) * WORD))
+        mc2.JMP(rel32(new_pos))
+        self.mcstack.give_mc_back(mc2)
         mc = codebuf.InMemoryCodeBuilder(old_pos, MachineCodeStack.MC_SIZE)
-        mc.JMP(rel32(new_pos))
+        mc.JMP(rel32(pos))
+        mc.done()
 
 #     def genop_discard_return(self, op, locs):
 #         if op.args:
@@ -617,6 +631,10 @@
 
     def genop_discard_jump(self, op, locs):
         targetmp = op.jump_target
+        if targetmp is not self.tree:
+            targetdepth = targetmp._x86_stack_depth
+            self.places_to_patch_framesize.append((self.mc.tell(), targetdepth))
+            self.mc.ADD(esp, imm32(0))
         self.mc.JMP(rel32(targetmp._x86_compiled))
 
     def genop_guard_guard_true(self, op, ign_1, addr, locs, ign_2):
@@ -734,7 +752,8 @@
             # clean up the original exception, we don't want
             # to enter more rpython code with exc set
             self.mc.MOV(heap(self._exception_addr), imm(0))
-        self.mc.ADD(esp, imm(FRAMESIZE))
+        self.places_to_patch_framesize.append((self.mc.tell(), 0))
+        self.mc.ADD(esp, imm32(0))
         self.mc.MOV(eax, imm(guard_index))
         self.mc.RET()
 

Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/backend/x86/regalloc.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/backend/x86/regalloc.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/backend/x86/regalloc.py	Wed Apr  8 01:18:05 2009
@@ -15,7 +15,6 @@
 # saved and restored
 REGS = [eax, ecx, edx, ebx]
 WORD = 4
-FRAMESIZE = 1024    # XXX should not be a constant at all!!
 
 class TempBox(Box):
     def __init__(self):
@@ -46,14 +45,15 @@
 
 class RegAlloc(object):
     guard_index = -1
+    max_stack_depth = 0
     
     def __init__(self, assembler, tree, translate_support_code=False,
                  regalloc=None, guard_op=None):
         # variables that have place in register
         self.assembler = assembler
         self.translate_support_code = translate_support_code
-        self.tree = tree
         if regalloc is None:
+            self.tree = tree
             self.reg_bindings = newcheckdict()
             self.stack_bindings = newcheckdict()
             # compute longevity of variables
@@ -88,6 +88,7 @@
             self.longevity = guard_op.longevity
             jump_or_fail = guard_op.suboperations[-1]
             self.loop_consts = {}
+            self.tree = regalloc.tree
             if jump_or_fail.opnum == rop.FAIL:
                 self.jump_reg_candidates = {}
             else:
@@ -212,6 +213,8 @@
         self.assembler.regalloc_perform_with_guard(op, guard_op, regalloc,
                                                    arglocs, result_loc,
                                                    overflow)
+        self.max_stack_depth = max(self.max_stack_depth,
+                                   regalloc.max_stack_depth)
 
     def perform_guard(self, op, regalloc, arglocs, result_loc):
         if not we_are_translated():
@@ -220,6 +223,8 @@
             else:
                 self.assembler.dump('%s(%s)' % (op, arglocs))
         self.assembler.regalloc_perform_guard(op, regalloc, arglocs, result_loc)
+        self.max_stack_depth = max(self.max_stack_depth,
+                                   regalloc.max_stack_depth)
 
     def PerformDiscard(self, op, arglocs):
         if not we_are_translated():
@@ -250,6 +255,8 @@
         self.position = -1
         self.process_inputargs(tree)
         self._walk_operations(operations)
+        self.max_stack_depth = max(self.max_stack_depth,
+                                   self.current_stack_depth)
 
     def walk_guard_ops(self, inputargs, operations):
         for arg in inputargs:
@@ -257,6 +264,8 @@
                 assert arg in self.stack_bindings
                 assert arg not in self.dirty_stack
         self._walk_operations(operations)
+        self.max_stack_depth = max(self.max_stack_depth,
+                                   self.current_stack_depth)
 
     def _walk_operations(self, operations):
         i = 0
@@ -462,8 +471,6 @@
             self.current_stack_depth += 1
             res = newloc
         assert isinstance(res, MODRM)
-        if res.position > FRAMESIZE/WORD:
-            raise NotImplementedError("Exceeded FRAME_SIZE")
         return res
 
     def make_sure_var_in_reg(self, v, forbidden_vars, selected_reg=None,
@@ -1132,9 +1139,9 @@
         num = getattr(rop, name.upper())
         oplist[num] = value
 
-def arg_pos(i):
-    res = mem(esp, FRAMESIZE + WORD * (i + 1))
-    res.position = (i + 1) + FRAMESIZE // WORD
+def arg_pos(i, framesize):
+    res = mem(esp, framesize + WORD * (i + 1))
+    res.position = (i + 1) + framesize // WORD
     return res
 
 def stack_pos(i):

Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/backend/x86/runner.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/backend/x86/runner.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/backend/x86/runner.py	Wed Apr  8 01:18:05 2009
@@ -85,7 +85,7 @@
         TP = lltype.GcArray(llmemory.GCREF)
         self.keepalives = []
         self.keepalives_index = 0
-        #self._bootstrap_cache = {}
+        self._bootstrap_cache = {}
         self._guard_list = []
         self._compiled_ops = {}
         self._builtin_implementations = {}
@@ -187,28 +187,32 @@
     def compile_operations(self, tree):
         old_loop = tree._x86_compiled
         if old_loop:
+            olddepth = tree._x86_stack_depth
             oldlocs = tree.arglocs
         else:
             oldlocs = None
-        self.assembler.assemble(tree)
+            olddepth = 0
+        stack_depth = self.assembler.assemble(tree)
         newlocs = tree.arglocs
         if old_loop != 0:
             self.assembler.patch_jump(old_loop, tree._x86_compiled,
-                                      oldlocs, newlocs)
+                                      oldlocs, newlocs, olddepth,
+                                      tree._x86_stack_depth)
 
     def get_bootstrap_code(self, loop):
         # key is locations of arguments
-        #key = ','.join([str(i) for i in loop.arglocs])
-        #try:
-        #    func = self._bootstrap_cache[key]
-        #except KeyError:
-        arglocs = loop.arglocs
-        addr = self.assembler.assemble_bootstrap_code(loop._x86_compiled,
-                                                      arglocs)
-        # arguments are as follows - address to jump to,
-        # and a list of args
-        func = rffi.cast(lltype.Ptr(self.BOOTSTRAP_TP), addr)
-        return func
+        key = loop._x86_compiled
+        try:
+            return self._bootstrap_cache[key]
+        except KeyError:
+            arglocs = loop.arglocs
+            addr = self.assembler.assemble_bootstrap_code(loop._x86_compiled,
+                                                          arglocs,
+                                                          loop._x86_stack_depth)
+            # passing arglist as the only arg
+            func = rffi.cast(lltype.Ptr(self.BOOTSTRAP_TP), addr)
+            self._bootstrap_cache[key] = func
+            return func
 
     def get_box_value_as_int(self, box):
         if isinstance(box, BoxInt):



More information about the Pypy-commit mailing list