[pypy-svn] r63518 - pypy/branch/optimize-refactoring/pypy/jit/backend/x86

fijal at codespeak.net fijal at codespeak.net
Thu Apr 2 07:20:38 CEST 2009


Author: fijal
Date: Thu Apr  2 07:20:36 2009
New Revision: 63518

Modified:
   pypy/branch/optimize-refactoring/pypy/jit/backend/x86/assembler.py
   pypy/branch/optimize-refactoring/pypy/jit/backend/x86/regalloc.py
   pypy/branch/optimize-refactoring/pypy/jit/backend/x86/runner.py
Log:
first round of fixing up the x86 backend. goes slowly though....


Modified: pypy/branch/optimize-refactoring/pypy/jit/backend/x86/assembler.py
==============================================================================
--- pypy/branch/optimize-refactoring/pypy/jit/backend/x86/assembler.py	(original)
+++ pypy/branch/optimize-refactoring/pypy/jit/backend/x86/assembler.py	Thu Apr  2 07:20:36 2009
@@ -39,20 +39,40 @@
         #raise NotImplementedError
         return "?%r" % (arg,)
 
-class Assembler386(object):
+class MachineCodeStack(object):
     MC_SIZE = 1024*1024     # 1MB, but assumed infinite for now
+
+    def __init__(self):
+        self.mcstack = []
+        self.counter = 0
+
+    def next_mc(self):
+        if len(self.mcstack) == self.counter:
+            mc = codebuf.MachineCodeBlock(self.MC_SIZE)
+            self.mcstack.append(mc)
+        else:
+            mc = self.mcstack[self.counter]
+        self.counter += 1
+        return mc
+
+    def give_mc_back(self, mc):
+        assert self.mcstack[self.counter - 1] is mc
+        self.counter -= 1
+
+class Assembler386(object):
     generic_return_addr = 0
     log_fd = -1
+    mc = None
+    mc2 = None
 
     def __init__(self, cpu, translate_support_code=False):
         self.cpu = cpu
         self.verbose = False
-        self.mc = None
-        self.mc2 = None
         self.rtyper = cpu.rtyper
         self.malloc_func_addr = 0
         self._exception_data = lltype.nullptr(rffi.CArray(lltype.Signed))
         self._exception_addr = 0
+        self.mcstack = MachineCodeStack()
         
     def _get_log(self):
         s = os.environ.get('PYPYJITLOG')
@@ -86,17 +106,18 @@
                                                 zero=True, flavor='raw')
             self._exception_bck_addr = self.cpu.cast_ptr_to_int(
                 self._exception_bck)
-            self.mc = codebuf.MachineCodeBlock(self.MC_SIZE)
-            self.mc2 = codebuf.MachineCodeBlock(self.MC_SIZE)
+            self.mc = self.mcstack.next_mc()
+            self.mc2 = self.mcstack.next_mc()
             self.generic_return_addr = self.assemble_generic_return()
             # the address of the function called by 'new': directly use
             # Boehm's GC_malloc function.
             if self.malloc_func_addr == 0:
                 self.malloc_func_addr = gc_malloc_fnaddr()
 
-    def eventually_log_operations(self, operations, guard_op):
+    def eventually_log_operations(self, operations):
         if self._log_fd == -1:
             return
+        xxx
         memo = {}
         os.write(self._log_fd, "<<<<<<<<<<\n")
         if guard_op is not None:
@@ -116,6 +137,7 @@
     def log_failure_recovery(self, gf, guard_index):
         if self._log_fd == -1:
             return
+        xxx
         os.write(self._log_fd, 'xxxxxxxxxx\n')
         memo = {}
         reprs = []
@@ -130,30 +152,24 @@
     def log_call(self, name, valueboxes):
         if self._log_fd == -1:
             return
+        xxx
         memo = {}
         args_s = ','.join([repr_of_arg(memo, box) for box in valueboxes])
         os.write(self._log_fd, "CALL\n")
         os.write(self._log_fd, "%s %s\n" % (name, args_s))
 
-    def assemble(self, operations, guard_op, verbose=False):
-        self.verbose = verbose
+    def assemble(self, tree):
         # 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.make_sure_mc_exists()
-        op0 = operations[0]
+        inputargs = tree.inputargs
+        op0 = tree.operations[0]
         op0.position = self.mc.tell()
-        self.eventually_log_operations(operations, guard_op)
-        regalloc = RegAlloc(self, operations, guard_op,
-                            self.cpu.translate_support_code)
+        self.eventually_log_operations(tree)
+        regalloc = RegAlloc(self, tree, self.cpu.translate_support_code)
         if not we_are_translated():
             self._regalloc = regalloc # for debugging
-        if guard_op is not None:
-            new_rel_addr = self.mc.tell() - guard_op._jmp_from
-            TP = rffi.CArrayPtr(lltype.Signed)
-            ptr = rffi.cast(TP, guard_op._jmp_from - WORD)
-            ptr[0] = new_rel_addr
-            self.mc.redone(guard_op._jmp_from - WORD, guard_op._jmp_from)
         if self.verbose and not we_are_translated():
             import pprint
             print
@@ -161,7 +177,7 @@
             print
             #pprint.pprint(computed_ops)
             #print
-        regalloc.walk_operations(operations)
+        regalloc.walk_operations(tree)
         self.mc.done()
         self.mc2.done()
 
@@ -193,17 +209,17 @@
         finally:
             Box._extended_display = _prev
 
-    def assemble_comeback_bootstrap(self, mp):
+    def assemble_comeback_bootstrap(self, position, arglocs, stacklocs):
         entry_point_addr = self.mc2.tell()
-        for i in range(len(mp.arglocs)):
-            argloc = mp.arglocs[i]
+        for i in range(len(arglocs)):
+            argloc = arglocs[i]
             if isinstance(argloc, REG):
-                self.mc2.MOV(argloc, stack_pos(mp.stacklocs[i]))
+                self.mc2.MOV(argloc, stack_pos(stacklocs[i]))
             elif not we_are_translated():
                 # debug checks
                 if not isinstance(argloc, (IMM8, IMM32)):
-                    assert repr(argloc) == repr(stack_pos(mp.stacklocs[i]))
-        self.mc2.JMP(rel32(mp.position))
+                    assert repr(argloc) == repr(stack_pos(stacklocs[i]))
+        self.mc2.JMP(rel32(position))
         self.mc2.done()
         return entry_point_addr
 
@@ -228,7 +244,10 @@
     def regalloc_perform_discard(self, op, arglocs):
         genop_discard_list[op.opnum](self, op, arglocs)
 
-    def regalloc_perform_with_guard(self, op, guard_op, arglocs, resloc):
+    def regalloc_perform_with_guard(self, op, guard_op, regalloc,
+                                    arglocs, resloc):
+        addr = self.implement_guard_recovery(guard_op, regalloc, arglocs)
+        xxx
         genop_guard_list[op.opnum](self, op, guard_op, arglocs, resloc)
 
     def _unaryop(asmop):
@@ -501,11 +520,11 @@
                                              self.cpu.translate_support_code)
         self.mc.MOVZX(resloc, addr8_add(base_loc, ofs_loc, basesize))
 
-    def genop_discard_merge_point(self, op, locs):
-        op.position = self.mc.tell()
-        op.comeback_bootstrap_addr = self.assemble_comeback_bootstrap(op)
-
-    genop_discard_catch = genop_discard_merge_point
+    def make_merge_point(self, tree, locs, stacklocs):
+        pos = self.mc.tell()
+        tree.position = pos
+        tree.comeback_bootstrap_addr = self.assemble_comeback_bootstrap(pos,
+                                                        locs, stacklocs)
 
     def genop_discard_return(self, op, locs):
         if op.args:
@@ -574,8 +593,19 @@
     #    self.mc.CMP(mem(eax, offset), imm(0))
     #    self.implement_guard(op, self.mc.JNE)
 
+    def implement_guard_recovery(self, guard_op, locs, regalloc):
+        oldmc = self.mc
+        self.mc = self.mc2
+        self.mc2 = self.mcstack.next_mc()
+        regalloc._walk_operations(guard_op.suboperations)
+        xxx
+        self.mcstack.give_mc_back(self.mc2)
+        self.mc2 = self.mc
+        self.mc = oldmc
+
     @specialize.arg(2)
     def implement_guard(self, guard_op, emit_jump, locs):
+        xxx
         # XXX add caching, as we need only one for each combination
         # of locs
         recovery_addr = self.get_recovery_code(guard_op, locs)
@@ -583,6 +613,7 @@
         guard_op._jmp_from = self.mc.tell()
 
     def get_recovery_code(self, guard_op, locs):
+        xxx
         index = self.cpu.make_guard_index(guard_op)
         recovery_code_addr = self.mc2.tell()
         stacklocs = guard_op.stacklocs

Modified: pypy/branch/optimize-refactoring/pypy/jit/backend/x86/regalloc.py
==============================================================================
--- pypy/branch/optimize-refactoring/pypy/jit/backend/x86/regalloc.py	(original)
+++ pypy/branch/optimize-refactoring/pypy/jit/backend/x86/regalloc.py	Thu Apr  2 07:20:36 2009
@@ -47,27 +47,38 @@
         raise ValueError("convert_to_imm: got a %s" % c)
 
 class RegAlloc(object):
-    def __init__(self, assembler, operations, guard_op=None,
-                 translate_support_code=False):
+    def __init__(self, assembler, tree, translate_support_code=False,
+                 regalloc=None):
         # variables that have place in register
         self.assembler = assembler
         self.translate_support_code = translate_support_code
-        self.reg_bindings = newcheckdict()
-        self.stack_bindings = {}
-        # compute longevity of variables
-        self._compute_vars_longevity(operations)
-        self.free_regs = REGS[:]
-        self.dirty_stack = {}
-        mp = operations[0]
-        self.first_merge_point = mp
-        jump = operations[-1]
-        self.startmp = mp
-        if guard_op:
-            loop_consts, sd = self._start_from_guard_op(guard_op, mp, jump)
+        if regalloc is None:
+            self.reg_bindings = newcheckdict()
+            self.stack_bindings = {}
+            # compute longevity of variables
+            self._compute_vars_longevity(tree)
+            self.free_regs = REGS[:]
+            self.dirty_stack = {} 
+            jump = tree.operations[-1]
+            #self.startmp = mp
+            #if guard_op:
+            #    loop_consts, sd = self._start_from_guard_op(guard_op, mp, jump)
+            #else:
+            loop_consts, sd = self._compute_loop_consts(tree.inputargs, jump)
+            self.loop_consts = loop_consts
+            self.current_stack_depth = sd
         else:
-            loop_consts, sd = self._compute_loop_consts(mp, jump)
-        self.loop_consts = loop_consts
-        self.current_stack_depth = sd
+            self.reg_bindings = regalloc.reg_bindings.copy()
+            self.stack_bindings = regalloc.stack_bindings.copy()
+            self.free_regs = regalloc.free_regs[:]
+            self.dirty_stack = regalloc.dirty_stack.copy()
+            self.loop_consts = regalloc.loop_consts # should never change
+            self.current_stack_depth = regalloc.current_stack_depth
+            self.jump_reg_candidates = regalloc.jump_reg_candidates
+
+    def copy(self):
+        return RegAlloc(self.assembler, None, self.translate_support_code,
+                        self)
 
     def _start_from_guard_op(self, guard_op, mp, jump):
         rev_stack_binds = {}
@@ -112,19 +123,18 @@
                 j += 1
         return {}, sd
 
-    def _compute_loop_consts(self, mp, jump):
+    def _compute_loop_consts(self, inputargs, jump):
         self.jump_reg_candidates = {}
         if jump.opnum != rop.JUMP:
             loop_consts = {}
         else:
-            assert jump.jump_target is mp
             free_regs = REGS[:]
             loop_consts = {}
-            for i in range(len(mp.args)):
-                if mp.args[i] is jump.args[i]:
-                    loop_consts[mp.args[i]] = i
-            for i in range(len(mp.args)):
-                arg = mp.args[i]
+            for i in range(len(inputargs)):
+                if inputargs[i] is jump.args[i]:
+                    loop_consts[inputargs[i]] = i
+            for i in range(len(inputargs)):
+                arg = inputargs[i]
                 jarg = jump.args[i]
                 if arg is not jarg and not isinstance(jarg, Const):
                     if free_regs:
@@ -136,7 +146,7 @@
                 else:
                     # these are loop consts, but we need stack space anyway
                     self.stack_bindings[jarg] = stack_pos(i)
-        return loop_consts, len(mp.args)
+        return loop_consts, len(inputargs)
 
     def _check_invariants(self):
         if not we_are_translated():
@@ -170,12 +180,12 @@
             self.assembler.dump('%s <- %s(%s)' % (result_loc, op, arglocs))
         self.assembler.regalloc_perform(op, arglocs, result_loc)
 
-    def PerformWithGuard(self, op, guard_op, arglocs, result_loc):
+    def perform_with_guard(self, op, guard_op, regalloc, arglocs, result_loc):
         if not we_are_translated():
             self.assembler.dump('%s <- %s(%s) [GUARDED]' % (result_loc, op,
                                                             arglocs))
         self.assembler.regalloc_perform_with_guard(op, guard_op, arglocs,
-                                                   result_loc)
+                                                   regalloc, result_loc)
 
     def PerformDiscard(self, op, arglocs):
         if not we_are_translated():
@@ -194,9 +204,15 @@
             return False
         return True
 
-    def walk_operations(self, operations):
+    def walk_operations(self, tree):
         # first pass - walk along the operations in order to find
         # load/store places
+        operations = tree.operations
+        self.position = 0
+        self.process_inputargs(tree)
+        self._walk_operations(operations)
+
+    def _walk_operations(self, operations):
         i = 0
         while i < len(operations):
             op = operations[i]
@@ -224,13 +240,14 @@
             i += 1
         assert not self.reg_bindings
 
-    def _compute_vars_longevity(self, operations):
+    def _compute_vars_longevity(self, tree):
         # compute a dictionary that maps variables to index in
         # operations that is a "last-time-seen"
         longevity = {}
         start_live = {}
-        for v in operations[0].args:
-            start_live[v] = 0
+        for inputarg in tree.inputargs:
+            start_live[inputarg] = 0
+        operations = tree.operations
         for i in range(len(operations)):
             op = operations[i]
             if op.result is not None:
@@ -239,7 +256,7 @@
                 if isinstance(arg, Box):
                     longevity[arg] = (start_live[arg], i)
             if op.is_guard():
-                for arg in op.liveboxes:
+                for arg in op.suboperations[-1].args:
                     assert isinstance(arg, Box)
                     longevity[arg] = (start_live[arg], i)
         self.longevity = longevity
@@ -453,13 +470,13 @@
             loc = self.reg_bindings[result_v]
         return loc
 
-    def consider_merge_point(self, op, ignored):
+    def process_inputargs(self, tree):
         # XXX we can sort out here by longevity if we need something
         # more optimal
-
-        locs = [None] * len(op.args)
-        for i in range(len(op.args)):
-            arg = op.args[i]
+        inputargs = tree.inputargs
+        locs = [None] * len(inputargs)
+        for i in range(len(inputargs)):
+            arg = inputargs[i]
             assert not isinstance(arg, Const)
             reg = None
             loc = stack_pos(i)
@@ -474,35 +491,26 @@
             else:
                 locs[i] = loc
             # otherwise we have it saved on stack, so no worry
-        op.arglocs = locs
-        op.stacklocs = range(len(op.args))
-        self.PerformDiscard(op, locs)
+        tree.arglocs = locs
+        tree.stacklocs = range(len(inputargs))
+        self.assembler.make_merge_point(tree, locs, tree.stacklocs)
         # XXX be a bit smarter and completely ignore such vars
-        self.eventually_free_vars(op.args)
-
-    def consider_catch(self, op, ignored):
-        locs = []
-        for arg in op.args:
-            l = self.loc(arg)
-            if isinstance(l, REG):
-                self.dirty_stack[arg] = True
-            locs.append(l)
-            # possibly constants
-        op.arglocs = locs
-        op.stacklocs = [self.stack_loc(arg).position for arg in op.args]
-        self.eventually_free_vars(op.args)
-        self.PerformDiscard(op, [])
+        self.eventually_free_vars(inputargs)
 
     def _consider_guard(self, op, ignored):
         loc = self.make_sure_var_in_reg(op.args[0], [])
         locs = self._locs_from_liveboxes(op)
         self.eventually_free_var(op.args[0])
         self.eventually_free_vars(op.liveboxes)
+        xxx
         self.PerformDiscard(op, [loc] + locs)
 
     consider_guard_true = _consider_guard
     consider_guard_false = _consider_guard
 
+    def consider_fail(self, op, ignored):
+        xxx
+
     def consider_guard_nonvirtualized(self, op, ignored):
         # XXX implement it
         locs = self._locs_from_liveboxes(op)
@@ -682,7 +690,9 @@
             self.position += 1
             self.eventually_free_var(op.result)
             self.eventually_free_vars(guard_op.liveboxes)
-            self.PerformWithGuard(op, guard_op, arglocs + locs, None)
+            regalloc = self.copy()
+            self.perform_with_guard(op, guard_op, regalloc, arglocs + locs,
+                                    None)
 
     consider_int_lt = _consider_compop
     consider_int_gt = _consider_compop
@@ -895,11 +905,10 @@
         middle_busy_regs = []
         for i in range(len(op.args)):
             arg = op.args[i]
-            mp = op.jump_target
-            res = mp.arglocs[i]
+            loop = op.jump_target
+            res = loop.inputargs[i]
             if not (isinstance(arg, Const) or (arg in self.loop_consts
                                                and self.loop_consts[arg] == i)):
-                assert mp.opnum == rop.MERGE_POINT
                 if arg in self.reg_bindings:
                     if not isinstance(res, REG):
                         self.Store(arg, self.loc(arg),

Modified: pypy/branch/optimize-refactoring/pypy/jit/backend/x86/runner.py
==============================================================================
--- pypy/branch/optimize-refactoring/pypy/jit/backend/x86/runner.py	(original)
+++ pypy/branch/optimize-refactoring/pypy/jit/backend/x86/runner.py	Thu Apr  2 07:20:36 2009
@@ -180,84 +180,8 @@
         self.assembler._exception_bck[0] = ovf_vtable
         self.assembler._exception_bck[1] = ovf_inst
 
-#     def execute_operation(self, opnum, valueboxes, result_type):
-#         xxx
-#         if execute[opnum] is not None:
-#             return execute[opnum](valueboxes)
-        
-#         # mostly a hack: fall back to compiling and executing the single
-#         # operation.
-#         key = []
-#         for valuebox in valueboxes:
-#             if isinstance(valuebox, Box):
-#                 key.append(valuebox.type)
-#             else:
-#                 key.append(str(valuebox.get_()))
-#         mp = self.get_compiled_single_operation(opnum, result_type,
-#                                                 key, valueboxes)
-#         res = self.execute_operations_in_new_frame(opname[opnum], mp,
-#                                                    valueboxes,
-#                                                    result_type)
-#         if not self.translate_support_code:
-#             if self.assembler._exception_data[0] != 0:
-#                 TP = lltype.Ptr(rclass.OBJECT_VTABLE)
-#                 TP_V = lltype.Ptr(rclass.OBJECT)
-#                 exc_t_a = self.cast_int_to_adr(self.get_exception(None))
-#                 exc_type = llmemory.cast_adr_to_ptr(exc_t_a, TP)
-#                 exc_v_a = self.get_exc_value(None)
-#                 exc_val = lltype.cast_opaque_ptr(TP_V, exc_v_a)
-#                 # clean up the exception
-#                 self.assembler._exception_data[0] = 0
-#                 raise LLException(exc_type, exc_val)
-#         # otherwise exception data is set correctly, no problem at all
-#         return res
-
-#     def get_compiled_single_operation(self, opnum, result_type, key,
-#                                       valueboxes):
-#         xxx
-#         real_key = '%d,%s' % (opnum, result_type) + ','.join(key)
-#         try:
-#             return self._compiled_ops[real_key]
-#         except KeyError:
-#             livevarlist = []
-#             i = 0
-#             # clonebox below is necessary, because sometimes we know
-#             # that the value is constant (ie ArrayDescr), but we're not
-#             # going to get the contant. So instead we get a box with correct
-#             # value
-#             for box in valueboxes:
-#                 if box.type == 'int':
-#                     box = valueboxes[i].clonebox()
-#                 elif box.type == 'ptr':
-#                     box = valueboxes[i].clonebox()
-#                 else:
-#                     raise ValueError(type)
-#                 livevarlist.append(box)
-#                 i += 1
-#             mp = ResOperation(rop.MERGE_POINT, livevarlist, None)
-#             if result_type == 'void':
-#                 result = None
-#             elif result_type == 'int':
-#                 result = history.BoxInt()
-#             elif result_type == 'ptr':
-#                 result = history.BoxPtr()
-#             else:
-#                 raise ValueError(result_type)
-#             if result is None:
-#                 results = []
-#             else:
-#                 results = [result]
-#             operations = [mp,
-#                           ResOperation(opnum, livevarlist, result),
-#                           ResOperation(rop.RETURN, results, None)]
-#             if operations[1].is_guard():
-#                 operations[1].liveboxes = []
-#             self.compile_operations(operations, verbose=False)
-#             self._compiled_ops[real_key] = mp
-#             return mp
-
-    def compile_operations(self, operations, guard_op=None, verbose=True):
-        self.assembler.assemble(operations, guard_op, verbose=verbose)
+    def compile_operations(self, tree):
+        self.assembler.assemble(tree)
 
     def get_bootstrap_code(self, startmp):
         # key is locations of arguments
@@ -312,7 +236,9 @@
         self.generated_mps[calldescr] = operations
         return operations
 
-    def execute_operations_in_new_frame(self, name, operations, valueboxes):
+    def execute_operations(self, loop, valueboxes):
+        import pdb
+        pdb.set_trace()
         startmp = operations[0]
         func = self.get_bootstrap_code(startmp)
         # turn all the values into integers
@@ -568,6 +494,7 @@
 
     def do_call(self, args, calldescr):
         num_args, size, ptr = self.unpack_calldescr(calldescr)
+        xxx
         mp = self._get_mp_for_call(num_args, calldescr)
         if size == 0:
             self.return_value_type = VOID
@@ -575,7 +502,7 @@
             self.return_value_type = PTR
         else:
             self.return_value_type = INT
-        result = self.execute_operations_in_new_frame('call', mp, args)
+        result = self.execute_operations(mp, args)
         return result
 
     # ------------------- helpers and descriptions --------------------



More information about the Pypy-commit mailing list