[pypy-commit] pypy vmprof: merge

fijal noreply at buildbot.pypy.org
Thu Mar 19 10:24:42 CET 2015


Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: vmprof
Changeset: r76463:b1f4cf8e7d91
Date: 2015-03-19 11:24 +0200
http://bitbucket.org/pypy/pypy/changeset/b1f4cf8e7d91/

Log:	merge

diff --git a/pypy/module/__pypy__/interp_magic.py b/pypy/module/__pypy__/interp_magic.py
--- a/pypy/module/__pypy__/interp_magic.py
+++ b/pypy/module/__pypy__/interp_magic.py
@@ -141,4 +141,4 @@
     try:
         return space.wrap(ec.code_info_file.read())
     finally:
-        ec.code_info_file.seek(2, 0)
+        ec.code_info_file.seek(0, 2)
diff --git a/pypy/module/_vmprof/src/fake_pypy_api.c b/pypy/module/_vmprof/src/fake_pypy_api.c
--- a/pypy/module/_vmprof/src/fake_pypy_api.c
+++ b/pypy/module/_vmprof/src/fake_pypy_api.c
@@ -1,25 +1,15 @@
-
-long pypy_jit_start_addr(void)
-{
-	return 3;
-}
-
-long pypy_jit_end_addr(void)
-{
-	return 3;
-}
 
 long pypy_jit_stack_depth_at_loc(long x)
 {
 	return 0;
 }
 
-long pypy_find_codemap_at_addr(long x)
+void *pypy_find_codemap_at_addr(long x)
 {
-	return 0;
+	return (void *)0;
 }
 
-long pypy_yield_codemap_at_addr(long x, long y, long *a)
+long pypy_yield_codemap_at_addr(void *x, long y, long *a)
 {
 	return 0;
 }
diff --git a/pypy/module/_vmprof/src/get_custom_offset.c b/pypy/module/_vmprof/src/get_custom_offset.c
--- a/pypy/module/_vmprof/src/get_custom_offset.c
+++ b/pypy/module/_vmprof/src/get_custom_offset.c
@@ -1,12 +1,12 @@
-
-long pypy_jit_start_addr();
-long pypy_jit_end_addr();
-long pypy_jit_stack_depth_at_loc(long);
-long pypy_find_codemap_at_addr(long);
-long pypy_yield_codemap_at_addr(long, long, long*);
 
 extern volatile int pypy_codemap_currently_invalid;
 
+void *pypy_find_codemap_at_addr(long addr);
+long pypy_yield_codemap_at_addr(void *codemap_raw, long addr,
+                                long *current_pos_addr);
+long pypy_jit_stack_depth_at_loc(long loc);
+
+
 void vmprof_set_tramp_range(void* start, void* end)
 {
 }
@@ -18,36 +18,26 @@
 
 static ptrdiff_t vmprof_unw_get_custom_offset(void* ip, unw_cursor_t *cp) {
 	intptr_t ip_l = (intptr_t)ip;
-
-	if (ip_l < pypy_jit_start_addr() || ip_l > pypy_jit_end_addr()) {
-		return -1;
-	}
-	return (void*)pypy_jit_stack_depth_at_loc(ip_l);
+	return pypy_jit_stack_depth_at_loc(ip_l);
 }
 
 static long vmprof_write_header_for_jit_addr(void **result, long n,
 											 void *ip, int max_depth)
 {
-	long codemap_pos;
+	void *codemap;
 	long current_pos = 0;
 	intptr_t id;
 	intptr_t addr = (intptr_t)ip;
 
-	if (addr < pypy_jit_start_addr() || addr > pypy_jit_end_addr()) {
+	codemap = pypy_find_codemap_at_addr(addr);
+	if (codemap == NULL)
 		return n;
+
+	while (n < max_depth) {
+		id = pypy_yield_codemap_at_addr(codemap, addr, &current_pos);
+		if (id == 0)
+			break;
+		result[n++] = (void *)id;
 	}
-	codemap_pos = pypy_find_codemap_at_addr(addr);
-	if (codemap_pos == -1) {
-		return n;
-	}
-	while (1) {
-		id = pypy_yield_codemap_at_addr(codemap_pos, addr, &current_pos);
-		if (id == 0) {
-			return n;
-		}
-		result[n++] = id;
-		if (n >= max_depth) {
-			return n;
-		}
-	}
+	return n;
 }
diff --git a/rpython/jit/backend/llsupport/asmmemmgr.py b/rpython/jit/backend/llsupport/asmmemmgr.py
--- a/rpython/jit/backend/llsupport/asmmemmgr.py
+++ b/rpython/jit/backend/llsupport/asmmemmgr.py
@@ -314,7 +314,8 @@
             assert gcrootmap is not None
             for pos, mark in self.gcroot_markers:
                 gcrootmap.register_asm_addr(rawstart + pos, mark)
-        cpu.codemap.register_frame_depth_map(rawstart, self.frame_positions,
+        cpu.codemap.register_frame_depth_map(rawstart, rawstart + size,
+                                             self.frame_positions,
                                              self.frame_assignments)
         self.frame_positions = None
         self.frame_assignments = None
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
@@ -9,6 +9,7 @@
 
 """
 
+import os
 from rpython.rlib import rgc
 from rpython.rlib.objectmodel import specialize, we_are_translated
 from rpython.rlib.entrypoint import jit_entrypoint
@@ -16,158 +17,55 @@
 from rpython.rlib.rbisect import bisect_left, bisect_left_addr
 from rpython.rtyper.lltypesystem import lltype, rffi
 from rpython.translator.tool.cbuild import ExternalCompilationInfo
+from rpython.translator import cdir
 
-INT_LIST = rffi.CArray(lltype.Signed)
 
-CODEMAP = lltype.Struct(
-    'pypy_codemap_item',
-    ('addr', lltype.Signed),
-    ('machine_code_size', lltype.Signed),
-    ('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)
+INT_LIST_PTR = rffi.CArrayPtr(lltype.Signed)
 
-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)
-
-_codemap = None
+srcdir = os.path.join(os.path.dirname(__file__), 'src')
 
 eci = ExternalCompilationInfo(post_include_bits=["""
-RPY_EXTERN volatile int pypy_codemap_currently_invalid;
-RPY_EXTERN void pypy_codemap_invalid_set(int);
+#include <stdint.h>
+RPY_EXTERN long pypy_jit_codemap_add(uintptr_t addr,
+                                     unsigned int machine_code_size,
+                                     long *bytecode_info,
+                                     unsigned int bytecode_info_size);
+RPY_EXTERN long *pypy_jit_codemap_del(uintptr_t addr);
+RPY_EXTERN uintptr_t pypy_jit_codemap_firstkey(void);
+RPY_EXTERN void *pypy_find_codemap_at_addr(long addr);
+RPY_EXTERN long pypy_yield_codemap_at_addr(void *codemap_raw, long addr,
+                                           long *current_pos_addr);
 
-typedef struct pypy_codemap_item {
-   long addr, machine_code_size, bytecode_info_size;
-   long* bytecode_info;
-} pypy_codemap_item;
+RPY_EXTERN long pypy_jit_depthmap_add(uintptr_t addr, unsigned int size,
+                                      unsigned int stackdepth);
+RPY_EXTERN void pypy_jit_depthmap_clear(uintptr_t addr, unsigned int size);
 
-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;
-}
-"""])
+"""], separate_module_sources=[
+    open(os.path.join(srcdir, 'skiplist.c'), 'r').read() +
+    open(os.path.join(srcdir, 'codemap.c'), 'r').read()
+], include_dirs=[cdir])
 
 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))
+pypy_jit_codemap_add = llexternal('pypy_jit_codemap_add',
+                                  [lltype.Signed, lltype.Signed,
+                                   INT_LIST_PTR, lltype.Signed],
+                                  lltype.Signed)
+pypy_jit_codemap_del = llexternal('pypy_jit_codemap_del',
+                                  [lltype.Signed], INT_LIST_PTR)
+pypy_jit_codemap_firstkey = llexternal('pypy_jit_codemap_firstkey',
+                                       [], lltype.Signed)
+
+pypy_jit_depthmap_add = llexternal('pypy_jit_depthmap_add',
+                                   [lltype.Signed, lltype.Signed,
+                                    lltype.Signed], lltype.Signed)
+pypy_jit_depthmap_clear = llexternal('pypy_jit_depthmap_clear',
+                                     [lltype.Signed, lltype.Signed],
+                                     lltype.Void)
+
 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',
@@ -177,186 +75,62 @@
                                      rffi.CArrayPtr(lltype.Signed)],
                                      lltype.Signed)
 
-def pypy_codemap_invalid_set(val):
-    #if we_are_translated():
-    ll_pypy_codemap_invalid_set(val)
 
- at specialize.ll()
-def copy_item(source, dest, si, di, baseline=0):
-    TP = lltype.typeOf(dest)
-    if isinstance(TP.TO.OF, lltype.Struct):
-        rgc.copy_struct_item(source, dest, si, di)
-    else:
-        dest[di] = source[si] + baseline
-
-class ListStorageMixin(object):
-    # 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
-        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 * allocated,
-                               (allocated + len(to_insert)) * 2)
-            else:
-                new_size = allocated
-            lst = lltype.malloc(lltype.typeOf(lst).TO, new_size,
-                                flavor='raw',
-                                track_allocation=False)
-            setattr(self, name + '_allocated', new_size)
-            for i in range(0, pos):
-                copy_item(old_lst, lst, i, i)
-            j = 0
-            for i in range(pos, pos + len(to_insert)):
-                copy_item(to_insert, lst, j, i, baseline)
-                j += 1
-            j = pos
-            for i in range(pos + len(to_insert), len(to_insert) + used):
-                copy_item(old_lst, lst, j, i)
-                j += 1
-            self.free_lst(name, old_lst)
-        else:
-            for i in range(len(to_insert)):
-                copy_item(to_insert, lst, i, i + pos, baseline)
-        setattr(g, name, lst)
-        setattr(g, name + '_used', len(to_insert) + used)
-
-    @specialize.arg(1)
-    def remove(self, name, start, end):
-        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)
-            if name == 'jit_codemap':
-                if i < end:
-                    info = lst[i].bytecode_info
-            copy_item(lst, lst, j, i)
-            if name == 'jit_codemap':
-                if info:
-                    lltype.free(info, flavor='raw', track_allocation=False)
-            j += 1
-        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):
+class CodemapStorage(object):
     """ An immortal wrapper around underlaying jit codemap data
     """
     def setup(self):
-        g = pypy_get_codemap_storage()
-        if g.jit_addr_map_used != 0:
-             # someone failed to call free(), in tests only anyway
+        if not we_are_translated():
+             # in case someone failed to call free(), in tests only anyway
              self.free()
 
+    def free(self):
+        while True:
+            key = pypy_jit_codemap_firstkey()
+            if not key:
+                break
+            items = pypy_jit_codemap_del(key)
+            lltype.free(items, flavor='raw', track_allocation=False)
+
     def free_asm_block(self, start, stop):
-        # fix up jit_addr_map
-        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(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)
+        items = pypy_jit_codemap_del(start)
+        if items:
+            lltype.free(items, flavor='raw', track_allocation=False)
+        pypy_jit_depthmap_clear(start, stop - start)
 
-    def register_frame_depth_map(self, rawstart, frame_positions,
+    def register_frame_depth_map(self, rawstart, rawstop, frame_positions,
                                  frame_assignments):
         if not frame_positions:
             return
-        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,
-                             g.jit_addr_map_used, rawstart)
-            self.extend_with('jit_frame_depth_map', frame_assignments,
-                             g.jit_frame_depth_map_used)
-        else:
-            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)
+        assert len(frame_positions) == len(frame_assignments)
+        for i in range(len(frame_positions)-1, -1, -1):
+            pos = rawstart + frame_positions[i]
+            length = rawstop - pos
+            if length > 0:
+                #print "ADD:", pos, length, frame_assignments[i]
+                pypy_jit_depthmap_add(pos, length, frame_assignments[i])
+            rawstop = pos
 
-    def register_codemap(self, codemap):
-        start = codemap[0]
-        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',
+    def register_codemap(self, (start, size, l)):
+        items = lltype.malloc(INT_LIST_PTR.TO, len(l), flavor='raw',
                               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)
+        for i in range(len(l)):
+            items[i] = l[i]
+        if pypy_jit_codemap_add(start, size, items, len(l)) < 0:
+            lltype.free(items, flavor='raw', track_allocation=False)
 
     def finish_once(self):
         self.free()
 
 def unpack_traceback(addr):
-    codemap_pos = find_codemap_at_addr(addr)
-    if codemap_pos == -1:
+    codemap_raw = find_codemap_at_addr(addr)
+    if not codemap_raw:
         return [] # no codemap for that position
     storage = lltype.malloc(rffi.CArray(lltype.Signed), 1, flavor='raw')
     storage[0] = 0
     res = []
     while True:
-        item = yield_bytecode_at_addr(codemap_pos, addr, storage)
+        item = yield_bytecode_at_addr(codemap_raw, addr, storage)
         if item == 0:
             break
         res.append(item)
diff --git a/rpython/jit/backend/llsupport/src/codemap.c b/rpython/jit/backend/llsupport/src/codemap.c
new file mode 100644
--- /dev/null
+++ b/rpython/jit/backend/llsupport/src/codemap.c
@@ -0,0 +1,196 @@
+#include "src/precommondefs.h"
+
+#ifndef HAS_SKIPLIST
+# error "skiplist.c needs to be included before"
+#endif
+
+volatile int pypy_codemap_currently_invalid = 0;
+
+void pypy_codemap_invalid_set(int value)
+{
+    if (value)
+        __sync_lock_test_and_set(&pypy_codemap_currently_invalid, 1);
+    else
+        __sync_lock_release(&pypy_codemap_currently_invalid);
+}
+
+
+/************************************************************/
+/***  codemap storage                                     ***/
+/************************************************************/
+
+typedef struct {
+    unsigned int machine_code_size;
+    unsigned int bytecode_info_size;
+    long *bytecode_info;
+} codemap_data_t;
+
+static skipnode_t jit_codemap_head;
+
+/*** interface used from codemap.py ***/
+
+RPY_EXTERN
+long pypy_jit_codemap_add(uintptr_t addr, unsigned int machine_code_size,
+                          long *bytecode_info, unsigned int bytecode_info_size)
+{
+    skipnode_t *new = skiplist_malloc(sizeof(codemap_data_t));
+    codemap_data_t *data;
+    if (new == NULL)
+        return -1;   /* too bad */
+
+    new->key = addr;
+    data = (codemap_data_t *)new->data;
+    data->machine_code_size = machine_code_size;
+    data->bytecode_info = bytecode_info;
+    data->bytecode_info_size = bytecode_info_size;
+
+    pypy_codemap_invalid_set(1);
+    skiplist_insert(&jit_codemap_head, new);
+    pypy_codemap_invalid_set(0);
+    return 0;
+}
+
+RPY_EXTERN
+long *pypy_jit_codemap_del(uintptr_t addr)
+{
+    long *result;
+    skipnode_t *node;
+
+    pypy_codemap_invalid_set(1);
+    node = skiplist_remove(&jit_codemap_head, addr);
+    pypy_codemap_invalid_set(0);
+
+    if (node == NULL)
+        return NULL;
+    result = ((codemap_data_t *)node->data)->bytecode_info;
+    free(node);
+    return result;
+}
+
+RPY_EXTERN
+uintptr_t pypy_jit_codemap_firstkey(void)
+{
+    return skiplist_firstkey(&jit_codemap_head);
+}
+
+/*** interface used from pypy/module/_vmprof ***/
+
+RPY_EXTERN
+void *pypy_find_codemap_at_addr(long addr)
+{
+    skipnode_t *codemap = skiplist_search(&jit_codemap_head, addr);
+    codemap_data_t *data;
+    uintptr_t rel_addr;
+
+    if (codemap == &jit_codemap_head)
+        return NULL;
+
+    rel_addr = (uintptr_t)addr - codemap->key;
+    data = (codemap_data_t *)codemap->data;
+    if (rel_addr >= data->machine_code_size)
+        return NULL;
+
+    return (void *)codemap;
+}
+
+RPY_EXTERN
+long pypy_yield_codemap_at_addr(void *codemap_raw, long addr,
+                                long *current_pos_addr)
+{
+    // will return consecutive unique_ids from codemap, starting from position
+    // `pos` until addr
+    skipnode_t *codemap = (skipnode_t *)codemap_raw;
+    long current_pos = *current_pos_addr;
+    long rel_addr = addr - codemap->key;
+    long next_start, next_stop;
+    codemap_data_t *data = (codemap_data_t *)codemap->data;
+
+    while (1) {
+        if (current_pos >= data->bytecode_info_size)
+            return 0;
+        next_start = data->bytecode_info[current_pos + 1];
+        if (next_start > rel_addr)
+            return 0;
+        next_stop = data->bytecode_info[current_pos + 2];
+        if (next_stop > rel_addr) {
+            *current_pos_addr = current_pos + 4;
+            return data->bytecode_info[current_pos];
+        }
+        // we need to skip potentially more than one
+        current_pos = data->bytecode_info[current_pos + 3];
+    }
+}
+
+/************************************************************/
+/***  depthmap storage                                    ***/
+/************************************************************/
+
+typedef struct {
+    unsigned int block_size;
+    unsigned int stack_depth;
+} depthmap_data_t;
+
+static skipnode_t jit_depthmap_head;
+
+/*** interface used from codemap.py ***/
+
+RPY_EXTERN
+long pypy_jit_depthmap_add(uintptr_t addr, unsigned int size,
+                           unsigned int stackdepth)
+{
+    skipnode_t *new = skiplist_malloc(sizeof(depthmap_data_t));
+    depthmap_data_t *data;
+    if (new == NULL)
+        return -1;   /* too bad */
+
+    new->key = addr;
+    data = (depthmap_data_t *)new->data;
+    data->block_size = size;
+    data->stack_depth = stackdepth;
+
+    pypy_codemap_invalid_set(1);
+    skiplist_insert(&jit_depthmap_head, new);
+    pypy_codemap_invalid_set(0);
+    return 0;
+}
+
+RPY_EXTERN
+void pypy_jit_depthmap_clear(uintptr_t addr, unsigned int size)
+{
+    uintptr_t search_key = addr + size - 1;
+    if (size == 0)
+        return;
+
+    pypy_codemap_invalid_set(1);
+    while (1) {
+        /* search for all nodes belonging to the range, and remove them */
+        skipnode_t *node = skiplist_search(&jit_depthmap_head, search_key);
+        if (node->key < addr)
+            break;   /* exhausted */
+        skiplist_remove(&jit_depthmap_head, node->key);
+        free(node);
+    }
+    pypy_codemap_invalid_set(0);
+}
+
+/*** interface used from pypy/module/_vmprof ***/
+
+RPY_EXTERN
+long pypy_jit_stack_depth_at_loc(long loc)
+{
+    skipnode_t *depthmap = skiplist_search(&jit_depthmap_head, (uintptr_t)loc);
+    depthmap_data_t *data;
+    uintptr_t rel_addr;
+
+    if (depthmap == &jit_depthmap_head)
+        return -1;
+
+    rel_addr = (uintptr_t)loc - depthmap->key;
+    data = (codemap_data_t *)depthmap->data;
+    if (rel_addr >= data->block_size)
+        return -1;
+
+    return data->stack_depth;
+}
+
+/************************************************************/
diff --git a/rpython/jit/backend/llsupport/src/skiplist.c b/rpython/jit/backend/llsupport/src/skiplist.c
new file mode 100644
--- /dev/null
+++ b/rpython/jit/backend/llsupport/src/skiplist.c
@@ -0,0 +1,103 @@
+#include <stdlib.h>
+#include <stdint.h>
+
+#define HAS_SKIPLIST
+#define SKIPLIST_HEIGHT   8
+
+typedef struct skipnode_s {
+    uintptr_t key;
+    char *data;
+    struct skipnode_s *next[SKIPLIST_HEIGHT];   /* may be smaller */
+} skipnode_t;
+
+static skipnode_t *skiplist_malloc(uintptr_t datasize)
+{
+    char *result;
+    uintptr_t basesize;
+    uintptr_t length = 1;
+    while (length < SKIPLIST_HEIGHT && (rand() & 3) == 0)
+        length++;
+    basesize = sizeof(skipnode_t) -
+               (SKIPLIST_HEIGHT - length) * sizeof(skipnode_t *);
+    result = malloc(basesize + datasize);
+    if (result != NULL) {
+        ((skipnode_t *)result)->data = result + basesize;
+    }
+    return (skipnode_t *)result;
+}
+
+static skipnode_t *skiplist_search(skipnode_t *head, uintptr_t searchkey)
+{
+    /* Returns the skipnode with key closest (but <=) searchkey.
+       Note that if there is no item with key <= searchkey in the list,
+       this will return the head node. */
+    uintptr_t level = SKIPLIST_HEIGHT - 1;
+    while (1) {
+        skipnode_t *next = head->next[level];
+        if (next != NULL && next->key <= searchkey) {
+            head = next;
+        }
+        else {
+            if (level == 0)
+                break;
+            level -= 1;
+        }
+    }
+    return head;
+}
+
+static void skiplist_insert(skipnode_t *head, skipnode_t *new)
+{
+    uintptr_t size0 = sizeof(skipnode_t) -
+                      SKIPLIST_HEIGHT * sizeof(skipnode_t *);
+    uintptr_t height_of_new = (new->data - ((char *)new + size0)) /
+                              sizeof(skipnode_t *);
+
+    uintptr_t level = SKIPLIST_HEIGHT - 1;
+    uintptr_t searchkey = new->key;
+    while (1) {
+        skipnode_t *next = head->next[level];
+        if (next != NULL && next->key <= searchkey) {
+            head = next;
+        }
+        else {
+            if (level < height_of_new) {
+                new->next[level] = next;
+                head->next[level] = new;
+                if (level == 0)
+                    break;
+            }
+            level -= 1;
+        }
+    }
+}
+
+static skipnode_t *skiplist_remove(skipnode_t *head, uintptr_t exact_key)
+{
+    uintptr_t level = SKIPLIST_HEIGHT - 1;
+    while (1) {
+        skipnode_t *next = head->next[level];
+        if (next != NULL && next->key <= exact_key) {
+            if (next->key == exact_key) {
+                head->next[level] = next->next[level];
+                if (level == 0)
+                    return next;    /* successfully removed */
+                level -= 1;
+            }
+            else
+                head = next;
+        }
+        else {
+            if (level == 0)
+                return NULL;    /* 'exact_key' not found! */
+            level -= 1;
+        }
+    }
+}
+
+static uintptr_t skiplist_firstkey(skipnode_t *head)
+{
+    if (head->next[0] == NULL)
+        return 0;
+    return head->next[0]->key;
+}
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,51 +1,55 @@
 
 from rpython.jit.backend.llsupport.codemap import stack_depth_at_loc
-from rpython.jit.backend.llsupport.codemap import CodemapStorage,\
-     ListStorageMixin, CodemapBuilder, unpack_traceback,\
-     pypy_get_codemap_storage
+from rpython.jit.backend.llsupport.codemap import CodemapStorage, \
+     CodemapBuilder, unpack_traceback, find_codemap_at_addr
 
-g = pypy_get_codemap_storage()
-
-def test_list_storage_mixin():
-    class X(ListStorageMixin):
-        def unpack(self):
-            return [g.jit_addr_map[i] for i in range(g.jit_addr_map_used)]
-
-    x = X()
-    x.extend_with('jit_addr_map', [1, 2, 3], 0)
-    assert x.unpack() == [1, 2, 3]
-    x.extend_with('jit_addr_map', [4, 5, 6], 3)
-    assert x.unpack() == [1, 2, 3, 4, 5, 6]
-    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('jit_addr_map', 3, 6)
-    assert x.unpack() == [1, 2, 17, 4, 5, 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('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()
+def test_register_codemap():
+    codemap = CodemapStorage()
+    codemap.setup()
+    codemap.register_codemap((100, 20, [13, 14, 15]))
+    codemap.register_codemap((300, 30, [16, 17, 18]))
+    codemap.register_codemap((200, 100, [19, 20, 21, 22, 23]))
+    #
+    raw100 = find_codemap_at_addr(100)
+    assert find_codemap_at_addr(119) == raw100
+    assert not find_codemap_at_addr(120)
+    #
+    raw200 = find_codemap_at_addr(200)
+    assert raw200 != raw100
+    assert find_codemap_at_addr(299) == raw200
+    #
+    raw300 = find_codemap_at_addr(329)
+    assert raw300 != raw100 and raw300 != raw200
+    assert find_codemap_at_addr(300) == raw300
+    #
+    codemap.free()
 
 def test_find_jit_frame_depth():
     codemap = CodemapStorage()
     codemap.setup()
-    codemap.register_frame_depth_map(11, [0, 5, 10], [1, 2, 3])
-    codemap.register_frame_depth_map(30, [0, 5, 10], [4, 5, 6])
-    codemap.register_frame_depth_map(0, [0, 5, 10], [7, 8, 9])
+    codemap.register_frame_depth_map(11, 26, [0, 5, 10], [1, 2, 3])
+    codemap.register_frame_depth_map(30, 41, [0, 5, 10], [4, 5, 6])
+    codemap.register_frame_depth_map(0, 11, [0, 5, 10], [7, 8, 9])
     assert stack_depth_at_loc(13) == 1
     assert stack_depth_at_loc(-3) == -1
+    assert stack_depth_at_loc(40) == 6
     assert stack_depth_at_loc(41) == -1
     assert stack_depth_at_loc(5) == 8
     assert stack_depth_at_loc(17) == 2
     assert stack_depth_at_loc(38) == 5
-    codemap.free_asm_block(11, 22)
-    assert stack_depth_at_loc(13) == 9
+    assert stack_depth_at_loc(25) == 3
+    assert stack_depth_at_loc(26) == -1
+    assert stack_depth_at_loc(11) == 1
+    assert stack_depth_at_loc(10) == 9
+    codemap.free_asm_block(11, 26)
+    assert stack_depth_at_loc(11) == -1
+    assert stack_depth_at_loc(13) == -1
     assert stack_depth_at_loc(-3) == -1
+    assert stack_depth_at_loc(40) == 6
     assert stack_depth_at_loc(41) == -1
     assert stack_depth_at_loc(5) == 8
-    assert stack_depth_at_loc(17) == 9
     assert stack_depth_at_loc(38) == 5
+    assert stack_depth_at_loc(10) == 9
     codemap.free()
 
 def test_codemaps():
diff --git a/rpython/jit/backend/llsupport/test/test_skiplist.py b/rpython/jit/backend/llsupport/test/test_skiplist.py
new file mode 100644
--- /dev/null
+++ b/rpython/jit/backend/llsupport/test/test_skiplist.py
@@ -0,0 +1,89 @@
+import random, os
+import cffi
+
+ffi = cffi.FFI()
+
+ffi.cdef("""
+typedef struct {
+    uintptr_t key;
+    char *data;
+    ...;
+} skipnode_t;
+
+skipnode_t *skiplist_malloc(uintptr_t datasize);
+skipnode_t *skiplist_search(skipnode_t *head, uintptr_t searchkey);
+void skiplist_insert(skipnode_t *head, skipnode_t *new);
+skipnode_t *skiplist_remove(skipnode_t *head, uintptr_t exact_key);
+uintptr_t skiplist_firstkey(skipnode_t *head);
+""")
+
+filename = os.path.join(os.path.dirname(__file__), '..', 'src', 'skiplist.c')
+lib = ffi.verify(open(filename).read())
+
+
+def test_insert_search_remove():
+    my_head = ffi.new("skipnode_t *")
+    assert lib.skiplist_search(my_head, 0) == my_head
+    #
+    keys = random.sample(xrange(2, 10**9), 50000)
+    nodes = {}
+    for key in keys:
+        node = lib.skiplist_malloc(4)
+        node.key = key
+        ffi.cast("int *", node.data)[0] = key
+        lib.skiplist_insert(my_head, node)
+        nodes[key] = node
+    #
+    random.shuffle(keys)
+    for key in keys:
+        node = lib.skiplist_search(my_head, key)
+        assert nodes[key] == node
+        if key + 1 not in nodes:
+            assert node == lib.skiplist_search(my_head, key + 1)
+    #
+    keys.sort()
+    following = {}
+    preceeding = {}
+    for key, next_key in zip(keys[:-1], keys[1:]):
+        following[key] = next_key
+        preceeding[next_key] = key
+    following[0] = keys[0]
+    following[keys[-1]] = 10**9
+    preceeding[keys[0]] = 0
+    #
+    for i in range(100000):
+        random_key = random.randrange(2, 10**9)
+        node = lib.skiplist_search(my_head, random_key)
+        assert node.key <= random_key
+        if node == my_head:
+            assert random_key < following[0]
+        else:
+            assert node == nodes[node.key]
+            assert following[node.key] > random_key
+    #
+    random_keys = list(keys)
+    random.shuffle(random_keys)
+    for i in range(10000):
+        node = nodes.pop(random_keys.pop())
+        prev = preceeding[node.key]
+        next = following[node.key]
+        following[prev] = next
+        preceeding[next] = prev
+        res = lib.skiplist_remove(my_head, node.key)
+        assert res == node
+        if prev == 0:
+            assert lib.skiplist_search(my_head, node.key) == my_head
+        else:
+            assert lib.skiplist_search(my_head, node.key) == nodes[prev]
+        res = lib.skiplist_remove(my_head, node.key)
+        assert res == ffi.NULL
+    #
+    for i in range(100000):
+        random_key = random.randrange(2, 10**9)
+        node = lib.skiplist_search(my_head, random_key)
+        assert node.key <= random_key
+        if node == my_head:
+            assert random_key < following[0]
+        else:
+            assert node == nodes[node.key]
+            assert following[node.key] > random_key
diff --git a/rpython/translator/c/gcc/trackgcroot.py b/rpython/translator/c/gcc/trackgcroot.py
--- a/rpython/translator/c/gcc/trackgcroot.py
+++ b/rpython/translator/c/gcc/trackgcroot.py
@@ -1069,6 +1069,7 @@
     visit_leaq = FunctionGcRootTracker._visit_lea
 
     visit_xorq = FunctionGcRootTracker.binary_insn
+    visit_xchgl = FunctionGcRootTracker._visit_xchg
     visit_xchgq = FunctionGcRootTracker._visit_xchg
     visit_testq = FunctionGcRootTracker._visit_test
 


More information about the pypy-commit mailing list