[pypy-svn] r63826 - in pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp: . test

arigo at codespeak.net arigo at codespeak.net
Wed Apr 8 14:23:03 CEST 2009


Author: arigo
Date: Wed Apr  8 14:23:00 2009
New Revision: 63826

Modified:
   pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/codewriter.py
   pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py
   pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/dump.py
   pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py
   pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_basic.py
   pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_recursive.py
   pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/warmspot.py
Log:
Fix test_recursive by splitting the class OOMetaInterp in three:
    MetaInterpStaticData: frozen global
    MetaInterpGlobalData: non-frozen global
    MetaInterp: local to a trace

Once this is done, we only have to worry about changing Boxes,
which can be taken care of by saving and restoring their content
across recursive calls (done lazily).


Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/codewriter.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/codewriter.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/codewriter.py	Wed Apr  8 14:23:00 2009
@@ -75,15 +75,15 @@
 class CodeWriter(object):
     portal_graph = None
 
-    def __init__(self, metainterp, policy):
+    def __init__(self, metainterp_sd, policy):
         self.all_prebuilt_values = {}
         self.all_graphs = {}
         self.all_indirectcallsets = {}
         self.all_listdescs = {}
         self.unfinished_graphs = []
-        self.metainterp = metainterp
-        self.rtyper = metainterp.cpu.rtyper
-        self.cpu = metainterp.cpu
+        self.metainterp_sd = metainterp_sd
+        self.rtyper = metainterp_sd.cpu.rtyper
+        self.cpu = metainterp_sd.cpu
         self.policy = policy
 
     def make_portal_bytecode(self, graph):
@@ -209,7 +209,7 @@
     
     def __init__(self, codewriter, graph, portal):
         self.codewriter = codewriter
-        self.cpu = codewriter.metainterp.cpu
+        self.cpu = codewriter.metainterp_sd.cpu
         self.portal = portal
         self.bytecode = self.codewriter.get_jitcode(graph)
         if not codewriter.policy.look_inside_graph(graph):
@@ -231,12 +231,13 @@
             self.make_exception_handler(self.pending_exception_handlers.pop())
 
         labelpos = {}
-        code = assemble(labelpos, self.codewriter.metainterp, self.assembler)
+        code = assemble(labelpos, self.codewriter.metainterp_sd,
+                        self.assembler)
         self.resolve_switch_targets(labelpos)
         self.bytecode.setup(code, self.constants)
 
         self.bytecode._source = self.assembler
-        self.bytecode._metainterp = self.codewriter.metainterp
+        self.bytecode._metainterp_sd = self.codewriter.metainterp_sd
         self.bytecode._labelpos = labelpos
         if self.debug:
             self.bytecode.dump()
@@ -749,7 +750,7 @@
         c_func, TP = support.builtin_func_for_spec(self.codewriter.rtyper,
                                                    oopspec_name, argtypes,
                                                    resulttype)
-        if self.codewriter.metainterp.options.listops:
+        if self.codewriter.metainterp_sd.options.listops:
             if self.handle_list_call(op, oopspec_name, args, TP):
                 return
 ##            if oopspec_name.startswith('list.getitem'):
@@ -903,16 +904,17 @@
         FIELDTYPE = getattr(STRUCTTYPE, argname)
         if FIELDTYPE != lltype.Void:
             TOPSTRUCT = heaptracker.cast_vable_type(STRUCTTYPE)
-            metainterp = self.codewriter.metainterp
+            metainterp_sd = self.codewriter.metainterp_sd
+            vdescs = metainterp_sd._virtualizabledescs
             try:
-                virtualizabledesc = metainterp._virtualizabledescs[TOPSTRUCT]
+                virtualizabledesc = vdescs[TOPSTRUCT]
             except KeyError:
                 from pypy.jit.metainterp import virtualizable
                 virtualizabledesc = virtualizable.VirtualizableDesc(
                     self.cpu, TOPSTRUCT, STRUCTTYPE)
-                virtualizabledesc.hash = len(metainterp._virtualizabledescs)
-                metainterp._virtualizabledescs[TOPSTRUCT] = virtualizabledesc
-                metainterp._can_have_virtualizables = virtualizabledesc
+                virtualizabledesc.hash = len(metainterp_sd._virtualizabledescs)
+                vdescs[TOPSTRUCT] = virtualizabledesc
+                metainterp_sd._can_have_virtualizables = virtualizabledesc
                 #             ^^^ stays None if this code is never seen
             guard_field = self.cpu.fielddescrof(STRUCTTYPE, argname)
             self.emit('guard_nonvirtualized')
@@ -1000,7 +1002,7 @@
             break
     return result
 
-def assemble(labelpos, metainterp, assembler):
+def assemble(labelpos, metainterp_sd, assembler):
     result = []
     for arg in assembler:
         if isinstance(arg, str):
@@ -1008,7 +1010,7 @@
                 continue
             #if arg == 'green':
             #    XXX should be removed and transformed into a list constant
-            opcode = metainterp.find_opcode(arg)
+            opcode = metainterp_sd.find_opcode(arg)
             result.append(chr(opcode))
         elif isinstance(arg, bool):
             result.append(chr(int(arg)))

Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py	Wed Apr  8 14:23:00 2009
@@ -74,13 +74,13 @@
             extraloops = []
         else:
             extraloops = [loop]
-        metainterp.stats.view(errmsg=errmsg, extraloops=extraloops)
+        metainterp.staticdata.stats.view(errmsg=errmsg, extraloops=extraloops)
 
 def create_empty_loop(metainterp):
     if we_are_translated():
         name = 'Loop'
     else:
-        name = 'Loop #%d' % len(metainterp.stats.loops)
+        name = 'Loop #%d' % len(metainterp.staticdata.stats.loops)
     return TreeLoop(name)
 
 # ____________________________________________________________
@@ -92,13 +92,14 @@
     loop.inputargs = history.inputargs
     loop.operations = history.operations
     loop.operations[-1].jump_target = loop
-    old_loop = metainterp.optimize_loop(metainterp.options, old_loops,
-                                        loop, metainterp.cpu)
+    metainterp_sd = metainterp.staticdata
+    old_loop = metainterp_sd.optimize_loop(metainterp_sd.options, old_loops,
+                                           loop, metainterp.cpu)
     if old_loop is not None:
         return old_loop
     history.source_link = loop
     send_loop_to_backend(metainterp, loop, "loop")
-    metainterp.stats.loops.append(loop)
+    metainterp.staticdata.stats.loops.append(loop)
     old_loops.append(loop)
     return loop
 
@@ -106,7 +107,7 @@
     metainterp.cpu.compile_operations(loop)
     if not we_are_translated():
         if type != "entry bridge":
-            metainterp.stats.compiled_count += 1
+            metainterp.staticdata.stats.compiled_count += 1
         else:
             loop._ignore_during_counting = True
         log.info("compiled new " + type)
@@ -114,19 +115,19 @@
 # ____________________________________________________________
 
 class DoneWithThisFrameDescr0(AbstractDescr):
-    def handle_fail_op(self, metainterp, fail_op):
-        raise metainterp.DoneWithThisFrame(None)
+    def handle_fail_op(self, metainterp_sd, fail_op):
+        raise metainterp_sd.DoneWithThisFrame(None)
 
 class DoneWithThisFrameDescr1(AbstractDescr):
-    def handle_fail_op(self, metainterp, fail_op):
+    def handle_fail_op(self, metainterp_sd, fail_op):
         resultbox = fail_op.args[0]
-        raise metainterp.DoneWithThisFrame(resultbox)
+        raise metainterp_sd.DoneWithThisFrame(resultbox)
 
 class ExitFrameWithExceptionDescr(AbstractDescr):
-    def handle_fail_op(self, metainterp, fail_op):
-        typebox = fail_op.args[0]
-        valuebox = fail_op.args[1]
-        raise metainterp.ExitFrameWithException(typebox, valuebox)
+    def handle_fail_op(self, metainterp_sd, fail_op):
+        assert len(fail_op.args) == 1
+        valuebox = fail_op.args[0]
+        raise metainterp_sd.ExitFrameWithException(valuebox)
 
 done_with_this_frame_descr_0 = DoneWithThisFrameDescr0()
 done_with_this_frame_descr_1 = DoneWithThisFrameDescr1()
@@ -153,27 +154,29 @@
 map_loop2descr[_loop] = done_with_this_frame_descr_0
 
 _loop = TreeLoop('exit_frame_with_exception')
-_loop.specnodes = [NotSpecNode(), NotSpecNode()]
-_loop.inputargs = [BoxInt(), BoxPtr()]
+_loop.specnodes = [NotSpecNode()]
+_loop.inputargs = [BoxPtr()]
 loops_exit_frame_with_exception = [_loop]
 map_loop2descr[_loop] = exit_frame_with_exception_descr
 del _loop
 
 
 class ResumeGuardDescr(AbstractDescr):
-    def __init__(self, guard_op, resume_info, history, history_guard_index):
+    def __init__(self, resume_info, history, history_guard_index):
         self.resume_info = resume_info
-        self.guard_op = guard_op
         self.counter = 0
         self.history = history
         assert history_guard_index >= 0
         self.history_guard_index = history_guard_index
 
-    def handle_fail_op(self, metainterp, fail_op):
+    def handle_fail_op(self, metainterp_sd, fail_op):
+        from pypy.jit.metainterp.pyjitpl import MetaInterp
+        metainterp = MetaInterp(metainterp_sd)
         return metainterp.handle_guard_failure(fail_op, self)
 
     def get_guard_op(self):
-        guard_op = self.guard_op
+        guard_op = self.history.operations[self.history_guard_index]
+        assert guard_op.is_guard()
         if guard_op.optimized is not None:   # should always be the case,
             return guard_op.optimized        # except if not optimizing at all
         else:
@@ -216,7 +219,8 @@
         # to previously-compiled code.  We keep 'new_loop', which is not
         # a loop at all but ends in a jump to the target loop.  It starts
         # with completely unoptimized arguments, as in the interpreter.
-        num_green_args = metainterp.num_green_args
+        metainterp_sd = metainterp.staticdata
+        num_green_args = metainterp_sd.num_green_args
         greenkey = self.original_boxes[:num_green_args]
         redkey = self.original_boxes[num_green_args:]
         metainterp.history.source_link = new_loop
@@ -224,10 +228,10 @@
         new_loop.greenkey = greenkey
         new_loop.inputargs = redkey
         send_loop_to_backend(metainterp, new_loop, "entry bridge")
-        metainterp.stats.loops.append(new_loop)
+        metainterp_sd.stats.loops.append(new_loop)
         # send the new_loop to warmspot.py, to be called directly the next time
-        metainterp.state.attach_unoptimized_bridge_from_interp(greenkey,
-                                                               new_loop)
+        metainterp_sd.state.attach_unoptimized_bridge_from_interp(greenkey,
+                                                                  new_loop)
 
 
 def compile_fresh_bridge(metainterp, old_loops, resumekey):
@@ -238,8 +242,10 @@
     # it does not work -- i.e. none of the existing old_loops match.
     new_loop = create_empty_loop(metainterp)
     new_loop.operations = metainterp.history.operations
-    target_loop = metainterp.optimize_bridge(metainterp.options, old_loops,
-                                             new_loop, metainterp.cpu)
+    metainterp_sd = metainterp.staticdata
+    target_loop = metainterp_sd.optimize_bridge(metainterp_sd.options,
+                                                old_loops, new_loop,
+                                                metainterp.cpu)
     # Did it work?  If not, prepare_loop_from_bridge() will probably be used.
     if target_loop is not None:
         # Yes, we managed to create a bridge.  Dispatch to resumekey to

Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/dump.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/dump.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/dump.py	Wed Apr  8 14:23:00 2009
@@ -89,7 +89,7 @@
     # XXX this is not really a disassembler, but just a pretty-printer
     # for the '_source' attribute that codewriter.py attaches
     source = jitcode._source
-    interpreter = jitcode._metainterp
+    interpreter = jitcode._metainterp_sd
     labelpos = jitcode._labelpos
     print >> file, 'JITCODE %r' % (jitcode.name,)
 

Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py	Wed Apr  8 14:23:00 2009
@@ -544,8 +544,8 @@
 
     def generate_merge_point(self, pc, varargs):
         if isinstance(self.metainterp.history, history.BlackHole):
-            raise self.metainterp.ContinueRunningNormally(varargs)
-        num_green_args = self.metainterp.num_green_args
+            raise self.metainterp.staticdata.ContinueRunningNormally(varargs)
+        num_green_args = self.metainterp.staticdata.num_green_args
         for i in range(num_green_args):
             varargs[i] = self.implement_guard_value(pc, varargs[i])
 
@@ -632,7 +632,8 @@
             op = ord(self.bytecode[pc])
             #print self.metainterp.opcode_names[op]
             self.pc = pc + 1
-            stop = self.metainterp.opcode_implementations[op](self, pc)
+            staticdata = self.metainterp.staticdata
+            stop = staticdata.opcode_implementations[op](self, pc)
             #self.metainterp.most_recent_mp = None
             if stop:
                 break
@@ -663,7 +664,7 @@
         else:
             moreargs = list(extraargs)
         guard_op = self.metainterp.history.record(opnum, moreargs, None)
-        resumedescr = compile.ResumeGuardDescr(guard_op, resume_info,
+        resumedescr = compile.ResumeGuardDescr(resume_info,
             self.metainterp.history, len(self.metainterp.history.operations)-1)
         op = history.ResOperation(rop.FAIL, liveboxes, None, descr=resumedescr)
         guard_op.suboperations = [op]
@@ -699,10 +700,7 @@
 
 # ____________________________________________________________
 
-class Optimizer(object):
-    pass
-
-class OOMetaInterp(object):
+class MetaInterpStaticData(object):
     num_green_args = 0
 
     def __init__(self, portal_graph, graphs, cpu, stats, options,
@@ -711,8 +709,7 @@
         self.cpu = cpu
         self.stats = stats
         self.options = options
-        self.compiled_merge_points = r_dict(history.mp_eq, history.mp_hash)
-                 # { greenkey: list-of-MergePoints }
+        self.globaldata = MetaInterpGlobalData()
 
         self.opcode_implementations = []
         self.opcode_names = []
@@ -723,7 +720,6 @@
         else:
             self.cpu.class_sizes = None
         self._virtualizabledescs = {}
-        self._debug_history = []
         if optimizer is not None:
             self.optimize_loop = optimizer.optimize_loop
             self.optimize_bridge = optimizer.optimize_bridge
@@ -732,6 +728,9 @@
             self.optimize_loop = optimize.optimize_loop
             self.optimize_bridge = optimize.optimize_bridge
 
+    def _freeze_(self):
+        return True
+
     def _recompute_class_sizes(self):
         if self.cpu.class_sizes is None:
             cs = {}
@@ -743,7 +742,58 @@
         self._codewriter = codewriter.CodeWriter(self, policy)
         self.portal_code = self._codewriter.make_portal_bytecode(
             self.portal_graph)
-        self.delete_history()
+
+    # ---------- construction-time interface ----------
+
+    def _register_opcode(self, opname):
+        assert len(self.opcode_implementations) < 256, \
+               "too many implementations of opcodes!"
+        name = "opimpl_" + opname
+        self.opname_to_index[opname] = len(self.opcode_implementations)
+        self.opcode_names.append(opname)
+        self.opcode_implementations.append(getattr(MIFrame, name).im_func)
+
+    def find_opcode(self, name):
+        try:
+            return self.opname_to_index[name]
+        except KeyError:
+            self._register_opcode(name)
+            return self.opname_to_index[name]
+
+# ____________________________________________________________
+
+class MetaInterpGlobalData(object):
+    def __init__(self):
+        self.metainterp_doing_call = None
+        self._debug_history = []
+        self.compiled_merge_points = r_dict(history.mp_eq, history.mp_hash)
+                 # { greenkey: list-of-MergePoints }
+
+    def set_metainterp_doing_call(self, metainterp):
+        self.save_recursive_call()
+        self.metainterp_doing_call = metainterp
+
+    def unset_metainterp_doing_call(self, metainterp):
+        if self.metainterp_doing_call != metainterp:
+            metainterp._restore_recursive_call()
+        self.metainterp_doing_call = None
+
+    def save_recursive_call(self):
+        if self.metainterp_doing_call is not None:
+            self.metainterp_doing_call._save_recursive_call()
+            self.metainterp_doing_call = None
+
+    def assert_empty(self):
+        assert self.metainterp_doing_call is None
+
+# ____________________________________________________________
+
+class MetaInterp(object):
+    def __init__(self, staticdata):
+        self.staticdata = staticdata
+        self.cpu = staticdata.cpu
+        if not we_are_translated():
+            self._debug_history = staticdata.globaldata._debug_history
 
     def newframe(self, jitcode):
         if not we_are_translated():
@@ -763,7 +813,7 @@
         else:
             if not isinstance(self.history, history.BlackHole):
                 self.compile_done_with_this_frame(resultbox)
-            raise self.DoneWithThisFrame(resultbox)
+            raise self.staticdata.DoneWithThisFrame(resultbox)
 
     def finishframe_exception(self, exceptionbox, excvaluebox):
         while self.framestack:
@@ -778,22 +828,13 @@
                 self._debug_history.append(['leave_exc', frame.jitcode, None])
             self.framestack.pop()
         if not isinstance(self.history, history.BlackHole):
-            self.compile_exit_frame_with_exception(exceptionbox, excvaluebox)
-        raise self.ExitFrameWithException(exceptionbox, excvaluebox)
+            self.compile_exit_frame_with_exception(excvaluebox)
+        raise self.staticdata.ExitFrameWithException(excvaluebox)
 
     def create_empty_history(self):
         self.history = history.History(self.cpu)
-        if self.stats is not None:
-            self.stats.history = self.history
-
-    def delete_history(self):
-        self.history = None
-        self.framestack = None
-        self.current_merge_points = None
-        self.resumekey = None
-
-    def set_blackhole_mode(self):
-        self.history = history.BlackHole(self.cpu)
+        if self.staticdata.stats is not None:
+            self.staticdata.stats.history = self.history
 
     def _all_constants(self, boxes):
         for box in boxes:
@@ -803,7 +844,9 @@
 
     @specialize.arg(1)
     def execute_and_record(self, opnum, argboxes, descr=None):
-        old_framestack = self.framestack
+        # detect recursions when using rop.CALL
+        if opnum == rop.CALL:
+            self.staticdata.globaldata.set_metainterp_doing_call(self)
         # execute the operation first
         history.check_descr(descr)
         resbox = executor.execute(self.cpu, opnum, argboxes, descr)
@@ -820,23 +863,55 @@
         else:
             assert resbox is None or isinstance(resbox, Box)
             if opnum == rop.CALL:
-                # with executor.execute(rop.CALL), there is a risk of recursion
-                if self.framestack is not old_framestack:
-                    if not we_are_translated():
-                        history.log.info('recursion detected')
-                    self.framestack = old_framestack
-                    self.set_blackhole_mode()
+                self.staticdata.globaldata.unset_metainterp_doing_call(self)
         # record the operation if not constant-folded away
         if not canfold:
             self.history.record(opnum, argboxes, resbox, descr)
         return resbox
 
+    def _save_recursive_call(self):
+        # A bit of a hack: we need to be safe against box.changevalue_xxx()
+        # called by cpu.execute_operations(), in case we are recursively
+        # in another MetaInterp.  Temporarily save away the content of the
+        # boxes.
+        if not we_are_translated():
+            history.log.info('recursive call to execute_operations()!')
+        saved_env = []
+        for f in self.framestack:
+            newenv = []
+            for box in f.env:
+                if isinstance(box, Box):
+                    saved_env.append(box.clonebox())
+        pseudoframe = instantiate(MIFrame)
+        pseudoframe.env = saved_env
+        self.framestack.append(pseudoframe)
+
+    def _restore_recursive_call(self):
+        if not we_are_translated():
+            history.log.info('recursion detected, restoring state')
+            assert not hasattr(self.framestack[-1], 'jitcode')
+            assert hasattr(self.framestack[-2], 'jitcode')
+        pseudoframe = self.framestack.pop()
+        saved_env = pseudoframe.env
+        i = 0
+        for f in self.framestack:
+            for box in f.env:
+                if isinstance(box, BoxInt):
+                    box.changevalue_int(saved_env[i].getint())
+                    i += 1
+                elif isinstance(box, BoxPtr):
+                    box.changevalue_ptr(saved_env[i].getptr_base())
+                    i += 1
+                else:
+                    assert isinstance(box, Const)
+        assert i == len(saved_env)
+
     def _interpret(self):
         # Execute the frames forward until we raise a DoneWithThisFrame,
         # a ContinueRunningNormally, or a GenerateMergePoint exception.
         if not we_are_translated():
             history.log.event('ENTER' + self.history.extratext)
-            self.stats.enter_count += 1
+            self.staticdata.stats.enter_count += 1
         else:
             debug_print('~~~ ENTER', self.history.extratext)
         try:
@@ -873,8 +948,8 @@
         except GenerateMergePoint, gmp:
             return self.designate_target_loop(gmp)
 
-    def handle_guard_failure(self, guard_failure, key):
-        self.initialize_state_from_guard_failure(guard_failure)
+    def handle_guard_failure(self, exec_result, key):
+        self.initialize_state_from_guard_failure(exec_result)
         assert isinstance(key, compile.ResumeGuardDescr)
         top_history = key.find_toplevel_history()
         source_loop = top_history.source_link
@@ -882,8 +957,9 @@
         original_boxes = source_loop.greenkey + top_history.inputargs
         self.current_merge_points = [(original_boxes, 0)]
         self.resumekey = key
+        guard_op = key.get_guard_op()
         try:
-            self.prepare_resume_from_failure(key.guard_op.opnum)
+            self.prepare_resume_from_failure(guard_op.opnum)
             self.interpret()
             assert False, "should always raise"
         except GenerateMergePoint, gmp:
@@ -906,7 +982,7 @@
         for j in range(len(self.current_merge_points)-1, -1, -1):
             original_boxes, start = self.current_merge_points[j]
             assert len(original_boxes) == len(live_arg_boxes)
-            for i in range(self.num_green_args):
+            for i in range(self.staticdata.num_green_args):
                 box1 = original_boxes[i]
                 box2 = live_arg_boxes[i]
                 if not box1.equals(box2):
@@ -942,9 +1018,8 @@
         raise GenerateMergePoint(live_arg_boxes, loop)
 
     def designate_target_loop(self, gmp):
-        self.delete_history()
         loop = gmp.target_loop
-        num_green_args = self.num_green_args
+        num_green_args = self.staticdata.num_green_args
         residual_args = self.get_residual_args(loop,
                                                gmp.argboxes[num_green_args:])
         return (loop, residual_args)
@@ -958,23 +1033,24 @@
             self.handle_exception()
 
     def compile(self, original_boxes, live_arg_boxes):
-        num_green_args = self.num_green_args
+        num_green_args = self.staticdata.num_green_args
         self.history.inputargs = original_boxes[num_green_args:]
         greenkey = original_boxes[:num_green_args]
-        old_loops = self.compiled_merge_points.setdefault(greenkey, [])
+        glob = self.staticdata.globaldata
+        old_loops = glob.compiled_merge_points.setdefault(greenkey, [])
         self.history.record(rop.JUMP, live_arg_boxes[num_green_args:], None)
         loop = compile.compile_new_loop(self, old_loops, greenkey)
         assert loop is not None
         if not we_are_translated():
             loop._call_history = self._debug_history
-            self.debug_history = []
         return loop
 
     def compile_bridge(self, live_arg_boxes):
-        num_green_args = self.num_green_args
+        num_green_args = self.staticdata.num_green_args
         greenkey = live_arg_boxes[:num_green_args]
         try:
-            old_loops = self.compiled_merge_points[greenkey]
+            glob = self.staticdata.globaldata
+            old_loops = glob.compiled_merge_points[greenkey]
         except KeyError:
             return
         self.history.record(rop.JUMP, live_arg_boxes[num_green_args:], None)
@@ -999,9 +1075,9 @@
         target_loop = compile.compile_new_bridge(self, loops, self.resumekey)
         assert target_loop is loops[0]
 
-    def compile_exit_frame_with_exception(self, typebox, valuebox):
+    def compile_exit_frame_with_exception(self, valuebox):
         # temporarily put a JUMP to a pseudo-loop
-        self.history.record(rop.JUMP, [typebox, valuebox], None)
+        self.history.record(rop.JUMP, [valuebox], None)
         loops = compile.loops_exit_frame_with_exception
         target_loop = compile.compile_new_bridge(self, loops, self.resumekey)
         assert target_loop is loops[0]
@@ -1045,14 +1121,14 @@
                                         *args[1:])
 
     def initialize_state_from_start(self, *args):
-        self._recompute_class_sizes()
+        self.staticdata._recompute_class_sizes()
         self.create_empty_history()
-        num_green_args = self.num_green_args
+        num_green_args = self.staticdata.num_green_args
         original_boxes = []
         self._initialize_from_start(original_boxes, num_green_args, *args)
         # ----- make a new frame -----
         self.framestack = []
-        f = self.newframe(self.portal_code)
+        f = self.newframe(self.staticdata.portal_code)
         f.pc = 0
         f.env = original_boxes[:]
         return original_boxes
@@ -1061,7 +1137,8 @@
         # guard failure: rebuild a complete MIFrame stack
         resumedescr = guard_failure.descr
         assert isinstance(resumedescr, compile.ResumeGuardDescr)
-        must_compile = self.state.must_compile_from_failure(resumedescr)
+        warmrunnerstate = self.staticdata.state
+        must_compile = warmrunnerstate.must_compile_from_failure(resumedescr)
         if must_compile:
             guard_op = resumedescr.get_guard_op()
             suboperations = guard_op.suboperations
@@ -1076,7 +1153,9 @@
                 self.history.operations.append(suboperations[i])
             self.extra_rebuild_operations = extra
         else:
-            self.set_blackhole_mode()
+            self.history = history.BlackHole(self.cpu)
+            # the BlackHole is invalid because it doesn't start with
+            # guard_failure.key.guard_op.suboperations, but that's fine
         self.rebuild_state_after_failure(resumedescr.resume_info,
                                          guard_failure.args)
 
@@ -1108,24 +1187,6 @@
                                            exception_target)
         assert nbindex == len(newboxes), "too many newboxes!"
 
-    # ____________________________________________________________
-    # construction-time interface
-
-    def _register_opcode(self, opname):
-        assert len(self.opcode_implementations) < 256, \
-               "too many implementations of opcodes!"
-        name = "opimpl_" + opname
-        self.opname_to_index[opname] = len(self.opcode_implementations)
-        self.opcode_names.append(opname)
-        self.opcode_implementations.append(getattr(MIFrame, name).im_func)
-
-    def find_opcode(self, name):
-        try:
-            return self.opname_to_index[name]
-        except KeyError:
-            self._register_opcode(name)
-            return self.opname_to_index[name]
-
 
 class GenerateMergePoint(Exception):
     def __init__(self, args, target_loop):

Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_basic.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_basic.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_basic.py	Wed Apr  8 14:23:00 2009
@@ -21,7 +21,8 @@
     cpu = CPUClass(rtyper, stats, False)
     graph = rtyper.annotator.translator.graphs[0]
     opt = history.Options(specialize=False, listops=listops)
-    metainterp = pyjitpl.OOMetaInterp(graph, [], cpu, stats, opt)
+    metainterp_sd = pyjitpl.MetaInterpStaticData(graph, [], cpu, stats, opt)
+    metainterp = pyjitpl.MetaInterp(metainterp_sd)
     metainterp.num_green_args = 0
     return metainterp, rtyper
 
@@ -68,16 +69,15 @@
         metainterp, rtyper = get_metainterp(f, args, self.CPUClass,
                                             self.type_system, policy=policy,
                                             **kwds)
-        cw = codewriter.CodeWriter(metainterp, policy)
+        cw = codewriter.CodeWriter(metainterp.staticdata, policy)
         graph = rtyper.annotator.translator.graphs[0]
         maingraph = cw.make_one_bytecode(graph, False)
         while cw.unfinished_graphs:
             graph, called_from = cw.unfinished_graphs.pop()
             cw.make_one_bytecode(graph, False, called_from)
-        metainterp.portal_code = maingraph
-        metainterp.delete_history()
-        metainterp.state = FakeWarmRunnerDesc()
-        metainterp.DoneWithThisFrame = DoneWithThisFrame
+        metainterp.staticdata.portal_code = maingraph
+        metainterp.staticdata.state = FakeWarmRunnerDesc()
+        metainterp.staticdata.DoneWithThisFrame = DoneWithThisFrame
         self.metainterp = metainterp
         try:
             metainterp.compile_and_run_once(*args)
@@ -89,7 +89,7 @@
             raise Exception("FAILED")
 
     def check_history_(self, expected=None, **isns):
-        self.metainterp.stats.check_history(expected, **isns)
+        self.metainterp.staticdata.stats.check_history(expected, **isns)
 
 class OOJitMixin(JitMixin):
     type_system = 'ootype'

Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_recursive.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_recursive.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_recursive.py	Wed Apr  8 14:23:00 2009
@@ -24,7 +24,6 @@
         assert res == main(20)
 
     def test_recursion_three_times(self):
-        py.test.skip("in-progress")
         myjitdriver = JitDriver(greens=[], reds=['n', 'm', 'total'])
         def f(n):
             m = n - 3
@@ -46,7 +45,7 @@
             print '%3d %9d' % (i, f(i))
         res = self.meta_interp(main, [10])
         assert res == main(10)
-        self.check_enter_count_at_most(6)
+        self.check_enter_count_at_most(10)
 
 
 class TestLLtype(RecursiveTests, LLJitMixin):

Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/warmspot.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/warmspot.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/warmspot.py	Wed Apr  8 14:23:00 2009
@@ -15,7 +15,7 @@
 from pypy.rpython.lltypesystem.lloperation import llop
 
 from pypy.jit.metainterp import support, history, pyjitpl
-from pypy.jit.metainterp.pyjitpl import OOMetaInterp, Options
+from pypy.jit.metainterp.pyjitpl import MetaInterpStaticData, MetaInterp
 from pypy.jit.backend.llgraph import runner
 from pypy.jit.metainterp.policy import JitPolicy
 
@@ -108,11 +108,11 @@
         self.build_meta_interp(**kwds)
         self.make_args_specification()
         self.rewrite_jit_merge_point()
-        self.metainterp.generate_bytecode(policy)
+        self.metainterp_sd.generate_bytecode(policy)
         self.make_enter_function()
         self.rewrite_can_enter_jit()
-        self.metainterp.num_green_args = self.num_green_args
-        self.metainterp.state = self.state
+        self.metainterp_sd.num_green_args = self.num_green_args
+        self.metainterp_sd.state = self.state
 
     def finish(self):
         if self.cpu.translate_support_code:
@@ -124,7 +124,7 @@
     def build_meta_interp(self, CPUClass=runner.CPU, view="auto",
                           translate_support_code=False, optimizer=None,
                           **kwds):
-        opt = Options(**kwds)
+        opt = pyjitpl.Options(**kwds)
         self.stats = history.Stats()
         if translate_support_code:
             self.annhelper = MixLevelHelperAnnotator(self.translator.rtyper)
@@ -149,8 +149,9 @@
         self.translator.graphs.append(graph)
         self.portal_graph = graph
         self.jitdriver = block.operations[pos].args[1].value
-        self.metainterp = OOMetaInterp(graph, graphs, cpu, self.stats, opt,
-                                       optimizer=optimizer)
+        self.metainterp_sd = MetaInterpStaticData(graph, graphs, cpu,
+                                                  self.stats, opt,
+                                                  optimizer=optimizer)
 
     def make_enter_function(self):
         WarmEnterState = make_state_class(self)
@@ -270,15 +271,13 @@
             def __init__(self, resultbox):
                 self.resultbox = resultbox
             def __str__(self):
-                return 'DoneWithThisFrame(%s)' % (self.result,)
+                return 'DoneWithThisFrame(%s)' % (self.resultbox,)
 
         class ExitFrameWithException(JitException):
-            def __init__(self, typebox, valuebox):
-                self.typebox = typebox
+            def __init__(self, valuebox):
                 self.valuebox = valuebox
             def __str__(self):
-                return 'ExitFrameWithException(%s, %s)' % (self.type,
-                                                           self.value)
+                return 'ExitFrameWithException(%s)' % (self.valuebox,)
 
         class ContinueRunningNormally(JitException):
             def __init__(self, args):
@@ -291,9 +290,9 @@
         self.DoneWithThisFrame = DoneWithThisFrame
         self.ExitFrameWithException = ExitFrameWithException
         self.ContinueRunningNormally = ContinueRunningNormally
-        self.metainterp.DoneWithThisFrame = DoneWithThisFrame
-        self.metainterp.ExitFrameWithException = ExitFrameWithException
-        self.metainterp.ContinueRunningNormally = ContinueRunningNormally
+        self.metainterp_sd.DoneWithThisFrame = DoneWithThisFrame
+        self.metainterp_sd.ExitFrameWithException = ExitFrameWithException
+        self.metainterp_sd.ContinueRunningNormally = ContinueRunningNormally
         rtyper = self.translator.rtyper
         portalfunc_ARGS = unrolling_iterable(list(enumerate(PORTALFUNC.ARGS)))
         RESULT = PORTALFUNC.RESULT
@@ -313,9 +312,7 @@
                 except ExitFrameWithException, e:
                     value = e.valuebox.getptr(lltype.Ptr(rclass.OBJECT))
                     if not we_are_translated():
-                        type = e.typebox.getaddr(self.metainterp.cpu)
-                        type = llmemory.cast_adr_to_ptr(type, rclass.CLASSTYPE)
-                        raise LLException(type, value)
+                        raise LLException(value.typeptr, value)
                     else:
                         value = cast_base_ptr_to_instance(Exception, value)
                         raise Exception, value
@@ -468,7 +465,8 @@
                     self.cells[argshash] = Counter(n)
                     return
                 #interp.debug_trace("jit_compile", *greenargs)
-                metainterp = warmrunnerdesc.metainterp
+                metainterp_sd = warmrunnerdesc.metainterp_sd
+                metainterp = MetaInterp(metainterp_sd)
                 loop, boxes = metainterp.compile_and_run_once(*args)
             else:
                 # machine code was already compiled for these greenargs
@@ -482,10 +480,13 @@
                 loop = cell.bridge
                 boxes = cell.fill_boxes(*args[num_green_args:])
             # ---------- execute assembler ----------
+            warmrunnerdesc.metainterp_sd.globaldata.save_recursive_call()
             while True:     # until interrupted by an exception
-                metainterp = warmrunnerdesc.metainterp
-                fail_op = metainterp.cpu.execute_operations(loop, boxes)
-                loop, boxes = fail_op.descr.handle_fail_op(metainterp, fail_op)
+                metainterp_sd = warmrunnerdesc.metainterp_sd
+                metainterp_sd.globaldata.assert_empty()
+                fail_op = metainterp_sd.cpu.execute_operations(loop, boxes)
+                loop, boxes = fail_op.descr.handle_fail_op(metainterp_sd,
+                                                           fail_op)
         maybe_compile_and_run._dont_inline_ = True
 
         def handle_hash_collision(self, cell, argshash, *args):



More information about the Pypy-commit mailing list