[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, ¤t_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, ¤t_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