Author: Maciej Fijalkowski <fij...@gmail.com>
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
+
+@rgc.no_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
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to