Commits

Maciej Fijalkowski committed 78ad080

Fix the problem with gaps and start writing a test for consts

  • Participants
  • Parent commits 07d4cfa
  • Branches resume-refactor

Comments (0)

Files changed (11)

File rpython/jit/backend/llgraph/runner.py

 
 class Position(object):
     def __init__(self, pos):
+        assert pos != -1
         self.pos = pos
 
     def get_jitframe_position(self):
         return self.pos
 
 class ResumeFrame(object):
-    def __init__(self, num, start_pos):
-        self.registers = [None] * num
+    def __init__(self, no, start_pos):
+        self.registers = [None] * no
         self.start_pos = start_pos
 
 class LLGraphResumeBuilder(ResumeBuilder):
         self.liveness = LivenessAnalyzer()
         self.numbering = {}
         self.framestack = []
-        locs = []
+        locs = None
         start_pos = 0
-        for frame_pos, frame in enumerate(inputframes):
-            if inputlocs is not None:
+        if inputlocs is not None:
+            locs = []
+            for frame_pos, frame in enumerate(inputframes):
                 self.framestack.append(ResumeFrame(len(frame), start_pos))
-            for pos_in_frame, box in enumerate(frame):
-                if inputlocs is not None:
+                for pos_in_frame, box in enumerate(frame):
+                    if box is None:
+                        continue
                     pos = inputlocs[frame_pos][pos_in_frame]
                     self.framestack[-1].registers[pos_in_frame] = box
-                else:
-                    pos = len(self.numbering)
-                self.numbering[box] = pos
-                locs.append(Position(pos))
-            start_pos += len(frame)
+                    self.numbering[box] = pos
+                    locs.append(Position(pos))
+                    start_pos += 1
         ResumeBuilder.__init__(self, self, frontend_liveness, descr,
                                inputframes, locs)
 
         lst = []
         for frame in self.framestack:
             for reg in frame.registers:
-                lst.append(mapping(reg))
+                if reg is None:
+                    lst.append(None)
+                else:
+                    lst.append(mapping(reg))
         return lst
     
 class LLTrace(object):
         assert frame.forced_deadframe is None
         values = []
         for box in frame.force_guard_op.failargs:
-            if box is not None:
-                if box is not frame.current_op.result:
-                    value = frame.env[box]
-                else:
-                    value = box.value    # 0 or 0.0 or NULL
+            if box is None:
+                value = None
+            elif box is not frame.current_op.result:
+                value = frame.env[box]
             else:
-                value = None
+                value = box.value    # 0 or 0.0 or NULL
             values.append(value)
         frame.forced_deadframe = LLDeadFrame(
             _getdescr(frame.force_guard_op), values)
             i += 1
 
     def do_renaming(self, newargs, newvalues):
-        assert len(newargs) == len(newvalues)
         self.env = {}
         self.framecontent = {}
-        for new, newvalue in zip(newargs, newvalues):
-            self.setenv(new, newvalue)
+        i = 0
+        for value in newvalues:
+            if value is None:
+                continue
+            self.setenv(newargs[i], value)
+            i += 1
 
     # -----------------------------------------------------
 
         for i in range(len(self.current_op.failargs)):
             arg = self.current_op.failargs[i]
             if arg is None:
-                values.append(None)
+                value = None
             else:
                 value = self.env[arg]
-                values.append(value)
+            values.append(value)
         if hasattr(descr, '_llgraph_bridge'):
             target = (descr._llgraph_bridge, -1)
             raise Jump(target, values)

File rpython/jit/backend/llsupport/assembler.py

         return r
 
     def rebuild_faillocs_from_descr(self, descr, inputframes, loc_positions):
-        lgt = 0
-        for frame in inputframes:
-            lgt += len(frame)
-        locs = [None] * lgt
+        locs = []
         GPR_REGS = len(self.cpu.gen_regs)
         XMM_REGS = len(self.cpu.float_regs)
         if self.cpu.IS_64_BIT:
             coeff = 1
         else:
             coeff = 2
-        locs_index = 0
         for i, frame in enumerate(inputframes):
             inputlocs = loc_positions[i]
             assert len(inputlocs) == len(frame)
             for j, item in enumerate(frame):
+                if item is None:
+                    continue
                 pos = inputlocs[j]
                 if pos < GPR_REGS:
-                    locs[locs_index] = self.cpu.gen_regs[pos]
+                    locs.append(self.cpu.gen_regs[pos])
                 elif pos < (GPR_REGS + XMM_REGS * coeff):
                     pos = (pos - GPR_REGS) // coeff
-                    locs[locs_index] = self.cpu.float_regs[pos]
+                    locs.append(self.cpu.float_regs[pos])
                 else:
                     stack_pos = pos - self.cpu.JITFRAME_FIXED_SIZE
                     assert stack_pos >= 0
                     tp = item.type
-                    locs[locs_index] = self.new_stack_loc(stack_pos,
-                                                          pos * WORD, tp)
-                locs_index += 1
-        return locs
+                    locs.append(self.new_stack_loc(stack_pos,
+                                pos * WORD, tp))
+        return locs[:]
 
     def store_info_on_descr(self, startspos, guardtok, resume_bytecode):
         withfloats = guardtok.has_floats

File rpython/jit/backend/resumebuilder.py

         if inputframes is not None:
             for frame in inputframes:
                 self.frame_starts.append(self.frame_starts[-1] + len(frame))
-                self.framestack.append(frame)
+                self.framestack.append(frame[:])
 
     def enter_frame(self, pc, jitcode):
         self.frame_starts.append(self.frame_starts[-1] + jitcode.num_regs())
             i = 0
             for frame_pos, frame in enumerate(inputframes):
                 for pos_in_frame, box in enumerate(frame):
-                    loc_pos = inputlocs[i].get_jitframe_position()
+                    if box is None:
+                        loc_pos = -1
+                    else:
+                        loc_pos = inputlocs[i].get_jitframe_position()
+                        i += 1
+                        self.frontend_pos[box] = (ConstInt(frame_pos),
+                                                  ConstInt(pos_in_frame))
                     self.current_attachment[box] = loc_pos
-                    self.frontend_pos[box] = (ConstInt(frame_pos),
-                                              ConstInt(pos_in_frame))
-                    i += 1
 
     def process(self, op):
         if op.getopnum() == rop.RESUME_PUT:
 def flatten(inputframes):
     count = 0
     for frame in inputframes:
-        count += len(frame)
+        for x in frame:
+            if x is not None:
+                count += 1
     inputargs = [None] * count
-    i = 0
+    pos = 0
     for frame in inputframes:
-        inputargs[i:i + len(frame)] = frame
-        i += len(frame)
+        for item in frame:
+            if item is not None:
+                inputargs[pos] = item
+                pos += 1
     return inputargs
 
 

File rpython/jit/backend/test/runner_test.py

         assert self.cpu.tracker.total_compiled_bridges == 1
         return looptoken
 
+    def test_compile_bridge_with_holes(self):
+        i0 = BoxInt()
+        i1 = BoxInt()
+        i2 = BoxInt()
+        i3 = BoxInt()
+        faildescr1 = BasicFailDescr(1)
+        faildescr2 = BasicFailDescr(2)
+        looptoken = JitCellToken()
+        targettoken = TargetToken()
+        jitcode = JitCode('name')
+        jitcode.setup(num_regs_i=3, num_regs_r=0, num_regs_f=0)
+        operations = [
+            ResOperation(rop.ENTER_FRAME, [ConstInt(-1)], None, descr=jitcode),
+            ResOperation(rop.INT_SUB, [i3, ConstInt(42)], i0),
+            ResOperation(rop.LABEL, [i0], None, descr=targettoken),
+            ResOperation(rop.INT_ADD, [i0, ConstInt(1)], i1),
+            ResOperation(rop.INT_LE, [i1, ConstInt(9)], i2),
+            ResOperation(rop.RESUME_PUT, [i1, ConstInt(0), ConstInt(1)],
+                         None),
+            ResOperation(rop.GUARD_TRUE, [i2], None, descr=faildescr1),
+            ResOperation(rop.JUMP, [i1], None, descr=targettoken),
+            ]
+        inputargs = [i3]
+        self.cpu.compile_loop(None, inputargs, operations, looptoken)
+
+        i1b = BoxInt()
+        i3 = BoxInt()
+        bridge = [
+            ResOperation(rop.INT_LE, [i1b, ConstInt(19)], i3),
+            ResOperation(rop.RESUME_PUT, [i3, ConstInt(0), ConstInt(2)],
+                         None),
+            ResOperation(rop.GUARD_TRUE, [i3], None, descr=faildescr2),
+            ResOperation(rop.JUMP, [i1b], None, descr=targettoken),
+        ]
+
+        locs = rebuild_locs_from_resumedata(faildescr1)
+        self.cpu.compile_bridge(None, faildescr1, [[None, i1b, None]],
+                                locs, bridge, looptoken)
+
+        deadframe = self.cpu.execute_token(looptoken, 2)
+        fail = self.cpu.get_latest_descr(deadframe)
+        assert fail.identifier == 2
+        locs = rebuild_locs_from_resumedata(fail)
+        res = self.cpu.get_int_value(deadframe, locs[0][1])
+        assert res == 20
+
     def test_compile_big_bridge_out_of_small_loop(self):
         jitcode = JitCode("name")
         jitcode.setup(num_regs_i=1, num_regs_r=0, num_regs_f=0)

File rpython/jit/backend/x86/regalloc.py

         used = {}
         i = 0
         inputargs = flatten(inputframes)
+        assert len(inputargs) == len(locs)
         for loc in locs:
             if loc is None: # xxx bit kludgy
                 loc = ebp

File rpython/jit/codewriter/codewriter.py

 
 class CodeWriter(object):
     callcontrol = None    # for tests
-    debug = False
+    debug = True
 
     def __init__(self, cpu=None, jitdrivers_sd=[]):
         self.cpu = cpu

File rpython/jit/metainterp/compile.py

 from rpython.jit.metainterp.inliner import Inliner
 from rpython.jit.metainterp.resume import NUMBERING, PENDINGFIELDSP, ResumeDataDirectReader
 from rpython.jit.codewriter import heaptracker, longlong
-
+from rpython.jit.backend.resumebuilder import flatten
 
 def giveup():
     from rpython.jit.metainterp.pyjitpl import SwitchToBlackhole
                                           inputargs, operations, looptoken,
                                           log=log, name=name)
 
-def do_compile_bridge(metainterp_sd, faildescr, inputargs, operations,
-                      original_loop_token, log=True):
-    metainterp_sd.logger_ops.log_bridge(inputargs, operations, "compiling")
+def do_compile_bridge(metainterp_sd, faildescr, inputframes,
+                      inputlocs, operations, original_loop_token, log=True):
+    metainterp_sd.logger_ops.log_bridge(flatten(inputframes), operations,
+                                        "compiling")
     assert isinstance(faildescr, AbstractFailDescr)
     return metainterp_sd.cpu.compile_bridge(metainterp_sd.logger_ops,
-                                            faildescr, inputargs, operations,
+                                            faildescr, inputframes,
+                                            inputlocs, operations,
                                             original_loop_token, log=log)
 
 def send_loop_to_backend(greenkey, jitdriver_sd, metainterp_sd, loop, type):
     if metainterp_sd.warmrunnerdesc is not None:    # for tests
         metainterp_sd.warmrunnerdesc.memory_manager.keep_loop_alive(original_jitcell_token)
 
-def send_bridge_to_backend(jitdriver_sd, metainterp_sd, faildescr, inputargs,
-                           operations, original_loop_token):
+def send_bridge_to_backend(jitdriver_sd, metainterp_sd, faildescr, inputframes,
+                           inputlocs, operations, original_loop_token):
     if not we_are_translated():
         show_procedures(metainterp_sd)
-        seen = dict.fromkeys(inputargs)
+        seen = dict.fromkeys(flatten(inputframes))
         TreeLoop.check_consistency_of_branch(operations, seen)
     if metainterp_sd.warmrunnerdesc is not None:
         hooks = metainterp_sd.warmrunnerdesc.hooks
     metainterp_sd.profiler.start_backend()
     debug_start("jit-backend")
     try:
-        asminfo = do_compile_bridge(metainterp_sd, faildescr, inputargs,
-                                    operations,
+        asminfo = do_compile_bridge(metainterp_sd, faildescr, inputframes,
+                                    inputlocs, operations,
                                     original_loop_token)
     finally:
         debug_stop("jit-backend")
         ops_offset = asminfo.ops_offset
     else:
         ops_offset = None
-    metainterp_sd.logger_ops.log_bridge(inputargs, operations, None, faildescr,
-                                        ops_offset)
+    metainterp_sd.logger_ops.log_bridge(flatten(inputframes), operations,
+                                        None, faildescr, ops_offset)
     #
     #if metainterp_sd.warmrunnerdesc is not None:    # for tests
     #    metainterp_sd.warmrunnerdesc.memory_manager.keep_loop_alive(
         # to the corresponding guard_op and compile from there
         assert metainterp.resumekey_original_loop_token is not None
         new_loop.original_jitcell_token = metainterp.resumekey_original_loop_token
-        inputargs = metainterp.history.inputargs
+        inputframes = metainterp.history.inputframes
+        inputlocs = metainterp.history.inputlocs
         if not we_are_translated():
             self._debug_suboperations = new_loop.operations
         propagate_original_jitcell_token(new_loop)
         send_bridge_to_backend(metainterp.jitdriver_sd, metainterp.staticdata,
-                               self, inputargs, new_loop.operations,
+                               self, inputframes, inputlocs,
+                               new_loop.operations,
                                new_loop.original_jitcell_token)
 
 class ResumeGuardNotInvalidated(ResumeGuardDescr):
     # Attempt to use optimize_bridge().  This may return None in case
     # it does not work -- i.e. none of the existing old_loop_tokens match.
     new_trace = create_empty_loop(metainterp)
-    new_trace.inputargs = metainterp.history.inputargs[:]
+    new_trace.inputframes = metainterp.history.inputframes[:]
+    new_trace.inputlocs = metainterp.history.inputlocs[:]
     # clone ops, as optimize_bridge can mutate the ops
 
     new_trace.operations = [op.clone() for op in metainterp.history.operations]

File rpython/jit/metainterp/optimizeopt/unroll.py

         jump_args = [self.getvalue(a).get_key_box() for a in original_jump_args]
 
         assert self.optimizer.loop.resume_at_jump_descr
-        resume_at_jump_descr = self.optimizer.loop.resume_at_jump_descr.clone_if_mutable()
+        resume_at_jump_descr = self.optimizer.loop.resume_at_jump_descr
         assert isinstance(resume_at_jump_descr, ResumeGuardDescr)
         resume_at_jump_descr.rd_snapshot = self.fix_snapshot(jump_args, resume_at_jump_descr.rd_snapshot)
 
             if op.is_guard():
                 op = op.clone()
                 op.setfailargs(None)
-                descr = target_token.resume_at_jump_descr.clone_if_mutable()
+                descr = target_token.resume_at_jump_descr
                 op.setdescr(descr)
                 short[i] = op
 
             if op.result and op.result in self.short_boxes.assumed_classes:
                 target_token.assumed_classes[newop.result] = self.short_boxes.assumed_classes[op.result]
             short[i] = newop
-        target_token.resume_at_jump_descr = target_token.resume_at_jump_descr.clone_if_mutable()
+        target_token.resume_at_jump_descr = target_token.resume_at_jump_descr
         inliner.inline_descr_inplace(target_token.resume_at_jump_descr)
 
         # Forget the values to allow them to be freed
             if not isinstance(a, Const) and a not in self.short_seen:
                 self.add_op_to_short(self.short_boxes.producer(a), emit, guards_needed)
         if op.is_guard():
-            descr = self.short_resume_at_jump_descr.clone_if_mutable()
+            descr = self.short_resume_at_jump_descr
             op.setdescr(descr)
 
         if guards_needed and self.short_boxes.has_producer(op.result):
 
                 for guard in extra_guards:
                     if guard.is_guard():
-                        descr = target.resume_at_jump_descr.clone_if_mutable()
+                        descr = target.resume_at_jump_descr
                         inliner.inline_descr_inplace(descr)
                         guard.setdescr(descr)
                     self.optimizer.send_extra_operation(guard)

File rpython/jit/metainterp/pyjitpl.py

     def is_main_jitcode(self, jitcode):
         return self.jitdriver_sd is not None and jitcode is self.jitdriver_sd.mainjitcode
 
-    def newframe(self, jitcode, greenkey=None):
+    def newframe(self, jitcode, greenkey=None, record_resume=True):
         if self.framestack:
             pc = self.framestack[-1].pc
         else:
             pc = -1
-        self.history.record(rop.ENTER_FRAME, [ConstInt(pc)], None,
-                            descr=jitcode)
+        if record_resume:
+            self.history.record(rop.ENTER_FRAME, [ConstInt(pc)], None,
+                                descr=jitcode)
         if jitcode.is_portal:
             self.portal_call_depth += 1
             self.call_ids.append(self.current_call_id)
         try:
             self.portal_call_depth = -1 # always one portal around
             self.history = history.History()
-            self.rebuild_state_after_failure(resumedescr, deadframe)
-            xxx
-            self.history.inputargs = [box for box in inputargs_and_holes if box]
+            state = self.rebuild_state_after_failure(resumedescr, deadframe)
+            self.history.inputframes, self.history.inputlocs = state
         finally:
             rstack._stack_criticalcode_stop()
 
         vinfo = self.jitdriver_sd.virtualizable_info
         ginfo = self.jitdriver_sd.greenfield_info
         self.framestack = []
-        inputframes = resume2.rebuild_from_resumedata(self, deadframe,
-                                                      resumedescr)
-        virtualizable_boxes = None
-        virtualref_boxes = None
+        inputlocs = resume2.rebuild_from_resumedata(self, deadframe,
+                                                    resumedescr)
+        virtualizable_boxes = []
+        virtualref_boxes = []
         #
         # virtual refs: make the vrefs point to the freshly allocated virtuals
         self.virtualref_boxes = virtualref_boxes
         else:
             assert not virtualizable_boxes
         #
-        return inputframes
+        return inputlocs
 
     def check_synchronized_virtualizable(self):
         if not we_are_translated():

File rpython/jit/metainterp/resume2.py

                                                             pos))
 
     def finish(self):
+        res = []
         for frame in self.framestack:
             jitcode = frame.jitcode
-            miframe = self.metainterp.newframe(jitcode)
+            res.append([None] * jitcode.num_regs())
+            miframe = self.metainterp.newframe(jitcode, record_resume=False)
             miframe.pc = frame.pc
             pos = 0
             for i in range(jitcode.num_regs_i()):
                 jitframe_pos = frame.registers[pos]
-                if jitframe_pos == -1:
-                    continue
-                miframe.registers_i[i] = self.get_int_box(jitframe_pos)
+                if jitframe_pos != -1:
+                    box = self.get_int_box(jitframe_pos)
+                    miframe.registers_i[i] = box
+                    res[-1][pos] = box
                 pos += 1
             for i in range(jitcode.num_regs_r()):
                 jitframe_pos = frame.registers[pos]
-                if jitframe_pos == -1:
-                    continue
-                miframe.registers_r[i] = self.get_ref_box(jitframe_pos)
+                if jitframe_pos != -1:
+                    box = self.get_int_box(jitframe_pos)
+                    res[-1][pos] = box
+                    miframe.registers_r[i] = box
                 pos += 1
             for i in range(jitcode.num_regs_f()):
                 jitframe_pos = frame.registers[pos]
-                if jitframe_pos == -1:
-                    continue
-                miframe.registers_f[i] = self.get_float_box(jitframe_pos)
+                if jitframe_pos != -1:
+                    box = self.get_int_box(jitframe_pos)
+                    res[-1][pos] = box
+                    miframe.registers_f[i] = box
                 pos += 1
+        return res, [f.registers for f in self.framestack]
             
 def rebuild_from_resumedata(metainterp, deadframe, faildescr):
     return BoxResumeReader(metainterp, deadframe).rebuild(faildescr)

File rpython/jit/metainterp/test/test_resume2.py

         self.registers_f = [None] * jitcode.num_regs_f()
 
     def num_nonempty_regs(self):
-        return len([i for i in self.registers_i if i.getint() != 2])
+        return len([i for i in self.registers_i if i is not None])
 
     def dump_registers(self, lst, backend_values):
         lst += [backend_values[x] for x in self.registers_i]
         self.cpu = MockCPU()
         self.framestack = []
 
-    def newframe(self, jitcode):
+    def newframe(self, jitcode, record_resume=False):
         f = Frame(jitcode)
         self.framestack.append(f)
         return f
         descr = Descr()
         descr.rd_resume_bytecode = ResumeBytecode(resume_loop.operations)
         descr.rd_bytecode_position = 5
-        rebuild_from_resumedata(metainterp, "myframe", descr)
+        state = rebuild_from_resumedata(metainterp, "myframe", descr)
         assert len(metainterp.framestack) == 2
         f = metainterp.framestack[-1]
         f2 = metainterp.framestack[0]
         descr.rd_bytecode_position = 5
         locs = rebuild_locs_from_resumedata(descr)
         assert locs == [[8, 11], [12]]
+
+    def test_resume_put_const(self):
+        xxx