Author: Maciej Fijalkowski <fij...@gmail.com>
Branch: resume-refactor
Changeset: r68960:672bb5aed066
Date: 2014-01-27 10:35 +0100
http://bitbucket.org/pypy/pypy/changeset/672bb5aed066/

Log:    implement new and new_with_vtable

diff --git a/rpython/jit/resume/frontend.py b/rpython/jit/resume/frontend.py
--- a/rpython/jit/resume/frontend.py
+++ b/rpython/jit/resume/frontend.py
@@ -1,125 +1,13 @@
 
 from rpython.jit.metainterp.resoperation import rop
 from rpython.jit.metainterp.history import BoxInt, BoxPtr, BoxFloat, ConstInt,\
-     INT, REF, Const
+     INT, REF, FLOAT
 from rpython.jit.metainterp import history
 from rpython.jit.resume.reader import AbstractResumeReader
 from rpython.jit.resume.rescode import TAGBOX, TAGCONST, TAGSMALLINT,\
      TAGVIRTUAL, CLEAR_POSITION
 
 
-# class AbstractResumeReader(object):
-#     """ A resume reader that can follow resume until given point. Consult
-#     the concrete classes for details
-#     """
-
-#     def __init__(self):
-#         self.framestack = []
-#         self.consts = [] # XXX cache?
-#         self.virtuals = {}
-#         self.virtual_list = []
-
-#     def rebuild(self, faildescr):
-#         self._rebuild_until(faildescr.rd_resume_bytecode,
-#                             faildescr.rd_bytecode_position)
-#         return self.finish()
-
-#     def finish(self):
-#         pass
-
-#     def enter_frame(self, pc, jitcode):
-#         if self.framestack:
-#             assert pc != -1
-#             self.framestack[-1].pc = pc
-#         self.framestack.append(ResumeFrame(jitcode))
-
-#     def encode_box(self, pos):
-#         return TAGBOX | (pos << TAGOFFSET)
-
-#     def encode_virtual(self, box):
-#         return TAGVIRTUAL | (self.virtuals[box].pos << TAGOFFSET)
-
-#     def encode_const(self, const):
-#         if isinstance(const, ConstInt) and const.getint() < (sys.maxint >> 
3):
-#             return TAGSMALLINT | (const.getint() << TAGOFFSET)
-#         self.consts.append(const)
-#         return TAGCONST | ((len(self.consts) - 1) << TAGOFFSET)
-
-#     def decode(self, pos):
-#         return pos & 0x3, pos >> TAGOFFSET
-
-#     def resume_put(self, jitframe_pos_box, frame_no, frontend_position):
-#         if isinstance(jitframe_pos_box, Box):
-#             jitframe_pos = self.encode_virtual(jitframe_pos_box)
-#         else:
-#             jitframe_pos = self.encode_box(jitframe_pos_box.getint())
-#         self.framestack[frame_no].registers[frontend_position] = jitframe_pos
-
-#     def encode(self, box):
-#         xxx
-
-#     def resume_new(self, box, descr):
-#         # XXX make it a list
-#         v = Virtual(len(self.virtual_list), descr)
-#         self.virtuals[box] = v
-#         self.virtual_list.append(v)
-
-#     def resume_setfield_gc(self, box, fieldbox, descr):
-#         # XXX optimize fields
-#         self.virtuals[box].fields[descr] = self.encode(fieldbox)
-
-#     def resume_clear(self, frame_no, frontend_position):
-#         self.framestack[frame_no].registers[frontend_position] = -1
-
-#     def resume_put_const(self, const, frame_no, frontend_position):
-#         pos = self.encode_const(const)
-#         self.framestack[frame_no].registers[frontend_position] = pos
-
-#     def resume_set_pc(self, pc):
-#         self.framestack[-1].pc = pc
-
-#     def leave_frame(self):
-#         self.framestack.pop()
-
-#     def _rebuild_until(self, rb, position):
-#         if rb.parent is not None:
-#             self._rebuild_until(rb.parent, rb.parent_position)
-#         self.interpret_until(rb.opcodes, position)
-
-#     def interpret_until(self, bytecode, until, pos=0):
-#         while pos < until:
-#             op = bytecode[pos]
-#             if op == rescode.ENTER_FRAME:
-#                 xxx
-#                 descr = op.getdescr()
-#                 assert isinstance(descr, JitCode)
-#                 self.enter_frame(op.getarg(0).getint(), descr)
-#             elif op.getopnum() == rop.LEAVE_FRAME:
-#                 self.leave_frame()
-#             elif op.getopnum() == rop.RESUME_PUT:
-#                 self.resume_put(op.getarg(0), op.getarg(1).getint(),
-#                                  op.getarg(2).getint())
-#             elif op.getopnum() == rop.RESUME_NEW:
-#                 self.resume_new(op.result, op.getdescr())
-#             elif op.getopnum() == rop.RESUME_SETFIELD_GC:
-#                 self.resume_setfield_gc(op.getarg(0), op.getarg(1),
-#                                         op.getdescr())
-#             elif op.getopnum() == rop.RESUME_SET_PC:
-#                 self.resume_set_pc(op.getarg(0).getint())
-#             elif op.getopnum() == rop.RESUME_CLEAR:
-#                 self.resume_clear(op.getarg(0).getint(),
-#                                   op.getarg(1).getint())
-#             elif not op.is_resume():
-#                 pos += 1
-#                 continue
-#             else:
-#                 xxx
-#             pos += 1
-
-#     def read_int(self, jitframe_pos):
-#         return self.metainterp.cpu.get_int_value(self.deadframe, 
jitframe_pos)
-
-
 class DirectResumeReader(AbstractResumeReader):
     """ Directly read values from the jitframe and put them in the blackhole
     interpreter
@@ -129,6 +17,7 @@
         self.bhinterpbuilder = binterpbuilder
         self.cpu = cpu
         self.deadframe = deadframe
+        self.virtuals_cache = {}
         AbstractResumeReader.__init__(self, metainterp_sd)
 
     def finish(self):
@@ -154,38 +43,55 @@
     def store_int_value(self, curbh, i, encoded_pos):
         if encoded_pos == CLEAR_POSITION:
             return
+        val = self.getint(encoded_pos)
+        curbh.registers_i[i] = val
+
+    def getint(self, encoded_pos):
         tag, index = self.decode(encoded_pos)
         if tag == TAGBOX:
-            curbh.registers_i[i] = self.cpu.get_int_value(self.deadframe, 
index)
+            return self.cpu.get_int_value(self.deadframe, index)
         elif tag == TAGSMALLINT:
-            curbh.registers_i[i] = index
+            return index
         else:
             xxx
-        return
-        xxx
-        if jitframe_pos >= 0:
-            curbh.registers_i[i] = self.cpu.get_int_value(
-                self.deadframe, jitframe_pos)
-        elif jitframe_pos < -1:
-            curbh.registers_i[i] = self.consts[-jitframe_pos - 2].getint()
 
     def store_ref_value(self, curbh, i, encoded_pos):
         if encoded_pos == CLEAR_POSITION:
             return
+        curbh.registers_r[i] = self.getref(encoded_pos)
+
+    def getref(self, encoded_pos):
         tag, index = self.decode(encoded_pos)
         if tag == TAGBOX:
-            curbh.registers_r[i] = self.cpu.get_ref_value(self.deadframe, 
index)
+            return self.cpu.get_ref_value(self.deadframe, index)
         elif tag == TAGCONST:
-            curbh.registers_r[i] = self.consts[index].getref_base()
+            return self.consts[index].getref_base()
+        elif tag == TAGVIRTUAL:
+            return self.allocate_virtual(index)
         else:
             xxx
-        return
-        xxxx
-        if jitframe_pos >= 0:
-            curbh.registers_r[i] = self.cpu.get_ref_value(
-                self.deadframe, jitframe_pos)
-        elif jitframe_pos < -1:
-            curbh.registers_r[i] = self.consts[-jitframe_pos - 2].getref_base()
+
+    def allocate_virtual(self, index):
+        try:
+            return self.virtuals_cache[index]
+        except KeyError:
+            pass
+        val = self.virtuals[index].allocate_direct(self.cpu)
+        self.virtuals_cache[index] = val
+        fields = self.virtuals[index].fields
+        for fielddescr, encoded_field_pos in fields.iteritems():
+            self.setfield_gc(val, encoded_field_pos, fielddescr)
+        return val
+
+    def setfield_gc(self, struct, encoded_field_pos, fielddescr):
+        if fielddescr.kind == INT:
+            intval = self.getint(encoded_field_pos)
+            self.cpu.bh_setfield_gc_i(struct, intval, fielddescr)
+        elif fielddescr.kind == REF:
+            refval = self.getref(encoded_field_pos)
+            self.cpu.bh_setfield_gc_r(struct, refval, fielddescr)
+        elif fielddescr.kind == FLOAT:
+            xxx
 
     def store_float_value(self, curbh, i, jitframe_pos):
         xxx
@@ -236,10 +142,10 @@
         else:
             assert tag == TAGVIRTUAL
             virtual = self.virtuals[pos]
-            virtual_box = self.allocate_struct(virtual)
+            virtual_box = virtual.allocate_box(self.metainterp)
+            self.cache[encoded_pos] = virtual_box
             for fielddescr, encoded_field_pos in virtual.fields.iteritems():
                 self.setfield_gc(virtual_box, encoded_field_pos, fielddescr)
-            self.cache[encoded_pos] = virtual_box
             if pos_in_frame != -1:
                 self.metainterp.history.record(rop.RESUME_PUT,
                                                [virtual_box,
@@ -248,9 +154,6 @@
                                                 None, None)
             return virtual_box
 
-    def allocate_struct(self, virtual):
-        return self.metainterp.execute_and_record(rop.NEW, virtual.descr)
-
     def setfield_gc(self, box, encoded_field_pos, fielddescr):
         field_box = self.get_box_value(-1, -1, encoded_field_pos,
                                        fielddescr.kind)
diff --git a/rpython/jit/resume/reader.py b/rpython/jit/resume/reader.py
--- a/rpython/jit/resume/reader.py
+++ b/rpython/jit/resume/reader.py
@@ -1,4 +1,6 @@
 
+from rpython.jit.metainterp.resoperation import rop
+from rpython.jit.metainterp.history import ConstInt
 from rpython.jit.resume import rescode
 
 class ResumeFrame(object):
@@ -7,13 +9,33 @@
         self.jitcode = jitcode
         self.pc = -1
 
+class BaseVirtual(object):
+    pass
 
-class Virtual(object):
+class VirtualStruct(BaseVirtual):
     def __init__(self, pos, descr):
         self.pos = pos
         self.fields = {}
         self.descr = descr
 
+    def allocate_box(self, metainterp):
+        return metainterp.execute_and_record(rop.NEW, self.descr)
+
+    def allocate_direct(self, cpu):
+        return cpu.bh_new(self.descr)
+    
+class VirtualWithVtable(BaseVirtual):
+    def __init__(self, pos, const_class):
+        self.pos = pos
+        self.const_class = const_class
+        self.fields = {}
+
+    def allocate_box(self, metainterp):
+        return metainterp.execute_and_record(rop.NEW_WITH_VTABLE,
+                                             ConstInt(self.const_class))
+
+    def allocate_direct(self, cpu):
+        return cpu.bh_new_with_vtable(self.const_class)
 
 class AbstractResumeReader(object):
     """ A resume reader that can follow resume until given point. Consult
@@ -46,11 +68,19 @@
         self.framestack[frame_no].registers[frontend_position] = encoded_pos
 
     def resume_new(self, v_pos, descr):
-        v = Virtual(v_pos, descr)
+        v = VirtualStruct(v_pos, descr)
+        self._add_to_virtuals(v, v_pos)
+
+    def resume_new_with_vtable(self, v_pos, c_const_class):
+        const_class = c_const_class.getint()
+        v = VirtualWithVtable(v_pos, const_class)
+        self._add_to_virtuals(v, v_pos)
+
+    def _add_to_virtuals(self, v, v_pos):
         if v_pos >= len(self.virtuals):
             self.virtuals += [None] * (len(self.virtuals) - v_pos + 1)
         self.virtuals[v_pos] = v
-
+        
     def resume_setfield_gc(self, pos, fieldpos, descr):
         # XXX optimize fields
         tag, index = self.decode(pos)
@@ -97,11 +127,15 @@
                 self.resume_put(encoded, frame_pos, pos_in_frame)
                 pos += 5
             elif op == rescode.RESUME_NEW:
-                tag, v_pos = self.decode(self.read_short(pos + 1))
-                assert tag == rescode.TAGVIRTUAL
+                v_pos = self.read_short(pos + 1)
                 descr = self.staticdata.opcode_descrs[self.read_short(pos + 3)]
                 self.resume_new(v_pos, descr)
                 pos += 5
+            elif op == rescode.RESUME_NEW_WITH_VTABLE:
+                v_pos = self.read_short(pos + 1)
+                const_class = self.consts[self.read_short(pos + 3)]
+                self.resume_new_with_vtable(v_pos, const_class)
+                pos += 5
             elif op == rescode.RESUME_SETFIELD_GC:
                 structpos = self.read_short(pos + 1)
                 fieldpos = self.read_short(pos + 3)
@@ -140,6 +174,10 @@
     def resume_new(self, v_pos, descr):
         self.l.append("%d = resume_new %d" % (v_pos, descr.global_descr_index))
 
+    def resume_new_with_vtable(self, v_pos, c_const_class):
+        self.l.append("%d = resume_new_with_vtable %d" % (v_pos,
+                                                c_const_class.getint()))
+
     def leave_frame(self):
         self.l.append("leave_frame")
 
diff --git a/rpython/jit/resume/rescode.py b/rpython/jit/resume/rescode.py
--- a/rpython/jit/resume/rescode.py
+++ b/rpython/jit/resume/rescode.py
@@ -64,9 +64,15 @@
             not isinstance(const.getint(), Symbolic) and
             0 <= const.getint() < 0x4000):
             return TAGSMALLINT | (const.getint() << 2)
+        assert len(self.consts) < 0x4000
         self.consts.append(const)
         return TAGCONST | ((len(self.consts) - 1) << 2)
 
+    def encode_const_not_small(self, const):
+        assert len(self.consts) < 0x4000
+        self.consts.append(const)
+        return len(self.consts) - 1
+
     def resume_set_pc(self, pc):
         self.write(RESUME_SET_PC)
         self.write_short(pc)
@@ -79,13 +85,13 @@
 
     def resume_new(self, v_pos, descr):
         self.write(RESUME_NEW)
-        self.write_short(self.encode(TAGVIRTUAL, v_pos))
+        self.write_short(v_pos) # XXX byte virtuals?
         self.write_short(descr.global_descr_index)
 
     def resume_new_with_vtable(self, v_pos, const_class):
         self.write(RESUME_NEW_WITH_VTABLE)
-        self.write_short(self.encode(TAGVIRTUAL, v_pos))
-        self.write_short(self.encode_const(const_class))
+        self.write_short(v_pos) # XXX byte virtuals?
+        self.write_short(self.encode_const_not_small(const_class))
 
     def resume_setfield_gc(self, structpos, fieldpos, descr):
         self.write(RESUME_SETFIELD_GC)
diff --git a/rpython/jit/resume/test/test_frontend.py 
b/rpython/jit/resume/test/test_frontend.py
--- a/rpython/jit/resume/test/test_frontend.py
+++ b/rpython/jit/resume/test/test_frontend.py
@@ -2,8 +2,9 @@
 from rpython.jit.tool.oparser import parse
 from rpython.jit.codewriter.jitcode import JitCode
 from rpython.jit.metainterp.history import AbstractDescr, Const, INT, Stats,\
-     ConstInt
-from rpython.jit.resume.frontend import rebuild_from_resumedata
+     ConstInt, REF
+from rpython.jit.resume.frontend import rebuild_from_resumedata,\
+     blackhole_from_resumedata
 from rpython.jit.resume.rescode import ResumeBytecode, TAGBOX,\
      ResumeBytecodeBuilder, TAGCONST, TAGSMALLINT, TAGVIRTUAL, CLEAR_POSITION
 from rpython.jit.resume.reader import AbstractResumeReader
@@ -72,10 +73,42 @@
         self.framestack.pop()
 
 class MockCPU(object):
+    def __init__(self):
+        self.history = []
+    
     def get_int_value(self, frame, index):
         assert frame == "myframe"
         return index + 3
 
+    def bh_new(self, descr):
+        self.history.append(("new", descr))
+        return "new"
+
+    def bh_setfield_gc_i(self, struct, intval, fielddescr):
+        self.history.append(("setfield_gc_i", struct, intval, fielddescr))
+
+    def bh_setfield_gc_r(self, struct, refval, fielddescr):
+        self.history.append(("setfield_gc_r", struct, refval, fielddescr))
+
+    def bh_new_with_vtable(self, const_class):
+        self.history.append(("new_with_vtable", const_class))
+        return "new_with_vtable"
+
+class MockBlackholeInterp(object):
+    def __init__(self):
+        pass
+
+    def setposition(self, jitcode, pos):
+        self.positions = pos
+        self.jitcode = jitcode
+        self.registers_i = [-1] * jitcode.num_regs_i()
+        self.registers_r = [None] * jitcode.num_regs_r()
+    
+class FakeInterpBuilder(object):
+    def acquire_interp(self):
+        self.interp = MockBlackholeInterp()
+        return self.interp
+
 class RebuildingResumeReader(AbstractResumeReader):
     def finish(self):
         res = []
@@ -111,6 +144,7 @@
         metainterp = MockMetaInterp()
         metainterp.staticdata = MockStaticData([jitcode], [])
         metainterp.cpu = MockCPU()
+        metainterp.staticdata.cpu = metainterp.cpu
         inputargs, inplocs = rebuild_from_resumedata(metainterp, "myframe",
                                                      descr)
         assert len(metainterp.framestack) == 1
@@ -172,28 +206,63 @@
         jitcode1.setup(num_regs_i=0, num_regs_r=1, num_regs_f=0)
         builder = ResumeBytecodeBuilder()
         descr = Descr()
+        const_class = ConstInt(13)
         descr.global_descr_index = 0
         builder.enter_frame(-1, jitcode1)
         builder.resume_new(0, descr)
+        builder.resume_new_with_vtable(1, const_class)
         d2 = Descr()
         d2.kind = INT
         d2.global_descr_index = 1
+        d3 = Descr()
+        d3.kind = REF
+        d3.global_descr_index = 2
         builder.resume_setfield_gc(TAGVIRTUAL | (0 << 2),
                                    TAGSMALLINT | (1 << 2), d2)
+        builder.resume_setfield_gc(TAGVIRTUAL | (0 << 2),
+                                   TAGVIRTUAL | (1 << 2), d3)
+
         builder.resume_put(TAGVIRTUAL | (0 << 2), 0, 0)
         rd = builder.build()
         descr = Descr()
-        descr.rd_resume_bytecode = ResumeBytecode(rd, [])
+        descr.rd_resume_bytecode = ResumeBytecode(rd, [const_class])
         descr.rd_bytecode_position = len(rd)
         metainterp = MockMetaInterp()
-        metainterp.staticdata = MockStaticData([jitcode1], [descr, d2])
+        metainterp.staticdata = MockStaticData([jitcode1], [descr, d2, d3])
         metainterp.cpu = MockCPU()
+        metainterp.staticdata.cpu = metainterp.cpu
         rebuild_from_resumedata(metainterp, "myframe", descr)
         expected = [(rop.NEW, descr),
                     (rop.SETFIELD_GC, d2, AnyBox(), EqConstInt(1)),
+                    (rop.NEW_WITH_VTABLE, EqConstInt(13)),
+                    (rop.SETFIELD_GC, d3, AnyBox(), AnyBox()),
                     (rop.RESUME_PUT, None, AnyBox(), EqConstInt(0),
                      EqConstInt(0))]
-        assert metainterp.history == expected
+        expected2 = [(rop.NEW, descr),
+                     (rop.NEW_WITH_VTABLE, EqConstInt(13)),
+                     (rop.SETFIELD_GC, d3, AnyBox(), AnyBox()),
+                     (rop.SETFIELD_GC, d2, AnyBox(), EqConstInt(1)),
+                     (rop.RESUME_PUT, None, AnyBox(), EqConstInt(0),
+                     EqConstInt(0))]
+        assert metainterp.history == expected or metainterp.history == 
expected2
+        ib = FakeInterpBuilder()
+        blackhole_from_resumedata(ib, metainterp.staticdata,
+                                  descr, "myframe")
+        hist = metainterp.cpu.history
+        dir_expected2 = [
+            ("new", descr),
+            ("new_with_vtable", 13),
+            ("setfield_gc_r", "new", "new_with_vtable", d3),
+            ("setfield_gc_i", "new", 1, d2),
+        ]
+        dir_expected = [
+            ("new", descr),
+            ("setfield_gc_i", "new", 1, d2),
+            ("new_with_vtable", 13),
+            ("setfield_gc_r", "new", "new_with_vtable", d3),
+        ]
+        assert hist == dir_expected or hist == dir_expected2
+        assert ib.interp.registers_r[0] == "new"
 
     def test_reconstructing_resume_reader(self):
         jitcode1 = JitCode("jitcode")
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to