[pypy-commit] pypy new-jit-log: added patch mark (rewrite machinecode). some refactoring to parse it more easily

plan_rich pypy.commits at gmail.com
Mon Mar 21 11:56:23 EDT 2016


Author: Richard Plangger <planrichi at gmail.com>
Branch: new-jit-log
Changeset: r83221:0b922ecc3d86
Date: 2016-03-21 16:55 +0100
http://bitbucket.org/pypy/pypy/changeset/0b922ecc3d86/

Log:	added patch mark (rewrite machinecode). some refactoring to parse it
	more easily

diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py
--- a/rpython/jit/backend/x86/assembler.py
+++ b/rpython/jit/backend/x86/assembler.py
@@ -533,9 +533,8 @@
             looptoken._x86_ops_offset = ops_offset
         looptoken._ll_function_addr = rawstart
         if logger:
-            logger.log_trace(MARK_TRACE_ASM, inputargs, operations,
-                             ops_offset=ops_offset, mc=self.mc)
-
+            log = logger.log_trace(MARK_TRACE_ASM, None, self.mc)
+            log.write(inputargs, operations, None, ops_offset)
         self.fixup_target_tokens(rawstart)
         self.teardown()
         # oprofile support
@@ -583,14 +582,15 @@
         debug_bridge(descr_number, rawstart, codeendpos)
         self.patch_pending_failure_recoveries(rawstart)
         # patch the jump from original guard
+        if logger:
+            logger.log_patch_guard(faildescr.adr_new_target, rawstart)
         self.patch_jump_for_descr(faildescr, rawstart)
         ops_offset = self.mc.ops_offset
         frame_depth = max(self.current_clt.frame_info.jfi_frame_depth,
                           frame_depth_no_fixed_size + JITFRAME_FIXED_SIZE)
         if logger:
-            logger.log_trace(MARK_TRACE_ASM, inputargs, operations,
-                             faildescr=faildescr, ops_offset=ops_offset,
-                             mc=self.mc)
+            log = logger.log_trace(MARK_TRACE_ASM, None, self.mc)
+            log.write(inputargs, operations, faildescr, ops_offset)
         self.fixup_target_tokens(rawstart)
         self.update_frame_depth(frame_depth)
         self.teardown()
diff --git a/rpython/jit/metainterp/compile.py b/rpython/jit/metainterp/compile.py
--- a/rpython/jit/metainterp/compile.py
+++ b/rpython/jit/metainterp/compile.py
@@ -481,7 +481,8 @@
 
 def do_compile_loop(jd_id, unique_id, metainterp_sd, inputargs, operations,
                     looptoken, log=True, name='', memo=None):
-    metainterp_sd.jitlog.log_trace(MARK_TRACE_OPT, inputargs, operations)
+    log = metainterp_sd.jitlog.log_trace(MARK_TRACE_OPT, metainterp_sd, None)
+    log.write(inputargs, operations)
     # TODO remove old
     metainterp_sd.logger_ops.log_loop(inputargs, operations, -2,
                                       'compiling', None, name, memo)
@@ -493,8 +494,8 @@
 
 def do_compile_bridge(metainterp_sd, faildescr, inputargs, operations,
                       original_loop_token, log=True, memo=None):
-    metainterp_sd.jitlog.log_trace(MARK_TRACE_OPT, inputargs, operations,
-                                   faildescr=faildescr)
+    log = metainterp_sd.jitlog.log_trace(MARK_TRACE_OPT, metainterp_sd, None)
+    log.write(inputargs, operations, faildescr=faildescr)
     # TODO remove old
     metainterp_sd.logger_ops.log_bridge(inputargs, operations, "compiling",
                                         memo=memo)
diff --git a/rpython/jit/metainterp/jitlog.py b/rpython/jit/metainterp/jitlog.py
--- a/rpython/jit/metainterp/jitlog.py
+++ b/rpython/jit/metainterp/jitlog.py
@@ -1,6 +1,8 @@
 from rpython.rlib.rvmprof.rvmprof import cintf
 from rpython.jit.metainterp import resoperation as resoperations
 from rpython.jit.metainterp.history import ConstInt, ConstFloat
+from rpython.rlib.objectmodel import we_are_translated
+from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
 import sys
 import weakref
 
@@ -24,27 +26,6 @@
 
 IS_32_BIT = sys.maxint == 2**31-1
 
-# why is there no rlib/rstruct/pack.py?
-def encode_le_16bit(val):
-    return chr((val >> 0) & 0xff) + chr((val >> 8) & 0xff)
-def encode_le_32bit(val):
-    return ''.join([chr((val >> 0) & 0xff),
-           chr((val >> 8) & 0xff),
-           chr((val >> 16) & 0xff),
-           chr((val >> 24) & 0xff)])
-def encode_le_addr(val):
-    if IS_32_BIT:
-        return encode_be_32bit(val)
-    else:
-        return ''.join([chr((val >> 0) & 0xff),
-                chr((val >> 8) & 0xff),
-                chr((val >> 16) & 0xff),
-                chr((val >> 24) & 0xff),
-                chr((val >> 32) & 0xff),
-                chr((val >> 40) & 0xff),
-                chr((val >> 48) & 0xff),
-                chr((val >> 56)& 0xff)])
-
 class VMProfJitLogger(object):
 
     def __init__(self):
@@ -58,7 +39,7 @@
         count = len(resoperations.opname)
         mark = MARK_RESOP_META
         for opnum, opname in resoperations.opname.items():
-            line = encode_le_16bit(opnum) + opname.lower()
+            line = self.encode_le_16bit(opnum) + opname.lower()
             self.write_marked(mark, line)
 
     def teardown(self):
@@ -67,52 +48,106 @@
     def write_marked(self, mark, line):
         self.cintf.jitlog_write_marked(mark, line, len(line))
 
-    def encode(self, op):
+    def log_trace(self, tag, metainterp_sd, mc, memo=None):
+        if self.cintf.jitlog_filter(tag):
+            return
+        assert isinstance(tag, int)
+        if memo is None:
+            memo = {}
+        return LogTrace(tag, memo, metainterp_sd, mc, self)
+
+    def log_patch_guard(self, addr, target_addr):
+        if self.cintf.jitlog_filter(tag):
+            return
+        le_addr_write = self.encode_le_addr(addr)
+        le_len = self.encode_le_32bit(8)
+        le_addr = self.encode_le_addr(target_addr)
+        lst = [le_addr, le_len, le_addr]
+        self.cintf.jitlog_filter(MARK_ASM_PATCH, ''.join(lst))
+
+    def encode_le_16bit(self, val):
+        return chr((val >> 0) & 0xff) + chr((val >> 8) & 0xff)
+
+    def encode_le_32bit(self, val):
+        return ''.join([chr((val >> 0) & 0xff),
+                        chr((val >> 8) & 0xff),
+                        chr((val >> 16) & 0xff),
+                        chr((val >> 24) & 0xff)])
+
+    def encode_le_addr(self,val):
+        if IS_32_BIT:
+            return encode_be_32bit(val)
+        else:
+            return ''.join([chr((val >> 0) & 0xff),
+                            chr((val >> 8) & 0xff),
+                            chr((val >> 16) & 0xff),
+                            chr((val >> 24) & 0xff),
+                            chr((val >> 32) & 0xff),
+                            chr((val >> 40) & 0xff),
+                            chr((val >> 48) & 0xff),
+                            chr((val >> 56)& 0xff)])
+
+
+class LogTrace(object):
+    def __init__(self, tag, memo, metainterp_sd, mc, logger):
+        self.memo = memo
+        self.metainterp_sd = metainterp_sd
+        if self.metainterp_sd is not None:
+            self.ts = metainterp_sd.cpu.ts
+        self.tag = tag
+        self.mc = mc
+        self.logger = logger
+
+    def write(self, args, ops, faildescr=None, ops_offset={}):
+        log = self.logger
+
+        # write the initial tag
+        if faildescr is None:
+            log.write_marked(self.tag, 'loop')
+        else:
+            log.write_marked(self.tag, 'bridge')
+
+        # input args
+        str_args = [self.var_to_str(arg) for arg in args]
+        log.write_marked(MARK_INPUT_ARGS, ','.join(str_args))
+
+        # assembler address (to not duplicate it in write_code_dump)
+        if self.mc is not None:
+            absaddr = self.mc.absolute_addr()
+            rel = self.mc.get_relative_pos()
+            # packs <start addr> <end addr> as two unsigend longs
+            le_addr1 = self.encode_le_addr(absaddr)
+            le_addr2 = self.encode_le_addr(absaddr + rel)
+            log.write_marked(MARK_ASM_ADDR, le_addr1 + le_addr2)
+        for i,op in enumerate(ops):
+            mark, line = self.encode_op(op)
+            log.write_marked(mark, line)
+            self.write_core_dump(ops, i, op, ops_offset)
+
+        self.memo = {}
+
+    def encode_op(self, op):
+        """ an operation is written as follows:
+            <marker> <opid (16 bit)> \
+                     <len (32 bit)> \
+                     <res_val>,<arg_0>,...,<arg_n>,<descr>
+            The marker indicates if the last argument is
+            a descr or a normal argument.
+        """
         str_args = [self.var_to_str(arg) for arg in op.getarglist()]
         descr = op.getdescr()
-        le_len = encode_le_32bit(op.getopnum())
-        line = le_len + ','.join(str_args)
+        le_opnum = self.logger.encode_le_16bit(op.getopnum())
+        str_res = self.var_to_str(op)
+        line = le_opnum + ','.join([str_res] + str_args)
         if descr:
-            line += "|" + str(descr)
-            return MARK_RESOP_DESCR, line
+            descr_str = descr.repr_of_descr()
+            return MARK_RESOP_DESCR, line + ',' + descr_str
         else:
             return MARK_RESOP, line
 
-    def log_trace(self, tag, args, ops,
-                  faildescr=None, ops_offset={}, mc=None):
-        # this is a mixture of binary and text!
-        if self.cintf.jitlog_filter(tag):
-            return
-        assert isinstance(tag, int)
 
-        # write the initial tag
-        if faildescr is None:
-            self.write_marked(tag, 'loop')
-        else:
-            self.write_marked(tag, 'bridge')
-
-        # input args
-        str_args = [self.var_to_str(arg) for arg in args]
-        self.write_marked(MARK_INPUT_ARGS, ','.join(str_args))
-
-        # assembler address (to not duplicate it in write_code_dump)
-        if mc is not None:
-            absaddr = mc.absolute_addr()
-            rel = mc.get_relative_pos()
-            # packs <start addr> <end addr> as two unsigend longs
-            le_addr1 = encode_le_addr(absaddr)
-            le_addr2 = encode_le_addr(absaddr + rel)
-            self.write_marked(MARK_ASM_ADDR, le_addr1 + le_addr2)
-        for i,op in enumerate(ops):
-            mark, line = self.encode(op)
-            self.write_marked(mark, line)
-            self.write_core_dump(ops, i, op, ops_offset, mc)
-
-        self.memo = {}
-
-    def write_core_dump(self, operations, i, op, ops_offset, mc):
-        return
-        if mc is None:
+    def write_core_dump(self, operations, i, op, ops_offset):
+        if self.mc is None:
             return
 
         op2 = None
@@ -138,12 +173,12 @@
         # end offset is either the last pos in the assembler
         # or the offset of op2
         if op2 is None:
-            end_offset = mc.get_relative_pos()
+            end_offset = self.mc.get_relative_pos()
         else:
             end_offset = ops_offset[op2]
 
-        dump = mc.copy_core_dump(mc.absolute_addr(), start_offset)
-        self.write_marked(MARK_ASM, dump)
+        dump = self.mc.copy_core_dump(self.mc.absolute_addr(), start_offset)
+        self.logger.write_marked(MARK_ASM, dump)
 
     def var_to_str(self, arg):
         try:
@@ -151,18 +186,17 @@
         except KeyError:
             mv = len(self.memo)
             self.memo[arg] = mv
-        # TODO
-        #if isinstance(arg, ConstInt):
-        #    if int_could_be_an_address(arg.value):
-        #        addr = arg.getaddr()
-        #        name = self.metainterp_sd.get_name_from_address(addr)
-        #        if name:
-        #            return 'ConstClass(' + name + ')'
-        #    return str(arg.value)
-        #elif isinstance(arg, self.ts.ConstRef):
-        #    if arg.value:
-        #        return 'ConstPtr(ptr' + str(mv) + ')'
-        #    return 'ConstPtr(null)'
+        if isinstance(arg, ConstInt):
+            if self.metainterp_sd and int_could_be_an_address(arg.value):
+                addr = arg.getaddr()
+                name = self.metainterp_sd.get_name_from_address(addr)
+                if name:
+                    return 'ConstClass(' + name + ')'
+            return str(arg.value)
+        elif self.ts is not None and isinstance(arg, self.ts.ConstRef):
+            if arg.value:
+                return 'ConstPtr(ptr' + str(mv) + ')'
+            return 'ConstPtr(null)'
         if isinstance(arg, ConstFloat):
             return str(arg.getfloat())
         elif arg is None:
@@ -178,3 +212,9 @@
         else:
             return '?'
 
+def int_could_be_an_address(x):
+    if we_are_translated():
+        x = rffi.cast(lltype.Signed, x)       # force it
+        return not (-32768 <= x <= 32767)
+    else:
+        return isinstance(x, llmemory.AddressAsInt)
diff --git a/rpython/jit/metainterp/optimizeopt/__init__.py b/rpython/jit/metainterp/optimizeopt/__init__.py
--- a/rpython/jit/metainterp/optimizeopt/__init__.py
+++ b/rpython/jit/metainterp/optimizeopt/__init__.py
@@ -55,8 +55,8 @@
     debug_start("jit-optimize")
     inputargs = compile_data.start_label.getarglist()
     try:
-        metainterp_sd.jitlog.log_trace(MARK_TRACE, inputargs,
-                                       compile_data.operations)
+        log = metainterp_sd.jitlog.log_trace(MARK_TRACE, metainterp_sd, None)
+        log.write(inputargs, compile_data.operations)
         #
         metainterp_sd.logger_noopt.log_loop(inputargs,
                                             compile_data.operations,


More information about the pypy-commit mailing list