Author: Maciej Fijalkowski <[email protected]>
Branch: vmprof
Changeset: r76142:254acb1e7174
Date: 2015-02-25 19:44 +0200
http://bitbucket.org/pypy/pypy/changeset/254acb1e7174/

Log:    Try quite hard to move all the logic to C

diff --git a/rpython/jit/backend/llsupport/codemap.py 
b/rpython/jit/backend/llsupport/codemap.py
--- a/rpython/jit/backend/llsupport/codemap.py
+++ b/rpython/jit/backend/llsupport/codemap.py
@@ -17,17 +17,26 @@
 from rpython.rtyper.lltypesystem import lltype, rffi
 from rpython.translator.tool.cbuild import ExternalCompilationInfo
 
-INITIAL_SIZE = 1000
-GROWTH_FACTOR = 4
-
-INT_LIST = lltype.Array(lltype.Signed) # raw, but with length
+INT_LIST = rffi.CArray(lltype.Signed)
 
 CODEMAP = lltype.Struct(
-    'codemap',
+    'pypy_codemap_item',
     ('addr', lltype.Signed),
     ('machine_code_size', lltype.Signed),
-    ('bytecode_info', lltype.Ptr(INT_LIST)))
-CODEMAP_LIST = lltype.Array(CODEMAP)
+    ('bytecode_info_size', lltype.Signed),
+    ('bytecode_info', lltype.Ptr(INT_LIST)),
+    hints=dict(external=True, c_name='pypy_codemap_item'))
+CODEMAP_LIST = rffi.CArray(CODEMAP)
+
+CODEMAP_STORAGE = lltype.Struct(
+    'pypy_codemap_storage',
+    ('jit_addr_map_used', lltype.Signed),
+    ('jit_frame_depth_map_used', lltype.Signed),
+    ('jit_codemap_used', lltype.Signed),
+    ('jit_addr_map', lltype.Ptr(INT_LIST)),
+    ('jit_frame_depth_map', lltype.Ptr(INT_LIST)),
+    ('jit_codemap', lltype.Ptr(CODEMAP_LIST)),
+    hints=dict(external=True, c_name='pypy_codemap_storage'))
 
 CODEMAP_GCARRAY = lltype.GcArray(CODEMAP)
 
@@ -36,23 +45,141 @@
 eci = ExternalCompilationInfo(post_include_bits=["""
 RPY_EXTERN volatile int pypy_codemap_currently_invalid;
 RPY_EXTERN void pypy_codemap_invalid_set(int);
+
+typedef struct pypy_codemap_item {
+   long addr, machine_code_size, bytecode_info_size;
+   long* bytecode_info;
+} pypy_codemap_item;
+
+typedef struct pypy_codemap_storage {
+   long jit_addr_map_used;
+   long jit_frame_depth_map_used;
+   long jit_codemap_used;
+   long* jit_addr_map;
+   long* jit_frame_depth_map;
+   pypy_codemap_item* jit_codemap;
+} pypy_codemap_storage;
+
+RPY_EXTERN pypy_codemap_storage *pypy_get_codemap_storage();
+RPY_EXTERN long pypy_jit_stack_depth_at_loc(long loc);
+RPY_EXTERN long pypy_find_codemap_at_addr(long addr);
+RPY_EXTERN long pypy_jit_start_addr(void);
+RPY_EXTERN long pypy_jit_end_addr(void);
+RPY_EXTERN long pypy_yield_codemap_at_addr(long, long, long*);
+
 """], separate_module_sources=["""
 volatile int pypy_codemap_currently_invalid = 0;
 
+static pypy_codemap_storage pypy_cs_g;
+
+long bisect_right(long *a, long x, long hi)
+{
+    long lo, mid;
+    lo = 0;
+    while (lo < hi) {
+        mid = (lo+hi) / 2;
+        if (x < a[mid]) { hi = mid; }
+        else { lo = mid+1; }
+    }
+    return lo;
+}
+
+long bisect_right_addr(pypy_codemap_item *a, long x, long hi)
+{
+    long lo, mid;
+    lo = 0;
+    while (lo < hi) {
+        mid = (lo+hi) / 2;
+        if (x < a[mid].addr) { hi = mid; }
+        else { lo = mid+1; }
+    }
+    return lo;
+}
+
+long pypy_jit_stack_depth_at_loc(long loc)
+{
+    long pos;
+    pos = bisect_right(pypy_cs_g.jit_addr_map, loc,
+                       pypy_cs_g.jit_addr_map_used);
+    if (pos == 0 || pos == pypy_cs_g.jit_addr_map_used)
+        return -1;
+    return pypy_cs_g.jit_frame_depth_map[pos - 1];
+}
+
+long pypy_find_codemap_at_addr(long addr)
+{
+    return bisect_right_addr(pypy_cs_g.jit_codemap, addr,
+                             pypy_cs_g.jit_codemap_used) - 1;
+}
+
+long pypy_jit_start_addr(void)
+{
+    return pypy_cs_g.jit_addr_map[0];
+}
+
+long pypy_jit_end_addr(void)
+{
+    return pypy_cs_g.jit_addr_map[pypy_cs_g.jit_addr_map_used - 1];
+}
+
+long pypy_yield_codemap_at_addr(long codemap_no, long addr,
+                                long* current_pos_addr)
+{
+    // will return consecutive unique_ids from codemap, starting from position
+    // `pos` until addr
+    pypy_codemap_item *codemap = &(pypy_cs_g.jit_codemap[codemap_no]);
+    long current_pos = *current_pos_addr;
+    long start_addr = codemap->addr;
+    long rel_addr = addr - start_addr;
+    long next_start, next_stop;
+
+    while (1) {
+        if (current_pos >= codemap->bytecode_info_size)
+            return 0;
+        next_start = codemap->bytecode_info[current_pos + 1];
+        if (next_start > rel_addr)
+            return 0;
+        next_stop = codemap->bytecode_info[current_pos + 2];
+        if (next_stop > rel_addr) {
+            *current_pos_addr = current_pos + 4;
+            return codemap->bytecode_info[current_pos];
+        }
+        // we need to skip potentially more than one
+        current_pos = codemap->bytecode_info[current_pos + 3];
+    }
+}
+
+pypy_codemap_storage *pypy_get_codemap_storage(void)
+{
+    return &pypy_cs_g;
+}
+
 void pypy_codemap_invalid_set(int value)
 {
     pypy_codemap_currently_invalid = value;
 }
 """])
 
-ll_pypy_codemap_invalid_set = rffi.llexternal('pypy_codemap_invalid_set',
-                                              [rffi.INT], lltype.Void,
-                                              compilation_info=eci,
-                                              releasegil=False)
+def llexternal(name, args, res):
+    return rffi.llexternal(name, args, res, compilation_info=eci,
+                           releasegil=False)
+
+ll_pypy_codemap_invalid_set = llexternal('pypy_codemap_invalid_set',
+                                         [rffi.INT], lltype.Void)
+pypy_get_codemap_storage = llexternal('pypy_get_codemap_storage',
+                                      [], lltype.Ptr(CODEMAP_STORAGE))
+stack_depth_at_loc = llexternal('pypy_jit_stack_depth_at_loc',
+                                [lltype.Signed], lltype.Signed)
+find_codemap_at_addr = llexternal('pypy_find_codemap_at_addr',
+                                  [lltype.Signed], lltype.Signed)
+yield_bytecode_at_addr = llexternal('pypy_yield_codemap_at_addr',
+                                    [lltype.Signed, lltype.Signed,
+                                     rffi.CArrayPtr(lltype.Signed)],
+                                     lltype.Signed)
 
 def pypy_codemap_invalid_set(val):
-    if we_are_translated():
-        ll_pypy_codemap_invalid_set(val)
+    #if we_are_translated():
+    ll_pypy_codemap_invalid_set(val)
 
 @specialize.ll()
 def copy_item(source, dest, si, di, baseline=0):
@@ -66,23 +193,28 @@
     # XXX this code has wrong complexity, we should come up with a better
     #     data structure ideally
     _mixin_ = True
+    jit_addr_map_allocated = 0
+    jit_codemap_allocated = 0
+    jit_frame_depth_map_allocated = 0
 
     @specialize.arg(1)
     def extend_with(self, name, to_insert, pos, baseline=0):
         # first check if we need to reallocate
-        used = getattr(self, name + '_used')
-        allocated = len(getattr(self, name))
-        lst = getattr(self, name)
+        g = pypy_get_codemap_storage()
+        used = getattr(g, name + '_used')
+        allocated = getattr(self, name + '_allocated')
+        lst = getattr(g, name)
         if used + len(to_insert) > allocated or pos != used:
             old_lst = lst
             if used + len(to_insert) > allocated:
-                new_size = max(4 * len(old_lst),
-                               (len(old_lst) + len(to_insert)) * 2)
+                new_size = max(4 * allocated,
+                               (allocated + len(to_insert)) * 2)
             else:
-                new_size = len(old_lst)
+                new_size = allocated
             lst = lltype.malloc(lltype.typeOf(lst).TO, new_size,
                                 flavor='raw',
-                                track_allocation=self.track_allocation)
+                                track_allocation=False)
+            setattr(self, name + '_allocated', new_size)
             for i in range(0, pos):
                 copy_item(old_lst, lst, i, i)
             j = 0
@@ -97,16 +229,14 @@
         else:
             for i in range(len(to_insert)):
                 copy_item(to_insert, lst, i, i + pos, baseline)
-        pypy_codemap_invalid_set(1)
-        setattr(self, name, lst)
-        setattr(self, name + '_used', len(to_insert) + used)
-        pypy_codemap_invalid_set(0)
+        setattr(g, name, lst)
+        setattr(g, name + '_used', len(to_insert) + used)
 
     @specialize.arg(1)
     def remove(self, name, start, end):
-        pypy_codemap_invalid_set(1)
-        lst = getattr(self, name)
-        used = getattr(self, name + '_used')
+        g = pypy_get_codemap_storage()
+        lst = getattr(g, name)
+        used = getattr(g, name + '_used')
         j = end
         for i in range(start, used - (end - start)):
             info = lltype.nullptr(INT_LIST)
@@ -118,164 +248,105 @@
                 if info:
                     lltype.free(info, flavor='raw', track_allocation=False)
             j += 1
-        setattr(self, name + '_used', used - (end - start))
-        pypy_codemap_invalid_set(0)
+        setattr(g, name + '_used', used - (end - start))
+
+    def free(self):
+        g = pypy_get_codemap_storage()
+        # if setup has not been called
+        if g.jit_addr_map_used:
+            lltype.free(g.jit_addr_map, flavor='raw', track_allocation=False)
+            g.jit_addr_map_used = 0
+            g.jit_addr_map = lltype.nullptr(INT_LIST)
+        i = 0
+        while i < g.jit_codemap_used:
+            lltype.free(g.jit_codemap[i].bytecode_info, flavor='raw',
+                        track_allocation=False)
+            i += 1
+        if g.jit_codemap_used:
+            lltype.free(g.jit_codemap, flavor='raw',
+                        track_allocation=False)
+            g.jit_codemap_used = 0
+            g.jit_codemap = lltype.nullptr(CODEMAP_LIST)
+        if g.jit_frame_depth_map_used:
+            lltype.free(g.jit_frame_depth_map, flavor='raw',
+                        track_allocation=False)
+            g.jit_frame_depth_map_used = 0
+            g.jit_frame_depth_map = lltype.nullptr(INT_LIST)
+
+    @specialize.arg(1)
+    def free_lst(self, name, lst):
+        if lst:
+            lltype.free(lst, flavor='raw', track_allocation=False)
 
 class CodemapStorage(ListStorageMixin):
     """ An immortal wrapper around underlaying jit codemap data
     """
-    track_allocation = False
-    jit_addr_map = lltype.nullptr(INT_LIST)
-    jit_addr_map_used = 0
-    jit_codemap = lltype.nullptr(CODEMAP_LIST)
-    jit_codemap_used = 0
-    jit_frame_depth_map = lltype.nullptr(INT_LIST)
-    jit_frame_depth_map_used = 0
-    
-    def __init__(self):
-        global _codemap
-
-        _codemap = self # a global singleton, for @entrypoint, self it's
-        # a prebuilt constant anyway
-
     def setup(self):
-        self.jit_addr_map = lltype.malloc(INT_LIST, INITIAL_SIZE, flavor='raw',
-                                          track_allocation=False)
-        self.jit_addr_map_used = 0
-        self.jit_codemap = lltype.malloc(CODEMAP_LIST, INITIAL_SIZE,
-                                         flavor='raw',
-                                         track_allocation=False)
-        self.jit_codemap_used = 0
-        self.jit_frame_depth_map = lltype.malloc(INT_LIST, INITIAL_SIZE,
-                                                 flavor='raw',
-                                                 track_allocation=False)
-        self.jit_frame_depth_map_used = 0
-
-    @specialize.arg(1)
-    def free_lst(self, name, lst):
-        lltype.free(lst, flavor='raw', track_allocation=False)
-
-    def __del__(self):
-        self.free()
-
-    def free(self):
-        # if setup has not been called
-        if not self.jit_addr_map:
-            return
-        lltype.free(self.jit_addr_map, flavor='raw')
-        i = 0
-        while i < self.jit_codemap_used:
-            lltype.free(self.jit_codemap[i].bytecode_info, flavor='raw')
-            i += 1
-        lltype.free(self.jit_codemap, flavor='raw')
-        lltype.free(self.jit_frame_depth_map, flavor='raw')
-        self.jit_adr_map = lltype.nullptr(INT_LIST)
+        g = pypy_get_codemap_storage()
+        if g.jit_addr_map_used != 0:
+             # someone failed to call free(), in tests only anyway
+             self.free()
 
     def free_asm_block(self, start, stop):
         # fix up jit_addr_map
-        jit_adr_start = bisect_left(self.jit_addr_map, start,
-                                    self.jit_addr_map_used)
-        jit_adr_stop = bisect_left(self.jit_addr_map, stop,
-                                   self.jit_addr_map_used)
+        g = pypy_get_codemap_storage()
+        jit_adr_start = bisect_left(g.jit_addr_map, start,
+                                    g.jit_addr_map_used)
+        jit_adr_stop = bisect_left(g.jit_addr_map, stop,
+                                   g.jit_addr_map_used)
+        pypy_codemap_invalid_set(1)
         self.remove('jit_addr_map', jit_adr_start, jit_adr_stop)
         self.remove('jit_frame_depth_map', jit_adr_start, jit_adr_stop)
         # fix up codemap
         # (there should only be zero or one codemap entry in that range,
         # but still we use a range to distinguish between zero and one)
-        codemap_adr_start = bisect_left_addr(self.jit_codemap, start,
-                                             self.jit_codemap_used)
-        codemap_adr_stop = bisect_left_addr(self.jit_codemap, stop,
-                                            self.jit_codemap_used)
+        codemap_adr_start = bisect_left_addr(g.jit_codemap, start,
+                                             g.jit_codemap_used)
+        codemap_adr_stop = bisect_left_addr(g.jit_codemap, stop,
+                                            g.jit_codemap_used)
         self.remove('jit_codemap', codemap_adr_start, codemap_adr_stop)
+        pypy_codemap_invalid_set(0)
 
     def register_frame_depth_map(self, rawstart, frame_positions,
                                  frame_assignments):
         if not frame_positions:
             return
-        if (not self.jit_addr_map_used or
-            rawstart > self.jit_addr_map[self.jit_addr_map_used - 1]):
-            start = self.jit_addr_map_used
+        pypy_codemap_invalid_set(1)
+        g = pypy_get_codemap_storage()
+        if (not g.jit_addr_map_used or
+            rawstart > g.jit_addr_map[g.jit_addr_map_used - 1]):
+            start = g.jit_addr_map_used
             self.extend_with('jit_addr_map', frame_positions,
-                             self.jit_addr_map_used, rawstart)
+                             g.jit_addr_map_used, rawstart)
             self.extend_with('jit_frame_depth_map', frame_assignments,
-                             self.jit_frame_depth_map_used)
+                             g.jit_frame_depth_map_used)
         else:
-            start = bisect_left(self.jit_addr_map, rawstart,
-                                self.jit_addr_map_used)
+            start = bisect_left(g.jit_addr_map, rawstart,
+                                g.jit_addr_map_used)
             self.extend_with('jit_addr_map', frame_positions, start, rawstart)
             self.extend_with('jit_frame_depth_map', frame_assignments,
                              start)
+        pypy_codemap_invalid_set(0)
 
     def register_codemap(self, codemap):
         start = codemap[0]
-        pos = bisect_left_addr(self.jit_codemap, start, self.jit_codemap_used)
+        g = pypy_get_codemap_storage()
+        pos = bisect_left_addr(g.jit_codemap, start, g.jit_codemap_used)
         items = lltype.malloc(INT_LIST, len(codemap[2]), flavor='raw',
-                             track_allocation=False)
+                              track_allocation=False)
         for i in range(len(codemap[2])):
             items[i] = codemap[2][i]
         s = lltype.malloc(CODEMAP_GCARRAY, 1)
         s[0].addr = codemap[0]
         s[0].machine_code_size = codemap[1]
         s[0].bytecode_info = items
+        s[0].bytecode_info_size = len(codemap[2])
+        pypy_codemap_invalid_set(1)
         self.extend_with('jit_codemap', s, pos)
+        pypy_codemap_invalid_set(0)
 
-@jit_entrypoint([lltype.Signed], lltype.Signed,
-                c_name='pypy_jit_stack_depth_at_loc')
[email protected]_collect
-def stack_depth_at_loc(loc):
-    global _codemap
-
-    pos = bisect_right(_codemap.jit_addr_map, loc, _codemap.jit_addr_map_used)
-    if pos == 0 or pos == _codemap.jit_addr_map_used:
-        return -1
-    return _codemap.jit_frame_depth_map[pos - 1]
-
-@jit_entrypoint([], lltype.Signed, c_name='pypy_jit_start_addr')
-def jit_start_addr():
-    global _codemap
-
-    return _codemap.jit_addr_map[0]
-
-@jit_entrypoint([], lltype.Signed, c_name='pypy_jit_end_addr')
-def jit_end_addr():
-    global _codemap
-
-    return _codemap.jit_addr_map[_codemap.jit_addr_map_used - 1]
-
-@jit_entrypoint([lltype.Signed], lltype.Signed,
-                c_name='pypy_find_codemap_at_addr')
-def find_codemap_at_addr(addr):
-    global _codemap
-
-    res = bisect_right_addr(_codemap.jit_codemap, addr,
-                            _codemap.jit_codemap_used) - 1
-    return res
-
-@jit_entrypoint([lltype.Signed, lltype.Signed,
-                 rffi.CArrayPtr(lltype.Signed)], lltype.Signed,
-                 c_name='pypy_yield_codemap_at_addr')
-def yield_bytecode_at_addr(codemap_no, addr, current_pos_addr):
-    """ will return consecutive unique_ids from codemap, starting from position
-    `pos` until addr
-    """
-    global _codemap
-
-    codemap = _codemap.jit_codemap[codemap_no]
-    current_pos = current_pos_addr[0]
-    start_addr = codemap.addr
-    rel_addr = addr - start_addr
-    while True:
-        if current_pos >= len(codemap.bytecode_info):
-            return 0
-        next_start = codemap.bytecode_info[current_pos + 1]
-        if next_start > rel_addr:
-            return 0
-        next_stop = codemap.bytecode_info[current_pos + 2]
-        if next_stop > rel_addr:
-            current_pos_addr[0] = current_pos + 4
-            return codemap.bytecode_info[current_pos]
-        # we need to skip potentially more than one
-        current_pos = codemap.bytecode_info[current_pos + 3]
+    def finish_once(self):
+        self.free()
 
 def unpack_traceback(addr):
     codemap_pos = find_codemap_at_addr(addr)
@@ -341,4 +412,3 @@
             item = self.l[i * 4 + 3] # end in l
             assert item > 0
         return (addr, size, self.l) # XXX compact self.l
-
diff --git a/rpython/jit/backend/llsupport/llmodel.py 
b/rpython/jit/backend/llsupport/llmodel.py
--- a/rpython/jit/backend/llsupport/llmodel.py
+++ b/rpython/jit/backend/llsupport/llmodel.py
@@ -79,6 +79,9 @@
     def setup(self):
         pass
 
+    def finish_once(self):
+        self.codemap.finish_once()
+
     def _setup_frame_realloc(self, translate_support_code):
         FUNC_TP = lltype.Ptr(lltype.FuncType([llmemory.GCREF, lltype.Signed],
                                              llmemory.GCREF))
diff --git a/rpython/jit/backend/llsupport/test/test_codemap.py 
b/rpython/jit/backend/llsupport/test/test_codemap.py
--- a/rpython/jit/backend/llsupport/test/test_codemap.py
+++ b/rpython/jit/backend/llsupport/test/test_codemap.py
@@ -1,39 +1,28 @@
 
 from rpython.jit.backend.llsupport.codemap import stack_depth_at_loc
 from rpython.jit.backend.llsupport.codemap import CodemapStorage,\
-     ListStorageMixin, INT_LIST, CodemapBuilder, unpack_traceback
-from rpython.rtyper.lltypesystem import lltype
+     ListStorageMixin, CodemapBuilder, unpack_traceback,\
+     pypy_get_codemap_storage
 
+g = pypy_get_codemap_storage()
 
 def test_list_storage_mixin():
     class X(ListStorageMixin):
-        track_allocation = True
-        
-        def __init__(self):
-            self.x = lltype.malloc(INT_LIST, 4, flavor='raw')
-            self.x_used = 0
-
         def unpack(self):
-            return [self.x[i] for i in range(self.x_used)]
-
-        def free_lst(self, name, lst):
-            lltype.free(lst, flavor='raw')
-        
-        def free(self):
-            lltype.free(self.x, flavor='raw')
+            return [g.jit_addr_map[i] for i in range(g.jit_addr_map_used)]
 
     x = X()
-    x.extend_with('x', [1, 2, 3], 0)
+    x.extend_with('jit_addr_map', [1, 2, 3], 0)
     assert x.unpack() == [1, 2, 3]
-    x.extend_with('x', [4, 5, 6], 3)
+    x.extend_with('jit_addr_map', [4, 5, 6], 3)
     assert x.unpack() == [1, 2, 3, 4, 5, 6]
-    x.extend_with('x', [7, 8, 9], 2, baseline=10)
+    x.extend_with('jit_addr_map', [7, 8, 9], 2, baseline=10)
     assert x.unpack() == [1, 2, 17, 18, 19, 3, 4, 5, 6]
-    x.remove('x', 3, 6)
+    x.remove('jit_addr_map', 3, 6)
     assert x.unpack() == [1, 2, 17, 4, 5, 6]
-    x.extend_with('x', [1] * 6, 6)
+    x.extend_with('jit_addr_map', [1] * 6, 6)
     assert x.unpack() == [1, 2, 17, 4, 5, 6, 1, 1, 1, 1, 1, 1]
-    x.extend_with('x', [10] * 4, 5)
+    x.extend_with('jit_addr_map', [10] * 4, 5)
     assert x.unpack() == [1, 2, 17, 4, 5, 10, 10, 10, 10, 6,
                           1, 1, 1, 1, 1, 1]
     x.free()
@@ -57,6 +46,7 @@
     assert stack_depth_at_loc(5) == 8
     assert stack_depth_at_loc(17) == 9
     assert stack_depth_at_loc(38) == 5
+    codemap.free()
 
 def test_codemaps():
     builder = CodemapBuilder()
@@ -93,3 +83,4 @@
     assert unpack_traceback(275) == [202]
     codemap.free_asm_block(200, 300)
     assert unpack_traceback(225) == []
+    codemap.free()
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to