1
0
blueloveTH 9 сар өмнө
parent
commit
c4ab63ca15

+ 1 - 1
include/pocketpy/common/smallmap.h

@@ -24,7 +24,7 @@
 
 #define SMALLMAP_T__HEADER
 #define K void*
-#define V int
+#define V py_i64
 #define NAME c11_smallmap_p2i
 #include "pocketpy/xmacros/smallmap.h"
 #undef SMALLMAP_T__HEADER

+ 25 - 0
include/pocketpy/interpreter/line_profiler.h

@@ -0,0 +1,25 @@
+#pragma once
+
+#include "pocketpy/pocketpy.h"
+#include <time.h>
+
+#include "pocketpy/interpreter/frame.h"
+
+typedef struct LineRecord {
+    py_i64 hits;
+    clock_t time;
+} LineRecord;
+
+typedef struct LineProfiler {
+    c11_smallmap_p2i records;  // SourceData* -> LineRecord[]
+    SourceLocation prev_loc;
+    clock_t prev_time;
+} LineProfiler;
+
+void LineProfiler__ctor(LineProfiler* self);
+void LineProfiler__dtor(LineProfiler* self);
+LineRecord* LineProfiler__get_record(LineProfiler* self, SourceLocation loc);
+void LineProfiler__begin(LineProfiler* self, bool reset);
+void LineProfiler__tracefunc_line(LineProfiler* self, py_Frame* frame);
+void LineProfiler__end(LineProfiler* self);
+void VM__set_line_profiler(VM* self, LineProfiler* profiler);

+ 2 - 0
include/pocketpy/interpreter/vm.h

@@ -7,6 +7,7 @@
 #include "pocketpy/interpreter/frame.h"
 #include "pocketpy/interpreter/typeinfo.h"
 #include "pocketpy/interpreter/name.h"
+#include "pocketpy/interpreter/line_profiler.h"
 #include <time.h>
 
 // TODO:
@@ -52,6 +53,7 @@ typedef struct VM {
     py_StackRef curr_decl_based_function;
     TraceInfo trace_info;
     WatchdogInfo watchdog_info;
+    LineProfiler* line_profiler;
     py_TValue vectorcall_buffer[PK_MAX_CO_VARNAMES];
 
     InternedNames names;

+ 1 - 1
src/common/smallmap.c

@@ -20,7 +20,7 @@
 
 #define SMALLMAP_T__SOURCE
 #define K void*
-#define V int
+#define V py_i64
 #define NAME c11_smallmap_p2i
 #include "pocketpy/xmacros/smallmap.h"
 #undef SMALLMAP_T__SOURCE

+ 4 - 1
src/interpreter/ceval.c

@@ -105,11 +105,14 @@ FrameResult VM__run_top_frame(VM* self) {
                 PK_INCREF(loc.src);
                 self->trace_info.prev_loc = loc;
                 self->trace_info.func(frame, TRACE_EVENT_LINE);
+                if(self->line_profiler) {
+                    LineProfiler__tracefunc_line(self->line_profiler, frame);
+                }
             }
         }
 
 #if PK_ENABLE_WATCHDOG
-        if(self->watchdog_info.max_reset_time > 0){
+        if(self->watchdog_info.max_reset_time > 0) {
             clock_t now = clock();
             if(now > self->watchdog_info.max_reset_time) {
                 self->watchdog_info.max_reset_time = 0;

+ 56 - 0
src/interpreter/line_profier.c

@@ -0,0 +1,56 @@
+#include "pocketpy/interpreter/line_profiler.h"
+
+void LineProfiler__ctor(LineProfiler* self) {
+    c11_smallmap_p2i__ctor(&self->records);
+    self->prev_loc.src = NULL;
+    self->prev_time = 0;
+}
+
+void LineProfiler__dtor(LineProfiler* self) {
+    for(int i = 0; i < self->records.length; i++) {
+        LineRecord* lines = c11__getitem(LineRecord*, &self->records, i);
+        PK_FREE(lines);
+    }
+    c11_smallmap_p2i__dtor(&self->records);
+}
+
+LineRecord* LineProfiler__get_record(LineProfiler* self, SourceLocation loc) {
+    LineRecord* lines = (LineRecord*)c11_smallmap_p2i__get(&self->records, loc.src, 0);
+    if(lines == NULL) {
+        int max_lineno = loc.src->line_starts.length;
+        lines = PK_MALLOC(sizeof(LineRecord) * (max_lineno + 1));
+        memset(lines, 0, sizeof(LineRecord) * (max_lineno + 1));
+        c11_smallmap_p2i__set(&self->records, loc.src, (py_i64)lines);
+    }
+    return &lines[loc.lineno];
+}
+
+void LineProfiler__begin(LineProfiler* self, bool reset) {
+    if(self->records.length > 0 && reset) {
+        LineProfiler__dtor(self);
+        LineProfiler__ctor(self);
+    }
+    self->prev_loc.src = NULL;
+    self->prev_time = 0;
+    VM__set_line_profiler(pk_current_vm, self);
+}
+
+void LineProfiler__tracefunc_line(LineProfiler* self, py_Frame* frame) {
+    clock_t now = clock();
+    if(self->prev_loc.src != NULL) {
+        LineRecord* line = LineProfiler__get_record(self, self->prev_loc);
+        line->hits++;
+        line->time += now - self->prev_time;
+    }
+    self->prev_loc = Frame__source_location(frame);
+    self->prev_time = now;
+}
+
+void LineProfiler__end(LineProfiler* self) {
+    if(self->prev_loc.src != NULL) {
+        LineRecord* line = LineProfiler__get_record(self, self->prev_loc);
+        line->hits++;
+        line->time += clock() - self->prev_time;
+    }
+    VM__set_line_profiler(pk_current_vm, NULL);
+}

+ 4 - 0
src/interpreter/vm.c

@@ -85,6 +85,8 @@ void VM__ctor(VM* self) {
     self->curr_class = NULL;
     self->curr_decl_based_function = NULL;
     memset(&self->trace_info, 0, sizeof(TraceInfo));
+    memset(&self->watchdog_info, 0, sizeof(WatchdogInfo));
+    self->line_profiler = NULL;
 
     FixedMemoryPool__ctor(&self->pool_frame, sizeof(py_Frame), 32);
 
@@ -269,6 +271,8 @@ void VM__dtor(VM* self) {
     InternedNames__dtor(&self->names);
 }
 
+void VM__set_line_profiler(VM* self, LineProfiler* profiler) { self->line_profiler = profiler; }
+
 void VM__push_frame(VM* self, py_Frame* frame) {
     frame->f_back = self->top_frame;
     self->top_frame = frame;