Author: Richard Plangger <planri...@gmail.com>
Branch: vmprof-native
Changeset: r90010:d671b63850ea
Date: 2017-02-08 19:37 +0100
http://bitbucket.org/pypy/pypy/changeset/d671b63850ea/

Log:    some more changes to the native test

diff --git a/rpython/rlib/rvmprof/cintf.py b/rpython/rlib/rvmprof/cintf.py
--- a/rpython/rlib/rvmprof/cintf.py
+++ b/rpython/rlib/rvmprof/cintf.py
@@ -46,7 +46,7 @@
 
 eci_kwds = dict(
     include_dirs = [SRC, SHARED, BACKTRACE, UDIS86],
-    includes = ['rvmprof.h', 'vmprof_stack.h'],
+    includes = ['rvmprof.h','vmprof_stack.h'],
     libraries = _libs,
     separate_module_files = [
         SRC.join('rvmprof.c'),
@@ -99,6 +99,7 @@
     return CInterface(locals())
 
 
+
 class CInterface(object):
     def __init__(self, namespace):
         for k, v in namespace.iteritems():
diff --git a/rpython/rlib/rvmprof/src/rvmprof.c 
b/rpython/rlib/rvmprof/src/rvmprof.c
--- a/rpython/rlib/rvmprof/src/rvmprof.c
+++ b/rpython/rlib/rvmprof/src/rvmprof.c
@@ -16,16 +16,3 @@
 #include "shared/vmprof_main_win32.h"
 #endif
 
-void dump_native_symbols(int fileno)
-{
-// TODO    PyObject * mod = NULL;
-// TODO
-// TODO    mod = PyImport_ImportModuleNoBlock("vmprof");
-// TODO    if (mod == NULL)
-// TODO        goto error;
-// TODO
-// TODO    PyObject_CallMethod(mod, "dump_native_symbols", "(l)", fileno);
-// TODO
-// TODOerror:
-// TODO    Py_XDECREF(mod);
-}
diff --git a/rpython/rlib/rvmprof/src/rvmprof.h 
b/rpython/rlib/rvmprof/src/rvmprof.h
--- a/rpython/rlib/rvmprof/src/rvmprof.h
+++ b/rpython/rlib/rvmprof/src/rvmprof.h
@@ -21,7 +21,6 @@
 #define RPY_EXPORTED  extern __attribute__((visibility("default")))
 #endif
 
-
 RPY_EXTERN char *vmprof_init(int fd, double interval, int memory,
                      int lines, const char *interp_name, int native);
 RPY_EXTERN void vmprof_ignore_signals(int);
diff --git a/rpython/rlib/rvmprof/src/shared/symboltable.c 
b/rpython/rlib/rvmprof/src/shared/symboltable.c
--- a/rpython/rlib/rvmprof/src/shared/symboltable.c
+++ b/rpython/rlib/rvmprof/src/shared/symboltable.c
@@ -170,11 +170,6 @@
     }
 }
 
-#else
-// other platforms than linux & mac os x
-void dump_all_known_symbols(int fd) {
-    // oh, nothing to do!! a not supported platform
-}
 #endif
 
 #ifdef __unix__
@@ -247,3 +242,193 @@
 #endif
     return 0;
 }
+
+#ifdef RPYTHON_VMPROF
+
+#define WORD_SIZE sizeof(long)
+#define ADDR_SIZE sizeof(void*)
+#define MAXLEN 1024
+
+void _dump_native_symbol(int fileno, void * addr, char * sym, int linenumber, 
char * filename) {
+    char natsym[64];
+    off_t pos_before;
+    struct str {
+        void * addr;
+        // NOTE windows 64, not supported yet
+        long size;
+        char str[1024];
+    } s;
+    pos_before = lseek(fileno, 0, SEEK_CUR);
+    lseek(fileno, 0, SEEK_END);
+
+    s.addr = addr;
+    /* must mach '<lang>:<name>:<line>:<file>'
+     * 'n' has been chosen as lang here, because the symbol
+     * can be generated from several languages (e.g. C, C++, ...)
+     */
+    // MARKER_NATIVE_SYMBOLS is \x08
+    write(fileno, "\x08", 1);
+    if (sym == NULL || sym[0] == '\x00') {
+        snprintf(natsym, 64, "<native symbol %p>", addr);
+        sym = natsym;
+    }
+    if (filename != NULL) {
+        s.size = snprintf(s.str, 1024, "n:%s:%d:%s", sym, linenumber, 
filename);
+    } else {
+        s.size = snprintf(s.str, 1024, "n:%s:%d:-", sym, linenumber);
+    }
+    write(fileno, &s, sizeof(void*)+sizeof(long)+s.size);
+
+    lseek(fileno, pos_before, SEEK_SET);
+}
+
+int _skip_string(int fileno)
+{
+    long chars;
+    int count = read(fileno, &chars, sizeof(long));
+    LOG("reading string of %d chars\n", chars);
+    if (count <= 0) {
+        return 1;
+    }
+    lseek(fileno, chars, SEEK_CUR);
+
+    return 0;
+}
+
+int _skip_header(int fileno, int * version, int * flags)
+{
+    unsigned char r[4];
+    (void)read(fileno, r, 4);
+    unsigned char count = r[3];
+    *version = (r[0] & 0xff) << 8 | (r[1] & 0xff);
+    *flags = r[2];
+    lseek(fileno, (int)count, SEEK_CUR);
+    return 0;
+}
+
+long _read_word(int fileno)
+{
+    long w;
+    read(fileno, &w, WORD_SIZE);
+    return w;
+}
+
+void * _read_addr(int fileno)
+{
+    void * a;
+    read(fileno, &a, ADDR_SIZE);
+    return a;
+}
+
+int _skip_word(int fileno)
+{
+    lseek(fileno, WORD_SIZE, SEEK_CUR);
+    return 0;
+}
+
+int _skip_addr(int fileno)
+{
+    lseek(fileno, ADDR_SIZE, SEEK_CUR);
+    return 0;
+}
+
+int _skip_time_and_zone(int fileno)
+{
+    lseek(fileno, sizeof(int64_t)*2 + 8, SEEK_CUR);
+    return 0;
+}
+
+
+void dump_native_symbols(int fileno)
+{
+    // only call this function
+    off_t orig_pos, cur_pos;
+    char marker;
+    ssize_t count;
+    int version;
+    int flags;
+    int memory, lines, native;
+    orig_pos = lseek(fileno, 0, SEEK_CUR);
+
+    lseek(fileno, 5*WORD_SIZE, SEEK_SET);
+
+    while (1) {
+        LOG("pre read\n");
+        count = read(fileno, &marker, 1);
+        LOG("post read\n");
+        if (count <= 0) {
+            break;
+        }
+        cur_pos = lseek(fileno, 0, SEEK_CUR);
+        LOG("posss 0x%llx %d\n", cur_pos-1, cur_pos-1);
+        switch (marker) {
+            case MARKER_HEADER: {
+                LOG("header 0x%llx\n", cur_pos);
+                if (_skip_header(fileno, &version, &flags) != 0) {
+                    return;
+                }
+                memory = (flags & PROFILE_MEMORY) != 0;
+                native = (flags & PROFILE_NATIVE) != 0;
+                lines = (flags & PROFILE_LINES) != 0;
+                break;
+            } case MARKER_META: {
+                LOG("meta 0x%llx\n", cur_pos);
+                if (_skip_string(fileno) != 0) { return; }
+                if (_skip_string(fileno) != 0) { return; }
+                break;
+            } case MARKER_TIME_N_ZONE:
+              case MARKER_TRAILER: {
+                LOG("tnz or trailer 0x%llx\n", cur_pos);
+                if (_skip_time_and_zone(fileno) != 0) { return; }
+                break;
+            } case MARKER_VIRTUAL_IP:
+              case MARKER_NATIVE_SYMBOLS: {
+                LOG("virtip 0x%llx\n", cur_pos);
+                if (_skip_addr(fileno) != 0) { return; }
+                if (_skip_string(fileno) != 0) { return; }
+                break;
+            } case MARKER_STACKTRACE: {
+                long trace_count = _read_word(fileno);
+                long depth = _read_word(fileno);
+
+                LOG("stack 0x%llx %d %d\n", cur_pos, trace_count, depth);
+
+                for (long i = depth/2-1; i >= 0; i--) {
+                    long kind = (long)_read_addr(fileno);
+                    void * addr = _read_addr(fileno);
+                    if (kind == VMPROF_NATIVE_TAG) {
+                        LOG("found kind %p\n", addr);
+                        char name[MAXLEN];
+                        char srcfile[MAXLEN];
+                        name[0] = 0;
+                        srcfile[0] = 0;
+                        int lineno = 0;
+                        if (vmp_resolve_addr(addr, name, MAXLEN, &lineno, 
srcfile, MAXLEN) == 0) {
+                            LOG("dumping add %p, name %s, %s:%d\n", addr, 
name, srcfile, lineno);
+                            _dump_native_symbol(fileno, addr, name, lineno, 
srcfile);
+                        }
+                    }
+                }
+                LOG("passed  memory %d \n", memory);
+
+                if (_skip_addr(fileno) != 0) { return; } // thread id
+                if (memory) {
+                    if (_skip_addr(fileno) != 0) { return; } // profile memory
+                }
+
+                break;
+            } default: {
+                fprintf(stderr, "unknown marker 0x%x\n", marker);
+                return;
+            }
+        }
+
+        cur_pos = lseek(fileno, 0, SEEK_CUR);
+        if (cur_pos >= orig_pos) {
+            break;
+        }
+    }
+
+    lseek(fileno, 0, SEEK_END);
+}
+#endif
diff --git a/rpython/rlib/rvmprof/src/shared/trampoline.c 
b/rpython/rlib/rvmprof/src/shared/trampoline.c
--- a/rpython/rlib/rvmprof/src/shared/trampoline.c
+++ b/rpython/rlib/rvmprof/src/shared/trampoline.c
@@ -183,7 +183,7 @@
     int pagesize;
 
     if (g_trampoline != NULL) {
-        fprintf(stderr, "trampoline already patched\n");
+        //fprintf(stderr, "trampoline already patched\n");
         return 0; // already patched
     }
 
diff --git a/rpython/rlib/rvmprof/src/shared/vmp_stack.c 
b/rpython/rlib/rvmprof/src/shared/vmp_stack.c
--- a/rpython/rlib/rvmprof/src/shared/vmp_stack.c
+++ b/rpython/rlib/rvmprof/src/shared/vmp_stack.c
@@ -98,8 +98,6 @@
     result[*depth] = (void*)CODE_ADDR_TO_UID(FRAME_CODE(frame));
     *depth = *depth + 1;
 #else
-    //result[*depth] = (void*)CODE_ADDR_TO_UID(FRAME_CODE(frame));
-    //*depth = *depth + 1;
 
     if (frame->kind == VMPROF_CODE_TAG) {
         int n = *depth;
@@ -107,12 +105,7 @@
         result[n++] = (void*)frame->value;
         *depth = n;
     }
-#ifdef PYPY_JIT_CODEMAP
-    else if (frame->kind == VMPROF_JITTED_TAG) {
-        intptr_t pc = ((intptr_t*)(frame->value - sizeof(intptr_t)))[0];
-        n = vmprof_write_header_for_jit_addr(result, n, pc, max_depth);
-    }
-#endif
+
 
 #endif
 
@@ -130,11 +123,15 @@
 
 #ifdef VMP_SUPPORTS_NATIVE_PROFILING
 int _write_native_stack(void* addr, void ** result, int depth) {
+#ifdef RPYTHON_VMPROF
+    result[depth++] = (void*)VMPROF_NATIVE_TAG;
+#else
     if (vmp_profiles_python_lines()) {
         // even if we do not log a python stack frame,
         // we must keep the profile readable
         result[depth++] = 0;
     }
+#endif
     result[depth++] = addr;
     return depth;
 }
@@ -143,16 +140,6 @@
 int vmp_walk_and_record_stack(PY_STACK_FRAME_T *frame, void ** result,
                               int max_depth, int native_skip, intptr_t pc) {
 
-//#ifdef PYPY_JIT_CODEMAP
-//    intptr_t codemap_addr;
-//    if (pypy_find_codemap_at_addr((intptr_t)pc, &codemap_addr)) {
-//        // the bottom part is jitted, means we can fill up the first part
-//        // from the JIT
-//        depth = vmprof_write_header_for_jit_addr(result, depth, pc, 
max_depth);
-//        frame = FRAME_STEP(frame); // skip the first item as it contains 
garbage
-//    }
-//#endif
-
     // called in signal handler
 #ifdef VMP_SUPPORTS_NATIVE_PROFILING
     intptr_t func_addr;
@@ -179,12 +166,22 @@
         native_skip--;
     }
 
+    //printf("stack trace:\n");
     int depth = 0;
     PY_STACK_FRAME_T * top_most_frame = frame;
     while (depth < max_depth) {
         unw_get_proc_info(&cursor, &pip);
 
         func_addr = pip.start_ip;
+
+        //{
+        //    char name[64];
+        //    unw_word_t x;
+        //    unw_get_proc_name(&cursor, name, 64, &x);
+        //    printf("  %s %p\n", name, func_addr);
+        //}
+
+
         //if (func_addr == 0) {
         //    unw_word_t rip = 0;
         //    if (unw_get_reg(&cursor, UNW_REG_IP, &rip) < 0) {
@@ -197,6 +194,7 @@
 
         if ((void*)pip.start_ip == (void*)VMPROF_EVAL()) {
             // yes we found one stack entry of the python frames!
+#ifndef RPYTHON_VMPROF
             unw_word_t rbx = 0;
             if (unw_get_reg(&cursor, REG_RBX, &rbx) < 0) {
                 break;
@@ -208,6 +206,9 @@
                 // current top_most_frame
                 return 0;
             } else {
+#else
+            {
+#endif
                 if (top_most_frame == NULL) {
                     break;
                 }
@@ -222,13 +223,27 @@
             // mark native routines with the first bit set,
             // this is possible because compiler align to 8 bytes.
             //
-            depth = _write_native_stack((void*)(func_addr | 0x1), result, 
depth);
+
+#ifdef PYPY_JIT_CODEMAP
+            if (func_addr == 0 && top_most_frame->kind == VMPROF_JITTED_TAG) {
+                intptr_t pc = ((intptr_t*)(frame->value - 
sizeof(intptr_t)))[0];
+                n = vmprof_write_header_for_jit_addr(result, n, pc, max_depth);
+                frame = FRAME_STEP(frame);
+            } else if (func_addr != 0) {
+                depth = _write_native_stack((void*)(func_addr | 0x1), result, 
depth);
+            }
+#else
+            if (func_addr != 0) {
+                depth = _write_native_stack((void*)(func_addr | 0x1), result, 
depth);
+            }
+#endif
         }
 
         int err = unw_step(&cursor);
-        if (err <= 0) {
-            // on mac this breaks on Py_Main?
+        if (err == 0) {
             break;
+        } else if (err < 0) {
+            return 0; // this sample is broken, cannot walk it fully
         }
     }
 
@@ -256,15 +271,25 @@
 int _ignore_symbols_from_path(const char * name) {
     // which symbols should not be considered while walking
     // the native stack?
+#ifdef RPYTHON_VMPROF
+    if (strstr(name, "libpypy-c.so") != NULL
+        || strstr(name, "pypy-c") != NULL
+        || strstr(name, "pypy") != NULL) {
+        printf("ignoring %s\n", name);
+        return 1;
+    }
+#else
+    // cpython
     if (strstr(name, "python") != NULL &&
-#ifdef __unix__
+#  ifdef __unix__
         strstr(name, ".so\n") == NULL
-#elif defined(__APPLE__)
+#  elif defined(__APPLE__)
         strstr(name, ".so") == NULL
-#endif
+#  endif
        ) {
         return 1;
     }
+#endif
     return 0;
 }
 
@@ -440,6 +465,9 @@
 }
 
 int vmp_ignore_ip(intptr_t ip) {
+    if (vmp_range_count == 0) {
+        return 0;
+    }
     int i = vmp_binary_search_ranges(ip, vmp_ranges, vmp_range_count);
     if (i == -1) {
         return 0;
diff --git a/rpython/rlib/rvmprof/src/shared/vmprof.h 
b/rpython/rlib/rvmprof/src/shared/vmprof.h
--- a/rpython/rlib/rvmprof/src/shared/vmprof.h
+++ b/rpython/rlib/rvmprof/src/shared/vmprof.h
@@ -1,5 +1,7 @@
 #pragma once
 
+#include <unistd.h>
+
 // common defines
 #define MARKER_STACKTRACE '\x01'
 #define MARKER_VIRTUAL_IP '\x02'
@@ -21,6 +23,7 @@
 #define PROFILE_MEMORY '\x01'
 #define PROFILE_LINES  '\x02'
 #define PROFILE_NATIVE '\x04'
+#define PROFILE_RPYTHON '\x08'
 
 #ifdef VMPROF_UNIX
 #define VMP_SUPPORTS_NATIVE_PROFILING
@@ -41,6 +44,9 @@
 #define PY_THREAD_STATE_T void
 #define FRAME_STEP(f) f->next
 #define FRAME_CODE(f) f->
+// Is there is a way to tell the compiler
+// that this prototype can have ANY return value. Just removing
+// the return type will default to int
 typedef long Signed;
 RPY_EXTERN Signed __vmprof_eval_vmprof();
 #define VMPROF_EVAL() __vmprof_eval_vmprof
diff --git a/rpython/rlib/rvmprof/src/shared/vmprof_common.h 
b/rpython/rlib/rvmprof/src/shared/vmprof_common.h
--- a/rpython/rlib/rvmprof/src/shared/vmprof_common.h
+++ b/rpython/rlib/rvmprof/src/shared/vmprof_common.h
@@ -106,6 +106,9 @@
     header.interp_name[2] = VERSION_TIMESTAMP;
     header.interp_name[3] = memory*PROFILE_MEMORY + lines*PROFILE_LINES + \
                             native*PROFILE_NATIVE;
+#ifdef RPYTHON_VMPROF
+    header.interp_name[3] += PROFILE_RPYTHON;
+#endif
     header.interp_name[4] = (char)namelen;
 
     memcpy(&header.interp_name[5], interp_name, namelen);
diff --git a/rpython/rlib/rvmprof/src/vmprof_stack.h 
b/rpython/rlib/rvmprof/src/vmprof_stack.h
--- a/rpython/rlib/rvmprof/src/vmprof_stack.h
+++ b/rpython/rlib/rvmprof/src/vmprof_stack.h
@@ -12,6 +12,7 @@
 #define VMPROF_JITTING_TAG 4
 #define VMPROF_GC_TAG 5
 #define VMPROF_ASSEMBLER_TAG 6
+#define VMPROF_NATIVE_TAG 7
 // whatever we want here
 
 typedef struct vmprof_stack_s {
diff --git a/rpython/rlib/rvmprof/test/test_rvmprof.py 
b/rpython/rlib/rvmprof/test/test_rvmprof.py
--- a/rpython/rlib/rvmprof/test/test_rvmprof.py
+++ b/rpython/rlib/rvmprof/test/test_rvmprof.py
@@ -154,7 +154,11 @@
     eci = ExternalCompilationInfo(compile_extra=['-g','-O2'],
             separate_module_sources=["""
             RPY_EXTERN int native_func(void) {
-                return 42;
+                int j = 0;
+                for (int i = 0; i < 420000; i++) {
+                    j += 1;
+                }
+                return j;
             }
             """])
 
@@ -176,8 +180,6 @@
         if num > 0:
             return main(code, num-1)
         else:
-            for i in range(100):
-                native_func()
             return native_func()
 
     tmpfilename = str(udir.join('test_rvmprof'))
@@ -188,15 +190,12 @@
             os.open('foo', 1, 1)
         code = MyCode()
         rvmprof.register_code(code, get_name)
-        fd = os.open(tmpfilename, os.O_WRONLY | os.O_CREAT, 0666)
-        if we_are_translated():
-            num = 100000000
-            period = 0.0001
-        else:
-            num = 10000
-            period = 0.9
+        fd = os.open(tmpfilename, os.O_RDWR | os.O_CREAT, 0666)
+        num = 10000
+        period = 0.0001
         rvmprof.enable(fd, period, native=1)
-        res = main(code, num)
+        for i in range(num):
+            res = main(code, 10)
         #assert res == 499999500000
         rvmprof.disable()
         os.close(fd)
@@ -204,10 +203,13 @@
 
     def check_profile(filename):
         from vmprof import read_profile
+        from vmprof.show import PrettyPrinter
 
         prof = read_profile(filename)
-        assert prof.get_tree().name.startswith("py:")
-        assert prof.get_tree().count
+        tree = prof.get_tree()
+        p = PrettyPrinter()
+        p._print_tree(tree)
+        assert tree.name.startswith("n:pypy_g_main")
 
     #assert f() == 0
     #assert os.path.exists(tmpfilename)
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to