Author: Maciej Fijalkowski <[email protected]>
Branch: vmprof
Changeset: r75358:d14d2b0ad1b6
Date: 2015-01-15 18:16 +0200
http://bitbucket.org/pypy/pypy/changeset/d14d2b0ad1b6/
Log: reimport vmprof.c and wrap errors
diff --git a/pypy/module/_vmprof/interp_vmprof.py
b/pypy/module/_vmprof/interp_vmprof.py
--- a/pypy/module/_vmprof/interp_vmprof.py
+++ b/pypy/module/_vmprof/interp_vmprof.py
@@ -3,10 +3,10 @@
from rpython.translator.tool.cbuild import ExternalCompilationInfo
from rpython.rtyper.annlowlevel import cast_instance_to_gcref,
cast_base_ptr_to_instance
from rpython.rlib.objectmodel import we_are_translated, CDefinedIntSymbolic
-from rpython.rlib import jit
+from rpython.rlib import jit, rgc, rposix
from rpython.tool.pairtype import extendabletype
from pypy.interpreter.baseobjspace import W_Root
-from pypy.interpreter.error import OperationError, oefmt
+from pypy.interpreter.error import OperationError, oefmt, wrap_oserror
from pypy.interpreter.gateway import interp2app, unwrap_spec
from pypy.interpreter.pyframe import PyFrame
from pypy.interpreter.pycode import PyCode
@@ -36,7 +36,8 @@
separate_module_sources=["""
void pypy_vmprof_init(void) {
- vmprof_set_mainloop(pypy_execute_frame_trampoline, 0,
pypy_vmprof_get_virtual_ip);
+ vmprof_set_mainloop(pypy_execute_frame_trampoline, 0,
+ pypy_vmprof_get_virtual_ip);
}
"""],
)
@@ -59,14 +60,18 @@
_nowrapper=True, sandboxsafe=True,
random_effects_on_gcobjs=True)
-pypy_vmprof_init = rffi.llexternal("pypy_vmprof_init", [], lltype.Void,
compilation_info=eci)
-vmprof_enable = rffi.llexternal("vmprof_enable", [rffi.CCHARP, rffi.LONG],
lltype.Void, compilation_info=eci)
-vmprof_disable = rffi.llexternal("vmprof_disable", [], lltype.Void,
compilation_info=eci)
+pypy_vmprof_init = rffi.llexternal("pypy_vmprof_init", [], lltype.Void,
+ compilation_info=eci)
+vmprof_enable = rffi.llexternal("vmprof_enable",
+ [rffi.INT, rffi.INT, rffi.LONG],
+ rffi.INT, compilation_info=eci)
+vmprof_disable = rffi.llexternal("vmprof_disable", [], rffi.INT,
+ compilation_info=eci)
-vmprof_register_virtual_function =
rffi.llexternal("vmprof_register_virtual_function",
- [rffi.CCHARP, rffi.VOIDP,
rffi.VOIDP],
- lltype.Void,
- compilation_info=eci)
+vmprof_register_virtual_function = rffi.llexternal(
+ "vmprof_register_virtual_function",
+ [rffi.CCHARP, rffi.VOIDP, rffi.VOIDP], lltype.Void,
+ compilation_info=eci)
original_execute_frame = PyFrame.execute_frame.im_func
original_execute_frame.c_name = 'pypy_pyframe_execute_frame'
@@ -115,29 +120,57 @@
get_virtual_ip.c_name = 'pypy_vmprof_get_virtual_ip'
get_virtual_ip._dont_inline_ = True
+def strncpy(src, tgt, tgt_ofs, count):
+ if len(src) < count:
+ count = len(src)
+ i = 0
+ while i < count:
+ tgt[i + tgt_ofs] = src[i]
+ i += 1
+ return i
+
+def int2str(num, s, ofs):
+ if num == 0:
+ s[ofs] = '0'
+ return 1
+ count = 0
+ c = num
+ while c != 0:
+ count += 1
+ c /= 10
+ pos = ofs + count - 1
+ c = num
+ while c != 0:
+ s[pos] = chr(ord('0') + c % 10)
+ c /= 10
+ pos -= 1
+ return count
+
[email protected]_collect
def do_get_virtual_ip(frame):
virtual_ip = frame.pycode._vmprof_virtual_ip
- if frame.pycode._vmprof_registered != _vmprof.counter:
+ if not frame.pycode._vmprof_registered:
# we need to register this code object
name = frame.pycode.co_name
+ filename = frame.pycode.co_filename
+ firstlineno = frame.pycode.co_firstlineno
start = rffi.cast(rffi.VOIDP, virtual_ip)
end = start # ignored for now
#
# manually fill the C buffer; we cannot use str2charp because we
# cannot call malloc from a signal handler
strbuf = _vmprof.strbuf
- strbuf[0] = 'p'
- strbuf[1] = 'y'
- strbuf[2] = ':'
- maxbuflen = min(len(name), 124)
- i = 0
- while i < maxbuflen:
- strbuf[i+3] = name[i]
- i += 1
- strbuf[i+3] = '\0'
- #
+ ofs = strncpy("py:", _vmprof.strbuf, 0, len("py:"))
+ ofs += strncpy(filename, _vmprof.strbuf, ofs, 128)
+ _vmprof.strbuf[ofs] = ':'
+ ofs += 1
+ ofs += int2str(firstlineno, _vmprof.strbuf, ofs)
+ _vmprof.strbuf[ofs] = ':'
+ ofs += 1
+ ofs += strncpy(name, _vmprof.strbuf, ofs, 1024 - 1 - ofs)
+ _vmprof.strbuf[ofs] = '\x00'
vmprof_register_virtual_function(strbuf, start, end)
- frame.pycode._vmprof_registered = _vmprof.counter
+ frame.pycode._vmprof_registered = 1
#
return virtual_ip
@@ -146,9 +179,9 @@
class VMProf(object):
def __init__(self):
self.virtual_ip = 0
- self.counter = 0 # the number of times we called enable()
self.is_enabled = False
- self.strbuf = lltype.malloc(rffi.CCHARP.TO, 128, flavor='raw',
immortal=True, zero=True)
+ self.ever_enabled = False
+ self.strbuf = lltype.malloc(rffi.CCHARP.TO, 1024, flavor='raw',
immortal=True, zero=True)
def get_next_virtual_IP(self):
self.virtual_ip -= 1
@@ -158,23 +191,30 @@
def _annotate_get_virtual_ip(self):
if FALSE_BUT_NON_CONSTANT:
# make sure it's annotated
- gcref = rffi.cast(llmemory.GCREF, self.counter) # just a random
non-constant value
+ gcref = rffi.cast(llmemory.GCREF, self.virtual_ip) # just a random
non-constant value
get_virtual_ip(gcref)
- def enable(self, space, filename, period):
+ def enable(self, space, fileno, symno, period):
self._annotate_get_virtual_ip()
if self.is_enabled:
raise oefmt(space.w_ValueError, "_vmprof already enabled")
self.is_enabled = True
- pypy_vmprof_init()
- self.counter += 1
- vmprof_enable(filename, period)
+ if not self.ever_enabled:
+ pypy_vmprof_init()
+ self.ever_enabled = True
+ res = vmprof_enable(fileno, symno, period)
+ if res == -1:
+ raise wrap_oserror(space, OSError(rposix.get_errno(),
+ "_vmprof.enable"))
def disable(self, space):
if not self.is_enabled:
raise oefmt(space.w_ValueError, "_vmprof not enabled")
- vmprof_disable()
self.is_enabled = False
+ res = vmprof_disable()
+ if res == -1:
+ raise wrap_oserror(space, OSError(rposix.get_errno(),
+ "_vmprof.disable"))
_vmprof = VMProf()
diff --git a/pypy/module/_vmprof/src/vmprof.c b/pypy/module/_vmprof/src/vmprof.c
--- a/pypy/module/_vmprof/src/vmprof.c
+++ b/pypy/module/_vmprof/src/vmprof.c
@@ -79,7 +79,6 @@
#include "get_custom_offset.c"
-
typedef struct {
void* _unused1;
void* _unused2;
@@ -107,7 +106,7 @@
void* bp = (void*)sp + sp_offset;
cp2->sp = bp;
cp2->ip = ((void**)(bp - sizeof(void*))[0];
- // the ret is on the top of the stack
+ // the ret is on the top of the stack minus WORD
return 1;
}
}
@@ -198,16 +197,27 @@
* *************************************************************
*/
-static void open_profile(const char* filename, long period_usec) {
- char buf[4096];
- profile_file = fopen(filename, "wb");
+static int open_profile(int fd, int sym_fd, long period_usec) {
+ if ((fd = dup(fd)) == -1) {
+ return -1;
+ }
+ if ((sym_fd = dup(sym_fd)) == -1) {
+ return -1;
+ }
+ profile_file = fdopen(fd, "wb");
+ if (!profile_file) {
+ return -1;
+ }
prof_header(profile_file, period_usec);
- assert(strlen(filename) < 4096);
- sprintf(buf, "%s.sym", filename);
- symbol_file = fopen(buf, "w");
+ symbol_file = fdopen(sym_fd, "w");
+ if (!symbol_file) {
+ return -1;
+ }
+ return 0;
}
-static void close_profile(void) {
+static int close_profile(void) {
+ // XXX all of this can happily fail
FILE* src;
char buf[BUFSIZ];
size_t size;
@@ -222,40 +232,50 @@
fclose(src);
fclose(profile_file);
fclose(symbol_file);
+ return 0;
}
-static void install_sigprof_handler(void) {
+static int install_sigprof_handler(void) {
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_sigaction = sigprof_handler;
sa.sa_flags = SA_RESTART | SA_SIGINFO;
- sigemptyset(&sa.sa_mask);
- sigaction(SIGPROF, &sa, NULL);
+ if (sigemptyset(&sa.sa_mask) == -1 ||
+ sigaction(SIGPROF, &sa, NULL) == -1) {
+ return -1;
+ }
+ return 0;
}
-static void remove_sigprof_handler(void) {
- signal(SIGPROF, SIG_DFL);
+static int remove_sigprof_handler(void) {
+ //sighandler_t res = signal(SIGPROF, SIG_DFL);
+ //if (res == SIG_ERR) {
+ // return -1;
+ //}
+ return 0;
};
-static void install_sigprof_timer(long period_usec) {
+static int install_sigprof_timer(long period_usec) {
static struct itimerval timer;
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = period_usec;
timer.it_value = timer.it_interval;
if (setitimer(ITIMER_PROF, &timer, NULL) != 0) {
- printf("Timer could not be initialized \n");
+ return -1;
}
+ return 0;
}
-static void remove_sigprof_timer(void) {
+static int remove_sigprof_timer(void) {
static struct itimerval timer;
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 0;
timer.it_value = timer.it_interval;
if (setitimer(ITIMER_PROF, &timer, NULL) != 0) {
- printf("Timer could not be deleted \n");
+ return -1;
}
+ return 0;
}
/* *************************************************************
@@ -270,18 +290,32 @@
mainloop_get_virtual_ip = get_virtual_ip;
}
-void vmprof_enable(const char* filename, long period_usec) {
+int vmprof_enable(int fd, int sym_fd, long period_usec) {
if (period_usec == -1)
period_usec = 1000000 / 100; /* 100hz */
- open_profile(filename, period_usec);
- install_sigprof_handler();
- install_sigprof_timer(period_usec);
+ if (open_profile(fd, sym_fd, period_usec) == -1) {
+ return -1;
+ }
+ if (install_sigprof_handler() == -1) {
+ return -1;
+ }
+ if (install_sigprof_timer(period_usec) == -1) {
+ return -1;
+ }
+ return 0;
}
-void vmprof_disable(void) {
- remove_sigprof_timer();
- remove_sigprof_handler();
- close_profile();
+int vmprof_disable(void) {
+ if (remove_sigprof_timer() == -1) {
+ return -1;
+ }
+ if (remove_sigprof_handler() == -1) {
+ return -1;
+ }
+ if (close_profile() == -1) {
+ return -1;
+ }
+ return 0;
}
void vmprof_register_virtual_function(const char* name, void* start, void*
end) {
diff --git a/pypy/module/_vmprof/src/vmprof.h b/pypy/module/_vmprof/src/vmprof.h
--- a/pypy/module/_vmprof/src/vmprof.h
+++ b/pypy/module/_vmprof/src/vmprof.h
@@ -12,7 +12,7 @@
void vmprof_register_virtual_function(const char* name, void* start, void*
end);
-void vmprof_enable(const char* filename, long period_usec);
-void vmprof_disable(void);
+int vmprof_enable(int fd, int sym_fd, long period_usec);
+int vmprof_disable(void);
#endif
diff --git a/pypy/module/_vmprof/test/test__vmprof.py
b/pypy/module/_vmprof/test/test__vmprof.py
--- a/pypy/module/_vmprof/test/test__vmprof.py
+++ b/pypy/module/_vmprof/test/test__vmprof.py
@@ -13,6 +13,8 @@
def __init__(self, co_name):
self.co_name = co_name
+ self.co_filename = 'filename'
+ self.co_firstlineno = 13
self._vmprof_setup_maybe()
def test_get_virtual_ip(monkeypatch):
@@ -31,7 +33,7 @@
_vmprof.counter = 42
ip = do_get_virtual_ip(myframe)
assert ip == mycode._vmprof_virtual_ip
- assert functions == [('py:foo', ip, ip)]
+ assert functions == [('py:filename:13:foo', ip, ip)]
# the second time, we don't register it again
functions = []
@@ -40,7 +42,7 @@
assert functions == []
# now, let's try with a long name
- mycode = FakePyCode('abcde' * 200)
+ mycode = FakePyCode('abcde' + 'f' * 20000)
myframe = FakePyFrame(mycode)
functions = []
ip2 = do_get_virtual_ip(myframe)
@@ -48,6 +50,6 @@
assert ip2 < ip # because it was generated later
assert len(functions) == 1
name, start, end = functions[0]
- assert len(name) == 127
- assert name == 'py:' + ('abcde'*200)[:124]
+ assert len(name) < 1025
+ assert name == 'py:filename:13:abcde' + 'f' * (1024 - 20 - 1)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit