This commit is contained in:
blueloveTH 2024-02-18 10:58:48 +08:00
parent 7d38f83008
commit 6ed8a262a8
7 changed files with 33 additions and 31 deletions

File diff suppressed because one or more lines are too long

View File

@ -58,14 +58,18 @@ using CodeObject_ = std::shared_ptr<CodeObject>;
using FuncDecl_ = std::shared_ptr<FuncDecl>; using FuncDecl_ = std::shared_ptr<FuncDecl>;
struct CodeObject { struct CodeObject {
struct LineInfo{
int lineno; // line number for each bytecode
bool is_virtual; // whether this bytecode is virtual (not in source code)
};
std::shared_ptr<SourceData> src; std::shared_ptr<SourceData> src;
Str name; Str name;
bool is_generator = false; bool is_generator = false;
std::vector<Bytecode> codes; std::vector<Bytecode> codes;
std::vector<int> iblocks; // block index for each bytecode std::vector<int> iblocks; // block index for each bytecode
std::vector<int> lines; // line number for each bytecode std::vector<LineInfo> lines;
std::vector<char> is_virtual; // whether this bytecode is virtual (not in source code)
List consts; List consts;
std::vector<StrName> varnames; // local variables std::vector<StrName> varnames; // local variables
NameDictInt varnames_inv; NameDictInt varnames_inv;

View File

@ -4,25 +4,25 @@
namespace pkpy { namespace pkpy {
struct LineRecord{ struct _LineRecord{
int line; int line;
i64 hits; i64 hits;
clock_t time; clock_t time;
LineRecord(): line(-1), hits(0), time(0) {} _LineRecord(): line(-1), hits(0), time(0) {}
bool is_valid() const { return line != -1; } bool is_valid() const { return line != -1; }
}; };
struct FrameRecord{ struct _FrameRecord{
FrameId frame; FrameId frame;
clock_t prev_time; clock_t prev_time;
LineRecord* prev_record; _LineRecord* prev_record;
}; };
struct LineProfiler{ struct LineProfiler{
// filename -> records // filename -> records
std::map<std::string_view, std::vector<LineRecord>> records; std::map<std::string_view, std::vector<_LineRecord>> records;
stack<FrameRecord> frames; stack<_FrameRecord> frames;
std::set<FuncDecl*> functions; std::set<FuncDecl*> functions;
void begin(); void begin();

View File

@ -2,7 +2,7 @@ import os
def generate_python_sources(): def generate_python_sources():
sources = {} sources = {}
for file in os.listdir("python"): for file in sorted(os.listdir("python")):
if not file.endswith(".py"): if not file.endswith(".py"):
continue continue
key = file.split(".")[0] key = file.split(".")[0]

View File

@ -55,12 +55,11 @@ namespace pkpy{
int CodeEmitContext::emit_(Opcode opcode, uint16_t arg, int line, bool is_virtual) { int CodeEmitContext::emit_(Opcode opcode, uint16_t arg, int line, bool is_virtual) {
co->codes.push_back(Bytecode{(uint8_t)opcode, arg}); co->codes.push_back(Bytecode{(uint8_t)opcode, arg});
co->iblocks.push_back(curr_block_i); co->iblocks.push_back(curr_block_i);
co->lines.push_back(line); co->lines.push_back({line, is_virtual});
co->is_virtual.push_back(is_virtual);
int i = co->codes.size() - 1; int i = co->codes.size() - 1;
if(line == BC_KEEPLINE){ if(line == BC_KEEPLINE){
if(i >= 1) co->lines[i] = co->lines[i-1]; if(i >= 1) co->lines[i].lineno = co->lines[i-1].lineno;
else co->lines[i] = 1; else co->lines[i].lineno = 1;
} }
return i; return i;
} }

View File

@ -19,11 +19,10 @@ void LineProfiler::begin(){
} }
void LineProfiler::_step(FrameId frame){ void LineProfiler::_step(FrameId frame){
bool is_virtual = frame->co->is_virtual[frame->_ip]; auto line_info = frame->co->lines[frame->_ip];
if(is_virtual) return; if(line_info.is_virtual) return;
std::string_view filename = frame->co->src->filename.sv(); std::string_view filename = frame->co->src->filename.sv();
int line = frame->co->lines[frame->_ip]; int line = line_info.lineno;
if(frames.empty()){ if(frames.empty()){
frames.push({frame, clock(), nullptr}); frames.push({frame, clock(), nullptr});
@ -31,7 +30,7 @@ void LineProfiler::_step(FrameId frame){
_step_end(frame, line); _step_end(frame, line);
} }
std::vector<LineRecord>& file_records = records[filename]; std::vector<_LineRecord>& file_records = records[filename];
if(file_records.empty()){ if(file_records.empty()){
// initialize file_records // initialize file_records
int total_lines = frame->co->src->line_starts.size(); int total_lines = frame->co->src->line_starts.size();
@ -46,8 +45,8 @@ void LineProfiler::_step(FrameId frame){
void LineProfiler::_step_end(FrameId frame, int line){ void LineProfiler::_step_end(FrameId frame, int line){
clock_t now = clock(); clock_t now = clock();
FrameRecord& top_frame_record = frames.top(); _FrameRecord& top_frame_record = frames.top();
LineRecord* prev_record = top_frame_record.prev_record; _LineRecord* prev_record = top_frame_record.prev_record;
int id_delta = frame.index - top_frame_record.frame.index; int id_delta = frame.index - top_frame_record.frame.index;
PK_ASSERT(id_delta >= -1 && id_delta <= 1); PK_ASSERT(id_delta >= -1 && id_delta <= 1);
@ -69,8 +68,8 @@ void LineProfiler::_step_end(FrameId frame, int line){
void LineProfiler::end(){ void LineProfiler::end(){
clock_t now = clock(); clock_t now = clock();
FrameRecord& top_frame_record = frames.top(); _FrameRecord& top_frame_record = frames.top();
LineRecord* prev_record = top_frame_record.prev_record; _LineRecord* prev_record = top_frame_record.prev_record;
clock_t delta = now - top_frame_record.prev_time; clock_t delta = now - top_frame_record.prev_time;
top_frame_record.prev_time = now; top_frame_record.prev_time = now;
@ -88,7 +87,7 @@ Str LineProfiler::stats(){
int end_line = decl->code->end_line; int end_line = decl->code->end_line;
if(start_line == -1 || end_line == -1) continue; if(start_line == -1 || end_line == -1) continue;
std::string_view filename = decl->code->src->filename.sv(); std::string_view filename = decl->code->src->filename.sv();
std::vector<LineRecord>& file_records = records[filename]; std::vector<_LineRecord>& file_records = records[filename];
if(file_records.empty()) continue; if(file_records.empty()) continue;
clock_t total_time = 0; clock_t total_time = 0;
for(int line = start_line; line <= end_line; line++){ for(int line = start_line; line <= end_line; line++){
@ -100,7 +99,7 @@ Str LineProfiler::stats(){
ss << "Line # Hits Time Per Hit % Time Line Contents\n"; ss << "Line # Hits Time Per Hit % Time Line Contents\n";
ss << "==============================================================\n"; ss << "==============================================================\n";
for(int line = start_line; line <= end_line; line++){ for(int line = start_line; line <= end_line; line++){
const LineRecord& record = file_records.at(line); const _LineRecord& record = file_records.at(line);
if(!record.is_valid()) continue; if(!record.is_valid()) continue;
ss << left_pad(std::to_string(line), 6); ss << left_pad(std::to_string(line), 6);
if(record.hits == 0){ if(record.hits == 0){

View File

@ -618,11 +618,11 @@ Str VM::disassemble(CodeObject_ co){
int prev_line = -1; int prev_line = -1;
for(int i=0; i<co->codes.size(); i++){ for(int i=0; i<co->codes.size(); i++){
const Bytecode& byte = co->codes[i]; const Bytecode& byte = co->codes[i];
Str line = std::to_string(co->lines[i]); Str line = std::to_string(co->lines[i].lineno);
if(co->lines[i] == prev_line) line = ""; if(co->lines[i].lineno == prev_line) line = "";
else{ else{
if(prev_line != -1) ss << "\n"; if(prev_line != -1) ss << "\n";
prev_line = co->lines[i]; prev_line = co->lines[i].lineno;
} }
std::string pointer; std::string pointer;
@ -633,7 +633,7 @@ Str VM::disassemble(CodeObject_ co){
} }
ss << pad(line, 8) << pointer << pad(std::to_string(i), 3); ss << pad(line, 8) << pointer << pad(std::to_string(i), 3);
std::string bc_name(OP_NAMES[byte.op]); std::string bc_name(OP_NAMES[byte.op]);
if(co->is_virtual[i]) bc_name += '*'; if(co->lines[i].is_virtual) bc_name += '*';
ss << " " << pad(bc_name, 25) << " "; ss << " " << pad(bc_name, 25) << " ";
// ss << pad(byte.arg == -1 ? "" : std::to_string(byte.arg), 5); // ss << pad(byte.arg == -1 ? "" : std::to_string(byte.arg), 5);
std::string argStr = _opcode_argstr(this, byte, co.get()); std::string argStr = _opcode_argstr(this, byte, co.get());
@ -1260,7 +1260,7 @@ void VM::_raise(bool re_raise){
int actual_ip = frame->_ip; int actual_ip = frame->_ip;
if(e._ip_on_error >= 0 && e._code_on_error == (void*)frame->co) actual_ip = e._ip_on_error; if(e._ip_on_error >= 0 && e._code_on_error == (void*)frame->co) actual_ip = e._ip_on_error;
int current_line = frame->co->lines[actual_ip]; // current line int current_line = frame->co->lines[actual_ip].lineno; // current line
auto current_f_name = frame->co->name.sv(); // current function name auto current_f_name = frame->co->name.sv(); // current function name
if(frame->_callable == nullptr) current_f_name = ""; // not in a function if(frame->_callable == nullptr) current_f_name = ""; // not in a function
e.st_push(frame->co->src, current_line, nullptr, current_f_name); e.st_push(frame->co->src, current_line, nullptr, current_f_name);