mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 19:40:18 +00:00
fix a bug
This commit is contained in:
parent
c7abc23ef4
commit
1558e5b40f
@ -63,8 +63,9 @@ struct CodeObject {
|
|||||||
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<int> lines; // line number for each bytecode
|
||||||
|
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;
|
||||||
|
@ -60,7 +60,7 @@ struct CodeEmitContext{
|
|||||||
CodeBlock* enter_block(CodeBlockType type);
|
CodeBlock* enter_block(CodeBlockType type);
|
||||||
void exit_block();
|
void exit_block();
|
||||||
void emit_expr(); // clear the expression stack and generate bytecode
|
void emit_expr(); // clear the expression stack and generate bytecode
|
||||||
int emit_(Opcode opcode, uint16_t arg, int line);
|
int emit_(Opcode opcode, uint16_t arg, int line, bool is_virtual=false);
|
||||||
void patch_jump(int index);
|
void patch_jump(int index);
|
||||||
bool add_label(StrName name);
|
bool add_label(StrName name);
|
||||||
int add_varname(StrName name);
|
int add_varname(StrName name);
|
||||||
|
@ -17,7 +17,6 @@ struct FrameRecord{
|
|||||||
FrameId frame;
|
FrameId frame;
|
||||||
clock_t prev_time;
|
clock_t prev_time;
|
||||||
LineRecord* prev_record;
|
LineRecord* prev_record;
|
||||||
int prev_line;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LineProfiler{
|
struct LineProfiler{
|
||||||
@ -28,7 +27,7 @@ struct LineProfiler{
|
|||||||
|
|
||||||
void begin();
|
void begin();
|
||||||
void _step(FrameId frame);
|
void _step(FrameId frame);
|
||||||
void _step_end(FrameId frame);
|
void _step_end(FrameId frame, int line);
|
||||||
void end();
|
void end();
|
||||||
Str stats();
|
Str stats();
|
||||||
};
|
};
|
||||||
|
@ -32,7 +32,7 @@ namespace pkpy{
|
|||||||
// add a `return None` in the end as a guard
|
// add a `return None` in the end as a guard
|
||||||
// previously, we only do this if the last opcode is not a return
|
// previously, we only do this if the last opcode is not a return
|
||||||
// however, this is buggy...since there may be a jump to the end (out of bound) even if the last opcode is a return
|
// however, this is buggy...since there may be a jump to the end (out of bound) even if the last opcode is a return
|
||||||
ctx()->emit_(OP_RETURN_VALUE, 1, BC_KEEPLINE);
|
ctx()->emit_(OP_RETURN_VALUE, 1, BC_KEEPLINE, true);
|
||||||
// find the last valid token
|
// find the last valid token
|
||||||
int j = i-1;
|
int j = i-1;
|
||||||
while(tokens[j].type == TK("@eol") || tokens[j].type == TK("@dedent") || tokens[j].type == TK("@eof")) j--;
|
while(tokens[j].type == TK("@eol") || tokens[j].type == TK("@dedent") || tokens[j].type == TK("@eof")) j--;
|
||||||
@ -627,7 +627,7 @@ __EAT_DOTS_END:
|
|||||||
ctx()->emit_expr();
|
ctx()->emit_expr();
|
||||||
int patch = ctx()->emit_(OP_POP_JUMP_IF_FALSE, BC_NOARG, prev().line);
|
int patch = ctx()->emit_(OP_POP_JUMP_IF_FALSE, BC_NOARG, prev().line);
|
||||||
compile_block_body();
|
compile_block_body();
|
||||||
ctx()->emit_(OP_LOOP_CONTINUE, ctx()->get_loop(), BC_KEEPLINE);
|
ctx()->emit_(OP_LOOP_CONTINUE, ctx()->get_loop(), BC_KEEPLINE, true);
|
||||||
ctx()->patch_jump(patch);
|
ctx()->patch_jump(patch);
|
||||||
ctx()->exit_block();
|
ctx()->exit_block();
|
||||||
// optional else clause
|
// optional else clause
|
||||||
@ -647,7 +647,7 @@ __EAT_DOTS_END:
|
|||||||
bool ok = vars->emit_store(ctx());
|
bool ok = vars->emit_store(ctx());
|
||||||
if(!ok) SyntaxError(); // this error occurs in `vars` instead of this line, but...nevermind
|
if(!ok) SyntaxError(); // this error occurs in `vars` instead of this line, but...nevermind
|
||||||
compile_block_body();
|
compile_block_body();
|
||||||
ctx()->emit_(OP_LOOP_CONTINUE, ctx()->get_loop(), BC_KEEPLINE);
|
ctx()->emit_(OP_LOOP_CONTINUE, ctx()->get_loop(), BC_KEEPLINE, true);
|
||||||
ctx()->exit_block();
|
ctx()->exit_block();
|
||||||
// optional else clause
|
// optional else clause
|
||||||
if (match(TK("else"))) {
|
if (match(TK("else"))) {
|
||||||
@ -805,9 +805,9 @@ __EAT_DOTS_END:
|
|||||||
ctx()->co->is_generator = true;
|
ctx()->co->is_generator = true;
|
||||||
ctx()->emit_(OP_GET_ITER, BC_NOARG, kw_line);
|
ctx()->emit_(OP_GET_ITER, BC_NOARG, kw_line);
|
||||||
ctx()->enter_block(CodeBlockType::FOR_LOOP);
|
ctx()->enter_block(CodeBlockType::FOR_LOOP);
|
||||||
ctx()->emit_(OP_FOR_ITER, BC_NOARG, BC_KEEPLINE);
|
ctx()->emit_(OP_FOR_ITER, BC_NOARG, kw_line);
|
||||||
ctx()->emit_(OP_YIELD_VALUE, BC_NOARG, BC_KEEPLINE);
|
ctx()->emit_(OP_YIELD_VALUE, BC_NOARG, kw_line);
|
||||||
ctx()->emit_(OP_LOOP_CONTINUE, ctx()->get_loop(), BC_KEEPLINE);
|
ctx()->emit_(OP_LOOP_CONTINUE, ctx()->get_loop(), kw_line);
|
||||||
ctx()->exit_block();
|
ctx()->exit_block();
|
||||||
consume_end_stmt();
|
consume_end_stmt();
|
||||||
break;
|
break;
|
||||||
|
@ -41,7 +41,7 @@ namespace pkpy{
|
|||||||
|
|
||||||
if(curr_type == CodeBlockType::FOR_LOOP){
|
if(curr_type == CodeBlockType::FOR_LOOP){
|
||||||
// add a no op here to make block check work
|
// add a no op here to make block check work
|
||||||
emit_(OP_NO_OP, BC_NOARG, BC_KEEPLINE);
|
emit_(OP_NO_OP, BC_NOARG, BC_KEEPLINE, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,13 +52,14 @@ namespace pkpy{
|
|||||||
expr->emit_(this);
|
expr->emit_(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CodeEmitContext::emit_(Opcode opcode, uint16_t arg, int line) {
|
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);
|
||||||
|
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] = co->lines[i-1];
|
||||||
else co->lines[i] = 1;
|
else co->lines[i] = 1;
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
|
@ -19,13 +19,16 @@ void LineProfiler::begin(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void LineProfiler::_step(FrameId frame){
|
void LineProfiler::_step(FrameId frame){
|
||||||
|
bool is_virtual = frame->co->is_virtual[frame->_ip];
|
||||||
|
if(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 = frame->co->lines[frame->_ip];
|
||||||
|
|
||||||
if(frames.empty()){
|
if(frames.empty()){
|
||||||
frames.push({frame, clock(), nullptr, -1});
|
frames.push({frame, clock(), nullptr});
|
||||||
}else{
|
}else{
|
||||||
_step_end(frame);
|
_step_end(frame, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<LineRecord>& file_records = records[filename];
|
std::vector<LineRecord>& file_records = records[filename];
|
||||||
@ -41,13 +44,13 @@ void LineProfiler::_step(FrameId frame){
|
|||||||
frames.top().prev_record = &file_records.at(line);
|
frames.top().prev_record = &file_records.at(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LineProfiler::_step_end(FrameId frame){
|
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;
|
||||||
|
|
||||||
if(prev_record->line != top_frame_record.prev_line){
|
// current line is about to change
|
||||||
top_frame_record.prev_line = prev_record->line;
|
if(prev_record->line != line){
|
||||||
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;
|
||||||
prev_record->hits++;
|
prev_record->hits++;
|
||||||
@ -58,7 +61,7 @@ void LineProfiler::_step_end(FrameId frame){
|
|||||||
PK_ASSERT(id_delta >= -1 && id_delta <= 1);
|
PK_ASSERT(id_delta >= -1 && id_delta <= 1);
|
||||||
|
|
||||||
if(id_delta == 1){
|
if(id_delta == 1){
|
||||||
frames.push({frame, now, nullptr, -1});
|
frames.push({frame, now, nullptr});
|
||||||
}else{
|
}else{
|
||||||
if(id_delta == -1) frames.pop();
|
if(id_delta == -1) frames.pop();
|
||||||
}
|
}
|
||||||
@ -69,13 +72,10 @@ void LineProfiler::end(){
|
|||||||
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;
|
||||||
|
|
||||||
if(prev_record->line != top_frame_record.prev_line){
|
clock_t delta = now - top_frame_record.prev_time;
|
||||||
top_frame_record.prev_line = prev_record->line;
|
top_frame_record.prev_time = now;
|
||||||
clock_t delta = now - top_frame_record.prev_time;
|
prev_record->hits++;
|
||||||
top_frame_record.prev_time = now;
|
prev_record->time += delta;
|
||||||
prev_record->hits++;
|
|
||||||
prev_record->time += delta;
|
|
||||||
}
|
|
||||||
|
|
||||||
frames.pop();
|
frames.pop();
|
||||||
PK_ASSERT(frames.empty());
|
PK_ASSERT(frames.empty());
|
||||||
|
@ -632,7 +632,9 @@ Str VM::disassemble(CodeObject_ co){
|
|||||||
pointer = " ";
|
pointer = " ";
|
||||||
}
|
}
|
||||||
ss << pad(line, 8) << pointer << pad(std::to_string(i), 3);
|
ss << pad(line, 8) << pointer << pad(std::to_string(i), 3);
|
||||||
ss << " " << pad(OP_NAMES[byte.op], 25) << " ";
|
std::string bc_name(OP_NAMES[byte.op]);
|
||||||
|
if(co->is_virtual[i]) bc_name += '*';
|
||||||
|
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());
|
||||||
ss << argStr;
|
ss << argStr;
|
||||||
|
@ -3,7 +3,8 @@ from line_profiler import LineProfiler
|
|||||||
def f2(x):
|
def f2(x):
|
||||||
a = 0
|
a = 0
|
||||||
for i in range(x):
|
for i in range(x):
|
||||||
a += i
|
if i % 5 == 0:
|
||||||
|
a += i
|
||||||
return a
|
return a
|
||||||
|
|
||||||
def f1(x):
|
def f1(x):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user